bug hunting

This commit is contained in:
zzzzrrr 2009-08-03 17:01:16 -04:00
parent 6228342454
commit 6517956535
6 changed files with 86 additions and 28 deletions

View File

@ -160,6 +160,14 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
g.setColor(red) g.setColor(red)
g.draw(triangle) g.draw(triangle)
}) })
slCDT.debugTriangles.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)
triangle.addPoint(t.points(2).x, t.points(2).y)
g.setColor(blue)
g.draw(triangle)
})
} }
if(drawSegs) { if(drawSegs) {

View File

@ -47,11 +47,11 @@ class AFront(iTriangle: Triangle) {
def locate(point: Point): Node = { def locate(point: Point): Node = {
var node = head var node = head
while(node != tail) { while(node != tail) {
if(point.x >= node.point.x && point.x <= node.next.point.x) if(point.x >= node.point.x && point.x < node.next.point.x)
return node return node
node = node.next node = node.next
} }
throw new Exception("Advancing front error") throw new Exception("Advancing front error: point not found")
} }
def insert(tuple: Tuple3[Point, Triangle, Node]) = { def insert(tuple: Tuple3[Point, Triangle, Node]) = {

View File

@ -108,6 +108,8 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// Triangle list // Triangle list
def triangles = mesh.map def triangles = mesh.map
def debugTriangles = mesh.debug
// The triangle mesh // The triangle mesh
private val mesh = new Mesh(iTriangle) private val mesh = new Mesh(iTriangle)
// Advancing front // Advancing front
@ -122,13 +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 10 /*points.size*/) {
val point = points(i) val point = points(i)
// Process Point event // Process Point event
//val triangle = val triangle = pointEvent(point)
pointEvent(point)
// Process edge events // Process edge events
//point.edges.foreach(e => edgeEvent(e, triangle)) point.edges.foreach(e => edgeEvent(e, triangle))
} }
} }
@ -136,6 +137,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
private def pointEvent(point: Point): Triangle = { private def pointEvent(point: Point): Triangle = {
val node = aFront.locate(point) val node = aFront.locate(point)
// Neightbor points (ccw & cw) and triangle(i) // Neightbor points (ccw & cw) and triangle(i)
val cwPoint = node.next.point val cwPoint = node.next.point
val ccwPoint = node.point val ccwPoint = node.point
@ -167,40 +169,76 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// STEP 1: Locate the first intersected triangle // STEP 1: Locate the first intersected triangle
val firstTriangle = triangle.locateFirst(edge) val firstTriangle = triangle.locateFirst(edge)
// STEP 2: Remove intersected triangles // STEP 2: Remove intersected triangles
if(firstTriangle != null && !firstTriangle.contains(edge)) { if(firstTriangle != null && !firstTriangle.contains(edge)) {
// Collect intersected triangles // Collect intersected triangles
val triangles = new ArrayBuffer[Triangle] val triangles = new ArrayBuffer[Triangle]
triangles += firstTriangle triangles += firstTriangle
val e = edge.p - edge.q
while(!triangles.last.contains(edge.p)) while(!triangles.last.contains(edge.p))
triangles += triangles.last.findNeighbor(edge.p - edge.q) triangles += triangles.last.findNeighbor(e)
// Remove from the mesh // Remove from the mesh
triangles.foreach(t => mesh.map -= t) //triangles.foreach(t => mesh.map -= t)
} else if(firstTriangle == null) { } else if(firstTriangle == null) {
// Traverse the AFront, and build triangle list // Traverse the AFront, and build triangle list
var node = aFront.locate(edge.q) var node = aFront.locate(edge.q)
node = node.next
val points = new ArrayBuffer[Point]
if(edge.p.x > edge.q.x) { if(edge.p.x > edge.q.x) {
// Search right // Search right
while(node.point != edge.p) { while(node.point != edge.p) {
// Collect points // Collect points
points += node.point
node = node.next node = node.next
} }
} else { } else {
// Search left // Search left
while(node.point != edge.p) { while(node.point != edge.p) {
// Collect points // Collect points
points += node.point
node = node.prev node = node.prev
} }
} }
val T = new ArrayBuffer[Triangle]
angladaTPD(points.toArray, List(edge.p, edge.q), T)
T.foreach(t => mesh.debug += t)
} }
// STEP 3: Triangulate empty areas. // STEP 3: Triangulate empty areas.
} }
// Marc Vigo Anglada's triangulatePseudopolygonDelaunay algo
def angladaTPD(P: Array[Point], ab: List[Point], T: ArrayBuffer[Triangle]) {
val a = ab.first
val b = ab.last
var c: Point = null
if(P.size > 1) {
c = P.first
var i = 0
for(j <- 1 until P.size) {
if(illegal(a, c, b, P(j))) {
c = P(j)
i = j
}
}
val PE = P.slice(0, i)
val PD = P.slice(i, P.size-1)
angladaTPD(PE, List(a, c), T)
angladaTPD(PD, List(c, b), T)
}
if(!P.isEmpty) {
c = P.first
val points = Array(a, b, c)
val neighbors = new Array[Triangle](3)
T += new Triangle(points, neighbors)
}
}
// Scan left and right along AFront to fill holes // Scan left and right along AFront to fill holes
def scan(n: Node) { def scan(n: Node) {
@ -231,11 +269,11 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
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))
if(angle <= PI_2) { if(angle <= PI_2) {
val points = Array(node.prev.point, node.next.point, node.point) val points = Array(node.prev.point, node.point, node.next.point)
val neighbors = Array(node.prev.triangle, null, node.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(1), triangle.points(2), triangle) node.prev.triangle.updateNeighbors(triangle.points(0), triangle.points(1), triangle)
node.triangle.updateNeighbors(triangle.points(1), triangle.points(2), triangle) node.triangle.updateNeighbors(triangle.points(1), triangle.points(2), triangle)
mesh.map += triangle mesh.map += triangle
aFront -= (node.prev, node, triangle) aFront -= (node.prev, node, triangle)
@ -250,7 +288,6 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val v3 = p1 - p4 val v3 = p1 - p4
val v4 = p3 - p4 val v4 = p3 - p4
if((v1 dot v2) < 0 && (v3 dot v4) < 0) if((v1 dot v2) < 0 && (v3 dot v4) < 0)
// swap the edge
true true
else else
false false
@ -267,8 +304,11 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
t2.points(1) = point t2.points(1) = point
t2.points(0) = t2.points(2) t2.points(0) = t2.points(2)
t2.points(2) = tmp t2.points(2) = tmp
// Rotate neighbors
t1.updatePoints
t2.updatePoints
// TODO: Rotate neighbors
println("legalize")
} }
private def finalization { private def finalization {

View File

@ -38,6 +38,7 @@ class Mesh(initialTriangle: Triangle) {
// Triangles that constitute the mesh // Triangles that constitute the mesh
val map = HashSet(initialTriangle) val map = HashSet(initialTriangle)
val debug = HashSet.empty[Triangle]
def addEdge(point:Point, triangle: Triangle) { def addEdge(point:Point, triangle: Triangle) {
/* /*

View File

@ -53,14 +53,13 @@ class Segment(var p: Point, var q: Point) {
// Update point edge list for CDT // Update point edge list for CDT
def updateEdge { def updateEdge {
if(q.y > p.y) { if(p.y > q.y) {
// For CDT we want q to be the point with > y // For CDT we want q to be the point with > y
// val tmp = p val tmp = p
//p = q p = q
//q = tmp q = tmp
q.edges += this
} }
q.edges += this
} }
} }

View File

@ -37,16 +37,21 @@ import scala.collection.mutable.ArrayBuffer
// "Triangulations in CGAL" // "Triangulations in CGAL"
class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
val ik = points(2) - points(0) var ik, ij , jk, ji, kj, ki: Point = null
val ij = points(1) - points(0) updatePoints
val jk = points(2) - points(1)
val ji = points(0) - points(1)
val kj = points(1) - points(2)
val ki = points(0) - points(2)
// Flags to determine if an edge is the final Delauney edge // Flags to determine if an edge is the final Delauney edge
val edges = new Array[Boolean](3) val edges = new Array[Boolean](3)
def updatePoints {
ik = points(2) - points(0)
ij = points(1) - points(0)
jk = points(2) - points(1)
ji = points(0) - points(1)
kj = points(1) - points(2)
ki = points(0) - points(2)
}
// Update neighbor pointers // Update neighbor pointers
def updateNeighbors(ccwPoint: Point, cwPoint: Point, triangle: Triangle) { def updateNeighbors(ccwPoint: Point, cwPoint: Point, triangle: Triangle) {
if(ccwPoint == points(2) && cwPoint == points(1)) if(ccwPoint == points(2) && cwPoint == points(1))
@ -105,7 +110,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
if(neighbors(1) == null) return null if(neighbors(1) == null) return null
return neighbors(1).locateFirst(edge) return neighbors(1).locateFirst(edge)
} }
throw new Exception("location error") null
} }
def findNeighbor(e: Point): Triangle = { def findNeighbor(e: Point): Triangle = {
@ -118,4 +123,9 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
this this
} }
def printDebug {
println("**************")
println(points(0) + "," + points(1) + "," + points(2))
}
} }