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.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) {

View File

@ -47,11 +47,11 @@ class AFront(iTriangle: Triangle) {
def locate(point: Point): Node = {
var node = head
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
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]) = {

View File

@ -108,6 +108,8 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// Triangle list
def triangles = mesh.map
def debugTriangles = mesh.debug
// The triangle mesh
private val mesh = new Mesh(iTriangle)
// Advancing front
@ -122,13 +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 10 /*points.size*/) {
val point = points(i)
// Process Point event
//val triangle =
pointEvent(point)
val triangle = pointEvent(point)
// 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 = {
val node = aFront.locate(point)
// Neightbor points (ccw & cw) and triangle(i)
val cwPoint = node.next.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
val firstTriangle = triangle.locateFirst(edge)
// STEP 2: Remove intersected triangles
if(firstTriangle != null && !firstTriangle.contains(edge)) {
// Collect intersected triangles
val triangles = new ArrayBuffer[Triangle]
triangles += firstTriangle
val e = edge.p - edge.q
while(!triangles.last.contains(edge.p))
triangles += triangles.last.findNeighbor(edge.p - edge.q)
triangles += triangles.last.findNeighbor(e)
// Remove from the mesh
triangles.foreach(t => mesh.map -= t)
//triangles.foreach(t => mesh.map -= t)
} else if(firstTriangle == null) {
// Traverse the AFront, and build triangle list
var node = aFront.locate(edge.q)
node = node.next
val points = new ArrayBuffer[Point]
if(edge.p.x > edge.q.x) {
// Search right
while(node.point != edge.p) {
// Collect points
points += node.point
node = node.next
}
} else {
// Search left
while(node.point != edge.p) {
// Collect points
points += node.point
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.
}
// 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
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 angle = Math.abs(Math.atan2(a cross b, a dot b))
if(angle <= PI_2) {
val points = Array(node.prev.point, node.next.point, node.point)
val neighbors = Array(node.prev.triangle, null, node.triangle)
val points = Array(node.prev.point, node.point, node.next.point)
val neighbors = Array(node.triangle, null, node.prev.triangle)
val triangle = new Triangle(points, neighbors)
// 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)
mesh.map += 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 v4 = p3 - p4
if((v1 dot v2) < 0 && (v3 dot v4) < 0)
// swap the edge
true
else
false
@ -267,8 +304,11 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
t2.points(1) = point
t2.points(0) = t2.points(2)
t2.points(2) = tmp
// Rotate neighbors
t1.updatePoints
t2.updatePoints
// TODO: Rotate neighbors
println("legalize")
}
private def finalization {

View File

@ -38,6 +38,7 @@ class Mesh(initialTriangle: Triangle) {
// Triangles that constitute the mesh
val map = HashSet(initialTriangle)
val debug = HashSet.empty[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
def updateEdge {
if(q.y > p.y) {
if(p.y > q.y) {
// For CDT we want q to be the point with > y
// val tmp = p
//p = q
//q = tmp
val tmp = p
p = q
q = tmp
}
q.edges += this
}
}
}

View File

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