mirror of
				https://github.com/jhasse/poly2tri.git
				synced 2025-10-30 20:17:10 +01:00 
			
		
		
		
	bug hunting
This commit is contained in:
		| @@ -170,7 +170,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { | |||||||
| 	    }) | 	    }) | ||||||
|     |     | ||||||
|    if(drawCDT) { |    if(drawCDT) { | ||||||
|        val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles |        //val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles | ||||||
|  |        val draw = slCDT.testTri | ||||||
| 	   draw.foreach( t => { | 	   draw.foreach( t => { | ||||||
| 	     val triangle = new Polygon | 	     val triangle = new Polygon | ||||||
| 		 triangle.addPoint(t.points(0).x, t.points(0).y) | 		 triangle.addPoint(t.points(0).x, t.points(0).y) | ||||||
|   | |||||||
| @@ -30,6 +30,8 @@ | |||||||
|  */ |  */ | ||||||
| package org.poly2tri.cdt | package org.poly2tri.cdt | ||||||
|  |  | ||||||
|  | import scala.collection.mutable.ArrayBuffer | ||||||
|  |  | ||||||
| import shapes.{Point, Triangle} | import shapes.{Point, Triangle} | ||||||
|  |  | ||||||
| // Advancing front | // Advancing front | ||||||
| @@ -87,7 +89,94 @@ class AFront(iTriangle: Triangle) { | |||||||
|     node |     node | ||||||
|   } |   } | ||||||
|    |    | ||||||
|   def constrainedEdge() { |   // Update advancing front with constrained edge triangles | ||||||
|  |   def constrainedEdge(sNode: Node, eNode: Node, T1: ArrayBuffer[Triangle],  | ||||||
|  |                       T2: ArrayBuffer[Triangle]): Triangle = { | ||||||
|  |      | ||||||
|  |     var node = sNode | ||||||
|  |     var t1r, t2r = false | ||||||
|  |      | ||||||
|  |     while(node != eNode) { | ||||||
|  |        | ||||||
|  |       T2.foreach(t => { | ||||||
|  |         if(t.contains(node.point, node.next.point)) { | ||||||
|  |           node.triangle = t | ||||||
|  |           t2r = true | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |        | ||||||
|  |       if(!t2r) | ||||||
|  |         T1.foreach(t => { | ||||||
|  |           if(t.contains(node.point, node.next.point)) { | ||||||
|  |             node.triangle = t | ||||||
|  |             t1r = true | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |        | ||||||
|  |       node = node.next | ||||||
|  |     } | ||||||
|  |         | ||||||
|  |     if(t1r && !t2r)  | ||||||
|  |       T1.first  | ||||||
|  |     else if(t2r && !t1r) | ||||||
|  |       T2.first | ||||||
|  |     else | ||||||
|  |       throw new Exception("edge insertion error") | ||||||
|  |      | ||||||
|  |   } | ||||||
|  |    | ||||||
|  |   // Update advancing front with qNode | ||||||
|  |   def constrainedEdge(qNode: Node, tList: ArrayBuffer[Triangle], T1: ArrayBuffer[Triangle],  | ||||||
|  |                       T2: ArrayBuffer[Triangle]): Triangle = { | ||||||
|  |      | ||||||
|  |     var t1r, t2r = false | ||||||
|  |      | ||||||
|  |     for(t <- tList) { | ||||||
|  |    | ||||||
|  | 	    if(qNode.triangle == t) { | ||||||
|  | 	       | ||||||
|  | 	      val p1 = qNode.point | ||||||
|  | 	      val p2 = qNode.next.point | ||||||
|  |         | ||||||
|  |           T2.foreach(tri => if(tri.contains(p1, p2)) { | ||||||
|  | 	        qNode.triangle = tri | ||||||
|  |             t2r = true | ||||||
|  | 	      }) | ||||||
|  |            | ||||||
|  |           if(!t2r) | ||||||
|  | 	        T1.foreach(tri => if(tri.contains(p1, p2)) { | ||||||
|  | 	          qNode.triangle = tri | ||||||
|  |               t1r = true | ||||||
|  |             })  | ||||||
|  |            | ||||||
|  | 	    } else if(qNode.prev.triangle == t) { | ||||||
|  | 	       | ||||||
|  | 	      val p1 = qNode.prev.point | ||||||
|  | 	      val p2 = qNode.point | ||||||
|  |         | ||||||
|  |           T2.foreach(tri => if(tri.contains(p1, p2)) { | ||||||
|  | 	        qNode.prev.triangle = tri | ||||||
|  |             t2r = true | ||||||
|  | 	      }) | ||||||
|  |            | ||||||
|  |           if(!t2r) | ||||||
|  | 	        T1.foreach(tri => if(tri.contains(p1, p2)) { | ||||||
|  | 	          qNode.prev.triangle = tri | ||||||
|  |               t1r = true | ||||||
|  | 	        }) | ||||||
|  |            | ||||||
|  | 	    } else if(qNode.next.triangle == t) { | ||||||
|  |           throw new Exception("unanticipated edge event!") | ||||||
|  |         } | ||||||
|  |       | ||||||
|  | 	} | ||||||
|  |      | ||||||
|  |     if(t1r && !t2r)  | ||||||
|  |       T1.first  | ||||||
|  |     else if(t2r && !t1r) | ||||||
|  |       T2.first | ||||||
|  |     else | ||||||
|  |       throw new Exception("edge insertion error") | ||||||
|      |      | ||||||
|   } |   } | ||||||
|    |    | ||||||
| @@ -98,6 +187,12 @@ class AFront(iTriangle: Triangle) { | |||||||
|     node.triangle = triangle |     node.triangle = triangle | ||||||
|   } |   } | ||||||
|    |    | ||||||
|  |   def link(node1: Node, node2: Node, t: Triangle) { | ||||||
|  |     node1.next = node2 | ||||||
|  |     node2.prev = node1 | ||||||
|  |     node1.triangle = t | ||||||
|  |   } | ||||||
|  |    | ||||||
|   def basin(node: Node) { |   def basin(node: Node) { | ||||||
|     if(node.next != tail) { |     if(node.next != tail) { | ||||||
|       val p1 = node.point |       val p1 = node.point | ||||||
|   | |||||||
| @@ -128,6 +128,18 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|   // Finalize triangulation |   // Finalize triangulation | ||||||
|   finalization |   finalization | ||||||
|    |    | ||||||
|  |   val testTri = new ArrayBuffer[Triangle] | ||||||
|  |    | ||||||
|  |   val p1 = Point(200, 300) | ||||||
|  |   val p2 = Point(500, 300) | ||||||
|  |    | ||||||
|  |   val p3 = Point(250, 500) | ||||||
|  |   val p4 = Point(350, 400) | ||||||
|  |   val p5 = Point(400, 350) | ||||||
|  |   | ||||||
|  |   val pts = Array(p3, p4, p5) | ||||||
|  |   triangulate(pts, List(p1, p2), testTri) | ||||||
|  |    | ||||||
|   // Implement sweep-line  |   // Implement sweep-line  | ||||||
|   private def sweep { |   private def sweep { | ||||||
|      |      | ||||||
| @@ -136,7 +148,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|       // Process Point event |       // Process Point event | ||||||
|       var triangle = pointEvent(point) |       var triangle = pointEvent(point) | ||||||
|       // Process edge events |       // Process edge events | ||||||
|       //point.edges.foreach(e => triangle = edgeEvent(e, triangle)) |       point.edges.foreach(e => triangle = edgeEvent(e, triangle)) | ||||||
|       if(i == CDT.clearPoint) {cleanTri = triangle; mesh.debug += cleanTri} |       if(i == CDT.clearPoint) {cleanTri = triangle; mesh.debug += cleanTri} | ||||||
|     } |     } | ||||||
|   }   |   }   | ||||||
| @@ -231,39 +243,15 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|        |        | ||||||
|       // Update advancing front |       // Update advancing front | ||||||
|    |    | ||||||
|       val qNode = aFront.locatePoint(edge.q)   |       var first: Triangle = null | ||||||
|       val pNode = aFront.locatePoint(edge.p) |       val sNode = aFront.locatePoint(point1)   | ||||||
|        |       val eNode = aFront.locatePoint(point2) | ||||||
|       // TODO: Make this more robust.... |  | ||||||
|        |  | ||||||
|       for(t <- tList) { |  | ||||||
|          |  | ||||||
|         if(qNode.triangle == t) { |  | ||||||
|           val p1 = qNode.point |  | ||||||
|           val p2 = qNode.next.point |  | ||||||
|           T1.foreach(tri => if(tri.contains(p1, p2)) qNode.triangle = tri) |  | ||||||
|           T2.foreach(tri => if(tri.contains(p1, p2)) qNode.triangle = tri) |  | ||||||
|         } else if(qNode.prev.triangle == t) { |  | ||||||
|           val p1 = qNode.prev.point |  | ||||||
|           val p2 = qNode.point |  | ||||||
|           T1.foreach(tri => if(tri.contains(p1, p2)) qNode.prev.triangle = tri) |  | ||||||
|           T2.foreach(tri => if(tri.contains(p1, p2)) qNode.prev.triangle = tri) |  | ||||||
|         }  |  | ||||||
|          |  | ||||||
|         if(pNode != null) { |  | ||||||
| 	        if(pNode.triangle == t) { |  | ||||||
| 	          val p1 = pNode.point |  | ||||||
| 	          val p2 = pNode.next.point |  | ||||||
| 	          T1.foreach(tri => if(tri.contains(p1, p2)) pNode.triangle = tri) |  | ||||||
| 	          T2.foreach(tri => if(tri.contains(p1, p2)) pNode.triangle = tri) |  | ||||||
| 	        } else if(pNode.prev.triangle == t) { |  | ||||||
| 	          val p1 = pNode.point |  | ||||||
| 	          val p2 = pNode.prev.point |  | ||||||
| 	          T1.foreach(tri => if(tri.contains(p1, p2)) pNode.prev.triangle = tri) |  | ||||||
| 	          T2.foreach(tri => if(tri.contains(p1, p2)) pNode.prev.triangle = tri) |  | ||||||
| 	        }  |  | ||||||
|         } |  | ||||||
|        |        | ||||||
|  |       if(sNode != null && eNode != null) { | ||||||
|  |         first = aFront.constrainedEdge(sNode, eNode, T1, T2) | ||||||
|  |       } else { | ||||||
|  |         val qNode = if(sNode == null) eNode else sNode | ||||||
|  |         first = aFront.constrainedEdge(qNode, tList, T1, T2) | ||||||
|       } |       } | ||||||
|       |       | ||||||
|       // Update neighbors |       // Update neighbors | ||||||
| @@ -275,7 +263,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|        T2.first.mark(point1, point2) |        T2.first.mark(point1, point2) | ||||||
|         |         | ||||||
|        // Double check returning T2.first vs T1.first       |        // Double check returning T2.first vs T1.first       | ||||||
|        T2.first |        first | ||||||
|  |  | ||||||
|     } else if(firstTriangle == null) { |     } else if(firstTriangle == null) { | ||||||
|       |       | ||||||
| @@ -283,6 +271,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|       // Apply constraint; traverse the AFront, and build triangles |       // Apply constraint; traverse the AFront, and build triangles | ||||||
|        |        | ||||||
|       val ahead = (edge.p.x > edge.q.x) |       val ahead = (edge.p.x > edge.q.x) | ||||||
|  |        | ||||||
|       val point1 = if(ahead) edge.q else edge.p |       val point1 = if(ahead) edge.q else edge.p | ||||||
|       val point2 = if(ahead) edge.p else edge.q |       val point2 = if(ahead) edge.p else edge.q | ||||||
|        |        | ||||||
| @@ -310,7 +299,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|       triangulate(points.toArray, endPoints, T) |       triangulate(points.toArray, endPoints, T) | ||||||
|        |        | ||||||
|       // Update advancing front  |       // Update advancing front  | ||||||
|       aFront -= (first, node.prev, T.first) |       aFront link (first, node, T.first) | ||||||
|        |        | ||||||
|       // Update neighbors |       // Update neighbors | ||||||
|       edgeNeighbors(nTriangles, T) |       edgeNeighbors(nTriangles, T) | ||||||
| @@ -318,6 +307,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|        // Mark constrained edge |        // Mark constrained edge | ||||||
|       T.first mark(edge.p, edge.q) |       T.first mark(edge.p, edge.q) | ||||||
|        |        | ||||||
|  |       // Return original triangle | ||||||
|       triangle |       triangle | ||||||
|        |        | ||||||
|     } else {  |     } else {  | ||||||
| @@ -347,9 +337,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|      |      | ||||||
|     val a = ab.first |     val a = ab.first | ||||||
|     val b = ab.last |     val b = ab.last | ||||||
|  |     var c = if(!P.isEmpty) P.first else null | ||||||
|      |      | ||||||
|     if(P.size > 1) { |     if(P.size > 1) { | ||||||
|       var c = P.first |  | ||||||
|       var i = 0 |       var i = 0 | ||||||
|       for(j <- 1 until P.size) { |       for(j <- 1 until P.size) { | ||||||
|         if(illegal(a, c, b, P(j))) { |         if(illegal(a, c, b, P(j))) { | ||||||
| @@ -358,13 +348,16 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | |||||||
|         }  |         }  | ||||||
|       } |       } | ||||||
|       val PE = P.slice(0, i) |       val PE = P.slice(0, i) | ||||||
|       val PD = P.slice(i, P.size-1) |       val PD = P.slice(i+1, P.size) | ||||||
|       triangulate(PE, List(a, c), T) |       triangulate(PE, List(a, c), T) | ||||||
|       triangulate(PD, List(c, b), T) |       triangulate(PD, List(c, b), T) | ||||||
|     }  |     }  | ||||||
|      |      | ||||||
|     if(!P.isEmpty) { |     if(!P.isEmpty) { | ||||||
|       val points = Array(a, P.first, b) |       val left = if(Util.orient(a, b, c) > 0) true else false | ||||||
|  |       val p2 = if(left) c else b | ||||||
|  |       val p3 = if(left) b else c | ||||||
|  |       val points = Array(a, p2, p3) | ||||||
|       T += new Triangle(points) |       T += new Triangle(points) | ||||||
|       mesh.map += T.last |       mesh.map += T.last | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -49,28 +49,14 @@ class Triangle(val points: Array[Point]) { | |||||||
|   var clean = false |   var clean = false | ||||||
|    |    | ||||||
|   // Update neighbor pointers |   // Update neighbor pointers | ||||||
|   // Debug version |   private def markNeighbor(p1: Point, p2: Point, t: Triangle) {     | ||||||
|   def markNeighbor(p1: Point, p2: Point, triangle: Triangle, debug: HashSet[Triangle]) { |     assert(t != this, "self-pointer error") | ||||||
|     if((p1 == points(2) && p2 == points(1)) || (p1 == points(1) && p2 == points(2)))  |     if((p1 == points(2) && p2 == points(1)) || (p1 == points(1) && p2 == points(2)))  | ||||||
|       neighbors(0) = triangle  |       neighbors(0) = t  | ||||||
|     else if((p1 == points(0) && p2 == points(2)) || (p1 == points(2) && p2 == points(0))) |     else if((p1 == points(0) && p2 == points(2)) || (p1 == points(2) && p2 == points(0))) | ||||||
|       neighbors(1) = triangle |       neighbors(1) = t | ||||||
|     else if((p1 == points(0) && p2 == points(1)) || (p1 == points(1) && p2 == points(0))) |     else if((p1 == points(0) && p2 == points(1)) || (p1 == points(1) && p2 == points(0))) | ||||||
|       neighbors(2) = triangle |       neighbors(2) = t | ||||||
|     else { |  | ||||||
|       debug += triangle |  | ||||||
|       println("Neighbor pointer ERROR!") |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|    |  | ||||||
|   // Update neighbor pointers |  | ||||||
|   private def markNeighbor(p1: Point, p2: Point, triangle: Triangle) {     |  | ||||||
|     if((p1 == points(2) && p2 == points(1)) || (p1 == points(1) && p2 == points(2)))  |  | ||||||
|       neighbors(0) = triangle  |  | ||||||
|     else if((p1 == points(0) && p2 == points(2)) || (p1 == points(2) && p2 == points(0))) |  | ||||||
|       neighbors(1) = triangle |  | ||||||
|     else if((p1 == points(0) && p2 == points(1)) || (p1 == points(1) && p2 == points(0))) |  | ||||||
|       neighbors(2) = triangle |  | ||||||
|     else { |     else { | ||||||
|       throw new Exception("Neighbor pointer error, please report!") |       throw new Exception("Neighbor pointer error, please report!") | ||||||
|     } |     } | ||||||
| @@ -78,6 +64,7 @@ class Triangle(val points: Array[Point]) { | |||||||
|    |    | ||||||
|   /* Exhaustive search to update neighbor pointers */ |   /* Exhaustive search to update neighbor pointers */ | ||||||
|   def markNeighbor(t: Triangle) { |   def markNeighbor(t: Triangle) { | ||||||
|  |     assert(t != this, "self-pointer error") | ||||||
|     if (t.contains(points(1), points(2))) { |     if (t.contains(points(1), points(2))) { | ||||||
|       neighbors(0) = t |       neighbors(0) = t | ||||||
|       t.markNeighbor(points(1), points(2), this) |       t.markNeighbor(points(1), points(2), this) | ||||||
| @@ -95,13 +82,16 @@ class Triangle(val points: Array[Point]) { | |||||||
|   } |   } | ||||||
|    |    | ||||||
|   def oppositePoint(t: Triangle): Point = { |   def oppositePoint(t: Triangle): Point = { | ||||||
|  |     assert(t != this, "self-pointer error") | ||||||
|     if(points(0) == t.points(1))  |     if(points(0) == t.points(1))  | ||||||
|       points(1) |       points(1) | ||||||
|     else if(points(0) == t.points(2)) |     else if(points(0) == t.points(2)) | ||||||
|       points(2) |       points(2) | ||||||
|     else if((points(2) == t.points(1) && points(1) == t.points(2)) || (points(1) == t.points(1) && points(2) == t.points(2))) |     else if(contains(t.points(1), t.points(2))) | ||||||
|       points(0) |       points(0) | ||||||
|     else { |     else { | ||||||
|  |       t.printDebug | ||||||
|  |       printDebug | ||||||
|       throw new Exception("Point location error, please report") |       throw new Exception("Point location error, please report") | ||||||
|     } |     } | ||||||
|      |      | ||||||
|   | |||||||
| @@ -49,6 +49,18 @@ object Util { | |||||||
|      |      | ||||||
|   } |   } | ||||||
|    |    | ||||||
|  |   // Return: positive if point p is left of ab | ||||||
|  |   //         negative if point p is right of ab | ||||||
|  |   //         zero if points are colinear | ||||||
|  |   // See: http://www-2.cs.cmu.edu/~quake/robust.html | ||||||
|  |   def orient(b: Point, a: Point, p: Point): Float = { | ||||||
|  |     val acx = a.x - p.x | ||||||
|  |     val bcx = b.x - p.x | ||||||
|  |     val acy = a.y - p.y | ||||||
|  |     val bcy = b.y - p.y | ||||||
|  |     acx * bcy - acy * bcx   | ||||||
|  |   } | ||||||
|  |    | ||||||
| } | } | ||||||
|  |  | ||||||
| /** The object <code>Random</code> offers a default implementation | /** The object <code>Random</code> offers a default implementation | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zzzzrrr
					zzzzrrr