mirror of
				https://github.com/jhasse/poly2tri.git
				synced 2025-11-04 14:09:33 +01:00 
			
		
		
		
	better decision-making about when to Fill hole
This commit is contained in:
		@@ -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 };
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   *
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user