bug hunting

This commit is contained in:
Mason 2009-08-06 07:33:35 -04:00
parent 2510a728a7
commit 0db13d6586
3 changed files with 98 additions and 36 deletions

View File

@ -37,11 +37,13 @@ class AFront(iTriangle: Triangle) {
// Doubly linked list // Doubly linked list
var head = new Node(iTriangle.points(1), iTriangle) 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) var tail = new Node(iTriangle.points(2), null)
head.next.next = tail head.next = middle
tail.prev = head.next middle.next = tail
middle.prev = head
tail.prev = middle
// TODO: Use Red-Black Tree or Interval Tree for better search performance! // TODO: Use Red-Black Tree or Interval Tree for better search performance!
def locate(point: Point): Node = { def locate(point: Point): Node = {

View File

@ -124,12 +124,12 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// Implement sweep-line // Implement sweep-line
private def sweep { private def sweep {
for(i <- 1 until points.size) { for(i <- 1 until 7 /*points.size*/) {
val point = points(i) val point = points(i)
// Process Point event // Process Point event
val triangle = pointEvent(point) val triangle = pointEvent(point)
// Process edge events // 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 // Projected point coincides with existing point; create two triangles
if(point.x == node.point.x && node.prev != null) { if(point.x == node.point.x && node.prev != null) {
val rPts = Array(point, node.point, node.next.point) val rPts = Array(point, node.point, node.next.point)
val rNeighbors = Array(node.triangle, null, null) val rNeighbors = Array(node.triangle, null, null)
val rTriangle = new Triangle(rPts, rNeighbors) 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 mesh.map += rTriangle
// Legalize new triangles // Legalize new triangles
legalization(rTriangle, rTriangle.neighbors(0)) val rLegal = legalization(rTriangle, rTriangle.neighbors(0))
legalization(lTriangle, lTriangle.neighbors(2)) val lLegal = legalization(lTriangle, lTriangle.neighbors(2))
var scanNode: Node = null
// Update neighbor pointers
node.triangle.updateNeighbors(node.point, node.next.point, lTriangle)
node.prev.triangle.updateNeighbors(node.point, node.prev.point, rTriangle)
// Update advancing front // Update advancing front
val newNode = aFront.insert(point, rTriangle, node) if(rLegal) {
aFront -= (node.prev, node, rTriangle) 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 // Fill in adjacent triangles if required
scanAFront(newNode) //scanAFront(scanNode)
scanNode.triangle
newNode.triangle
} else { } else {
// Projected point hits advancing front; create new triangle // Projected point hits advancing front; create new triangle
val cwPoint = node.next.point val cwPoint = node.next.point
val ccwPoint = node.point val ccwPoint = node.point
@ -181,15 +198,24 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
mesh.map += triangle mesh.map += triangle
// Legalize // Legalize
legalization(triangle, nTri) val legal = legalization(triangle, nTri)
// Update neighbor pointers var scanNode: Node = null
nTri.updateNeighbors(triangle.points(1), triangle.points(2), triangle)
// Update advancing front // 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 // Fill in adjacent triangles if required
scanAFront(newNode) //scanAFront(scanNode)
scanNode.triangle
newNode.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) triangles += triangles.last.findNeighbor(edge.p - edge.q)
// TODO: fix triangles.last == null bug! // TODO: fix triangles.last == null bug!
// This happens in the bird demo... // This happens in the bird & nazca monkey demo...
if(triangles.last == null) if(triangles.last == null)
triangles -= triangles.last 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 // Fill empty space with a triangle
def fill(node: Node): Double = { def fill(node: Node): Double = {
val a = (node.prev.point - node.point) val a = (node.prev.point - node.point)
val b = (node.next.point - node.point) val b = (node.next.point - node.point)
val angle = Math.abs(Math.atan2(a cross b, a dot b)) 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 neighbors = Array(node.triangle, null, node.prev.triangle)
val triangle = new Triangle(points, neighbors) val triangle = new Triangle(points, neighbors)
// Update neighbor pointers // Update neighbor pointers
node.prev.triangle.updateNeighbors(triangle.points(0), triangle.points(1), triangle) node.prev.triangle.updateNeighbors(triangle.points(0), triangle.points(1), triangle, mesh.debug)
node.triangle.updateNeighbors(triangle.points(1), triangle.points(2), triangle) node.triangle.updateNeighbors(triangle.points(1), triangle.points(2), triangle, mesh.debug)
mesh.map += triangle mesh.map += triangle
aFront -= (node.prev, node, 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 // Ensure adjacent triangles are legal
// If illegal, flip edges and update triangle's pointers // 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 val oPoint = t2 oppositePoint t1
if(illegal(t1.points(1), oPoint, t1.points(2), t1.points(0))) { if(illegal(t1.points(1), oPoint, t1.points(2), t1.points(0))) {
println("illegal")
// Flip edges and rotate everything clockwise // Flip edges and rotate everything clockwise
val point = t1.points(0) val point = t1.points(0)
t1.legalize(oPoint) 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(1) = t1
t2.neighbors(2) = null t2.neighbors(2) = null
} }
false
} else {
true
} }
} }

View File

@ -30,6 +30,7 @@
*/ */
package org.poly2tri.shapes package org.poly2tri.shapes
import scala.collection.mutable.HashSet
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
// Triangle-based data structures are know to have better performance than quad-edge structures // 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) val edges = new Array[Boolean](3)
// Update neighbor pointers // 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))) if((ccwPoint == points(2) && cwPoint == points(1)) || (ccwPoint == points(1) && cwPoint == points(2)))
neighbors(0) = triangle 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 neighbors(1) = triangle
else else if((ccwPoint == points(1) && cwPoint == points(0)) || (ccwPoint == points(0) && cwPoint == points(1)))
neighbors(2) = triangle neighbors(2) = triangle
else {
mesh += this
throw new Exception("neighbor error")
}
} }
def oppositePoint(t: Triangle) = { def oppositePoint(t: Triangle) = {
@ -127,7 +132,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
acx * bcy - acy * bcx acx * bcy - acy * bcx
} }
// The neighbor CW to given point // The neighbor clockwise to given point
def neighborCW(point: Point): Triangle = { def neighborCW(point: Point): Triangle = {
if(point == points(0)) { if(point == points(0)) {
neighbors(2) neighbors(2)
@ -137,7 +142,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
neighbors(1) neighbors(1)
} }
// The neighbor CW to given point // The neighbor counter-clockwise to given point
def neighborCCW(point: Point): Triangle = { def neighborCCW(point: Point): Triangle = {
if(point == points(0)) { if(point == points(0)) {
neighbors(1) neighbors(1)
@ -147,6 +152,32 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
neighbors(0) 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) // Legalized triangle by rotating clockwise around point(0)
def legalize(oPoint: Point) { def legalize(oPoint: Point) {
points(1) = points(0) points(1) = points(0)