diff --git a/poly2tri/common/shapes.cc b/poly2tri/common/shapes.cc index 01fecb9..c5f0562 100644 --- a/poly2tri/common/shapes.cc +++ b/poly2tri/common/shapes.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -30,35 +30,35 @@ */ #include "shapes.h" -Triangle::Triangle(Point& a, Point& b, Point& c) { - +Triangle::Triangle(Point& a, Point& b, Point& c) +{ points_[0] = &a; points_[1] = &b; points_[2] = &c; neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL; constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; - delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; interior_ = false; } // Update neighbor pointers -void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) { - - if((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) +void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) +{ + if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) neighbors_[0] = t; - else if((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) + else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) neighbors_[1] = t; - else if((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) + else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) neighbors_[2] = t; - else + else assert(0); } -// Exhaustive search to update neighbor pointers -void Triangle::MarkNeighbor(Triangle& t) { - +// Exhaustive search to update neighbor pointers +void Triangle::MarkNeighbor(Triangle& t) +{ if (t.Contains(points_[1], points_[2])) { neighbors_[0] = &t; t.MarkNeighbor(points_[1], points_[2], this); - } else if(t.Contains(points_[0], points_[2])) { + } else if (t.Contains(points_[0], points_[2])) { neighbors_[1] = &t; t.MarkNeighbor(points_[0], points_[2], this); } else if (t.Contains(points_[0], points_[1])) { @@ -67,39 +67,41 @@ void Triangle::MarkNeighbor(Triangle& t) { } } -void Triangle::ClearNeighbors() { +void Triangle::ClearNeighbors() +{ neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL; } -void Triangle::ClearDelunayEdges() { - delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; +void Triangle::ClearDelunayEdges() +{ + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; } - -Point* Triangle::OppositePoint(Triangle& t, Point& p) { - - Point *cw = t.PointCW(p); - double x = cw->x; - double y = cw->y; - x = p.x; - y = p.y; - Point* ham = PointCW(*cw); + +Point* Triangle::OppositePoint(Triangle& t, Point& p) +{ + Point *cw = t.PointCW(p); + double x = cw->x; + double y = cw->y; + x = p.x; + y = p.y; + Point* ham = PointCW(*cw); return PointCW(*cw); } // Legalized triangle by rotating clockwise around point(0) -void Triangle::Legalize(Point& point) { - +void Triangle::Legalize(Point& point) +{ points_[1] = points_[0]; points_[0] = points_[2]; points_[2] = &point; } // Legalize triagnle by rotating clockwise around oPoint -void Triangle::Legalize(Point& opoint, Point& npoint) { - - if(&opoint == points_[0]) { +void Triangle::Legalize(Point& opoint, Point& npoint) +{ + if (&opoint == points_[0]) { points_[1] = points_[0]; points_[0] = points_[2]; points_[2] = &npoint; @@ -111,211 +113,214 @@ void Triangle::Legalize(Point& opoint, Point& npoint) { points_[0] = points_[2]; points_[2] = points_[1]; points_[1] = &npoint; - } else { + } else { assert(0); } } -int Triangle::Index(const Point* p) { - - if(p == points_[0]) { - return 0; - } else if(p == points_[1]) { - return 1; - } else if(p == points_[2]) { - return 2; - } - assert(0); +int Triangle::Index(const Point* p) +{ + if (p == points_[0]) { + return 0; + } else if (p == points_[1]) { + return 1; + } else if (p == points_[2]) { + return 2; + } + assert(0); } -int Triangle::EdgeIndex(const Point* p1, const Point* p2) { - - if(points_[0] == p1) { - if(points_[1] == p2){ - return 2; - } else if(points_[2] == p2){ - return 1; - } - } else if(points_[1] == p1) { - if(points_[2] == p2) { - return 0; - } else if(points_[0] == p2) { - return 2; - } - } else if(points_[2] == p1) { - if(points_[0] == p2 ) { - return 1; - } else if(points_[1] == p2) { - return 0; - } - } - return -1; +int Triangle::EdgeIndex(const Point* p1, const Point* p2) +{ + if (points_[0] == p1) { + if (points_[1] == p2) { + return 2; + } else if (points_[2] == p2) { + return 1; + } + } else if (points_[1] == p1) { + if (points_[2] == p2) { + return 0; + } else if (points_[0] == p2) { + return 2; + } + } else if (points_[2] == p1) { + if (points_[0] == p2) { + return 1; + } else if (points_[1] == p2) { + return 0; + } + } + return -1; } -void Triangle::MarkConstrainedEdge(const int index) { - constrained_edge[index] = true; +void Triangle::MarkConstrainedEdge(const int index) +{ + constrained_edge[index] = true; } -void Triangle::MarkConstrainedEdge(Edge& edge) { - MarkConstrainedEdge(edge.p, edge.q); +void Triangle::MarkConstrainedEdge(Edge& edge) +{ + MarkConstrainedEdge(edge.p, edge.q); } // Mark edge as constrained -void Triangle::MarkConstrainedEdge(Point* p, Point* q) { - - if((q == points_[0] && p == points_[1] ) || (q == points_[1] && p == points_[0])) { - constrained_edge[2] = true; - } else if((q == points_[0] && p == points_[2] ) || (q == points_[2] && p == points_[0])) { - constrained_edge[1] = true; - } else if((q == points_[1] && p == points_[2] ) || (q == points_[2] && p == points_[1])) { - constrained_edge[0] = true; - } - -} - -// The point counter-clockwise to given point -Point* Triangle::PointCW(Point& point) { - - if(&point == points_[0]) { - return points_[2]; - } else if(&point == points_[1]) { - return points_[0]; - } else if(&point == points_[2]) { - return points_[1]; - } - assert(0); +void Triangle::MarkConstrainedEdge(Point* p, Point* q) +{ + if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { + constrained_edge[2] = true; + } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { + constrained_edge[1] = true; + } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { + constrained_edge[0] = true; + } } // The point counter-clockwise to given point -Point* Triangle::PointCCW(Point& point) { +Point* Triangle::PointCW(Point& point) +{ + if (&point == points_[0]) { + return points_[2]; + } else if (&point == points_[1]) { + return points_[0]; + } else if (&point == points_[2]) { + return points_[1]; + } + assert(0); +} - if(&point == points_[0]) { - return points_[1]; - } else if(&point == points_[1]) { - return points_[2]; - } else if(&point == points_[2]) { - return points_[0]; - } - assert(0); +// The point counter-clockwise to given point +Point* Triangle::PointCCW(Point& point) +{ + if (&point == points_[0]) { + return points_[1]; + } else if (&point == points_[1]) { + return points_[2]; + } else if (&point == points_[2]) { + return points_[0]; + } + assert(0); } // The neighbor clockwise to given point -Triangle* Triangle::NeighborCW(Point& point) { - - if(&point == points_[0]) { - return neighbors_[1]; - } else if(&point == points_[1]) { - return neighbors_[2]; - } - return neighbors_[0]; +Triangle* Triangle::NeighborCW(Point& point) +{ + if (&point == points_[0]) { + return neighbors_[1]; + } else if (&point == points_[1]) { + return neighbors_[2]; + } + return neighbors_[0]; } // The neighbor counter-clockwise to given point -Triangle* Triangle::NeighborCCW(Point& point) { - - if(&point == points_[0]) { - return neighbors_[2]; - } else if(&point == points_[1]) { - return neighbors_[0]; - } - return neighbors_[1]; -} - -bool Triangle::GetConstrainedEdgeCCW(Point& p) { - - if(&p == points_[0]) { - return constrained_edge[2]; - } else if(&p == points_[1]) { - return constrained_edge[0]; - } - return constrained_edge[1]; +Triangle* Triangle::NeighborCCW(Point& point) +{ + if (&point == points_[0]) { + return neighbors_[2]; + } else if (&point == points_[1]) { + return neighbors_[0]; + } + return neighbors_[1]; } -bool Triangle::GetConstrainedEdgeCW(Point& p) { +bool Triangle::GetConstrainedEdgeCCW(Point& p) +{ + if (&p == points_[0]) { + return constrained_edge[2]; + } else if (&p == points_[1]) { + return constrained_edge[0]; + } + return constrained_edge[1]; +} - if(&p == points_[0]) { +bool Triangle::GetConstrainedEdgeCW(Point& p) +{ + if (&p == points_[0]) { return constrained_edge[1]; - } else if(&p == points_[1]) { + } else if (&p == points_[1]) { return constrained_edge[2]; } return constrained_edge[0]; } -void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) { - - if(&p == points_[0]) { - constrained_edge[2] = ce; - } else if(&p == points_[1]) { - constrained_edge[0] = ce; - } else { - constrained_edge[1] = ce; - } +void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) +{ + if (&p == points_[0]) { + constrained_edge[2] = ce; + } else if (&p == points_[1]) { + constrained_edge[0] = ce; + } else { + constrained_edge[1] = ce; + } } -void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) { - - if(&p == points_[0]) { - constrained_edge[1] = ce; - } else if(&p == points_[1]) { - constrained_edge[2] = ce; - } else { - constrained_edge[0] = ce; - } -} - -bool Triangle::GetDelunayEdgeCCW(Point& p) { - - if(&p == points_[0]){ - return delaunay_edge[2]; - } else if(&p == points_[1]) { - return delaunay_edge[0]; - } - return delaunay_edge[1]; +void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) +{ + if (&p == points_[0]) { + constrained_edge[1] = ce; + } else if (&p == points_[1]) { + constrained_edge[2] = ce; + } else { + constrained_edge[0] = ce; + } } -bool Triangle::GetDelunayEdgeCW(Point& p) { - - if(&p == points_[0]) { - return delaunay_edge[1]; - } else if(&p == points_[1]) { - return delaunay_edge[2]; - } - return delaunay_edge[0]; +bool Triangle::GetDelunayEdgeCCW(Point& p) +{ + if (&p == points_[0]) { + return delaunay_edge[2]; + } else if (&p == points_[1]) { + return delaunay_edge[0]; + } + return delaunay_edge[1]; } -void Triangle::SetDelunayEdgeCCW(Point& p, bool e) { - - if(&p == points_[0]) { - delaunay_edge[2] = e; - } else if(&p == points_[1]) { - delaunay_edge[0] = e; - } else { - delaunay_edge[1] = e; - } +bool Triangle::GetDelunayEdgeCW(Point& p) +{ + if (&p == points_[0]) { + return delaunay_edge[1]; + } else if (&p == points_[1]) { + return delaunay_edge[2]; + } + return delaunay_edge[0]; } -void Triangle::SetDelunayEdgeCW(Point& p, bool e) { +void Triangle::SetDelunayEdgeCCW(Point& p, bool e) +{ + if (&p == points_[0]) { + delaunay_edge[2] = e; + } else if (&p == points_[1]) { + delaunay_edge[0] = e; + } else { + delaunay_edge[1] = e; + } +} - if(&p == points_[0]) { - delaunay_edge[1] = e; - } else if(&p == points_[1]) { - delaunay_edge[2] = e; - } else { - delaunay_edge[0] = e; - } +void Triangle::SetDelunayEdgeCW(Point& p, bool e) +{ + if (&p == points_[0]) { + delaunay_edge[1] = e; + } else if (&p == points_[1]) { + delaunay_edge[2] = e; + } else { + delaunay_edge[0] = e; + } } // The neighbor across to given point -Triangle& Triangle::NeighborAcross(Point& opoint) { - if(&opoint == points_[0]) { - return *neighbors_[0]; - } else if(&opoint == points_[1]) { - return *neighbors_[1]; - } - return *neighbors_[2]; +Triangle& Triangle::NeighborAcross(Point& opoint) +{ + if (&opoint == points_[0]) { + return *neighbors_[0]; + } else if (&opoint == points_[1]) { + return *neighbors_[1]; + } + return *neighbors_[2]; } -void Triangle::DebugPrint() { +void Triangle::DebugPrint() +{ using namespace std; cout << points_[0]->x << "," << points_[0]->y << " "; cout << points_[1]->x << "," << points_[1]->y << " "; diff --git a/poly2tri/common/shapes.h b/poly2tri/common/shapes.h index 5ba58a3..76c144b 100644 --- a/poly2tri/common/shapes.h +++ b/poly2tri/common/shapes.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -42,241 +42,271 @@ struct Node; struct Edge; -struct Point { - +struct Point { double x, y; - + /// Default constructor does nothing (for performance). - Point() { x = 0.0; y = 0.0; } - + Point() + { + x = 0.0; y = 0.0; + } + /// The edges this point constitutes an upper ending point std::vector edge_list; - + /// Construct using coordinates. - Point(double x, double y) : x(x), y(y) {} + Point(double x, double y) : x(x), y(y) + { + } - /// Set this point to all zeros. - void set_zero() { x = 0.0f; y = 0.0f; } + /// Set this point to all zeros. + void set_zero() + { + x = 0.0f; y = 0.0f; + } - /// Set this point to some specified coordinates. - void set(double x_, double y_) { x = x_; y = y_; } + /// Set this point to some specified coordinates. + void set(double x_, double y_) + { + x = x_; y = y_; + } - /// Negate this point. - Point operator -() const { Point v; v.set(-x, -y); return v; } - - /// Add a point to this point. - void operator += (const Point& v) { - x += v.x; y += v.y; - } - - /// Subtract a point from this point. - void operator -= (const Point& v) { - x -= v.x; y -= v.y; - } + /// Negate this point. + Point operator -() const + { + Point v; v.set(-x, -y); return v; + } + + /// Add a point to this point. + void operator +=(const Point& v) + { + x += v.x; y += v.y; + } + + /// Subtract a point from this point. + void operator -=(const Point& v) + { + x -= v.x; y -= v.y; + } + + /// Multiply this point by a scalar. + void operator *=(double a) + { + x *= a; y *= a; + } - /// Multiply this point by a scalar. - void operator *= (double a) { - x *= a; y *= a; - } - /// Get the length of this point (the norm). - double Length() const { + double Length() const + { return sqrt(x * x + y * y); } - + /// Convert this point into a unit point. Returns the Length. - double Normalize() { + double Normalize() + { double len = Length(); x /= len; y /= len; return len; } - - void DebugPrint() { + + void DebugPrint() + { printf("%f,%f ", x, y); } - }; // Represents a simple polygon's edge struct Edge { - Point* p, *q; /// Constructor - Edge(Point& p1, Point& p2) : p(&p1), q(&p2) { - - if(p1.y > p2.y) { + Edge(Point& p1, Point& p2) : p(&p1), q(&p2) + { + if (p1.y > p2.y) { q = &p1; p = &p2; - } else if(p1.y == p2.y) { - if(p1.x > p2.x) { + } else if (p1.y == p2.y) { + if (p1.x > p2.x) { q = &p1; p = &p2; - } else if(p1.x == p2.x) { + } else if (p1.x == p2.x) { // Repeat points assert(false); } } - + q->edge_list.push_back(this); - } - }; // Triangle-based data structures are know to have better performance than quad-edge structures // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // "Triangulations in CGAL" class Triangle { - public: - /// Constructor - Triangle(Point& a, Point& b, Point& c); +/// Constructor +Triangle(Point& a, Point& b, Point& c); - /// Flags to determine if an edge is a Constrained edge - bool constrained_edge[3]; - /// Flags to determine if an edge is a Delauney edge - bool delaunay_edge[3]; - - Point* GetPoint(const int& index); - Point* PointCW(Point& point); - Point* PointCCW(Point& point); - Point* OppositePoint(Triangle& t, Point& p); - - Triangle* GetNeighbor(const int& index); - void MarkNeighbor(Point* p1, Point* p2, Triangle* t); - void MarkNeighbor(Triangle& t); - - void MarkConstrainedEdge(const int index); - void MarkConstrainedEdge(Edge& edge); - void MarkConstrainedEdge(Point* p, Point* q); +/// Flags to determine if an edge is a Constrained edge +bool constrained_edge[3]; +/// Flags to determine if an edge is a Delauney edge +bool delaunay_edge[3]; - int Index(const Point* p); - int EdgeIndex(const Point* p1, const Point* p2); +Point* GetPoint(const int& index); +Point* PointCW(Point& point); +Point* PointCCW(Point& point); +Point* OppositePoint(Triangle& t, Point& p); - Triangle* NeighborCW(Point& point); - Triangle* NeighborCCW(Point& point); - bool GetConstrainedEdgeCCW(Point& p); - bool GetConstrainedEdgeCW(Point& p); - void SetConstrainedEdgeCCW(Point& p, bool ce); - void SetConstrainedEdgeCW(Point& p, bool ce); - bool GetDelunayEdgeCCW(Point& p); - bool GetDelunayEdgeCW(Point& p); - void SetDelunayEdgeCCW(Point& p, bool e); - void SetDelunayEdgeCW(Point& p, bool e); - - bool Contains(Point* p); - bool Contains(const Edge& e); - bool Contains(Point* p, Point* q); - void Legalize(Point& point); - void Legalize(Point& opoint, Point& npoint); - void ClearNeighbors(); - void ClearDelunayEdges(); - - inline bool IsInterior(); - inline void IsInterior(bool b); - - Triangle& NeighborAcross(Point& opoint); +Triangle* GetNeighbor(const int& index); +void MarkNeighbor(Point* p1, Point* p2, Triangle* t); +void MarkNeighbor(Triangle& t); + +void MarkConstrainedEdge(const int index); +void MarkConstrainedEdge(Edge& edge); +void MarkConstrainedEdge(Point* p, Point* q); + +int Index(const Point* p); +int EdgeIndex(const Point* p1, const Point* p2); + +Triangle* NeighborCW(Point& point); +Triangle* NeighborCCW(Point& point); +bool GetConstrainedEdgeCCW(Point& p); +bool GetConstrainedEdgeCW(Point& p); +void SetConstrainedEdgeCCW(Point& p, bool ce); +void SetConstrainedEdgeCW(Point& p, bool ce); +bool GetDelunayEdgeCCW(Point& p); +bool GetDelunayEdgeCW(Point& p); +void SetDelunayEdgeCCW(Point& p, bool e); +void SetDelunayEdgeCW(Point& p, bool e); + +bool Contains(Point* p); +bool Contains(const Edge& e); +bool Contains(Point* p, Point* q); +void Legalize(Point& point); +void Legalize(Point& opoint, Point& npoint); +void ClearNeighbors(); +void ClearDelunayEdges(); + +inline bool IsInterior(); +inline void IsInterior(bool b); + +Triangle& NeighborAcross(Point& opoint); + +void DebugPrint(); - void DebugPrint(); - private: - /// Triangle points - Point* points_[3]; - /// Neighbor list - Triangle* neighbors_[3]; - - /// Has this triangle been marked as an interior triangle? - bool interior_; - +/// Triangle points +Point* points_[3]; +/// Neighbor list +Triangle* neighbors_[3]; + +/// Has this triangle been marked as an interior triangle? +bool interior_; }; -inline bool cmp (const Point* a, const Point* b) { +inline bool cmp(const Point* a, const Point* b) +{ if (a->y < b->y) { return true; } else if (a->y == b->y) { - // Make sure q is point with greater x value - if(a->x < b->x) { + // Make sure q is point with greater x value + if (a->x < b->x) { return true; - } + } } return false; } - + /// Add two points_ component-wise. -inline Point operator + (const Point& a, const Point& b) { - return Point(a.x + b.x, a.y + b.y); +inline Point operator +(const Point& a, const Point& b) +{ + return Point(a.x + b.x, a.y + b.y); } /// Subtract two points_ component-wise. -inline Point operator - (const Point& a, const Point& b) { - return Point(a.x - b.x, a.y - b.y); +inline Point operator -(const Point& a, const Point& b) +{ + return Point(a.x - b.x, a.y - b.y); } /// Multiply point by scalar -inline Point operator * (double s, const Point& a) { - return Point(s * a.x, s * a.y); +inline Point operator *(double s, const Point& a) +{ + return Point(s * a.x, s * a.y); } -inline bool operator == (const Point& a, const Point& b) { - return a.x == b.x && a.y == b.y; +inline bool operator ==(const Point& a, const Point& b) +{ + return a.x == b.x && a.y == b.y; } -inline bool operator != (const Point& a, const Point& b) { - return a.x != b.x && a.y != b.y; +inline bool operator !=(const Point& a, const Point& b) +{ + return a.x != b.x && a.y != b.y; } /// Peform the dot product on two vectors. -inline double Dot(const Point& a, const Point& b) { - return a.x * b.x + a.y * b.y; +inline double Dot(const Point& a, const Point& b) +{ + return a.x * b.x + a.y * b.y; } /// Perform the cross product on two vectors. In 2D this produces a scalar. -inline double Cross(const Point& a, const Point& b) { - return a.x * b.y - a.y * b.x; +inline double Cross(const Point& a, const Point& b) +{ + return a.x * b.y - a.y * b.x; } /// Perform the cross product on a point and a scalar. In 2D this produces /// a point. -inline Point Cross(const Point& a, double s) { - return Point(s * a.y, -s * a.x); +inline Point Cross(const Point& a, double s) +{ + return Point(s * a.y, -s * a.x); } /// Perform the cross product on a scalar and a point. In 2D this produces /// a point. -inline Point Cross(const double s, const Point& a) { - return Point(-s * a.y, s * a.x); +inline Point Cross(const double s, const Point& a) +{ + return Point(-s * a.y, s * a.x); } -inline Point* Triangle::GetPoint(const int& index) { +inline Point* Triangle::GetPoint(const int& index) +{ return points_[index]; } -inline Triangle* Triangle::GetNeighbor(const int& index) { +inline Triangle* Triangle::GetNeighbor(const int& index) +{ return neighbors_[index]; } -inline bool Triangle::Contains(Point* p) { +inline bool Triangle::Contains(Point* p) +{ return p == points_[0] || p == points_[1] || p == points_[2]; } -inline bool Triangle::Contains(const Edge& e) { +inline bool Triangle::Contains(const Edge& e) +{ return Contains(e.p) && Contains(e.q); } -inline bool Triangle::Contains(Point* p, Point* q) { +inline bool Triangle::Contains(Point* p, Point* q) +{ return Contains(p) && Contains(q); } -inline bool Triangle::IsInterior() { +inline bool Triangle::IsInterior() +{ return interior_; } -inline void Triangle::IsInterior(bool b) { - interior_ = b; +inline void Triangle::IsInterior(bool b) +{ + interior_ = b; } #endif diff --git a/poly2tri/common/utils.h b/poly2tri/common/utils.h index 5e6a1b2..a91377a 100644 --- a/poly2tri/common/utils.h +++ b/poly2tri/common/utils.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -35,9 +35,12 @@ #include template -int array_length(T(&)[size]){return size;} +int array_length(T(&)[size]) +{ + return size; +} -const double PI_3div4 = 3*M_PI/4; +const double PI_3div4 = 3 * M_PI / 4; const double EPSILON = 1e-12; enum Orientation { CW, CCW, COLLINEAR }; @@ -50,28 +53,27 @@ enum Orientation { CW, CCW, COLLINEAR }; *
  * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
  *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
