From 0db13d658655a1603f9af09d1ef4efb9357eaff5 Mon Sep 17 00:00:00 2001 From: Mason Date: Thu, 6 Aug 2009 07:33:35 -0400 Subject: [PATCH] bug hunting --- src/org/poly2tri/cdt/AFront.scala | 8 ++- src/org/poly2tri/cdt/CDT.scala | 85 +++++++++++++++++--------- src/org/poly2tri/shapes/Triangle.scala | 41 +++++++++++-- 3 files changed, 98 insertions(+), 36 deletions(-) diff --git a/src/org/poly2tri/cdt/AFront.scala b/src/org/poly2tri/cdt/AFront.scala index 8e3fa89..9f84575 100644 --- a/src/org/poly2tri/cdt/AFront.scala +++ b/src/org/poly2tri/cdt/AFront.scala @@ -37,11 +37,13 @@ class AFront(iTriangle: Triangle) { // Doubly linked list var head = new Node(iTriangle.points(1), iTriangle) - head.next = new Node(iTriangle.points(0), iTriangle) + val middle = new Node(iTriangle.points(0), iTriangle) var tail = new Node(iTriangle.points(2), null) - head.next.next = tail - tail.prev = head.next + head.next = middle + middle.next = tail + middle.prev = head + tail.prev = middle // TODO: Use Red-Black Tree or Interval Tree for better search performance! def locate(point: Point): Node = { diff --git a/src/org/poly2tri/cdt/CDT.scala b/src/org/poly2tri/cdt/CDT.scala index 51651a2..bc57445 100644 --- a/src/org/poly2tri/cdt/CDT.scala +++ b/src/org/poly2tri/cdt/CDT.scala @@ -124,12 +124,12 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian // Implement sweep-line private def sweep { - for(i <- 1 until points.size) { + for(i <- 1 until 7 /*points.size*/) { val point = points(i) // Process Point event val triangle = pointEvent(point) // Process edge events - point.edges.foreach(e => if(!triangle.contains(e)) edgeEvent(e, triangle)) + point.edges.foreach(e => edgeEvent(e, triangle)) } } @@ -140,7 +140,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian // Projected point coincides with existing point; create two triangles if(point.x == node.point.x && node.prev != null) { - + val rPts = Array(point, node.point, node.next.point) val rNeighbors = Array(node.triangle, null, null) val rTriangle = new Triangle(rPts, rNeighbors) @@ -154,22 +154,39 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian mesh.map += rTriangle // Legalize new triangles - legalization(rTriangle, rTriangle.neighbors(0)) - legalization(lTriangle, lTriangle.neighbors(2)) - - // Update neighbor pointers - node.triangle.updateNeighbors(node.point, node.next.point, lTriangle) - node.prev.triangle.updateNeighbors(node.point, node.prev.point, rTriangle) + val rLegal = legalization(rTriangle, rTriangle.neighbors(0)) + val lLegal = legalization(lTriangle, lTriangle.neighbors(2)) + var scanNode: Node = null // Update advancing front - val newNode = aFront.insert(point, rTriangle, node) - aFront -= (node.prev, node, rTriangle) + if(rLegal) { + println("rLegal") + // Update neighbors + node.triangle.updateNeighbors(rTriangle.points(1), rTriangle.points(2), rTriangle, mesh.debug) + scanNode = aFront.insert(point, rTriangle, node) + } else { + println("rIllegal") + scanNode = new Node(rTriangle.points(1), rTriangle) + scanNode.next = node.next + node.next = scanNode + scanNode.prev = node + } + + // Update neighbor pointers + if(lLegal) { + println("lLegal") + node.prev.triangle.updateNeighbors(lTriangle.points(0), lTriangle.points(1), lTriangle, mesh.debug) + aFront -= (scanNode, node, lTriangle) + } else { + println("lIllegal") + } + // Fill in adjacent triangles if required - scanAFront(newNode) - - newNode.triangle - + //scanAFront(scanNode) + scanNode.triangle + } else { + // Projected point hits advancing front; create new triangle val cwPoint = node.next.point val ccwPoint = node.point @@ -181,15 +198,24 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian mesh.map += triangle // Legalize - legalization(triangle, nTri) - // Update neighbor pointers - nTri.updateNeighbors(triangle.points(1), triangle.points(2), triangle) + val legal = legalization(triangle, nTri) + var scanNode: Node = null + // Update advancing front - val newNode = aFront.insert(point, triangle, node) + if(legal) { + // Update neighbors + nTri.updateNeighbors(triangle.points(1), triangle.points(2), triangle, mesh.debug) + scanNode = aFront.insert(point, triangle, node) + } else { + scanNode = new Node(triangle.points(1), triangle) + scanNode.next = node.next + node.next = scanNode + scanNode.prev = node + } + // Fill in adjacent triangles if required - scanAFront(newNode) - - newNode.triangle + //scanAFront(scanNode) + scanNode.triangle } } @@ -210,7 +236,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian triangles += triangles.last.findNeighbor(edge.p - edge.q) // TODO: fix triangles.last == null bug! - // This happens in the bird demo... + // This happens in the bird & nazca monkey demo... if(triangles.last == null) triangles -= triangles.last @@ -342,7 +368,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian // Fill empty space with a triangle 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)) @@ -351,8 +377,8 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian val neighbors = Array(node.triangle, null, node.prev.triangle) val triangle = new Triangle(points, neighbors) // Update neighbor pointers - node.prev.triangle.updateNeighbors(triangle.points(0), triangle.points(1), triangle) - node.triangle.updateNeighbors(triangle.points(1), triangle.points(2), triangle) + node.prev.triangle.updateNeighbors(triangle.points(0), triangle.points(1), triangle, mesh.debug) + node.triangle.updateNeighbors(triangle.points(1), triangle.points(2), triangle, mesh.debug) mesh.map += triangle aFront -= (node.prev, node, triangle) } @@ -388,12 +414,12 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian // Ensure adjacent triangles are legal // If illegal, flip edges and update triangle's pointers - private def legalization(t1: Triangle, t2: Triangle) { + private def legalization(t1: Triangle, t2: Triangle): Boolean = { val oPoint = t2 oppositePoint t1 if(illegal(t1.points(1), oPoint, t1.points(2), t1.points(0))) { - + println("illegal") // Flip edges and rotate everything clockwise val point = t1.points(0) t1.legalize(oPoint) @@ -416,6 +442,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian t2.neighbors(1) = t1 t2.neighbors(2) = null } + false + } else { + true } } diff --git a/src/org/poly2tri/shapes/Triangle.scala b/src/org/poly2tri/shapes/Triangle.scala index 5a6ca10..265d4c9 100644 --- a/src/org/poly2tri/shapes/Triangle.scala +++ b/src/org/poly2tri/shapes/Triangle.scala @@ -30,6 +30,7 @@ */ package org.poly2tri.shapes +import scala.collection.mutable.HashSet import scala.collection.mutable.ArrayBuffer // Triangle-based data structures are know to have better performance than quad-edge structures @@ -41,13 +42,17 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { val edges = new Array[Boolean](3) // Update neighbor pointers - def updateNeighbors(ccwPoint: Point, cwPoint: Point, triangle: Triangle) { + def updateNeighbors(ccwPoint: Point, cwPoint: Point, triangle: Triangle, mesh: HashSet[Triangle]) { if((ccwPoint == points(2) && cwPoint == points(1)) || (ccwPoint == points(1) && cwPoint == points(2))) neighbors(0) = triangle - else if((ccwPoint == points(0) && cwPoint == points(2)) || (ccwPoint == points(0) && cwPoint == points(2))) + else if((ccwPoint == points(0) && cwPoint == points(2)) || (ccwPoint == points(2) && cwPoint == points(0))) neighbors(1) = triangle - else + else if((ccwPoint == points(1) && cwPoint == points(0)) || (ccwPoint == points(0) && cwPoint == points(1))) neighbors(2) = triangle + else { + mesh += this + throw new Exception("neighbor error") + } } def oppositePoint(t: Triangle) = { @@ -127,7 +132,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { acx * bcy - acy * bcx } - // The neighbor CW to given point + // The neighbor clockwise to given point def neighborCW(point: Point): Triangle = { if(point == points(0)) { neighbors(2) @@ -137,7 +142,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { neighbors(1) } - // The neighbor CW to given point + // The neighbor counter-clockwise to given point def neighborCCW(point: Point): Triangle = { if(point == points(0)) { neighbors(1) @@ -147,6 +152,32 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { neighbors(0) } + // The point counter-clockwise to given point + def pointCCW(point: Point): Point = { + if(point == points(0)) { + points(1) + } else if(point == points(1)) { + points(2) + } else if(point == points(2)){ + points(0) + } else { + throw new Exception("point location error") + } + } + + // The point counter-clockwise to given point + def pointCW(point: Point): Point = { + if(point == points(0)) { + points(2) + } else if(point == points(1)) { + points(0) + } else if(point == points(2)){ + points(1) + } else { + throw new Exception("point location error") + } + } + // Legalized triangle by rotating clockwise around point(0) def legalize(oPoint: Point) { points(1) = points(0)