From d776b54e5780eda965de22019a9bc78320e29eef Mon Sep 17 00:00:00 2001 From: zzzzrrr Date: Tue, 19 Jan 2010 17:23:38 -0500 Subject: [PATCH] fixed edge pointer bug - yay --- poly2tri/common/shapes.cc | 7 ++ poly2tri/common/shapes.h | 28 ++++--- poly2tri/common/utils.h | 54 +++++++------- poly2tri/sweep/advancing_front.cc | 6 +- poly2tri/sweep/cdt.cc | 2 +- poly2tri/sweep/cdt.h | 2 +- poly2tri/sweep/sweep.cc | 110 +++++++++++++-------------- poly2tri/sweep/sweep.h | 2 - poly2tri/sweep/sweep_context.cc | 32 ++++---- poly2tri/sweep/sweep_context.h | 12 +-- testbed/data/2.dat | 120 +++++++++++++++--------------- testbed/data/custom.dat | 2 +- testbed/main.cc | 26 ++++--- wscript | 6 +- 14 files changed, 216 insertions(+), 193 deletions(-) diff --git a/poly2tri/common/shapes.cc b/poly2tri/common/shapes.cc index 0349a93..7918ab3 100644 --- a/poly2tri/common/shapes.cc +++ b/poly2tri/common/shapes.cc @@ -329,5 +329,12 @@ Triangle& Triangle::NeighborAcross(Point& opoint) { return *neighbors_[2]; } +void Triangle::DebugPrint() { + using namespace std; + cout << points_[0]->x << "," << points_[0]->y << " "; + cout << points_[1]->x << "," << points_[1]->y << " "; + cout << points_[2]->x << "," << points_[2]->y << endl; +} + diff --git a/poly2tri/common/shapes.h b/poly2tri/common/shapes.h index 0aaaee7..cd8f07f 100644 --- a/poly2tri/common/shapes.h +++ b/poly2tri/common/shapes.h @@ -28,7 +28,6 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - // Include guard #ifndef SHAPES_H #define SHAPES_H @@ -48,7 +47,8 @@ struct Point { double x, y; /// Default constructor does nothing (for performance). - Point() {} + Point() { x = 0.0; y = 0.0; } + /// The edges this point constitutes an upper ending point std::vector edge_list; @@ -91,6 +91,18 @@ struct Point { y /= len; return len; } + + bool operator < (Point& b) { + if (y < b.y) { + return true; + } else if (y == b.y) { + // Make sure q is point with greater x value + if(x < b.x) { + return true; + } + } + return false; + } }; @@ -110,6 +122,7 @@ struct Edge { q = &p1; p = &p2; } else if(p1.x == p2.x) { + // Repeat points assert(false); } } @@ -176,6 +189,8 @@ public: Triangle& NeighborAcross(Point& opoint); + void DebugPrint(); + private: /// Triangle points @@ -192,14 +207,7 @@ inline bool operator < (const Point& a, const Point& b) { // Make sure q is point with greater x value if(a.x < b.x) { return true; - } else if (a.x > b.x) { - return false; - } else { - // Repeat point - //std::cout << "Repeat points not alowed: "; - //std::cout << a.x << "," << a.y << " " << b.x << "," << b.y << std::endl; - //assert(false); - } + } } return false; } diff --git a/poly2tri/common/utils.h b/poly2tri/common/utils.h index 01c5857..5e6a1b2 100644 --- a/poly2tri/common/utils.h +++ b/poly2tri/common/utils.h @@ -28,10 +28,11 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +#ifndef UTILS_H +#define UTILS_H -#include "shapes.h" +#include +#include template int array_length(T(&)[size]){return size;} @@ -67,32 +68,35 @@ Orientation Orient2d(Point& pa, Point& pb, Point& pc ) { bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { - const double pdx = pd.x; - const double pdy = pd.y; - const double adx = pa.x - pdx; - const double ady = pa.y - pdy; - const double bdx = pb.x - pdx; - const double bdy = pb.y - pdy; + double pdx = pd.x; + double pdy = pd.y; + double adx = pa.x - pdx; + double ady = pa.y - pdy; + double bdx = pb.x - pdx; + double bdy = pb.y - pdy; - const double adxbdy = adx * bdy; - const double bdxady = bdx * ady; - const double oabd = adxbdy - bdxady; + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; - if(oabd <= 0) { - return false; - } + if(oabd <= EPSILON) { + return false; + } - const double cdx = pc.x - pdx; - const double cdy = pc.y - pdy; + double cdx = pc.x - pdx; + double cdy = pc.y - pdy; - const double cdxady = cdx * ady; - const double adxcdy = adx * cdy; - const double ocad = cdxady - adxcdy; + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; - if(ocad <= 0) { - return false; - } - - return true; + if(ocad <= EPSILON) { + return false; + } + + return true; + } +#endif + diff --git a/poly2tri/sweep/advancing_front.cc b/poly2tri/sweep/advancing_front.cc index fbc2efd..27a5ba3 100644 --- a/poly2tri/sweep/advancing_front.cc +++ b/poly2tri/sweep/advancing_front.cc @@ -86,10 +86,12 @@ Node* AdvancingFront::LocatePoint(Point* point) { break; } } - search_node_ = node; + if(node) search_node_ = node; return node; } AdvancingFront::~AdvancingFront() { - delete head_; search_node_; tail_; + delete head_; + delete search_node_; + delete tail_; } diff --git a/poly2tri/sweep/cdt.cc b/poly2tri/sweep/cdt.cc index 6b19528..6332414 100644 --- a/poly2tri/sweep/cdt.cc +++ b/poly2tri/sweep/cdt.cc @@ -30,7 +30,7 @@ */ #include "cdt.h" -CDT::CDT(Point polyline[], const int& point_count) { +CDT::CDT(Point** polyline, const int& point_count) { sweep_context_ = new SweepContext(polyline, point_count); sweep_ = new Sweep; } diff --git a/poly2tri/sweep/cdt.h b/poly2tri/sweep/cdt.h index a8f089b..67c6a06 100644 --- a/poly2tri/sweep/cdt.h +++ b/poly2tri/sweep/cdt.h @@ -39,7 +39,7 @@ class CDT public: /// Constructor - CDT(Point poly_line[], const int& point_count); + CDT(Point** poly_line, const int& point_count); /// Add a hole void AddHole(const Point poly_line[], const int point_count); /// Triangulate points diff --git a/poly2tri/sweep/sweep.cc b/poly2tri/sweep/sweep.cc index 674b800..b195ac4 100644 --- a/poly2tri/sweep/sweep.cc +++ b/poly2tri/sweep/sweep.cc @@ -57,11 +57,13 @@ void Sweep::SweepPoints(SweepContext& tcx ) { for(int i = 1; i < tcx.point_count(); i++ ) { Point& point = *tcx.GetPoint(i); + Node& node = PointEvent(tcx, point); - + for(int i = 0; i < point.edge_list.size(); i++) { - EdgeEvent(tcx, point.edge_list[i], node ); + EdgeEvent(tcx, point.edge_list[i], node); } + } } @@ -93,10 +95,10 @@ Node& Sweep::PointEvent(SweepContext& tcx, Point& point) { } 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; } @@ -274,7 +276,7 @@ double Sweep::HoleAngle(Node& node) { 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); + return atan2(ax * by - ay * bx, ax * bx + ay * by); } /** @@ -380,7 +382,7 @@ bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) { double oabd = adxbdy - bdxady; if( oabd <= 0 ) - return false; + return false; double cdx = pc.x - pd.x; double cdy = pc.y - pd.y; @@ -390,7 +392,7 @@ bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) { double ocad = cdxady - adxcdy; if( ocad <= 0 ) - return false; + return false; double bdxcdy = bdx * cdy; double cdxbdy = cdx * bdy; @@ -693,7 +695,7 @@ void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge& edge, Node& node) { - // Next concave or convex? + // 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); @@ -788,25 +790,25 @@ void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, } 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) { - 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? - } - } else { - Orientation o = Orient2d(eq, op, ep); - t = NextFlipTriangle(tcx, (int) o, t, ot, p, op); - FlipEdgeEvent(tcx, ep, eq, t, p); - } + // 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) { + 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? + } + } else { + Orientation o = Orient2d(eq, op, ep); + 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); @@ -816,36 +818,36 @@ void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& t, 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; - Legalize(tcx, ot); - 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(); - return ot; + if(o == CCW) { + // ot is not crossing edge after flip + int edge_index = ot.EdgeIndex(&p, &op); + ot.delaunay_edge[edge_index] = true; + Legalize(tcx, ot); + 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(); + 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) { - // Right - return *ot.PointCCW(op); - } else if(o2d == CCW) { - // Left - return *ot.PointCW(op); - } else { - //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); - assert(0); - } + Orientation o2d = Orient2d(eq, op, ep); + if(o2d == CW) { + // Right + return *ot.PointCCW(op); + } else if(o2d == CCW) { + // Left + return *ot.PointCW(op); + } else { + //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); + assert(0); + } } diff --git a/poly2tri/sweep/sweep.h b/poly2tri/sweep/sweep.h index a4e5d54..b190900 100644 --- a/poly2tri/sweep/sweep.h +++ b/poly2tri/sweep/sweep.h @@ -37,8 +37,6 @@ * "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com */ -#include - class SweepContext; struct Node; struct Point; diff --git a/poly2tri/sweep/sweep_context.cc b/poly2tri/sweep/sweep_context.cc index da4b99d..2aec4d3 100644 --- a/poly2tri/sweep/sweep_context.cc +++ b/poly2tri/sweep/sweep_context.cc @@ -4,16 +4,17 @@ #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(); - point_count_ = point_count; - points_ = polyline; + for(int i = 0; i < point_count; i++) { + points_.push_back(**&polyline[i]); + } + InitEdges(polyline, point_count); InitTriangulation(); - InitEdges(); } @@ -27,7 +28,7 @@ void SweepContext::InitTriangulation() { double ymax(points_[0].y), ymin(points_[0].y); // Calculate bounds. - for(int i = 0; i < point_count_; i++) { + for(int i = 0; i < points_.size(); i++) { Point p = points_[i]; if(p.x > xmax) xmax = p.x; @@ -46,22 +47,17 @@ void SweepContext::InitTriangulation() { // Sort points along y-axis double init_time = glfwGetTime(); - std::sort(points_, points_ + point_count_); + std::sort(points_.begin(), points_.end()); double dt = glfwGetTime() - init_time; printf("Sort time (secs) = %f\n", dt); - - /* - for(int i = 0; i < point_count_; i++) { - printf("%i: %f, %f\n", i+1, points_[i].x, points_[i].y); - } - */ - + } -void SweepContext::InitEdges() { - for(int i = 0; i < point_count_; i++) { - int j = i < point_count_ - 1 ? i + 1 : 0; - new Edge(points_[i], points_[j]); +void SweepContext::InitEdges(Point** polyline, const int& point_count) { + + for(int i = 0; i < point_count; i++) { + int j = i < points_.size() - 1 ? i + 1 : 0; + edge_list.push_back(new Edge(**&polyline[i], **&polyline[j])); } } @@ -157,7 +153,7 @@ void SweepContext::MeshCleanReq(Triangle& triangle ) { */ SweepContext::~SweepContext() { - delete [] points_; + //delete [] points_; delete head_; delete tail_; delete front_; diff --git a/poly2tri/sweep/sweep_context.h b/poly2tri/sweep/sweep_context.h index d942686..65e05bb 100644 --- a/poly2tri/sweep/sweep_context.h +++ b/poly2tri/sweep/sweep_context.h @@ -29,6 +29,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include // Inital triangle factor, seed triangle will extend 30% of // PointSet width to both left and right. @@ -46,7 +47,7 @@ class SweepContext { public: // Constructor - SweepContext(Point polyline[], const int& point_count); + SweepContext(Point** polyline, const int& point_count); // Destructor ~SweepContext(); @@ -81,6 +82,7 @@ public: std::list GetTriangles(); + std::vector edge_list; struct Basin { @@ -118,9 +120,7 @@ public: private: std::list tri_list_; - - Point* points_; - int point_count_; + std::vector points_; // Advancing front AdvancingFront* front_; @@ -132,7 +132,7 @@ private: //EdgeEvent edgeEvent = new EdgeEvent(); void InitTriangulation(); - void InitEdges(); + void InitEdges(Point** polyline, const int& point_count); //void MeshCleanReq(Triangle& triangle ) @@ -147,7 +147,7 @@ private: inline AdvancingFront* SweepContext::front() { return front_; } -inline int SweepContext::point_count() { return point_count_; } +inline int SweepContext::point_count() { return points_.size(); } inline void SweepContext::set_head(Point* p1) { head_ = p1; } diff --git a/testbed/data/2.dat b/testbed/data/2.dat index c1a3a30..991301f 100644 --- a/testbed/data/2.dat +++ b/testbed/data/2.dat @@ -1,60 +1,60 @@ -2158.9981,2350.2286 -2158.9981,3245.4557 --1042.9463,3245.4557 --1042.9463,2496.1895 -91.149593,800.20639 -441.75649,251.73749 -648.06929,-97.04991 -765.46219,-332.30851 -849.31479,-540.20071 -899.62689,-720.72671 -916.39869,-873.88651 -896.13819,-1060.7944 -835.35969,-1193.3788 -789.54889,-1239.4959 -733.15879,-1272.4376 -666.18939,-1292.204 -588.64059,-1298.7951 -511.08979,-1291.4964 -444.11959,-1269.6012 -387.73029,-1233.1107 -341.92169,-1182.0263 -306.46619,-1109.2461 -281.14119,-1007.6808 -260.88259,-718.19491 -260.88259,-218.68401 --1042.9463,-218.68401 --1042.9463,-410.05511 --1030.3404,-804.55201 --992.52205,-1105.8022 --958.08057,-1232.6032 --905.18018,-1358.3923 --833.82067,-1483.1695 --744.00213,-1606.9348 --637.5262,-1722.6871 --516.1928,-1823.4397 --380.00205,-1909.1927 --228.95374,-1979.9461 --62.599167,-2035.2866 -119.51329,-2074.8167 -317.38399,-2098.5364 -531.01279,-2106.4456 -938.57049,-2082.2155 -1122.512,-2051.9328 -1293.2285,-2009.5383 -1450.7202,-1955.0316 -1594.987,-1888.4129 -1726.0289,-1809.6817 -1843.846,-1718.8382 -2038.4505,-1512.159 -2177.4543,-1279.7356 -2260.8578,-1021.5681 -2288.6606,-737.65631 -2273.0151,-508.98211 -2226.0792,-273.82221 -2147.8538,-32.17651 -2038.3398,215.95519 -1852.2859,537.88159 -1544.4495,1000.9025 -1114.8304,1605.018 -563.42839,2350.2286 +2158.9981 2350.2286 +2158.9981 3245.4557 +-1042.9463 3245.4557 +-1042.9463 2496.1895 +91.149593 800.20639 +441.75649 251.73749 +648.06929 -97.04991 +765.46219 -332.30851 +849.31479 -540.20071 +899.62689 -720.72671 +916.39869 -873.88651 +896.13819 -1060.7944 +835.35969 -1193.3788 +789.54889 -1239.4959 +733.15879 -1272.4376 +666.18939 -1292.204 +588.64059 -1298.7951 +511.08979 -1291.4964 +444.11959 -1269.6012 +387.73029 -1233.1107 +341.92169 -1182.0263 +306.46619 -1109.2461 +281.14119 -1007.6808 +260.88259 -718.19491 +260.88259 -218.68401 +-1042.9463 -218.68401 +-1042.9463 -410.05511 +-1030.3404 -804.55201 +-992.52205 -1105.8022 +-958.08057 -1232.6032 +-905.18018 -1358.3923 +-833.82067 -1483.1695 +-744.00213 -1606.9348 +-637.5262 -1722.6871 +-516.1928 -1823.4397 +-380.00205 -1909.1927 +-228.95374 -1979.9461 +-62.599167 -2035.2866 +119.51329 -2074.8167 +317.38399 -2098.5364 +531.01279 -2106.4456 +938.57049 -2082.2155 +1122.512 -2051.9328 +1293.2285 -2009.5383 +1450.7202 -1955.0316 +1594.987 -1888.4129 +1726.0289 -1809.6817 +1843.846 -1718.8382 +2038.4505 -1512.159 +2177.4543 -1279.7356 +2260.8578 -1021.5681 +2288.6606 -737.65631 +2273.0151 -508.98211 +2226.0792 -273.82221 +2147.8538 -32.17651 +2038.3398 215.95519 +1852.2859 537.88159 +1544.4495 1000.9025 +1114.8304 1605.018 +563.42839 2350.2286 diff --git a/testbed/data/custom.dat b/testbed/data/custom.dat index 1b2847d..fb1cefb 100644 --- a/testbed/data/custom.dat +++ b/testbed/data/custom.dat @@ -1,7 +1,7 @@ 0 130 -270 0 130 -40 -10 -60 +10 -60 -10 -20 100 30 40 -40 \ No newline at end of file diff --git a/testbed/main.cc b/testbed/main.cc index 8186035..e8a8d1b 100644 --- a/testbed/main.cc +++ b/testbed/main.cc @@ -44,8 +44,8 @@ using namespace std; void Init(); void ShutDown(int return_code); -void MainLoop(); -void Draw(); +void MainLoop(const double zoom); +void Draw(const double zoom); float rotate_y = 0, rotate_z = 0; @@ -63,6 +63,11 @@ double StringToDouble(const std::string& s) { int main(int argc, char* argv[]) { + if (argc != 3) { + cout << "Usage: p2t filename zoom" << endl; + return 1; + } + /* // initialize random seed: srand ( time(NULL) ); @@ -112,9 +117,9 @@ int main(int argc, char* argv[]) { int num_points = points.size(); cout << "Number of points = " << num_points << endl; - Point* polyline = new Point[num_points]; + Point** polyline = new Point *[num_points]; for(int i = 0; i < num_points; i++) { - polyline[i] = points[i]; + polyline[i] = &points[i]; } Init(); @@ -128,7 +133,7 @@ int main(int argc, char* argv[]) { triangles = cdt->GetTriangles(); - MainLoop(); + MainLoop(atof(argv[2])); delete [] polyline; ShutDown(0); @@ -161,7 +166,7 @@ void ShutDown(int return_code) exit(return_code); } -void MainLoop() +void MainLoop(const double zoom) { // the time of the previous frame double old_time = glfwGetTime(); @@ -187,7 +192,7 @@ void MainLoop() rotate_z += delta_rotate; // Draw the scene - Draw(); + Draw(zoom); // swap back and front buffers glfwSwapBuffers(); } @@ -217,11 +222,12 @@ void ResetZoom(double zoom, double cx, double cy, double width, double height) { } -void Draw() +void Draw(const double zoom) { // reset zoom - double zoom = 0.5; - ResetZoom(zoom, 0, 0, 800, 600); + Point center = Point(0, 0); + + ResetZoom(zoom, center.x, center.y, 800, 600); list::iterator it; for (it = triangles.begin(); it != triangles.end(); it++) { diff --git a/wscript b/wscript index acddb9a..9660a95 100644 --- a/wscript +++ b/wscript @@ -4,12 +4,12 @@ APPNAME='p2t' srcdir = '.' blddir = 'build' -p2t_source_files = ['poly2tri/sweep/cdt.cc', +p2t_source_files = ['poly2tri/common/shapes.cc', + 'poly2tri/sweep/cdt.cc', 'poly2tri/sweep/advancing_front.cc', 'poly2tri/sweep/mesh.cc', 'poly2tri/sweep/sweep_context.cc', - 'poly2tri/sweep/sweep.cc', - 'poly2tri/common/shapes.cc'] + 'poly2tri/sweep/sweep.cc'] testbed_source_files = ['testbed/main.cc']