fixed bugs

This commit is contained in:
zzzzrrr 2009-08-05 16:47:04 -04:00
parent 850b809c7b
commit 19e6c4208f
3 changed files with 86 additions and 55 deletions

View File

@ -43,7 +43,7 @@ class AFront(iTriangle: Triangle) {
head.next.next = tail
tail.prev = head.next
// TODO: Usea 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 = {
var node = head
while(node != tail) {

View File

@ -138,9 +138,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val node = aFront.locate(point)
// Projected point coincides with existing point; create two triangles
if(point.x == node.point.x && node.prev != null) {
// Projected point coincides with existing point; create two triangles
val rPts = Array(point, node.point, node.next.point)
val rNeighbors = Array(node.triangle, null, null)
val rTriangle = new Triangle(rPts, rNeighbors)
@ -170,7 +170,6 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
newNode.triangle
} else {
// Projected point hits advancing front; create new triangle
val cwPoint = node.next.point
val ccwPoint = node.point
@ -201,19 +200,52 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val firstTriangle = triangle.locateFirst(edge)
// STEP 2: Remove intersected triangles
// STEP 3: Triangulate empty areas.
if(firstTriangle != null && !firstTriangle.contains(edge) && firstTriangle != triangle) {
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 != null && !triangles.last.contains(edge.p))
triangles += triangles.last.findNeighbor(e)
triangles += triangles.last.findNeighbor(edge.p - edge.q)
// TODO: Implement this section
//triangles.foreach(t => mesh.map -= t)
// TODO: triangles.last == null bug!
if(triangles.last == null)
triangles -= triangles.last
// Remove old triangles
triangles.foreach(t => mesh.map -= t)
val lPoints = new ArrayBuffer[Point]
val rPoints = new ArrayBuffer[Point]
val ahead = (edge.p.x > edge.q.x)
val point1 = if(ahead) edge.q else edge.p
val point2 = if(ahead) edge.p else edge.q
// Collect points left and right of edge
triangles.foreach(t => {
t.points.foreach(p => {
if(p != edge.q && p != edge.p) {
if(t.orient(point1, point2, p) >= 0 ) {
if(!lPoints.contains(p)) {
lPoints += p
}
} else {
if(!rPoints.contains(p))
rPoints += p
}
}
})
})
// STEP 3: Triangulate empty areas.
val T1 = new ArrayBuffer[Triangle]
triangulate(lPoints.toArray, List(point1, point2), T1)
val T2 = new ArrayBuffer[Triangle]
triangulate(rPoints.toArray, List(point1, point2), T2)
// TODO: Update Delauney Edge Pointers
} else if(firstTriangle == null) {
@ -226,43 +258,37 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val points = new ArrayBuffer[Point]
var node = aFront.locate(point1)
val node1 = node
val foo = node
node = node.next
while(node.point != point2) {
points += node.point
node = node.next
}
val node2 = node
// STEP 3: Triangulate empty areas.
triangulateEmpty(point1, point2, points)
val T = new ArrayBuffer[Triangle]
angladaTPD(points.toArray, List(point1, point2), T)
node1.triangle = T.first
node1.next = node2
node2.prev = node1
T.first.neighbors(0) = foo.next.triangle
T.first.neighbors(2) = foo.triangle
T.foreach(t => mesh.map += t)
// TODO: Update Delauney Edge Pointers
} else if(firstTriangle.contains(edge)) {
// TODO: Update Delauney Edge Pointers
}
}
// Marc Vigo Anglada's triangulatePseudopolygonDelaunay algo
// TODO: Bugy fix - works for a single triangle
def angladaTPD(P: Array[Point], ab: List[Point], T: ArrayBuffer[Triangle]) {
// Triangulate empty areas.
def triangulateEmpty(point1: Point, point2: Point, points: ArrayBuffer[Point]) {
val T = new ArrayBuffer[Triangle]
triangulate(points.toArray, List(point1, point2), T)
}
// Marc Vigo Anglada's triangulate pseudo-polygon algo
private def triangulate(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 c = P.first
var i = 0
for(j <- 1 until P.size) {
if(illegal(a, c, b, P(j))) {
@ -272,15 +298,17 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
}
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)
triangulate(PE, List(a, c), T)
triangulate(PD, List(c, b), T)
}
if(!P.isEmpty) {
c = P.first
val points = Array(a, b, c)
// TODO: Correctly update neighbor pointers
val points = Array(a, P.first, b)
// TODO: Correctly update neighbor pointers?
// Not updating seems to work with simple polygons...
val neighbors = new Array[Triangle](3)
T += new Triangle(points, neighbors)
mesh.map += T.last
}
}
@ -327,7 +355,8 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
angle
}
// Do edges need to be swapped?
// Do edges need to be swapped? Robust CircumCircle test
// See section 3.7 from "Triangulations and Applications" by O. Hjelle & M. Deahlen
private def illegal(p1: Point, p2: Point, p3: Point, p4:Point): Boolean = {
val v1 = p3 - p2
@ -346,6 +375,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val sinA = v1 cross v2
val sinB = v3 cross v4
// Some small number
if(cosA*sinB + sinA*cosB < -0.01f)
true
else

View File

@ -37,23 +37,9 @@ import scala.collection.mutable.ArrayBuffer
// "Triangulations in CGAL"
class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
var ik, ij , jk, ji, kj, ki: Point = null
updateEdges
// Flags to determine if an edge is the final Delauney edge
val edges = new Array[Boolean](3)
// Update the edges that consitite this triangle
// May change during legalization
def updateEdges {
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)) || (ccwPoint == points(1) && cwPoint == points(2)))
@ -116,13 +102,13 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
null
}
// Locate next triangle crossed by constraied edge
// Locate next triangle crossed by edge
def findNeighbor(e: Point): Triangle = {
if(orient(points(0), points(1), e) > 0)
if(orient(points(0), points(1), e) >= 0)
return neighbors(2)
if(orient(points(1), points(2), e) > 0)
if(orient(points(1), points(2), e) >= 0)
return neighbors(0)
if(orient(points(2), points(0), e) > 0)
if(orient(points(2), points(0), e) >= 0)
return neighbors(1)
else
// Point must reside inside this triangle
@ -132,6 +118,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
// Return: positive if point p is left of ab
// negative if point p is right of ab
// zero if points are colinear
// See: http://www-2.cs.cmu.edu/~quake/robust.html
def orient(b: Point, a: Point, p: Point): Float = {
val acx = a.x - p.x
val bcx = b.x - p.x
@ -191,4 +178,18 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
println(points(0) + "," + points(1) + "," + points(2))
}
private var ik, ij , jk, ji, kj, ki: Point = null
updateEdges
// Update the edges that consitite this triangle
// May change during legalization
private def updateEdges {
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)
}
}