bug fixes and optimizations

This commit is contained in:
zzzzrrr 2009-08-11 22:40:56 -04:00
parent 5fa8c4501e
commit 14980edabe
6 changed files with 94 additions and 137 deletions

View File

@ -87,7 +87,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
val i18 = "data/i.18"
val tank = "data/tank.dat"
var currentModel = tank
var currentModel = strange
var doCDT = true
var mouseButton = 0
@ -112,7 +112,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
def render(container: GameContainer, g: Graphics) {
g.drawString("'1-7' to cycle models, mouse to pan & zoom", 10, 520)
g.drawString("'1-8' to cycle models, mouse to pan & zoom", 10, 520)
g.drawString("'SPACE' to show Seidel debug info", 10, 532)
g.drawString("'m' to show trapezoidal map (Seidel debug mode)", 10, 544)
g.drawString("'e' to switch Seidel / EarClip", 10, 556)
@ -305,13 +305,14 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
CDT.clearPoint = 7
loadModel(i18, 20f, Point(600f, 500f), 20)
case "data/nazca_heron.dat" =>
doCDT = false; drawCDT = false; drawcdtMesh = false
CDT.clearPoint = 7
loadModel(nazcaHeron, 4.5f, Point(400f, 300f), 1500)
loadModel(nazcaHeron, 4.2f, Point(400f, 300f), 1500)
case "data/tank.dat" =>
//doCDT = false; drawCDT = false; drawcdtMesh = false
doCDT = true; drawCDT = true
CDT.clearPoint = 50
loadModel(tank, -1f, Point(0f, 0f), 10)
CDT.clearPoint = 38
loadModel(tank, -1f, Point(100f, 0f), 10)
case _ =>
assert(false)
}
@ -361,7 +362,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
}
if(!drawEarClip) {
// Sediel triangulation
seidel = new Triangulator(segments)

View File

@ -32,7 +32,7 @@ package org.poly2tri.cdt
import scala.collection.mutable.ArrayBuffer
import shapes.{Point, Triangle}
import shapes.{Point, Triangle, Segment}
// Advancing front
class AFront(iTriangle: Triangle) {
@ -91,11 +91,13 @@ class AFront(iTriangle: Triangle) {
// Update advancing front with constrained edge triangles
def constrainedEdge(sNode: Node, eNode: Node, T1: ArrayBuffer[Triangle],
T2: ArrayBuffer[Triangle]): Triangle = {
T2: ArrayBuffer[Triangle], edge: Segment): Triangle = {
var node = sNode
var t1r, t2r = false
// Scan the advancing front and update Node triangle pointers
// Either T1 OR T2
while(node != eNode) {
T2.foreach(t => {
@ -115,68 +117,44 @@ class AFront(iTriangle: Triangle) {
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 = {
val point1 = edge.q
val point2 = edge.p
var t1r, t2r = false
// Select edge triangles
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!")
}
}
var edgeTri1: Triangle = null
var i = 0
while(edgeTri1 == null) {
if(T1(i).contains(point1, point2))
edgeTri1 = T1(i)
i += 1
}
// Mark constrained edge
edgeTri1 markEdge(point1, point2)
var edgeTri2: Triangle = null
i = 0
while(edgeTri2 == null) {
if(T2(i).contains(point1, point2))
edgeTri2 = T2(i)
i += 1
}
// Mark constrained edge
edgeTri2 markEdge(point1, point2)
// Update neighbor pointer
edgeTri1.markNeighbor(edgeTri2)
if(t1r && !t2r)
T1.first
else if(t2r && !t1r)
T2.first
else
edgeTri1
else if(t2r && !t1r) {
edgeTri2
} else {
throw new Exception("edge insertion error")
}
}
@ -193,6 +171,7 @@ class AFront(iTriangle: Triangle) {
node1.triangle = t
}
// NOT IMPLEMENTED
def basin(node: Node) {
if(node.next != tail) {
val p1 = node.point

View File

@ -30,7 +30,7 @@
*/
package org.poly2tri.cdt
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.{ArrayBuffer, Set}
import shapes.{Segment, Point, Triangle}
import utils.Util
@ -44,7 +44,7 @@ object CDT {
// Inital triangle factor
val ALPHA = 0.3f
val SHEER = 0.001f
val SHEER = 0.0001
var clearPoint = 0
@ -101,7 +101,7 @@ object CDT {
// Prevents any two distinct endpoints from lying on a common horizontal line, and avoiding
// the degenerate case. See Mark de Berg et al, Chapter 6.3
private def shearTransform(point: Point) = Point(point.x, point.y + point.x * SHEER)
private def shearTransform(point: Point) = Point(point.x, point.y + point.x * 0.001f)
}
@ -144,7 +144,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
} catch {
case e: Exception =>
throw new Exception("Systect point = " + i)
//throw new Exception("Suspect point = " + i)
}
}
@ -154,9 +154,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// Clean exterior triangles
private def finalization {
mesh.map.foreach(m => m.markEdges)
mesh.map.foreach(m => m.markNeighborEdges)
mesh clean cleanTri
}
// Point event
@ -191,17 +191,14 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val tList = new ArrayBuffer[Triangle]
tList += firstTriangle
while(tList.last != null && !tList.last.contains(edge.p))
while(!tList.last.contains(edge.p))
tList += tList.last.findNeighbor(edge.p - edge.q)
// TODO: fix tList.last == null bug!
// Not sure why this happens in bird & nazca monkey demo...
if(tList.last == null) tList -= tList.last
// Neighbor triangles
val nTriangles = new ArrayBuffer[Triangle]
// Remove old triangles; collect neighbor triangles
// Keep duplicates out
tList.foreach(t => {
t.neighbors.foreach(n => if(n != null && !tList.contains(n)) nTriangles += n)
mesh.map -= t
@ -240,47 +237,16 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
val point1 = if(ahead) edge.q else edge.p
val point2 = if(ahead) edge.p else edge.q
var first: Triangle = null
val sNode = aFront.locatePoint(point1)
val eNode = aFront.locatePoint(point2)
val sNode = aFront.locate(point1)
val eNode = aFront.locate(point2)
val first = aFront.constrainedEdge(sNode, eNode, T1, T2, edge)
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
edgeNeighbors(nTriangles, T1)
edgeNeighbors(nTriangles, T2)
// Select edge triangle
var edgeTri1: Triangle = null
var i = 0
while(edgeTri1 == null) {
if(T1(i).contains(point1, point2))
edgeTri1 = T1(i)
i += 1
}
// Select edge triangle
var edgeTri2: Triangle = null
i = 0
while(edgeTri2 == null) {
if(T2(i).contains(point1, point2))
edgeTri2 = T2(i)
i += 1
}
edgeTri1.markNeighbor(edgeTri2)
// Mark constrained edge
edgeTri1 mark(point1, point2)
edgeTri2 mark(point1, point2)
// Double check returning T2.first vs T1.first
first
first
} else if(firstTriangle == null) {
@ -330,17 +296,18 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
edgeNeighbors(nTriangles, T)
// Mark constrained edge
edgeTri mark(edge.p, edge.q)
edgeTri markEdge(point1, point2)
// Return original triangle
triangle
} else if(firstTriangle.contains(edge.p, edge.q)) {
// Mark constrained edge
firstTriangle mark(edge.p, edge.q)
firstTriangle markEdge(edge.p, edge.q)
triangle
} else {
throw new Exception("Triangulation error")
//null
}
}

View File

@ -42,17 +42,25 @@ class Mesh(initialTriangle: Triangle) {
val debug = HashSet.empty[Triangle]
val triangles = new ArrayBuffer[Triangle]
def test(triangle: Triangle) {
if(triangle != null && !triangle.test){
triangle.test = true
debug += triangle
for(i <- 0 until 3) {
test(triangle.neighbors(i))
}
}
}
// Recursively collect triangles
def clean(triangle: Triangle) {
if(triangle != null && !triangle.clean) {
triangle.clean = true
if(triangle != null && !triangle.interior) {
triangle.interior = true
triangles += triangle
if(!triangle.edges(0))
clean(triangle.neighbors(0))
if(!triangle.edges(1))
clean(triangle.neighbors(1))
if(!triangle.edges(2))
clean(triangle.neighbors(2))
for(i <- 0 until 3) {
if(!triangle.edges(i))
clean(triangle.neighbors(i))
}
}
}

View File

@ -46,10 +46,12 @@ class Triangle(val points: Array[Point]) {
val edges = Array(false, false, false)
// Finalization flag
var clean = false
var interior = false
var finalized = false
var test = false
// Update neighbor pointers
private def markNeighbor(p1: Point, p2: Point, t: Triangle) {
@ -284,15 +286,9 @@ class Triangle(val points: Array[Point]) {
}
def printDebug = println(points(0) + "," + points(1) + "," + points(2))
// Initial mark edges sweep
def mark(p: Point, q: Point) {
markEdge(p, q)
markNeighborEdge(p, q)
}
// Finalize edge marking
def markEdges {
def markNeighborEdges {
for(i <- 0 to 2)
if(edges(i))
i match {
@ -302,18 +298,24 @@ class Triangle(val points: Array[Point]) {
}
}
// Mark neighbor's edge
private def markNeighborEdge(p: Point, q: Point) =
neighbors.foreach(n => if(n != null) n.markEdge(p, q))
def markEdge(triangle: Triangle) {
for(i <- 0 to 2)
if(edges(i))
i match {
case 0 => triangle.markEdge(points(1), points(2))
case 1 => triangle.markEdge(points(0), points(2))
case _ => triangle.markEdge(points(0), points(1))
}
}
// Mark edge as constrained
private def markEdge(p: Point, q: Point) {
def markEdge(p: Point, q: Point) {
if((q == points(0) && p == points(1)) || (q == points(1) && p == points(0))) {
finalized = true
edges(2) = true
} else if ((q == points(0) && p == points(2)) || (q == points(2) && p == points(0))) {
finalized = true
edges(1) = true
finalized = true
} else if ((q == points(1) && p == points(2)) || (q == points(2) && p == points(1))){
finalized = true
edges(0) = true

View File

@ -8,7 +8,7 @@ import shapes.Point
object Util {
// Almost zero
val COLLINEAR_SLOP = 0.01f
val COLLINEAR_SLOP = 0.1f
val epsilon = exactinit
val ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon