diff --git a/data/bird.dat b/data/bird.dat index 3f76eae..caa9652 100644 --- a/data/bird.dat +++ b/data/bird.dat @@ -272,4 +272,4 @@ 6.20462 5.25418 5.72617 4.80159 5.13134 4.41366 -4.87271 4.16797 +4.87271 4.16797 \ No newline at end of file diff --git a/src/org/poly2tri/shapes/Triangle.scala b/src/org/poly2tri/shapes/Triangle.scala index b78dadf..5fb7be6 100644 --- a/src/org/poly2tri/shapes/Triangle.scala +++ b/src/org/poly2tri/shapes/Triangle.scala @@ -123,43 +123,43 @@ class Triangle(val points: Array[Point]) { // Locate first triangle crossed by constrained edge def locateFirst(edge: Segment): Triangle = { - val p = edge.p - val q = edge.q - val e = p - q + + if(edge.q == points(0)) + search(points(1), points(2), edge, neighbors(2)) + else if(edge.q == points(1)) + search(points(0), points(2), edge, neighbors(0)) + else if(edge.q == points(2)) + search(points(1), points(0), edge, neighbors(1)) + else + throw new Exception("Point not found") + + } + + def search(p1: Point, p2: Point, edge: Segment, neighbor: Triangle): Triangle = { - val ik = points(2) - points(0) - val ij = points(1) - points(0) - val jk = points(2) - points(1) - val ji = points(0) - points(1) - val kj = points(1) - points(2) - val ki = points(0) - points(2) - - if(q == points(0)) { - val sameSign = Math.signum(ik cross e) == Math.signum(ij cross e) - if(!sameSign) return this - if(neighbors(2) == null) return null - return neighbors(2).locateFirst(edge) - } else if(q == points(1)) { - val sameSign = Math.signum(jk cross e) == Math.signum(ji cross e) - if(!sameSign) return this - if(neighbors(0) == null) return null - return neighbors(0).locateFirst(edge) - } else if(q == points(2)) { - val sameSign = Math.signum(kj cross e) == Math.signum(ki cross e) - if(!sameSign) return this - if(neighbors(1) == null) return null - return neighbors(1).locateFirst(edge) - } - throw new Exception("Point not found") + val o1 = Util.orient2d(edge.q, p1, edge.p) + val o2 = Util.orient2d(edge.q, p2, edge.p) + val sameSign = Math.signum(o1) == Math.signum(o2) + + // Edge crosses this triangle + if(!sameSign) + return this + + // Look at neighbor + if(neighbor == null) + null + else + neighbor.locateFirst(edge) + } // Locate next triangle crossed by edge def findNeighbor(e: Point): Triangle = { - if(Util.orient2d(points(0), points(1), e) > 0) + if(Util.orient2d(points(0), points(1), e) < 0) return neighbors(2) - else if(Util.orient2d(points(1), points(2), e) > 0) + else if(Util.orient2d(points(1), points(2), e) < 0) return neighbors(0) - else if(Util.orient2d(points(2), points(0), e) > 0) + else if(Util.orient2d(points(2), points(0), e) < 0) return neighbors(1) else // Point must reside inside this triangle @@ -249,10 +249,10 @@ class Triangle(val points: Array[Point]) { } - // Make legalized triangle will not be collinear + // Check if legalized triangle will be collinear def collinear(oPoint: Point): Boolean = Util.collinear(points(1), points(0), oPoint) - // Make sure legalized triangle will not be collinear + // Check if legalized triangle will be collinear def collinear(oPoint: Point, nPoint: Point): Boolean = { if(oPoint == points(0)) { Util.collinear(points(0), points(2), nPoint) diff --git a/src/org/poly2tri/utils/Util.scala b/src/org/poly2tri/utils/Util.scala index bbb72c9..ec5e9b9 100644 --- a/src/org/poly2tri/utils/Util.scala +++ b/src/org/poly2tri/utils/Util.scala @@ -43,7 +43,7 @@ object Util { // Tests if the given points are collinear def collinear(p1: Point, p2: Point, p3: Point): Boolean = { - val d = (p2 - p1) cross (p1 - p3) + val d = orient2d(p1, p2, p3) if(Math.abs(d) <= COLLINEAR_SLOP) true @@ -93,7 +93,7 @@ object Util { } // Adaptive exact 2D orientation test. Robust. By Jonathan Shewchuk - // Return: positive if point a, b, and c are counterclockwise + // Return: positive if point a, b, and c are counterclockwise // negative if point a, b, and c are clockwise // zero if points are collinear // See: http://www-2.cs.cmu.edu/~quake/robust.html @@ -124,15 +124,13 @@ object Util { if ((det >= errbound) || (-det >= errbound)) { return det } else { - println(pa + "," + pb + "," + pc) - println(detleft + "," + detright) - println("Det = " + det + " , errbound = " + errbound) - throw new Exception("Degenerate triangle") + + // Cheat a little bit.... we have a degenerate triangle + val c = pc * 1.00001f + return orient2d(pa, pb, c) + } - - // Not implemented; - // http://www.cs.cmu.edu/afs/cs/project/quake/public/code/predicates.c - // return orient2dadapt(pa, pb, pc, detsum) + } }