diff --git a/src/org/poly2tri/Poly2Tri.scala b/src/org/poly2tri/Poly2Tri.scala index 90852b9..17d0ba0 100644 --- a/src/org/poly2tri/Poly2Tri.scala +++ b/src/org/poly2tri/Poly2Tri.scala @@ -76,6 +76,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { var hiLighter = 0 var drawEarClip = false var drawCDT = true + var drawcdtMesh = true val nazcaMonkey = "data/nazca_monkey.dat" val bird = "data/bird.dat" @@ -84,7 +85,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { val strange = "data/strange.dat" val i18 = "data/i.18" - var currentModel = star + var currentModel = i18 var mouseButton = 0 var mousePressed = false @@ -167,7 +168,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { }) if(drawCDT) { - slCDT.triangles.foreach( t => { + val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles + draw.foreach( t => { val triangle = new Polygon triangle.addPoint(t.points(0).x, t.points(0).y) triangle.addPoint(t.points(1).x, t.points(1).y) @@ -264,6 +266,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { if(c == '5') selectModel(star) if(c == '6') selectModel(i18) if(c == 's') drawSegs = !drawSegs + if(c == 'c') drawcdtMesh = !drawcdtMesh //if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)} } diff --git a/src/org/poly2tri/cdt/CDT.scala b/src/org/poly2tri/cdt/CDT.scala index 96998d9..60225f5 100644 --- a/src/org/poly2tri/cdt/CDT.scala +++ b/src/org/poly2tri/cdt/CDT.scala @@ -107,7 +107,7 @@ object CDT { class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Triangle) { // Triangle list - def triangles = mesh.map + def triangles = mesh.triangles def triangleMesh = mesh.map def debugTriangles = mesh.debug @@ -119,6 +119,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian private val PI_2 = Math.Pi/2 private val PI_34 = Math.Pi*3/4 + // Triangle used to clean interior + var cleanTri: Triangle = null + // Sweep points; build mesh sweep // Finalize triangulation @@ -126,7 +129,6 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian // Implement sweep-line private def sweep { - //var cTri: Triangle = null for(i <- 1 until points.size) { val point = points(i) // Process Point event @@ -139,12 +141,18 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian } // Process edge events point.edges.foreach(e => edgeEvent(e, triangle)) - //if(i == 7) {cTri = triangle; mesh.debug += cTri} + //if(i == 7) {cleanTri = triangle; mesh.debug += cleanTri} } - //mesh clean cTri - //mesh.map.foreach(m => m.edges.foreach(e => if(e) mesh.debug += m)) } + // Final step in the sweep-line CDT algo + // Clean exterior triangles + private def finalization { + mesh.map.foreach(m => m.markEdges) + mesh clean cleanTri + //mesh.map.foreach(m => m.edges.foreach(e => if(e) mesh.debug += m)) + } + // Point event private def pointEvent(point: Point): Triangle = { @@ -276,11 +284,14 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian // Mark constrained edges val dEdge = new Segment(point1, point2) - T1.first mark dEdge - T2.first mark dEdge + T1.first mark(point1, point2) + T2.first mark(point1, point2) + + //TODO update neighbor pointers } else if(firstTriangle == null) { + // NOTE: So far this only works for single triangles // No triangles are intersected by the edge; edge must lie outside the mesh // Apply constraint; traverse the AFront, and build triangles @@ -292,29 +303,45 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian var node = aFront.locate(point1) val first = node + node = node.next + while(node.point != point2) { points += node.point node = node.next } + //assert(points.size == 1, "not implemented yet, points = " + points.size) + + val endPoints = if(ahead) List(point2, point1) else List(point1, point2) + // STEP 3: Triangulate empty areas. val T = new ArrayBuffer[Triangle] - triangulate(points.toArray, List(point1, point2), T) + triangulate(points.toArray, endPoints, T) // Update advancing front - first.triangle = T.first - first.next = node - node.prev = first + aFront -= (first, node.prev, T.first) + + // Update neigbor pointers + if(ahead) { + T.first.neighbors(2) = node.prev.triangle; + T.first.neighbors(0) = first.triangle + node.prev.triangle.updateNeighbors(T.first.points(0), T.first.points(1), T.first, mesh.debug) + first.triangle.updateNeighbors(T.first.points(1), T.first.points(2), T.first, mesh.debug) + } else { + T.first.neighbors(2) = first.triangle; + T.first.neighbors(0) = node.prev.triangle + node.prev.triangle.updateNeighbors(T.first.points(1), T.first.points(2), T.first, mesh.debug) + first.triangle.updateNeighbors(T.first.points(0), T.first.points(1), T.first, mesh.debug) + } + // Mark constrained edge + T.first mark(edge.p, edge.q) + + + } else { // Mark constrained edge - val dEdge = new Segment(point1, point2) - T.first mark dEdge - } - - // Mark constrained edge - if(contains) - firstTriangle mark edge - + firstTriangle mark(edge.p, edge.q) + } } // Marc Vigo Anglada's triangulate pseudo-polygon algo @@ -347,7 +374,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian } // Scan left and right along AFront to fill holes - def scanAFront(n: Node) { + private def scanAFront(n: Node) { var node = n.next // Update right @@ -371,7 +398,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian } // Fill empty space with a triangle - def fill(node: Node): Double = { + private def fill(node: Node): Double = { val a = (node.prev.point - node.point) val b = (node.next.point - node.point) val angle = Math.abs(Math.atan2(a cross b, a dot b)) @@ -423,7 +450,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian val oPoint = t2 oppositePoint t1 if(illegal(t1.points(1), oPoint, t1.points(2), t1.points(0))) { - + // Prevent creation of collinear traingles val c1 = t1.collinear(oPoint) val c2 = t2.collinear(oPoint, t1.points(0)) @@ -453,11 +480,5 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian true } true - } - - // Final step in the sweep-line CDT algo - private def finalization { - - } - + } } diff --git a/src/org/poly2tri/cdt/Mesh.scala b/src/org/poly2tri/cdt/Mesh.scala index 09f2410..bb5f884 100644 --- a/src/org/poly2tri/cdt/Mesh.scala +++ b/src/org/poly2tri/cdt/Mesh.scala @@ -44,7 +44,7 @@ class Mesh(initialTriangle: Triangle) { // Recursively collect triangles def clean(triangle: Triangle) { - if(triangle != null && triangle.clean == false) { + if(triangle != null && !triangle.clean) { triangle.clean = true triangles += triangle if(!triangle.edges(0)) diff --git a/src/org/poly2tri/shapes/Triangle.scala b/src/org/poly2tri/shapes/Triangle.scala index 64a51f4..94e461e 100644 --- a/src/org/poly2tri/shapes/Triangle.scala +++ b/src/org/poly2tri/shapes/Triangle.scala @@ -56,7 +56,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { neighbors(2) = triangle else { debug += triangle - throw new Exception("Neighbor pointer error, please report!") + //throw new Exception("Neighbor pointer error, please report!") } } @@ -267,22 +267,37 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { ki = points(0) - points(2) } - def mark(e: Segment) { - markEdge(e) - markNeighbors(e) + // Initial mark edges sweep + def mark(p: Point, q: Point) { + if(contains(p) && contains(q)) { + markEdge(p, q) + markNeighbors(p, q) + } } - private def markNeighbors(e: Segment) = neighbors.foreach(n => if(n != null) n.markEdge(e)) + // Finalize edge marking + def markEdges { + for(i <- 0 to 2) + if(edges(i)) + i match { + case 0 => if(neighbors(0) != null) neighbors(0).markEdge(points(1), points(2)) + case 1 => if(neighbors(1) != null) neighbors(1).markEdge(points(0), points(2)) + case _ => if(neighbors(2) != null) neighbors(2).markEdge(points(0), points(1)) + } + } + + // Mark neighbor's edge + private def markNeighbors(p: Point, q: Point) = neighbors.foreach(n => if(n != null) n.markEdge(p, q)) // Mark edge as constrained - private def markEdge(e: Segment) { - if((e.q == points(0) && e.p == points(1)) || (e.q == points(1) && e.p == points(0))) { + private def markEdge(p: Point, q: Point) { + if((q == points(0) && p == points(1)) || (q == points(1) && p == points(0))) { edges(2) = true - } else if ((e.q == points(0) && e.p == points(2)) || (e.q == points(2) && e.p == points(0))) { + } else if ((q == points(0) && p == points(2)) || (q == points(2) && p == points(0))) { edges(1) = true - } else { + } else if ((q == points(1) && p == points(2)) || (q == points(2) && p == points(1))){ edges(0) = true - } + } } }