mirror of
				https://github.com/jhasse/poly2tri.git
				synced 2025-10-31 12:27:10 +01:00 
			
		
		
		
	bug hunting
This commit is contained in:
		| @@ -170,7 +170,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { | ||||
| 	    }) | ||||
|     | ||||
|    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 => { | ||||
| 	     val triangle = new Polygon | ||||
| 		 triangle.addPoint(t.points(0).x, t.points(0).y) | ||||
|   | ||||
| @@ -30,6 +30,8 @@ | ||||
|  */ | ||||
| package org.poly2tri.cdt | ||||
|  | ||||
| import scala.collection.mutable.ArrayBuffer | ||||
|  | ||||
| import shapes.{Point, Triangle} | ||||
|  | ||||
| // Advancing front | ||||
| @@ -87,7 +89,94 @@ class AFront(iTriangle: Triangle) { | ||||
|     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 | ||||
|   } | ||||
|    | ||||
|   def link(node1: Node, node2: Node, t: Triangle) { | ||||
|     node1.next = node2 | ||||
|     node2.prev = node1 | ||||
|     node1.triangle = t | ||||
|   } | ||||
|    | ||||
|   def basin(node: Node) { | ||||
|     if(node.next != tail) { | ||||
|       val p1 = node.point | ||||
|   | ||||
| @@ -128,6 +128,18 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | ||||
|   // Finalize triangulation | ||||
|   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  | ||||
|   private def sweep { | ||||
|      | ||||
| @@ -136,7 +148,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | ||||
|       // Process Point event | ||||
|       var triangle = pointEvent(point) | ||||
|       // 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} | ||||
|     } | ||||
|   }   | ||||
| @@ -231,39 +243,15 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | ||||
|        | ||||
|       // Update advancing front | ||||
|    | ||||
|       val qNode = aFront.locatePoint(edge.q)   | ||||
|       val pNode = aFront.locatePoint(edge.p) | ||||
|        | ||||
|       // 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) | ||||
| 	        }  | ||||
|         } | ||||
|       var first: Triangle = null | ||||
|       val sNode = aFront.locatePoint(point1)   | ||||
|       val eNode = aFront.locatePoint(point2) | ||||
|        | ||||
|       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 | ||||
| @@ -275,7 +263,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | ||||
|        T2.first.mark(point1, point2) | ||||
|         | ||||
|        // Double check returning T2.first vs T1.first       | ||||
|        T2.first | ||||
|        first | ||||
|  | ||||
|     } 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 | ||||
|        | ||||
|       val ahead = (edge.p.x > edge.q.x) | ||||
|        | ||||
|       val point1 = if(ahead) edge.q else edge.p | ||||
|       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) | ||||
|        | ||||
|       // Update advancing front  | ||||
|       aFront -= (first, node.prev, T.first) | ||||
|       aFront link (first, node, T.first) | ||||
|        | ||||
|       // Update neighbors | ||||
|       edgeNeighbors(nTriangles, T) | ||||
| @@ -318,6 +307,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | ||||
|        // Mark constrained edge | ||||
|       T.first mark(edge.p, edge.q) | ||||
|        | ||||
|       // Return original triangle | ||||
|       triangle | ||||
|        | ||||
|     } else {  | ||||
| @@ -347,9 +337,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian | ||||
|      | ||||
|     val a = ab.first | ||||
|     val b = ab.last | ||||
|     var c = if(!P.isEmpty) P.first else null | ||||
|      | ||||
|     if(P.size > 1) { | ||||
|       var c = P.first | ||||
|       var i = 0 | ||||
|       for(j <- 1 until P.size) { | ||||
|         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 PD = P.slice(i, P.size-1) | ||||
|       val PD = P.slice(i+1, P.size) | ||||
|       triangulate(PE, List(a, c), T) | ||||
|       triangulate(PD, List(c, b), T) | ||||
|     }  | ||||
|      | ||||
|     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) | ||||
|       mesh.map += T.last | ||||
|     } | ||||
|   | ||||
| @@ -49,28 +49,14 @@ class Triangle(val points: Array[Point]) { | ||||
|   var clean = false | ||||
|    | ||||
|   // Update neighbor pointers | ||||
|   // Debug version | ||||
|   def markNeighbor(p1: Point, p2: Point, triangle: Triangle, debug: HashSet[Triangle]) { | ||||
|   private def markNeighbor(p1: Point, p2: Point, t: Triangle) {     | ||||
|     assert(t != this, "self-pointer error") | ||||
|     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))) | ||||
|       neighbors(1) = triangle | ||||
|       neighbors(1) = t | ||||
|     else if((p1 == points(0) && p2 == points(1)) || (p1 == points(1) && p2 == points(0))) | ||||
|       neighbors(2) = triangle | ||||
|     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 | ||||
|       neighbors(2) = t | ||||
|     else { | ||||
|       throw new Exception("Neighbor pointer error, please report!") | ||||
|     } | ||||
| @@ -78,6 +64,7 @@ class Triangle(val points: Array[Point]) { | ||||
|    | ||||
|   /* Exhaustive search to update neighbor pointers */ | ||||
|   def markNeighbor(t: Triangle) { | ||||
|     assert(t != this, "self-pointer error") | ||||
|     if (t.contains(points(1), points(2))) { | ||||
|       neighbors(0) = t | ||||
|       t.markNeighbor(points(1), points(2), this) | ||||
| @@ -95,13 +82,16 @@ class Triangle(val points: Array[Point]) { | ||||
|   } | ||||
|    | ||||
|   def oppositePoint(t: Triangle): Point = { | ||||
|     assert(t != this, "self-pointer error") | ||||
|     if(points(0) == t.points(1))  | ||||
|       points(1) | ||||
|     else if(points(0) == t.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) | ||||
|     else { | ||||
|       t.printDebug | ||||
|       printDebug | ||||
|       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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 zzzzrrr
					zzzzrrr