better decision-making about when to Fill hole

This commit is contained in:
Mason Green 2012-04-07 10:43:27 -04:00
parent 8c53b5f07e
commit 6f70496b5d
3 changed files with 67 additions and 4 deletions

View File

@ -41,6 +41,7 @@
namespace p2t { namespace p2t {
const double PI_3div4 = 3 * M_PI / 4; const double PI_3div4 = 3 * M_PI / 4;
const double PI_div2 = 1.57079632679489661923;
const double EPSILON = 1e-12; const double EPSILON = 1e-12;
enum Orientation { CW, CCW, COLLINEAR }; enum Orientation { CW, CCW, COLLINEAR };

View File

@ -225,8 +225,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
Node* node = n.next; Node* node = n.next;
while (node->next) { while (node->next) {
double angle = HoleAngle(*node); // if HoleAngle exceeds 90 degrees then break.
if (angle > M_PI_2 || angle < -M_PI_2) break; if (LargeHole_DontFill(node)) break;
Fill(tcx, *node); Fill(tcx, *node);
node = node->next; node = node->next;
} }
@ -235,8 +235,8 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
node = n.prev; node = n.prev;
while (node->prev) { while (node->prev) {
double angle = HoleAngle(*node); // if HoleAngle exceeds 90 degrees then break.
if (angle > M_PI_2 || angle < -M_PI_2) break; if (LargeHole_DontFill(node)) break;
Fill(tcx, *node); Fill(tcx, *node);
node = node->prev; 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 Sweep::BasinAngle(Node& node)
{ {
double ax = node.point->x - node.next->next->point->x; double ax = node.point->x - node.next->next->point->x;

View File

@ -169,6 +169,13 @@ private:
*/ */
void FillAdvancingFront(SweepContext& tcx, Node& 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);
/** /**
* *
* @param node - middle node * @param node - middle node