- * 
+ * */ -Orientation Orient2d(Point& pa, Point& pb, Point& pc ) { - +Orientation Orient2d(Point& pa, Point& pb, Point& pc) +{ double detleft = (pa.x - pc.x) * (pb.y - pc.y); double detright = (pa.y - pc.y) * (pb.x - pc.x); double val = detleft - detright; - if( val > -EPSILON && val < EPSILON ) { - return COLLINEAR; - } else if( val > 0 ) { + if (val > -EPSILON && val < EPSILON) { + return COLLINEAR; + } else if (val > 0) { return CCW; } return CW; - } -bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { - +bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) +{ double pdx = pd.x; double pdy = pd.y; double adx = pa.x - pdx; - double ady = pa.y - pdy; + double ady = pa.y - pdy; double bdx = pb.x - pdx; double bdy = pb.y - pdy; @@ -79,7 +81,7 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { double bdxady = bdx * ady; double oabd = adxbdy - bdxady; - if(oabd <= EPSILON) { + if (oabd <= EPSILON) { return false; } @@ -90,12 +92,11 @@ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { double adxcdy = adx * cdy; double ocad = cdxady - adxcdy; - if(ocad <= EPSILON) { + if (ocad <= EPSILON) { return false; - } - + } + return true; - } #endif diff --git a/poly2tri/sweep/advancing_front.cc b/poly2tri/sweep/advancing_front.cc index c0accd8..df12b3b 100644 --- a/poly2tri/sweep/advancing_front.cc +++ b/poly2tri/sweep/advancing_front.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -30,75 +30,78 @@ */ #include "advancing_front.h" -AdvancingFront::AdvancingFront() { +AdvancingFront::AdvancingFront() +{ head_ = tail_ = search_node_ = NULL; } -Node* AdvancingFront::Locate(const double& x) { - - Node* node = search_node_; +Node* AdvancingFront::Locate(const double& x) +{ + Node* node = search_node_; - if(x < node->value) { + if (x < node->value) { //printf("<: - %f,%f - %p\n", x, node->value, node->next); - while((node = node->prev) != NULL) { - if(x >= node->value) { + while ((node = node->prev) != NULL) { + if (x >= node->value) { search_node_ = node; return node; - } - } - } else { + } + } + } else { //printf("%p - %p\n", node, node->next); //printf(">: %f - %f\n", x, node->value); - while((node = node->next) != NULL) { - if(x < node->value) { + while ((node = node->next) != NULL) { + if (x < node->value) { search_node_ = node->prev; return node->prev; - } - } - } - return NULL; + } + } + } + return NULL; } -Node* AdvancingFront::FindSearchNode(const double& x) { - // TODO: implement BST index - return search_node_; +Node* AdvancingFront::FindSearchNode(const double& x) +{ + // TODO: implement BST index + return search_node_; } - -Node* AdvancingFront::LocatePoint(Point* point) { - const double px = point->x; - Node* node = FindSearchNode(px); - const double nx = node->point->x; - - if(px == nx) { - if(point != node->point) { - // We might have two nodes with same x value for a short time - if(point == node->prev->point) { - node = node->prev; - } else if(point == node->next->point) { - node = node->next; - } else { - assert(0); - } - } - } else if(px < nx) { - while((node = node->prev) != NULL) { - if(point == node->point) { - break; - } - } - } else { - while((node = node->next) != NULL) { - if(point == node->point) - break; - } - } - if(node) search_node_ = node; - return node; +Node* AdvancingFront::LocatePoint(Point* point) +{ + const double px = point->x; + Node* node = FindSearchNode(px); + const double nx = node->point->x; + + if (px == nx) { + if (point != node->point) { + // We might have two nodes with same x value for a short time + if (point == node->prev->point) { + node = node->prev; + } else if (point == node->next->point) { + node = node->next; + } else { + assert(0); + } + } + } else if (px < nx) { + while ((node = node->prev) != NULL) { + if (point == node->point) { + break; + } + } + } else { + while ((node = node->next) != NULL) { + if (point == node->point) + break; + } + } + if (node) search_node_ = node; + return node; } - -AdvancingFront::~AdvancingFront() { - delete head_; - delete search_node_; + +AdvancingFront::~AdvancingFront() +{ + delete head_; + delete search_node_; delete tail_; } diff --git a/poly2tri/sweep/advancing_front.h b/poly2tri/sweep/advancing_front.h index 3468618..15fd037 100644 --- a/poly2tri/sweep/advancing_front.h +++ b/poly2tri/sweep/advancing_front.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -34,66 +34,84 @@ struct Node; // Advancing front node struct Node { - Point* point; Triangle* triangle; - + Node* next; Node* prev; - - double value; - - Node(Point& p) : point(&p), triangle(NULL), value(p.x), next(NULL), prev(NULL) {} - Node(Point& p, Triangle& t) : point(&p), triangle(&t), value(p.x), - next(NULL), prev(NULL) {} - - /* - ~Node() { - printf("going... "); - printf("bye node"); - printf(" ... gone!\n"); + double value; + + Node(Point& p) : point(&p), triangle(NULL), value(p.x), next(NULL), prev(NULL) + { } - */ - + + Node(Point& p, Triangle& t) : point(&p), triangle(&t), value(p.x), + next(NULL), prev(NULL) + { + } + + /* + ~Node() { + printf("going... "); + printf("bye node"); + printf(" ... gone!\n"); + } + */ }; // Advancing front class AdvancingFront { - public: - AdvancingFront(); - // Destructor - ~AdvancingFront(); - - Node* head(); - void set_head(Node* node); - Node* tail(); - void set_tail(Node* node); - Node* search(); - void set_search(Node* node); - - /// Locate insertion point along advancing front - Node* Locate(const double& x); - - Node* LocatePoint(Point* point); - +AdvancingFront(); +// Destructor +~AdvancingFront(); + +Node* head(); +void set_head(Node* node); +Node* tail(); +void set_tail(Node* node); +Node* search(); +void set_search(Node* node); + +/// Locate insertion point along advancing front +Node* Locate(const double& x); + +Node* LocatePoint(Point* point); + private: - - Node* head_, *tail_, *search_node_; - - Node* FindSearchNode(const double& x); - + +Node* head_, *tail_, *search_node_; + +Node* FindSearchNode(const double& x); }; -inline Node* AdvancingFront::head() { return head_; } -inline void AdvancingFront::set_head(Node* node) { head_ = node; } +inline Node* AdvancingFront::head() +{ + return head_; +} +inline void AdvancingFront::set_head(Node* node) +{ + head_ = node; +} -inline Node* AdvancingFront::tail() { return tail_; } -inline void AdvancingFront::set_tail(Node* node) { tail_ = node; } +inline Node* AdvancingFront::tail() +{ + return tail_; +} +inline void AdvancingFront::set_tail(Node* node) +{ + tail_ = node; +} -inline Node* AdvancingFront::search() { return search_node_; } +inline Node* AdvancingFront::search() +{ + return search_node_; +} -inline void AdvancingFront::set_search(Node* node) { search_node_ = node; } +inline void AdvancingFront::set_search(Node* node) +{ + search_node_ = node; +} diff --git a/poly2tri/sweep/cdt.cc b/poly2tri/sweep/cdt.cc index 3987cc8..c2523ba 100644 --- a/poly2tri/sweep/cdt.cc +++ b/poly2tri/sweep/cdt.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -30,29 +30,34 @@ */ #include "cdt.h" -CDT::CDT(Point** polyline, const int& point_count) { - sweep_context_ = new SweepContext(polyline, point_count); - sweep_ = new Sweep; +CDT::CDT(Point** polyline, const int& point_count) +{ + sweep_context_ = new SweepContext(polyline, point_count); + sweep_ = new Sweep; } -void CDT::AddHole(const Point poly_line[], const int point_count) { - +void CDT::AddHole(const Point poly_line[], const int point_count) +{ } -void CDT::Triangulate() { - sweep_->Triangulate(*sweep_context_); +void CDT::Triangulate() +{ + sweep_->Triangulate(*sweep_context_); } -std::vector CDT::GetTriangles() { +std::vector CDT::GetTriangles() +{ return sweep_context_->GetTriangles(); } -std::list CDT::GetMap() { +std::list CDT::GetMap() +{ return sweep_context_->GetMap(); } -CDT::~CDT() { - delete sweep_context_; - delete sweep_; +CDT::~CDT() +{ + delete sweep_context_; + delete sweep_; } diff --git a/poly2tri/sweep/cdt.h b/poly2tri/sweep/cdt.h index b7cc058..7674bd6 100644 --- a/poly2tri/sweep/cdt.h +++ b/poly2tri/sweep/cdt.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -33,28 +33,26 @@ #include "sweep_context.h" #include "sweep.h" -class CDT +class CDT { - public: - - /// Constructor - CDT(Point** poly_line, const int& point_count); - /// Add a hole - void AddHole(const Point poly_line[], const int point_count); - /// Triangulate points - void Triangulate(); - /// Get Delaunay triangles - std::vector GetTriangles(); - /// Get triangle map - std::list CDT::GetMap(); + +/// Constructor +CDT(Point** poly_line, const int& point_count); +/// Add a hole +void AddHole(const Point poly_line[], const int point_count); +/// Triangulate points +void Triangulate(); +/// Get Delaunay triangles +std::vector GetTriangles(); +/// Get triangle map +std::list CDT::GetMap(); private: - SweepContext* sweep_context_; - Sweep* sweep_; - - /// Destructor - ~CDT(); - +SweepContext* sweep_context_; +Sweep* sweep_; + +/// Destructor +~CDT(); }; diff --git a/poly2tri/sweep/mesh.cc b/poly2tri/sweep/mesh.cc index 1dc71f1..18616cf 100644 --- a/poly2tri/sweep/mesh.cc +++ b/poly2tri/sweep/mesh.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -34,16 +34,16 @@ // Excludes exterior triangles outside constrained edges // Depth first search -void Mesh::clean(Triangle& triangle) +void Mesh::clean(Triangle& triangle) { - /* - if(triangle != NULL && !triangle.interior) - { - triangle.interior = true; - triangles += triangle; - for(i <- 0 until 3) - if(!triangle.edges(i)) - clean(triangle.neighbors(i)); - } - */ + /* + if(triangle != NULL && !triangle.interior) + { + triangle.interior = true; + triangles += triangle; + for(i <- 0 until 3) + if(!triangle.edges(i)) + clean(triangle.neighbors(i)); + } + */ } diff --git a/poly2tri/sweep/mesh.h b/poly2tri/sweep/mesh.h index 895e726..e8f1ee8 100644 --- a/poly2tri/sweep/mesh.h +++ b/poly2tri/sweep/mesh.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -33,18 +33,16 @@ using namespace std; class Triangle; -class Mesh +class Mesh { - public: - - /// Triangles that constitute the mesh - vector map; - - // Debug triangles - //val debug = new ArrayBuffer[Triangle] - //val triangles = new ArrayBuffer[Triangle] - - void clean(Triangle& triangle); - + +/// Triangles that constitute the mesh +vector map; + +// Debug triangles +//val debug = new ArrayBuffer[Triangle] +//val triangles = new ArrayBuffer[Triangle] + +void clean(Triangle& triangle); }; diff --git a/poly2tri/sweep/sweep.cc b/poly2tri/sweep/sweep.cc index dd7b751..fb720f2 100644 --- a/poly2tri/sweep/sweep.cc +++ b/poly2tri/sweep/sweep.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -33,155 +33,149 @@ #include "advancing_front.h" #include "../common/utils.h" - // Triangulate simple polygon with holes -void Sweep::Triangulate(SweepContext& tcx) { - +// Triangulate simple polygon with holes +void Sweep::Triangulate(SweepContext& tcx) +{ tcx.CreateAdvancingFront(); // Sweep points; build mesh SweepPoints(tcx); // Clean up //FinalizationPolygon(tcx); - -} - -void Sweep::SweepPoints(SweepContext& tcx) { - - for(int i = 1; i < tcx.point_count(); i++ ) { - - //printf("%i = ",i); - Point& point = *tcx.GetPoint(i); - //printf("size = %i\n", point.edge_list.size()); - Node& node = PointEvent(tcx, point); - - for(int i = 0; i < point.edge_list.size(); i++) { - EdgeEvent(tcx, point.edge_list[i], node); - } - - } - } -void Sweep::FinalizationPolygon(SweepContext& tcx) { +void Sweep::SweepPoints(SweepContext& tcx) +{ + for (int i = 1; i < tcx.point_count(); i++) { + printf("%i = ", i); + Point& point = *tcx.GetPoint(i); + printf("%f,%f\n", point.x, point.y); + Node& node = PointEvent(tcx, point); + for (int i = 0; i < point.edge_list.size(); i++) { + EdgeEvent(tcx, point.edge_list[i], node); + } + } +} + +void Sweep::FinalizationPolygon(SweepContext& tcx) +{ // Get an Internal triangle to start with Triangle* t = tcx.front()->head()->next->triangle; Point* p = tcx.front()->head()->next->point; - while(!t->GetConstrainedEdgeCW(*p)) { + while (!t->GetConstrainedEdgeCW(*p)) { t = t->NeighborCCW(*p); } - + // Collect interior triangles constrained by edges tcx.MeshClean(*t); } - + /** * Find closes node to the left of the new point and * create a new triangle. If needed new holes and basins * will be filled to. - * + * * @param tcx * @param point * @return */ -Node& Sweep::PointEvent(SweepContext& tcx, Point& point) { - +Node& Sweep::PointEvent(SweepContext& tcx, Point& point) +{ Node& node = tcx.LocateNode(point); Node& new_node = NewFrontTriangle(tcx, point, node); - - // Only need to check +epsilon since point never have smaller + + // Only need to check +epsilon since point never have smaller // x value than node due to how we fetch nodes from the front - if(point.x <= node.point->x + EPSILON) { + if (point.x <= node.point->x + EPSILON) { Fill(tcx, node); - } - + } + //tcx.AddNode(new_node); - + FillAdvancingFront(tcx, new_node); return new_node; } -void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - tcx.edge_event.constrained_edge = edge; - tcx.edge_event.right = edge->p->x > edge->q->x; - - if(IsEdgeSideOfTriangle(*node.triangle, *edge->p, *edge->q)){ - return; - } - - // For now we will do all needed filling - // TODO: integrate with flip process might give some better performance - // but for now this avoid the issue with cases that needs both flips and fills - FillEdgeEvent(tcx, edge, node); - EdgeEvent(tcx, *edge->p, *edge->q , node.triangle, *edge->q); - +void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + tcx.edge_event.constrained_edge = edge; + tcx.edge_event.right = edge->p->x > edge->q->x; + + if (IsEdgeSideOfTriangle(*node.triangle, *edge->p, *edge->q)) { + return; + } + + // For now we will do all needed filling + // TODO: integrate with flip process might give some better performance + // but for now this avoid the issue with cases that needs both flips and fills + FillEdgeEvent(tcx, edge, node); + EdgeEvent(tcx, *edge->p, *edge->q, node.triangle, *edge->q); } -void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) { - - if(IsEdgeSideOfTriangle(*triangle, ep, eq)) { - return; - } - - Point* p1 = triangle->PointCCW(point); - Orientation o1 = Orient2d(eq, *p1, ep); - if(o1 == COLLINEAR) { - //throw new RuntimeException( "EdgeEvent - Collinear not supported" ); - assert(false); - } +void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) +{ + if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { + return; + } - Point* p2 = triangle->PointCW(point); - Orientation o2 = Orient2d(eq, *p2, ep); - if(o2 == COLLINEAR) { - //throw new RuntimeException( "EdgeEvent - Collinear not supported" ); - assert(false); - } - - if(o1 == o2) { - // Need to decide if we are rotating CW or CCW to get to a triangle - // that will cross edge - if(o1 == CW) { - triangle = triangle->NeighborCCW(point); - } else { - triangle = triangle->NeighborCW(point); - } - EdgeEvent(tcx, ep, eq, triangle, point); - } else { - // This triangle crosses constraint so lets flippin start! - FlipEdgeEvent(tcx, ep, eq, *triangle, point); - } - + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { + //throw new RuntimeException( "EdgeEvent - Collinear not supported" ); + assert(false); + } + + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { + //throw new RuntimeException( "EdgeEvent - Collinear not supported" ); + assert(false); + } + + if (o1 == o2) { + // Need to decide if we are rotating CW or CCW to get to a triangle + // that will cross edge + if (o1 == CW) { + triangle = triangle->NeighborCCW(point); + } else{ + triangle = triangle->NeighborCW(point); + } + EdgeEvent(tcx, ep, eq, triangle, point); + } else { + // This triangle crosses constraint so lets flippin start! + FlipEdgeEvent(tcx, ep, eq, *triangle, point); + } } - -bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) { - int index = triangle.EdgeIndex(&ep, &eq); - - if(index != -1) { - triangle.MarkConstrainedEdge(index); - Triangle* t = triangle.GetNeighbor(index); - if(t){ - t->MarkConstrainedEdge(&ep, &eq); - } - return true; - } - return false; +bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) +{ + int index = triangle.EdgeIndex(&ep, &eq); + + if (index != -1) { + triangle.MarkConstrainedEdge(index); + Triangle* t = triangle.GetNeighbor(index); + if (t) { + t->MarkConstrainedEdge(&ep, &eq); + } + return true; + } + return false; } - -Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node ) { +Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node) +{ Triangle* triangle = new Triangle(point, *node.point, *node.next->point); - + triangle->MarkNeighbor(*node.triangle); - tcx.AddToMap(triangle); + tcx.AddToMap(triangle); Node* new_node = new Node(point); new_node->next = node.next; new_node->prev = &node; node.next->prev = new_node; - node.next = new_node; - - if(!Legalize(tcx, *triangle)) { + node.next = new_node; + + if (!Legalize(tcx, *triangle)) { tcx.MapTriangleToNodes(*triangle); } @@ -193,165 +187,160 @@ Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node ) { * @param tcx * @param node - middle node, that is the bottom of the hole */ -void Sweep::Fill(SweepContext& tcx, Node& node) { +void Sweep::Fill(SweepContext& tcx, Node& node) +{ + Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); - Triangle* triangle = new Triangle(*node.prev->point, *node.point, - *node.next->point); - // TODO: should copy the constrained_edge value from neighbor triangles - // for now constrained_edge values are copied during the legalize + // for now constrained_edge values are copied during the legalize triangle->MarkNeighbor(*node.prev->triangle); triangle->MarkNeighbor(*node.triangle); - + tcx.AddToMap(triangle); // Update the advancing front node.prev->next = node.next; node.next->prev = node.prev; - + // If it was legalized the triangle has already been mapped - if(!Legalize(tcx, *triangle)) { + if (!Legalize(tcx, *triangle)) { tcx.MapTriangleToNodes(*triangle); } - + // TODO: delete node from memory //tcx.RemoveNode(node); - } /** - * Fills holes in the Advancing Front - * - * + * Fills holes in the Advancing Front + * + * * @param tcx * @param n */ -void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) { - - // Fill right holes - Node* node = n.next; - - while(node->next) { - double angle = HoleAngle(*node); - if(angle > M_PI_2 || angle < -M_PI_2) break; - Fill(tcx, *node); - node = node->next; - } +void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) +{ + // Fill right holes + Node* node = n.next; + + while (node->next) { + double angle = HoleAngle(*node); + if (angle > M_PI_2 || angle < -M_PI_2) break; + Fill(tcx, *node); + node = node->next; + } + + // Fill left holes + node = n.prev; + + while (node->prev) { + double angle = HoleAngle(*node); + if (angle > M_PI_2 || angle < -M_PI_2) break; + Fill(tcx, *node); + node = node->prev; + } - // Fill left holes - node = n.prev; - - while(node->prev) { - double angle = HoleAngle(*node); - if(angle > M_PI_2 || angle < -M_PI_2) break; - Fill(tcx, *node); - node = node->prev; - } - // Fill right basins - if(n.next && n.next->next) { + if (n.next && n.next->next) { double angle = BasinAngle(n); - if(angle < PI_3div4) { + if (angle < PI_3div4) { FillBasin(tcx, n); } } - } -double Sweep::BasinAngle(Node& node) { +double Sweep::BasinAngle(Node& node) +{ double ax = node.point->x - node.next->next->point->x; double ay = node.point->y - node.next->next->point->y; return atan2(ay, ax); } - + /** - * + * * @param node - middle node * @return the angle between 3 front nodes */ -double Sweep::HoleAngle(Node& node) { - - /* Complex plane - * ab = cosA +i*sinA - * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) - * atan2(y,x) computes the principal value of the argument function - * applied to the complex number x+iy - * Where x = ax*bx + ay*by - * y = ax*by - ay*bx - */ - double ax = node.next->point->x - node.point->x; - double ay = node.next->point->y - node.point->y; - double bx = node.prev->point->x - node.point->x; - double by = node.prev->point->y - node.point->y; - return atan2(ax * by - ay * bx, ax * bx + ay * by); +double Sweep::HoleAngle(Node& node) +{ + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + double ax = node.next->point->x - node.point->x; + double ay = node.next->point->y - node.point->y; + double bx = node.prev->point->x - node.point->x; + double by = node.prev->point->y - node.point->y; + return atan2(ax * by - ay * bx, ax * bx + ay * by); } /** * Returns true if triangle was legalized */ -bool Sweep::Legalize(SweepContext& tcx, Triangle& t) { - - // To legalize a triangle we start by finding if any of the three edges - // violate the Delaunay condition - for(int i=0; i<3; i++) { - - if(t.delaunay_edge[i]) - continue; - - Triangle* ot = t.GetNeighbor(i); - - if(ot) { +bool Sweep::Legalize(SweepContext& tcx, Triangle& t) +{ + // To legalize a triangle we start by finding if any of the three edges + // violate the Delaunay condition + for (int i = 0; i < 3; i++) { + if (t.delaunay_edge[i]) + continue; - Point* p = t.GetPoint(i); - Point* op = ot->OppositePoint(t, *p); - int oi = ot->Index(op); - - // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) - // then we should not try to legalize - if(ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { - t.constrained_edge[i] = ot->constrained_edge[oi]; - continue; - } - - bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); - - if(inside) { - - // Lets mark this shared edge as Delaunay - t.delaunay_edge[i] = true; - ot->delaunay_edge[oi] = true; + Triangle* ot = t.GetNeighbor(i); - // Lets rotate shared edge one vertex CW to legalize it - RotateTrianglePair(t, *p, *ot, *op); + if (ot) { + Point* p = t.GetPoint(i); + Point* op = ot->OppositePoint(t, *p); + int oi = ot->Index(op); - // We now got one valid Delaunay Edge shared by two triangles - // This gives us 4 new edges to check for Delaunay + // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) + // then we should not try to legalize + if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { + t.constrained_edge[i] = ot->constrained_edge[oi]; + continue; + } - // Make sure that triangle to node mapping is done only one time for a specific triangle - bool not_legalized = !Legalize(tcx, t); - if(not_legalized) { - tcx.MapTriangleToNodes(t); - } - - not_legalized = !Legalize(tcx, *ot); - if(not_legalized) - tcx.MapTriangleToNodes(*ot); - - // Reset the Delaunay edges, since they only are valid Delaunay edges - // until we add a new triangle or point. - // XXX: need to think about this. Can these edges be tried after we - // return to previous recursive level? - t.delaunay_edge[i] = false; - ot->delaunay_edge[oi] = false; + bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); - // If triangle have been legalized no need to check the other edges since - // the recursive legalization will handles those so we can end here. - return true; - } - } - } - return false; -} + if (inside) { + // Lets mark this shared edge as Delaunay + t.delaunay_edge[i] = true; + ot->delaunay_edge[oi] = true; + + // Lets rotate shared edge one vertex CW to legalize it + RotateTrianglePair(t, *p, *ot, *op); + + // We now got one valid Delaunay Edge shared by two triangles + // This gives us 4 new edges to check for Delaunay + + // Make sure that triangle to node mapping is done only one time for a specific triangle + bool not_legalized = !Legalize(tcx, t); + if (not_legalized) { + tcx.MapTriangleToNodes(t); + } + + not_legalized = !Legalize(tcx, *ot); + if (not_legalized) + tcx.MapTriangleToNodes(*ot); + + // Reset the Delaunay edges, since they only are valid Delaunay edges + // until we add a new triangle or point. + // XXX: need to think about this. Can these edges be tried after we + // return to previous recursive level? + t.delaunay_edge[i] = false; + ot->delaunay_edge[oi] = false; + + // If triangle have been legalized no need to check the other edges since + // the recursive legalization will handles those so we can end here. + return true; + } + } + } + return false; +} /** * Requirement:
@@ -363,9 +352,9 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t) { * / \ * / \ * b/ \c - * +-------+ - * / d \ - * / \ + * +-------+ + * / d \ + * / \ * * Fact: d has to be in area B to have a chance to be inside the circle formed by * a,b and c
@@ -374,43 +363,43 @@ bool Sweep::Legalize(SweepContext& tcx, Triangle& t) { * @param a - triangle point, opposite d * @param b - triangle point * @param c - triangle point - * @param d - point opposite a + * @param d - point opposite a * @return true if d is inside circle, false if on circle edge */ -bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) { +bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) +{ + double adx = pa.x - pd.x; + double ady = pa.y - pd.y; + double bdx = pb.x - pd.x; + double bdy = pb.y - pd.y; - double adx = pa.x - pd.x; - double ady = pa.y - pd.y; - double bdx = pb.x - pd.x; - double bdy = pb.y - pd.y; + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; - double adxbdy = adx * bdy; - double bdxady = bdx * ady; - double oabd = adxbdy - bdxady; + if (oabd <= 0) + return false; - if( oabd <= 0 ) - return false; + double cdx = pc.x - pd.x; + double cdy = pc.y - pd.y; - double cdx = pc.x - pd.x; - double cdy = pc.y - pd.y; + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; - double cdxady = cdx * ady; - double adxcdy = adx * cdy; - double ocad = cdxady - adxcdy; + if (ocad <= 0) + return false; - if( ocad <= 0 ) - return false; - - double bdxcdy = bdx * cdy; - double cdxbdy = cdx * bdy; - - double alift = adx * adx + ady * ady; - double blift = bdx * bdx + bdy * bdy; - double clift = cdx * cdx + cdy * cdy; + double bdxcdy = bdx * cdy; + double cdxbdy = cdx * bdy; - double det = alift * ( bdxcdy - cdxbdy ) + blift * ocad + clift * oabd; + double alift = adx * adx + ady * ady; + double blift = bdx * bdx + bdy * bdy; + double clift = cdx * cdx + cdy * cdy; - return det > 0; + double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; + + return det > 0; } /** @@ -418,7 +407,7 @@ bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) { *
  *       n2                    n2
  *  P +-----+             P +-----+
- *    | t  /|               |\  t |  
+ *    | t  /|               |\  t |
  *    |   / |               | \   |
  *  n1|  /  |n3           n1|  \  |n3
  *    | /   |    after CW   |   \ |
@@ -427,343 +416,333 @@ bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) {
  *       n4                    n4
  * 
*/ -void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) { +void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) +{ + Triangle* n1, *n2, *n3, *n4; + n1 = t.NeighborCCW(p); + n2 = t.NeighborCW(p); + n3 = ot.NeighborCCW(op); + n4 = ot.NeighborCW(op); - Triangle* n1, *n2, *n3, *n4; - n1 = t.NeighborCCW(p); - n2 = t.NeighborCW(p); - n3 = ot.NeighborCCW(op); - n4 = ot.NeighborCW(op); + bool ce1, ce2, ce3, ce4; + ce1 = t.GetConstrainedEdgeCCW(p); + ce2 = t.GetConstrainedEdgeCW(p); + ce3 = ot.GetConstrainedEdgeCCW(op); + ce4 = ot.GetConstrainedEdgeCW(op); - bool ce1,ce2,ce3,ce4; - ce1 = t.GetConstrainedEdgeCCW(p); - ce2 = t.GetConstrainedEdgeCW(p); - ce3 = ot.GetConstrainedEdgeCCW(op); - ce4 = ot.GetConstrainedEdgeCW(op); - - bool de1,de2,de3,de4; - de1 = t.GetDelunayEdgeCCW(p); - de2 = t.GetDelunayEdgeCW(p); - de3 = ot.GetDelunayEdgeCCW(op); - de4 = ot.GetDelunayEdgeCW(op); - - t.Legalize(p, op); - ot.Legalize(op, p); - - // Remap delaunay_edge - ot.SetDelunayEdgeCCW(p, de1); - t.SetDelunayEdgeCW(p, de2); - t.SetDelunayEdgeCCW(op, de3); - ot.SetDelunayEdgeCW(op, de4); + bool de1, de2, de3, de4; + de1 = t.GetDelunayEdgeCCW(p); + de2 = t.GetDelunayEdgeCW(p); + de3 = ot.GetDelunayEdgeCCW(op); + de4 = ot.GetDelunayEdgeCW(op); - // Remap constrained_edge - ot.SetConstrainedEdgeCCW(p, ce1); - t.SetConstrainedEdgeCW(p, ce2); - t.SetConstrainedEdgeCCW(op, ce3); - ot.SetConstrainedEdgeCW(op, ce4); - - // Remap neighbors - // XXX: might optimize the markNeighbor by keeping track of - // what side should be assigned to what neighbor after the - // rotation. Now mark neighbor does lots of testing to find - // the right side. - t.ClearNeighbors(); - ot.ClearNeighbors(); - if(n1 != NULL) ot.MarkNeighbor(*n1); - if(n2 != NULL) t.MarkNeighbor(*n2); - if(n3 != NULL) t.MarkNeighbor(*n3); - if(n4 != NULL) ot.MarkNeighbor(*n4); - t.MarkNeighbor(ot); -} + t.Legalize(p, op); + ot.Legalize(op, p); + + // Remap delaunay_edge + ot.SetDelunayEdgeCCW(p, de1); + t.SetDelunayEdgeCW(p, de2); + t.SetDelunayEdgeCCW(op, de3); + ot.SetDelunayEdgeCW(op, de4); + + // Remap constrained_edge + ot.SetConstrainedEdgeCCW(p, ce1); + t.SetConstrainedEdgeCW(p, ce2); + t.SetConstrainedEdgeCCW(op, ce3); + ot.SetConstrainedEdgeCW(op, ce4); + + // Remap neighbors + // XXX: might optimize the markNeighbor by keeping track of + // what side should be assigned to what neighbor after the + // rotation. Now mark neighbor does lots of testing to find + // the right side. + t.ClearNeighbors(); + ot.ClearNeighbors(); + if (n1 != NULL) ot.MarkNeighbor(*n1); + if (n2 != NULL) t.MarkNeighbor(*n2); + if (n3 != NULL) t.MarkNeighbor(*n3); + if (n4 != NULL) ot.MarkNeighbor(*n4); + t.MarkNeighbor(ot); +} /** -* Fills a basin that has formed on the Advancing Front to the right -* of given node.
-* First we decide a left,bottom and right node that forms the -* boundaries of the basin. Then we do a reqursive fill. -* -* @param tcx -* @param node - starting node, this or next node will be left node -*/ -void Sweep::FillBasin(SweepContext& tcx, Node& node) { - - if(Orient2d(*node.point, *node.next->point, *node.next->next->point ) == CCW) { + * Fills a basin that has formed on the Advancing Front to the right + * of given node.
+ * First we decide a left,bottom and right node that forms the + * boundaries of the basin. Then we do a reqursive fill. + * + * @param tcx + * @param node - starting node, this or next node will be left node + */ +void Sweep::FillBasin(SweepContext& tcx, Node& node) +{ + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { tcx.basin.left_node = node.next->next; } else { tcx.basin.left_node = node.next; } - + // Find the bottom and right node tcx.basin.bottom_node = tcx.basin.left_node; - while(tcx.basin.bottom_node->next - && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { + while (tcx.basin.bottom_node->next + && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { tcx.basin.bottom_node = tcx.basin.bottom_node->next; } - if(tcx.basin.bottom_node == tcx.basin.left_node) { + if (tcx.basin.bottom_node == tcx.basin.left_node) { // No valid basin return; } - + tcx.basin.right_node = tcx.basin.bottom_node; - while(tcx.basin.right_node->next - && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { + while (tcx.basin.right_node->next + && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { tcx.basin.right_node = tcx.basin.right_node->next; - } - if(tcx.basin.right_node == tcx.basin.bottom_node) { + } + if (tcx.basin.right_node == tcx.basin.bottom_node) { // No valid basins return; } - + tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; - - FillBasinReq(tcx, *tcx.basin.bottom_node); - -} - -/** -* Recursive algorithm to fill a Basin with triangles -* -* @param tcx -* @param node - bottom_node -* @param cnt - counter used to alternate on even and odd numbers -*/ -void Sweep::FillBasinReq(SweepContext& tcx, Node& node) { + FillBasinReq(tcx, *tcx.basin.bottom_node); +} + +/** + * Recursive algorithm to fill a Basin with triangles + * + * @param tcx + * @param node - bottom_node + * @param cnt - counter used to alternate on even and odd numbers + */ +void Sweep::FillBasinReq(SweepContext& tcx, Node& node) +{ // if shallow stop filling - if(IsShallow(tcx, node)) { + if (IsShallow(tcx, node)) { return; } - + Fill(tcx, node); - - if(node.prev == tcx.basin.left_node && node.next == tcx.basin.right_node) { + + if (node.prev == tcx.basin.left_node && node.next == tcx.basin.right_node) { return; - } else if(node.prev == tcx.basin.left_node) { - Orientation o = Orient2d(*node.point, *node.next->point, *node.next->next->point ); - if(o == CW) { + } else if (node.prev == tcx.basin.left_node) { + Orientation o = Orient2d(*node.point, *node.next->point, *node.next->next->point); + if (o == CW) { return; } node = *node.next; - } else if(node.next == tcx.basin.right_node) { + } else if (node.next == tcx.basin.right_node) { Orientation o = Orient2d(*node.point, *node.prev->point, *node.prev->prev->point); - if(o == CCW) { + if (o == CCW) { return; } node = *node.prev; } else { // Continue with the neighbor node with lowest Y value - if(node.prev->point->y < node.next->point->y) { + if (node.prev->point->y < node.next->point->y) { node = *node.prev; } else { node = *node.next; } - } - + } + FillBasinReq(tcx, node); - } -bool Sweep::IsShallow(SweepContext& tcx, Node& node) { - +bool Sweep::IsShallow(SweepContext& tcx, Node& node) +{ double height; - if(tcx.basin.left_highest) { + if (tcx.basin.left_highest) { height = tcx.basin.left_node->point->y - node.point->y; } else { - height = tcx.basin.right_node->point->y - node.point->y; + height = tcx.basin.right_node->point->y - node.point->y; } - + // if shallow stop filling - if(tcx.basin.width > height) { + if (tcx.basin.width > height) { return true; - } + } return false; } -void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - if(tcx.edge_event.right) { - FillRightAboveEdgeEvent(tcx, edge, node); - } else { - FillLeftAboveEdgeEvent(tcx, edge, node); - } - +void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (tcx.edge_event.right) { + FillRightAboveEdgeEvent(tcx, edge, node); + } else { + FillLeftAboveEdgeEvent(tcx, edge, node); + } } -void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - while(node.next->point->x < edge->p->x) { - // Check if next node is below the edge - if(Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { - FillRightBelowEdgeEvent(tcx, edge, node); - } else { - node = *node.next; - } - } - +void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + while (node.next->point->x < edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { + FillRightBelowEdgeEvent(tcx, edge, node); + } else { + node = *node.next; + } + } } -void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - if(node.point->x < edge->p->x) { - if(Orient2d(*node.point, *node.next->point, *node.next->next->point ) == CCW ) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, node ); - } else { - // Convex - FillRightConvexEdgeEvent(tcx, edge, node ); - // Retry this one - FillRightBelowEdgeEvent(tcx, edge, node ); - } - } - +void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (node.point->x < edge->p->x) { + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else{ + // Convex + FillRightConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillRightBelowEdgeEvent(tcx, edge, node); + } + } } -void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - Fill(tcx, *node.next); - if(node.next->point != edge->p) { - // Next above or below edge? - if(Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { - // Below - if(Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Next is concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else { - // Next is convex - } - } - } - +void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + Fill(tcx, *node.next); + if (node.next->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { + // Below + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Next is concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } + } } -void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - // Next concave or convex? - if(Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point ) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, *node.next); - } else{ - // Convex - // Next above or below edge? - if(Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { - // Below - FillRightConvexEdgeEvent(tcx, edge, *node.next); - } else{ - // Above - } - } - +void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + // Next concave or convex? + if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, *node.next); + } else{ + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { + // Below + FillRightConvexEdgeEvent(tcx, edge, *node.next); + } else{ + // Above + } + } } -void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - while(node.prev->point->x > edge->p->x) { - // Check if next node is below the edge - if(Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { - FillLeftBelowEdgeEvent(tcx, edge, node); - } else { - node = *node.prev; - } - } - +void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + while (node.prev->point->x > edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { + FillLeftBelowEdgeEvent(tcx, edge, node); + } else { + node = *node.prev; + } + } } -void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - if( node.point->x > edge->p->x) { - if(Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW ) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else { - // Convex - FillLeftConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillLeftBelowEdgeEvent(tcx, edge, node); - } - - } +void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + if (node.point->x > edge->p->x) { + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillLeftConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillLeftBelowEdgeEvent(tcx, edge, node); + } + } } -void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - // Next concave or convex? - if(Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); - } else { - // Convex - // Next above or below edge? - if(Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { - // Below - FillLeftConvexEdgeEvent(tcx, edge, *node.prev); - } else { - // Above - } - } +void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + // Next concave or convex? + if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); + } else{ + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { + // Below + FillLeftConvexEdgeEvent(tcx, edge, *node.prev); + } else{ + // Above + } + } } -void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - - Fill(tcx, *node.prev); - if(node.prev->point != edge->p) { - // Next above or below edge? - if(Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { - // Below - if(Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Next is concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else { - // Next is convex - } - } - } - +void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) +{ + Fill(tcx, *node.prev); + if (node.prev->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { + // Below + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Next is concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else{ + // Next is convex + } + } + } } -void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, Point& p) { - - Triangle& ot = t.NeighborAcross(p); - Point& op = *ot.OppositePoint(t, p); +void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, Point& p) +{ + Triangle& ot = t.NeighborAcross(p); + Point& op = *ot.OppositePoint(t, p); - if(&t.NeighborAcross(p) == NULL) { - // If we want to integrate the fillEdgeEvent do it here - // With current implementation we should never get here - //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); - assert(0); - } - - if(InScanArea(p, *t.PointCCW(p), *t.PointCW(p), op)) { + if (&t.NeighborAcross(p) == NULL) { + // If we want to integrate the fillEdgeEvent do it here + // With current implementation we should never get here + //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); + assert(0); + } + + if (InScanArea(p, *t.PointCCW(p), *t.PointCW(p), op)) { // Lets rotate shared edge one vertex CW RotateTrianglePair(t, p, ot, op); tcx.MapTriangleToNodes(t); tcx.MapTriangleToNodes(ot); - - if( p == eq && op == ep ) { - if(eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { + + if (p == eq && op == ep) { + if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { t.MarkConstrainedEdge(&ep, &eq); ot.MarkConstrainedEdge(&ep, &eq); - Legalize(tcx, t); - Legalize(tcx, ot); - } else { - // XXX: I think one of the triangles should be legalized here? + Legalize(tcx, t); + Legalize(tcx, ot); + } else { + // XXX: I think one of the triangles should be legalized here? } } else { Orientation o = Orient2d(eq, op, ep); - t = NextFlipTriangle(tcx, (int) o, t, ot, p, op); + t = NextFlipTriangle(tcx, (int)o, t, ot, p, op); FlipEdgeEvent(tcx, ep, eq, t, p); } - } else { - Point& newP = NextFlipPoint( ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP); - EdgeEvent(tcx, ep, eq, &t, p); - } + } else { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP); + EdgeEvent(tcx, ep, eq, &t, p); + } } -Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) { - - if(o == CCW) { +Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) +{ + if (o == CCW) { // ot is not crossing edge after flip int edge_index = ot.EdgeIndex(&p, &op); ot.delaunay_edge[edge_index] = true; @@ -771,59 +750,57 @@ Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triang ot.ClearDelunayEdges(); return t; } - + // t is not crossing edge after flip int edge_index = t.EdgeIndex(&p, &op); t.delaunay_edge[edge_index] = true; Legalize(tcx, t); - t.ClearDelunayEdges(); + t.ClearDelunayEdges(); return ot; } -Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) { - +Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) +{ Orientation o2d = Orient2d(eq, op, ep); - if(o2d == CW) { + if (o2d == CW) { // Right return *ot.PointCCW(op); - } else if(o2d == CCW) { - // Left + } else if (o2d == CCW) { + // Left return *ot.PointCW(op); - } else { + } else{ //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); assert(0); - } - + } } -void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, - Triangle& t, Point& p ) { - - Triangle& ot = t.NeighborAcross(p); - Point& op = *ot.OppositePoint(t, p); - - if(&t.NeighborAcross(p) == NULL) { - // If we want to integrate the fillEdgeEvent do it here - // With current implementation we should never get here - //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); - assert(0); - } - - if(InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW( eq ), op)) { - // flip with new edge op->eq - FlipEdgeEvent(tcx, eq, op, ot, op); - // TODO: Actually I just figured out that it should be possible to - // improve this by getting the next ot and op before the the above - // flip and continue the flipScanEdgeEvent here - // set new ot and op here and loop back to inScanArea test - // also need to set a new flip_triangle first - // Turns out at first glance that this is somewhat complicated - // so it will have to wait. - } else { - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); - } - +void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, + Triangle& t, Point& p) +{ + Triangle& ot = t.NeighborAcross(p); + Point& op = *ot.OppositePoint(t, p); + + if (&t.NeighborAcross(p) == NULL) { + // If we want to integrate the fillEdgeEvent do it here + // With current implementation we should never get here + //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); + assert(0); + } + + if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { + // flip with new edge op->eq + FlipEdgeEvent(tcx, eq, op, ot, op); + // TODO: Actually I just figured out that it should be possible to + // improve this by getting the next ot and op before the the above + // flip and continue the flipScanEdgeEvent here + // set new ot and op here and loop back to inScanArea test + // also need to set a new flip_triangle first + // Turns out at first glance that this is somewhat complicated + // so it will have to wait. + } else{ + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); + } } - + diff --git a/poly2tri/sweep/sweep.h b/poly2tri/sweep/sweep.h index 00d8a69..0b0dc90 100644 --- a/poly2tri/sweep/sweep.h +++ b/poly2tri/sweep/sweep.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -33,8 +33,8 @@ * Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation', * International Journal of Geographical Information Science - * - * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com + * + * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com */ class SweepContext; @@ -44,71 +44,69 @@ struct Edge; class Triangle; class Sweep { - public: - void Triangulate(SweepContext& tcx); +void Triangulate(SweepContext& tcx); private: - - void SweepPoints(SweepContext& tcx); - - Node& PointEvent(SweepContext& tcx, Point& point); - - void EdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); - Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); - - void Fill(SweepContext& tcx, Node& node); - - bool Legalize(SweepContext& tcx, Triangle& t); - - bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd); +void SweepPoints(SweepContext& tcx); - void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op); - - void FillAdvancingFront(SweepContext& tcx, Node& n); - - double HoleAngle(Node& node); - - double BasinAngle(Node& node); - - void FillBasin(SweepContext& tcx, Node& node); - - void FillBasinReq(SweepContext& tcx, Node& node); - - bool IsShallow(SweepContext& tcx, Node& node); - - bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); - - void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); +Node& PointEvent(SweepContext& tcx, Point& point); - void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); +void EdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); +void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); - void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); +Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); - void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); +void Fill(SweepContext& tcx, Node& node); - void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); +bool Legalize(SweepContext& tcx, Triangle& t); - void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, Point& p); - - Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); - - Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op ); - - void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); +bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd); - void FinalizationPolygon(SweepContext& tcx); +void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op); +void FillAdvancingFront(SweepContext& tcx, Node& n); + +double HoleAngle(Node& node); + +double BasinAngle(Node& node); + +void FillBasin(SweepContext& tcx, Node& node); + +void FillBasinReq(SweepContext& tcx, Node& node); + +bool IsShallow(SweepContext& tcx, Node& node); + +bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); + +void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + +void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, Point& p); + +Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); + +Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); + +void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); + +void FinalizationPolygon(SweepContext& tcx); }; diff --git a/poly2tri/sweep/sweep_context.cc b/poly2tri/sweep/sweep_context.cc index 9283493..3f0ed86 100644 --- a/poly2tri/sweep/sweep_context.cc +++ b/poly2tri/sweep/sweep_context.cc @@ -4,157 +4,162 @@ #include #include "advancing_front.h" -SweepContext::SweepContext(Point** polyline, const int& point_count) { - +SweepContext::SweepContext(Point** polyline, const int& point_count) +{ basin = Basin(); edge_event = EdgeEvent(); - + points_ = polyline; point_count_ = point_count; - + InitEdges(points_, point_count_); InitTriangulation(); - } -std::vector SweepContext::GetTriangles() { +std::vector SweepContext::GetTriangles() +{ return triangles_; } -std::list SweepContext::GetMap() { +std::list SweepContext::GetMap() +{ return map_; } -void SweepContext::InitTriangulation() { - +void SweepContext::InitTriangulation() +{ double xmax(points_[0]->x), xmin(points_[0]->x); double ymax(points_[0]->y), ymin(points_[0]->y); - - // Calculate bounds. - for(int i = 0; i < point_count_; i++) { + + // Calculate bounds. + for (int i = 0; i < point_count_; i++) { Point p = *points_[i]; - if(p.x > xmax) - xmax = p.x; - if(p.x < xmin) - xmin = p.x; - if(p.y > ymax) - ymax = p.y; - if(p.y < ymin) - ymin = p.y; + if (p.x > xmax) + xmax = p.x; + if (p.x < xmin) + xmin = p.x; + if (p.y > ymax) + ymax = p.y; + if (p.y < ymin) + ymin = p.y; } - double dx = kAlpha * ( xmax - xmin ); - double dy = kAlpha * ( ymax - ymin ); + double dx = kAlpha * (xmax - xmin); + double dy = kAlpha * (ymax - ymin); head_ = new Point(xmax + dx, ymin - dy); tail_ = new Point(xmin - dx, ymin - dy); - + // Sort points along y-axis double init_time = glfwGetTime(); std::sort(points_, points_ + point_count_, cmp); double dt = glfwGetTime() - init_time; printf("Sort time (secs) = %f\n", dt); - - /* + printf("*************************\n"); - for(int i = 0; i < point_count_; i++) { + for (int i = 0; i < point_count_; i++) { printf("%f,%f ", points_[i]->x, points_[i]->y); printf("%p\n", points_[i]); } - - printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - for(int i = 0; i < edge_list.size(); i++) { - edge_list[i]->p->DebugPrint(); edge_list[i]->q->DebugPrint(); - printf("%p, %p\n", edge_list[i]->p, edge_list[i]->q); - } - */ - + + /* + printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + for(int i = 0; i < edge_list.size(); i++) { + edge_list[i]->p->DebugPrint(); edge_list[i]->q->DebugPrint(); + printf("%p, %p\n", edge_list[i]->p, edge_list[i]->q); + } + */ } -void SweepContext::InitEdges(Point** polyline, const int& point_count) { - - for(int i = 0; i < point_count; i++) { +void SweepContext::InitEdges(Point** polyline, const int& point_count) +{ + for (int i = 0; i < point_count; i++) { int j = i < point_count - 1 ? i + 1 : 0; edge_list.push_back(new Edge(*polyline[i], *polyline[j])); } - + /* - for(int i = 0; i < edge_list.size(); i++) { - edge_list[i]->p->DebugPrint(); edge_list[i]->q->DebugPrint(); - printf("%p, %p\n", edge_list[i]->p, edge_list[i]->q); - } - */ - -} - -Point* SweepContext::GetPoint(const int& index) { - return points_[index]; + for(int i = 0; i < edge_list.size(); i++) { + edge_list[i]->p->DebugPrint(); edge_list[i]->q->DebugPrint(); + printf("%p, %p\n", edge_list[i]->p, edge_list[i]->q); + } + */ } -void SweepContext::AddToMap(Triangle* triangle ) { +Point* SweepContext::GetPoint(const int& index) +{ + return points_[index]; +} + +void SweepContext::AddToMap(Triangle* triangle) +{ map_.push_back(triangle); } -Node& SweepContext::LocateNode(Point& point) { - // TODO implement search tree - return *front_->Locate(point.x); +Node& SweepContext::LocateNode(Point& point) +{ + // TODO implement search tree + return *front_->Locate(point.x); } -void SweepContext::CreateAdvancingFront() { - - // Initial triangle - Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); +void SweepContext::CreateAdvancingFront() +{ + // Initial triangle + Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); - map_.push_back(triangle); - - front_ = new AdvancingFront; - - front_->set_head(new Node(*triangle->GetPoint(1))); - front_->head()->triangle = triangle; - Node* middle = new Node(*triangle->GetPoint(0)); - middle->triangle = triangle; - front_->set_tail(new Node(*triangle->GetPoint(2))); - front_->set_search(middle); - - // TODO: More intuitive if head is middles next and not previous? - // so swap head and tail - front_->head()->next = middle; - middle->next = front_->tail(); - middle->prev = front_->head(); - front_->tail()->prev = middle; - + map_.push_back(triangle); + + front_ = new AdvancingFront; + + front_->set_head(new Node(*triangle->GetPoint(1))); + front_->head()->triangle = triangle; + Node* middle = new Node(*triangle->GetPoint(0)); + middle->triangle = triangle; + front_->set_tail(new Node(*triangle->GetPoint(2))); + front_->set_search(middle); + + // TODO: More intuitive if head is middles next and not previous? + // so swap head and tail + front_->head()->next = middle; + middle->next = front_->tail(); + middle->prev = front_->head(); + front_->tail()->prev = middle; } - -void SweepContext::RemoveNode(Node* node) { - delete node; + +void SweepContext::RemoveNode(Node* node) +{ + delete node; } - -void SweepContext::MapTriangleToNodes(Triangle& t) { - for(int i=0; i<3; i++) { - if(t.GetNeighbor(i) == NULL) { + +void SweepContext::MapTriangleToNodes(Triangle& t) +{ + for (int i = 0; i < 3; i++) { + if (t.GetNeighbor(i) == NULL) { Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); - if(n) + if (n) n->triangle = &t; - } - } -} - -void SweepContext::RemoveFromMap(Triangle* triangle) { - map_.remove(triangle); -} - -void SweepContext::MeshClean(Triangle& triangle ) { - - if(&triangle != NULL && !triangle.IsInterior()) { - triangle.IsInterior(true); - triangles_.push_back(&triangle); - for(int i = 0; i < 3; i++) { - if(!triangle.constrained_edge[i]) - MeshClean(*triangle.GetNeighbor(i)); } } } -SweepContext::~SweepContext() { +void SweepContext::RemoveFromMap(Triangle* triangle) +{ + map_.remove(triangle); +} + +void SweepContext::MeshClean(Triangle& triangle) +{ + if (&triangle != NULL && !triangle.IsInterior()) { + triangle.IsInterior(true); + triangles_.push_back(&triangle); + for (int i = 0; i < 3; i++) { + if (!triangle.constrained_edge[i]) + MeshClean(*triangle.GetNeighbor(i)); + } + } +} + +SweepContext::~SweepContext() +{ delete head_; delete tail_; delete front_; diff --git a/poly2tri/sweep/sweep_context.h b/poly2tri/sweep/sweep_context.h index f0a63fb..19b0a3b 100644 --- a/poly2tri/sweep/sweep_context.h +++ b/poly2tri/sweep/sweep_context.h @@ -31,7 +31,7 @@ #include #include -// Inital triangle factor, seed triangle will extend 30% of +// Inital triangle factor, seed triangle will extend 30% of // PointSet width to both left and right. const double kAlpha = 0.3; @@ -41,124 +41,141 @@ struct Node; struct Edge; class AdvancingFront; - -class SweepContext { +class SweepContext { public: - // Constructor - SweepContext(Point** polyline, const int& point_count); - // Destructor - ~SweepContext(); - - //void MeshClean(Triangle& triangle); - // Get Advancing Front - //AdvancingFront front(); - - void set_head(Point* p1); - Point* head(); +// Constructor +SweepContext(Point** polyline, const int& point_count); +// Destructor +~SweepContext(); - void set_tail(Point* p1 ); - Point* tail(); - - int point_count(); - - Node& LocateNode(Point& point); - void RemoveNode(Node* node); - - void CreateAdvancingFront(); - - // Try to map a node to all sides of this triangle that don't have a neighbor - void MapTriangleToNodes(Triangle& t); - - void AddToMap(Triangle* triangle); - - Point* GetPoint(const int& index); - Point* GetPoints(); - - void RemoveFromMap(Triangle* triangle); - - AdvancingFront* front(); - - void MeshClean(Triangle& triangle); - - std::vector GetTriangles(); - std::list GetMap(); - - std::vector edge_list; - - struct Basin { - - Node* left_node; - Node* bottom_node; - Node* right_node; - double width; - bool left_highest; - - Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), - width(0.0), left_highest(false) {} - - void Clear() { - left_node = NULL; - bottom_node = NULL; - right_node = NULL; - width = 0.0; - left_highest = false; - } - - }; - - struct EdgeEvent { - - Edge* constrained_edge; - bool right; - - EdgeEvent() : constrained_edge(NULL), right(false) {} - - }; - - Basin basin; - EdgeEvent edge_event; - -private: +//void MeshClean(Triangle& triangle); +// Get Advancing Front +//AdvancingFront front(); - std::vector triangles_; - std::list map_; - - Point** points_; - int point_count_; - - // Advancing front - AdvancingFront* front_; - // head point used with advancing front - Point* head_; - // tail point used with advancing front - Point* tail_; - - //EdgeEvent edgeEvent = new EdgeEvent(); - - void InitTriangulation(); - void InitEdges(Point** polyline, const int& point_count); - - //void MeshCleanReq(Triangle& triangle ) - - /* - class EdgeEvent { - Edge* constrainedEdge; - bool right; - }; - */ - +void set_head(Point* p1); +Point* head(); + +void set_tail(Point* p1); +Point* tail(); + +int point_count(); + +Node& LocateNode(Point& point); +void RemoveNode(Node* node); + +void CreateAdvancingFront(); + +// Try to map a node to all sides of this triangle that don't have a neighbor +void MapTriangleToNodes(Triangle& t); + +void AddToMap(Triangle* triangle); + +Point* GetPoint(const int& index); +Point* GetPoints(); + +void RemoveFromMap(Triangle* triangle); + +AdvancingFront* front(); + +void MeshClean(Triangle& triangle); + +std::vector GetTriangles(); +std::list GetMap(); + +std::vector edge_list; + +struct Basin { + Node* left_node; + Node* bottom_node; + Node* right_node; + double width; + bool left_highest; + + Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), + width(0.0), left_highest(false) + { + } + + void Clear() + { + left_node = NULL; + bottom_node = NULL; + right_node = NULL; + width = 0.0; + left_highest = false; + } }; -inline AdvancingFront* SweepContext::front() { return front_; } +struct EdgeEvent { + Edge* constrained_edge; + bool right; -inline int SweepContext::point_count() { return point_count_; } + EdgeEvent() : constrained_edge(NULL), right(false) + { + } +}; -inline void SweepContext::set_head(Point* p1) { head_ = p1; } +Basin basin; +EdgeEvent edge_event; -inline Point* SweepContext::head() { return head_; } +private: -inline void SweepContext::set_tail(Point* p1) { tail_ = p1; } +std::vector triangles_; +std::list map_; -inline Point* SweepContext::tail() { return tail_; } +Point** points_; +int point_count_; + +// Advancing front +AdvancingFront* front_; +// head point used with advancing front +Point* head_; +// tail point used with advancing front +Point* tail_; + +//EdgeEvent edgeEvent = new EdgeEvent(); + +void InitTriangulation(); +void InitEdges(Point** polyline, const int& point_count); + +//void MeshCleanReq(Triangle& triangle ) + +/* + class EdgeEvent { + Edge* constrainedEdge; + bool right; + }; + */ +}; + +inline AdvancingFront* SweepContext::front() +{ + return front_; +} + +inline int SweepContext::point_count() +{ + return point_count_; +} + +inline void SweepContext::set_head(Point* p1) +{ + head_ = p1; +} + +inline Point* SweepContext::head() +{ + return head_; +} + +inline void SweepContext::set_tail(Point* p1) +{ + tail_ = p1; +} + +inline Point* SweepContext::tail() +{ + return tail_; +} diff --git a/testbed/main.cc b/testbed/main.cc index 6f69447..0584f7b 100644 --- a/testbed/main.cc +++ b/testbed/main.cc @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Mason Green * http://code.google.com/p/poly2tri/ * @@ -58,50 +58,51 @@ vector triangles; /// Triangle map list map; -double StringToDouble(const std::string& s) { +double StringToDouble(const std::string& s) +{ std::istringstream i(s); double x; if (!(i >> x)) - return 0; + return 0; return x; } bool draw_map = true; -int main(int argc, char* argv[]) { - +int main(int argc, char* argv[]) +{ if (argc != 3) { cout << "Usage: p2t filename zoom" << endl; return 1; } - - /* - // initialize random seed: - srand ( time(NULL) ); - - int a = 0; - int b = 2000; - - for(int i = 0; i < num_points; i++) { - double x = rand() % (b - a - 1) + a + 1; - double y = rand() % (b - a - 1) + a + 1; - polyline[i] = Point(x, y); - } - - */ - + + /* + // initialize random seed: + srand ( time(NULL) ); + + int a = 0; + int b = 2000; + + for(int i = 0; i < num_points; i++) { + double x = rand() % (b - a - 1) + a + 1; + double y = rand() % (b - a - 1) + a + 1; + polyline[i] = Point(x, y); + } + + */ + string line; - ifstream myfile (argv[1]); + ifstream myfile(argv[1]); vector points; if (myfile.is_open()) { while (!myfile.eof()) { - getline (myfile,line); - if(line.size() == 0) { + getline(myfile, line); + if (line.size() == 0) { break; } istringstream iss(line); vector tokens; - copy(istream_iterator(iss), istream_iterator(), + copy(istream_iterator(iss), istream_iterator(), back_inserter >(tokens)); double x = StringToDouble(tokens[0]); double y = StringToDouble(tokens[1]); @@ -111,187 +112,179 @@ int main(int argc, char* argv[]) { } else { cout << "File not opened" << endl; } - + int num_points = points.size(); cout << "Number of points = " << num_points << endl; - - Point** polyline = new Point *[num_points]; - for(int i = 0; i < num_points; i++) { + + Point** polyline = new Point *[num_points]; + for (int i = 0; i < num_points; i++) { polyline[i] = points[i]; } - + Init(); - + // Perform triangulation double init_time = glfwGetTime(); CDT * cdt = new CDT(polyline, num_points); cdt->Triangulate(); double dt = glfwGetTime() - init_time; cout << "Elapsed time (secs) = " << dt << endl; - + triangles = cdt->GetTriangles(); map = cdt->GetMap(); - + MainLoop(atof(argv[2])); - + delete [] polyline; ShutDown(0); return 0; } - + void Init() { const int window_width = 800, window_height = 600; - + if (glfwInit() != GL_TRUE) ShutDown(1); // 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed if (glfwOpenWindow(window_width, window_height, 5, 6, 5, 0, 0, 0, GLFW_WINDOW) != GL_TRUE) - ShutDown(1); - + ShutDown(1); + glfwSetWindowTitle("Poly2Tri - C++"); - + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.0, 0.0, 0.0, 0.0); - glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); - + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); } - + void ShutDown(int return_code) { glfwTerminate(); exit(return_code); } - + void MainLoop(const double zoom) { // the time of the previous frame double old_time = glfwGetTime(); // this just loops as long as the program runs bool running = true; - - while(running) - { + + while (running) { // calculate time elapsed, and the amount by which stuff rotates double current_time = glfwGetTime(), - delta_rotate = (current_time - old_time) * rotations_per_tick * 360; + delta_rotate = (current_time - old_time) * rotations_per_tick * 360; old_time = current_time; - + // escape to quit, arrow keys to rotate view // Check if ESC key was pressed or window was closed - running = !glfwGetKey( GLFW_KEY_ESC ) && glfwGetWindowParam( GLFW_OPENED ); - + running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED); + if (glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS) rotate_y += delta_rotate; if (glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS) rotate_y -= delta_rotate; // z axis always rotates rotate_z += delta_rotate; - + // Draw the scene - if(draw_map) { + if (draw_map) { DrawMap(zoom); } else { Draw(zoom); } - + // swap back and front buffers glfwSwapBuffers(); } } -void ResetZoom(double zoom, double cx, double cy, double width, double height) { +void ResetZoom(double zoom, double cx, double cy, double width, double height) +{ + double left = -width / zoom; + double right = width / zoom; + double bottom = -height / zoom; + double top = height / zoom; - double left = -width / zoom; - double right = width / zoom; - double bottom = -height / zoom; - double top = height / zoom; - - // Reset viewport - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - // Reset ortho view - glOrtho(left, right, bottom, top, 1, -1); - glTranslatef(-cx, -cy, 0); - glMatrixMode(GL_MODELVIEW); - glDisable(GL_DEPTH_TEST); - glLoadIdentity(); - - // Clear the screen - glClear(GL_COLOR_BUFFER_BIT); - + // Reset viewport + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Reset ortho view + glOrtho(left, right, bottom, top, 1, -1); + glTranslatef(-cx, -cy, 0); + glMatrixMode(GL_MODELVIEW); + glDisable(GL_DEPTH_TEST); + glLoadIdentity(); + + // Clear the screen + glClear(GL_COLOR_BUFFER_BIT); } - -void Draw(const double zoom) { +void Draw(const double zoom) +{ // reset zoom Point center = Point(0, 0); - + ResetZoom(zoom, center.x, center.y, 800, 600); - + for (int i = 0; i < triangles.size(); i++) { - Triangle& t = *triangles[i]; Point& a = *t.GetPoint(0); Point& b = *t.GetPoint(1); Point& c = *t.GetPoint(2); - + // Red glColor3f(1, 0, 0); - - glBegin(GL_LINE_LOOP); - glVertex2f(a.x, a.y); - glVertex2f(b.x, b.y); - glVertex2f(c.x, c.y); - glEnd(); + glBegin(GL_LINE_LOOP); + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); + glVertex2f(c.x, c.y); + glEnd(); } - } -void DrawMap(const double zoom) { - +void DrawMap(const double zoom) +{ // reset zoom Point center = Point(0, 0); - + ResetZoom(zoom, center.x, center.y, 800, 600); - - list::iterator it; + + list::iterator it; for (it = map.begin(); it != map.end(); it++) { - Triangle& t = **it; Point& a = *t.GetPoint(0); Point& b = *t.GetPoint(1); Point& c = *t.GetPoint(2); - - ConstrainedColor(t.constrained_edge[2]); - glBegin(GL_LINES); - glVertex2f(a.x, a.y); - glVertex2f(b.x, b.y); + + ConstrainedColor(t.constrained_edge[2]); + glBegin(GL_LINES); + glVertex2f(a.x, a.y); + glVertex2f(b.x, b.y); glEnd( ); - ConstrainedColor(t.constrained_edge[0]); + ConstrainedColor(t.constrained_edge[0]); glBegin(GL_LINES); - glVertex2f(b.x, b.y); - glVertex2f(c.x, c.y); + glVertex2f(b.x, b.y); + glVertex2f(c.x, c.y); glEnd( ); - ConstrainedColor(t.constrained_edge[1]); + ConstrainedColor(t.constrained_edge[1]); glBegin(GL_LINES); - glVertex2f(c.x, c.y); - glVertex2f(a.x, a.y); + glVertex2f(c.x, c.y); + glVertex2f(a.x, a.y); glEnd( ); - } - } -void ConstrainedColor(bool constrain) { - if(constrain) { +void ConstrainedColor(bool constrain) +{ + if (constrain) { // Green glColor3f(0, 1, 0); } else {