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
2510a728a7
commit
0db13d6586
@ -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 = {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user