#ifndef __MESHTRIANGLE_H__ #define __MESHTRIANGLE_H__ #include "point.h" // Points #include "vector.h" // Vectors for normals #include using namespace std; #include "ADFCreator_debug_flags.h" namespace SDF { class PointOnTriangle; //----------------------- // This is used by the TriMeshSdfAlgo classes. // When using one of those algorithms, you must // feed triangles to them in this form. // This implements a closest-distance-to-triangle algorithm. //----------------------- class MeshTriangle { friend ostream& operator<< (ostream &os, const MeshTriangle &tri); public: PointOnTriangle closest_point_from(const Point &p); Point pts[3]; Vector norm; Point avg_pt; // MeshTriangle is NOT responsible for the given pts MeshTriangle(const Point &a, const Point &b, const Point &c) { this->pts[0] = a; this->pts[1] = b; this->pts[2] = c; this->calculate_and_store_normal(); this->calculate_and_store_avg_pt(); } MeshTriangle(const MeshTriangle &from) { this->pts[0] = from.pts[0]; this->pts[1] = from.pts[1]; this->pts[2] = from.pts[2]; this->calculate_and_store_normal(); this->calculate_and_store_avg_pt(); } bool is_behind(const MeshTriangle &tri) const; //-------------------------------- // Test-friendly functions // Most of these are NOT meant to be used except for testing! //-------------------------------- static MeshTriangle* create_test_tri( double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3) { return new MeshTriangle( Point(x1, y1, z1), Point(x2, y2, z2), Point(x3, y3, z3)); } static MeshTriangle* create_test_tri( const Point &p1, double x2, double y2, double z2, double x3, double y3, double z3) { return new MeshTriangle( p1, Point(x2, y2, z2), Point(x3, y3, z3)); } private: void calculate_and_store_normal() { Vector L1 = (pts[1])-(pts[0]); //edge 1 Vector L2 = (pts[2])-(pts[1]); //edge 1 this->norm = L1 * L2; BOOL normSuccess = this->norm.Normalize(); assert(normSuccess == TRUE); } void calculate_and_store_avg_pt() { this->avg_pt = (pts[0] + pts[1] + pts[2]) * (1.0f/3.0f); } }; //----------------------- // A closest point on a triangle. // This includes more information than just a Point, which // is useful for ACCURATELY deciding when two closest points are actually the same. // This DOES make a few assumptions about the numerical Points. // For example, it assumes if two triangles have any points in common, those points // will be numerically equal! // Second, if a closest point is a vertex, then it will be numerically equal to the vertex. //----------------------- class PointOnTriangle { friend ostream& operator<< (ostream &os, const PointOnTriangle &pot); public: enum POTType {POT_FACE, POT_EDGE, POT_VERTEX, POT_UNKNOWN}; // Use this for POT_FACE and POT_VERTEX - convenience PointOnTriangle(const MeshTriangle &tri, POTType type, const Point &p ) : tri(tri), p(p) { assert(type != POT_EDGE); this->type = type; this->e1 = -1; this->e2 = -1; } PointOnTriangle(const MeshTriangle &tri, POTType type, const Point &p, unsigned int e1, unsigned int e2) : tri(tri), p(p) { this->type = type; this->e1 = e1; this->e2 = e2; } Point getPoint() const { return this->p; } MeshTriangle getTri() const { return this->tri; } POTType getType() const { return this->type; } //----------------------- // Only sensible if getType() == POT_EDGE //----------------------- Point getEdgeStart() const; //----------------------- // Only sensible if getType() == POT_EDGE //----------------------- Point getEdgeEnd() const; //----------------------- // This does not do a simple numerical == between the two points. // This actually looks at the type of the point, and determines from that // if the two POTs are equal. //----------------------- bool equal_to(const PointOnTriangle &other) const { if(this->getType() == other.getType()) { // Types are equal. What type? if(this->getType() == POT_VERTEX) { // Vertex. The actual vertices should be numerically equal return this->getPoint() == other.getPoint(); } else if(this->getType() == POT_EDGE) { // The edge indices may be flipped, so make sure to allow both possibilities if(this->getEdgeStart() == other.getEdgeStart()) { return (this->getEdgeEnd() == other.getEdgeEnd()); } else if(this->getEdgeEnd() == other.getEdgeStart() ) { return (this->getEdgeStart() == other.getEdgeEnd()); } } // Otherwise, both must be POT_FACE - in which case, it's impossible to be equal. } return false; } private: Point p; MeshTriangle tri; POTType type; unsigned int e1; unsigned int e2; }; ostream& operator<< (ostream &os, const PointOnTriangle::POTType &type); } #endif /* __MESHTRIANGLE_H__ */