mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-30 01:03:30 +01:00
bug hunting
This commit is contained in:
parent
a6b338d88d
commit
f06c23d4e8
@ -170,7 +170,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
})
|
||||
|
||||
if(drawCDT) {
|
||||
val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles
|
||||
//val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles
|
||||
val draw = slCDT.testTri
|
||||
draw.foreach( t => {
|
||||
val triangle = new Polygon
|
||||
triangle.addPoint(t.points(0).x, t.points(0).y)
|
||||
|
@ -30,6 +30,8 @@
|
||||
*/
|
||||
package org.poly2tri.cdt
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
import shapes.{Point, Triangle}
|
||||
|
||||
// Advancing front
|
||||
@ -87,7 +89,94 @@ class AFront(iTriangle: Triangle) {
|
||||
node
|
||||
}
|
||||
|
||||
def constrainedEdge() {
|
||||
// Update advancing front with constrained edge triangles
|
||||
def constrainedEdge(sNode: Node, eNode: Node, T1: ArrayBuffer[Triangle],
|
||||
T2: ArrayBuffer[Triangle]): Triangle = {
|
||||
|
||||
var node = sNode
|
||||
var t1r, t2r = false
|
||||
|
||||
while(node != eNode) {
|
||||
|
||||
T2.foreach(t => {
|
||||
if(t.contains(node.point, node.next.point)) {
|
||||
node.triangle = t
|
||||
t2r = true
|
||||
}
|
||||
})
|
||||
|
||||
if(!t2r)
|
||||
T1.foreach(t => {
|
||||
if(t.contains(node.point, node.next.point)) {
|
||||
node.triangle = t
|
||||
t1r = true
|
||||
}
|
||||
})
|
||||
|
||||
node = node.next
|
||||
}
|
||||
|
||||
if(t1r && !t2r)
|
||||
T1.first
|
||||
else if(t2r && !t1r)
|
||||
T2.first
|
||||
else
|
||||
throw new Exception("edge insertion error")
|
||||
|
||||
}
|
||||
|
||||
// Update advancing front with qNode
|
||||
def constrainedEdge(qNode: Node, tList: ArrayBuffer[Triangle], T1: ArrayBuffer[Triangle],
|
||||
T2: ArrayBuffer[Triangle]): Triangle = {
|
||||
|
||||
var t1r, t2r = false
|
||||
|
||||
for(t <- tList) {
|
||||
|
||||
if(qNode.triangle == t) {
|
||||
|
||||
val p1 = qNode.point
|
||||
val p2 = qNode.next.point
|
||||
|
||||
T2.foreach(tri => if(tri.contains(p1, p2)) {
|
||||
qNode.triangle = tri
|
||||
t2r = true
|
||||
})
|
||||
|
||||
if(!t2r)
|
||||
T1.foreach(tri => if(tri.contains(p1, p2)) {
|
||||
qNode.triangle = tri
|
||||
t1r = true
|
||||
})
|
||||
|
||||
} else if(qNode.prev.triangle == t) {
|
||||
|
||||
val p1 = qNode.prev.point
|
||||
val p2 = qNode.point
|
||||
|
||||
T2.foreach(tri => if(tri.contains(p1, p2)) {
|
||||
qNode.prev.triangle = tri
|
||||
t2r = true
|
||||
})
|
||||
|
||||
if(!t2r)
|
||||
T1.foreach(tri => if(tri.contains(p1, p2)) {
|
||||
qNode.prev.triangle = tri
|
||||
t1r = true
|
||||
})
|
||||
|
||||
} else if(qNode.next.triangle == t) {
|
||||
throw new Exception("unanticipated edge event!")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(t1r && !t2r)
|
||||
T1.first
|
||||
else if(t2r && !t1r)
|
||||
T2.first
|
||||
else
|
||||
throw new Exception("edge insertion error")
|
||||
|
||||
}
|
||||
|
||||
@ -98,6 +187,12 @@ class AFront(iTriangle: Triangle) {
|
||||
node.triangle = triangle
|
||||
}
|
||||
|
||||
def link(node1: Node, node2: Node, t: Triangle) {
|
||||
node1.next = node2
|
||||
node2.prev = node1
|
||||
node1.triangle = t
|
||||
}
|
||||
|
||||
def basin(node: Node) {
|
||||
if(node.next != tail) {
|
||||
val p1 = node.point
|
||||
|
@ -128,6 +128,18 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
// Finalize triangulation
|
||||
finalization
|
||||
|
||||
val testTri = new ArrayBuffer[Triangle]
|
||||
|
||||
val p1 = Point(200, 300)
|
||||
val p2 = Point(500, 300)
|
||||
|
||||
val p3 = Point(250, 500)
|
||||
val p4 = Point(350, 400)
|
||||
val p5 = Point(400, 350)
|
||||
|
||||
val pts = Array(p3, p4, p5)
|
||||
triangulate(pts, List(p1, p2), testTri)
|
||||
|
||||
// Implement sweep-line
|
||||
private def sweep {
|
||||
|
||||
@ -136,7 +148,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
// Process Point event
|
||||
var triangle = pointEvent(point)
|
||||
// Process edge events
|
||||
//point.edges.foreach(e => triangle = edgeEvent(e, triangle))
|
||||
point.edges.foreach(e => triangle = edgeEvent(e, triangle))
|
||||
if(i == CDT.clearPoint) {cleanTri = triangle; mesh.debug += cleanTri}
|
||||
}
|
||||
}
|
||||
@ -231,39 +243,15 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
|
||||
// Update advancing front
|
||||
|
||||
val qNode = aFront.locatePoint(edge.q)
|
||||
val pNode = aFront.locatePoint(edge.p)
|
||||
|
||||
// TODO: Make this more robust....
|
||||
|
||||
for(t <- tList) {
|
||||
|
||||
if(qNode.triangle == t) {
|
||||
val p1 = qNode.point
|
||||
val p2 = qNode.next.point
|
||||
T1.foreach(tri => if(tri.contains(p1, p2)) qNode.triangle = tri)
|
||||
T2.foreach(tri => if(tri.contains(p1, p2)) qNode.triangle = tri)
|
||||
} else if(qNode.prev.triangle == t) {
|
||||
val p1 = qNode.prev.point
|
||||
val p2 = qNode.point
|
||||
T1.foreach(tri => if(tri.contains(p1, p2)) qNode.prev.triangle = tri)
|
||||
T2.foreach(tri => if(tri.contains(p1, p2)) qNode.prev.triangle = tri)
|
||||
}
|
||||
|
||||
if(pNode != null) {
|
||||
if(pNode.triangle == t) {
|
||||
val p1 = pNode.point
|
||||
val p2 = pNode.next.point
|
||||
T1.foreach(tri => if(tri.contains(p1, p2)) pNode.triangle = tri)
|
||||
T2.foreach(tri => if(tri.contains(p1, p2)) pNode.triangle = tri)
|
||||
} else if(pNode.prev.triangle == t) {
|
||||
val p1 = pNode.point
|
||||
val p2 = pNode.prev.point
|
||||
T1.foreach(tri => if(tri.contains(p1, p2)) pNode.prev.triangle = tri)
|
||||
T2.foreach(tri => if(tri.contains(p1, p2)) pNode.prev.triangle = tri)
|
||||
}
|
||||
}
|
||||
var first: Triangle = null
|
||||
val sNode = aFront.locatePoint(point1)
|
||||
val eNode = aFront.locatePoint(point2)
|
||||
|
||||
if(sNode != null && eNode != null) {
|
||||
first = aFront.constrainedEdge(sNode, eNode, T1, T2)
|
||||
} else {
|
||||
val qNode = if(sNode == null) eNode else sNode
|
||||
first = aFront.constrainedEdge(qNode, tList, T1, T2)
|
||||
}
|
||||
|
||||
// Update neighbors
|
||||
@ -275,7 +263,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
T2.first.mark(point1, point2)
|
||||
|
||||
// Double check returning T2.first vs T1.first
|
||||
T2.first
|
||||
first
|
||||
|
||||
} else if(firstTriangle == null) {
|
||||
|
||||
@ -283,6 +271,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
// Apply constraint; traverse the AFront, and build triangles
|
||||
|
||||
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
|
||||
|
||||
@ -310,7 +299,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
triangulate(points.toArray, endPoints, T)
|
||||
|
||||
// Update advancing front
|
||||
aFront -= (first, node.prev, T.first)
|
||||
aFront link (first, node, T.first)
|
||||
|
||||
// Update neighbors
|
||||
edgeNeighbors(nTriangles, T)
|
||||
@ -318,6 +307,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
// Mark constrained edge
|
||||
T.first mark(edge.p, edge.q)
|
||||
|
||||
// Return original triangle
|
||||
triangle
|
||||
|
||||
} else {
|
||||
@ -347,9 +337,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
||||
|
||||
val a = ab.first
|
||||
val b = ab.last
|
||||
var c = if(!P.isEmpty) P.first else null
|
||||
|
||||
if(P.size > 1) {
|
||||
var c = P.first
|
||||
var i = 0
|
||||
for(j <- 1 until P.size) {
|
||||
if(illegal(a, c, b, P(j))) {
|
||||
@ -358,13 +348,16 @@ 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)
|
||||
val PD = P.slice(i+1, P.size)
|
||||
triangulate(PE, List(a, c), T)
|
||||
triangulate(PD, List(c, b), T)
|
||||
}
|
||||
|
||||
if(!P.isEmpty) {
|
||||
val points = Array(a, P.first, b)
|
||||
val left = if(Util.orient(a, b, c) > 0) true else false
|
||||
val p2 = if(left) c else b
|
||||
val p3 = if(left) b else c
|
||||
val points = Array(a, p2, p3)
|
||||
T += new Triangle(points)
|
||||
mesh.map += T.last
|
||||
}
|
||||
|
@ -49,28 +49,14 @@ class Triangle(val points: Array[Point]) {
|
||||
var clean = false
|
||||
|
||||
// Update neighbor pointers
|
||||
// Debug version
|
||||
def markNeighbor(p1: Point, p2: Point, triangle: Triangle, debug: HashSet[Triangle]) {
|
||||
private def markNeighbor(p1: Point, p2: Point, t: Triangle) {
|
||||
assert(t != this, "self-pointer error")
|
||||
if((p1 == points(2) && p2 == points(1)) || (p1 == points(1) && p2 == points(2)))
|
||||
neighbors(0) = triangle
|
||||
neighbors(0) = t
|
||||
else if((p1 == points(0) && p2 == points(2)) || (p1 == points(2) && p2 == points(0)))
|
||||
neighbors(1) = triangle
|
||||
neighbors(1) = t
|
||||
else if((p1 == points(0) && p2 == points(1)) || (p1 == points(1) && p2 == points(0)))
|
||||
neighbors(2) = triangle
|
||||
else {
|
||||
debug += triangle
|
||||
println("Neighbor pointer ERROR!")
|
||||
}
|
||||
}
|
||||
|
||||
// Update neighbor pointers
|
||||
private def markNeighbor(p1: Point, p2: Point, triangle: Triangle) {
|
||||
if((p1 == points(2) && p2 == points(1)) || (p1 == points(1) && p2 == points(2)))
|
||||
neighbors(0) = triangle
|
||||
else if((p1 == points(0) && p2 == points(2)) || (p1 == points(2) && p2 == points(0)))
|
||||
neighbors(1) = triangle
|
||||
else if((p1 == points(0) && p2 == points(1)) || (p1 == points(1) && p2 == points(0)))
|
||||
neighbors(2) = triangle
|
||||
neighbors(2) = t
|
||||
else {
|
||||
throw new Exception("Neighbor pointer error, please report!")
|
||||
}
|
||||
@ -78,6 +64,7 @@ class Triangle(val points: Array[Point]) {
|
||||
|
||||
/* Exhaustive search to update neighbor pointers */
|
||||
def markNeighbor(t: Triangle) {
|
||||
assert(t != this, "self-pointer error")
|
||||
if (t.contains(points(1), points(2))) {
|
||||
neighbors(0) = t
|
||||
t.markNeighbor(points(1), points(2), this)
|
||||
@ -95,13 +82,16 @@ class Triangle(val points: Array[Point]) {
|
||||
}
|
||||
|
||||
def oppositePoint(t: Triangle): Point = {
|
||||
assert(t != this, "self-pointer error")
|
||||
if(points(0) == t.points(1))
|
||||
points(1)
|
||||
else if(points(0) == t.points(2))
|
||||
points(2)
|
||||
else if((points(2) == t.points(1) && points(1) == t.points(2)) || (points(1) == t.points(1) && points(2) == t.points(2)))
|
||||
else if(contains(t.points(1), t.points(2)))
|
||||
points(0)
|
||||
else {
|
||||
t.printDebug
|
||||
printDebug
|
||||
throw new Exception("Point location error, please report")
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,18 @@ object Util {
|
||||
|
||||
}
|
||||
|
||||
// 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
|
||||
val acy = a.y - p.y
|
||||
val bcy = b.y - p.y
|
||||
acx * bcy - acy * bcx
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** The object <code>Random</code> offers a default implementation
|
||||
|
Loading…
Reference in New Issue
Block a user