From 6f70496b5d290f3b373765eea853afc1d1947eb4 Mon Sep 17 00:00:00 2001 From: Mason Green Date: Sat, 7 Apr 2012 10:43:27 -0400 Subject: [PATCH] better decision-making about when to Fill hole --- poly2tri/common/utils.h | 1 + poly2tri/sweep/sweep.cc | 63 ++++++++++++++++++++++++++++++++++++++--- poly2tri/sweep/sweep.h | 7 +++++ 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/poly2tri/common/utils.h b/poly2tri/common/utils.h index a38e448..ad27efa 100644 --- a/poly2tri/common/utils.h +++ b/poly2tri/common/utils.h @@ -41,6 +41,7 @@ namespace p2t { const double PI_3div4 = 3 * M_PI / 4; +const double PI_div2 = 1.57079632679489661923; const double EPSILON = 1e-12; enum Orientation { CW, CCW, COLLINEAR }; diff --git a/poly2tri/sweep/sweep.cc b/poly2tri/sweep/sweep.cc index 3682c30..992f0e5 100644 --- a/poly2tri/sweep/sweep.cc +++ b/poly2tri/sweep/sweep.cc @@ -225,8 +225,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) Node* node = n.next; while (node->next) { - double angle = HoleAngle(*node); - if (angle > M_PI_2 || angle < -M_PI_2) break; + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; Fill(tcx, *node); node = node->next; } @@ -235,8 +235,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) node = n.prev; while (node->prev) { - double angle = HoleAngle(*node); - if (angle > M_PI_2 || angle < -M_PI_2) break; + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; Fill(tcx, *node); node = node->prev; } @@ -250,6 +250,61 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) } } +// True if HoleAngle exceeds 90 degrees. +bool Sweep::LargeHole_DontFill(Node* node) { + + Node* nextNode = node->next; + Node* prevNode = node->prev; + if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) + return false; + + // Check additional points on front. + Node* next2Node = nextNode->next; + // "..Plus.." because only want angles on same side as point being added. + if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) + return false; + + Node* prev2Node = prevNode->prev; + // "..Plus.." because only want angles on same side as point being added. + if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) + return false; + + return true; +} + +bool Sweep::AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb) { + double angle = Angle(*origin, *pa, *pb); + bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2)); + return exceeds90Degrees; +} + +bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb) { + double angle = Angle(*origin, *pa, *pb); + bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0); + return exceedsPlus90DegreesOrIsNegative; +} + +double Sweep::Angle(Point& origin, Point& pa, Point& pb) { + /* 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 px = origin.x; + double py = origin.y; + double ax = pa.x- px; + double ay = pa.y - py; + double bx = pb.x - px; + double by = pb.y - py; + double x = ax * by - ay * bx; + double y = ax * bx + ay * by; + double angle = atan2(x, y); + return angle; +} + double Sweep::BasinAngle(Node& node) { double ax = node.point->x - node.next->next->point->x; diff --git a/poly2tri/sweep/sweep.h b/poly2tri/sweep/sweep.h index bd98adf..f62c4cc 100644 --- a/poly2tri/sweep/sweep.h +++ b/poly2tri/sweep/sweep.h @@ -168,6 +168,13 @@ private: * @param n */ void FillAdvancingFront(SweepContext& tcx, Node& n); + + // Decision-making about when to Fill hole. + // Contributed by ToolmakerSteve2 + bool LargeHole_DontFill(Node* node); + bool AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb); + bool AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb); + double Angle(Point& origin, Point& pa, Point& pb); /** *