edge event work

This commit is contained in:
Mason 2009-08-07 21:08:13 -04:00
parent 552cc3f564
commit 7d87363ba7
4 changed files with 81 additions and 42 deletions

View File

@ -76,6 +76,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
var hiLighter = 0 var hiLighter = 0
var drawEarClip = false var drawEarClip = false
var drawCDT = true var drawCDT = true
var drawcdtMesh = true
val nazcaMonkey = "data/nazca_monkey.dat" val nazcaMonkey = "data/nazca_monkey.dat"
val bird = "data/bird.dat" val bird = "data/bird.dat"
@ -84,7 +85,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
val strange = "data/strange.dat" val strange = "data/strange.dat"
val i18 = "data/i.18" val i18 = "data/i.18"
var currentModel = star var currentModel = i18
var mouseButton = 0 var mouseButton = 0
var mousePressed = false var mousePressed = false
@ -167,7 +168,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
}) })
if(drawCDT) { if(drawCDT) {
slCDT.triangles.foreach( t => { val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles
draw.foreach( t => {
val triangle = new Polygon val triangle = new Polygon
triangle.addPoint(t.points(0).x, t.points(0).y) triangle.addPoint(t.points(0).x, t.points(0).y)
triangle.addPoint(t.points(1).x, t.points(1).y) triangle.addPoint(t.points(1).x, t.points(1).y)
@ -264,6 +266,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
if(c == '5') selectModel(star) if(c == '5') selectModel(star)
if(c == '6') selectModel(i18) if(c == '6') selectModel(i18)
if(c == 's') drawSegs = !drawSegs if(c == 's') drawSegs = !drawSegs
if(c == 'c') drawcdtMesh = !drawcdtMesh
//if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)} //if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)}
} }

View File

@ -107,7 +107,7 @@ object CDT {
class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Triangle) { class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Triangle) {
// Triangle list // Triangle list
def triangles = mesh.map def triangles = mesh.triangles
def triangleMesh = mesh.map def triangleMesh = mesh.map
def debugTriangles = mesh.debug def debugTriangles = mesh.debug
@ -119,6 +119,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
private val PI_2 = Math.Pi/2 private val PI_2 = Math.Pi/2
private val PI_34 = Math.Pi*3/4 private val PI_34 = Math.Pi*3/4
// Triangle used to clean interior
var cleanTri: Triangle = null
// Sweep points; build mesh // Sweep points; build mesh
sweep sweep
// Finalize triangulation // Finalize triangulation
@ -126,7 +129,6 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// Implement sweep-line // Implement sweep-line
private def sweep { private def sweep {
//var cTri: Triangle = null
for(i <- 1 until points.size) { for(i <- 1 until points.size) {
val point = points(i) val point = points(i)
// Process Point event // Process Point event
@ -139,9 +141,15 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
} }
// Process edge events // Process edge events
point.edges.foreach(e => edgeEvent(e, triangle)) point.edges.foreach(e => edgeEvent(e, triangle))
//if(i == 7) {cTri = triangle; mesh.debug += cTri} //if(i == 7) {cleanTri = triangle; mesh.debug += cleanTri}
} }
//mesh clean cTri }
// Final step in the sweep-line CDT algo
// Clean exterior triangles
private def finalization {
mesh.map.foreach(m => m.markEdges)
mesh clean cleanTri
//mesh.map.foreach(m => m.edges.foreach(e => if(e) mesh.debug += m)) //mesh.map.foreach(m => m.edges.foreach(e => if(e) mesh.debug += m))
} }
@ -276,11 +284,14 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// Mark constrained edges // Mark constrained edges
val dEdge = new Segment(point1, point2) val dEdge = new Segment(point1, point2)
T1.first mark dEdge T1.first mark(point1, point2)
T2.first mark dEdge T2.first mark(point1, point2)
//TODO update neighbor pointers
} else if(firstTriangle == null) { } else if(firstTriangle == null) {
// NOTE: So far this only works for single triangles
// No triangles are intersected by the edge; edge must lie outside the mesh // No triangles are intersected by the edge; edge must lie outside the mesh
// Apply constraint; traverse the AFront, and build triangles // Apply constraint; traverse the AFront, and build triangles
@ -292,29 +303,45 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
var node = aFront.locate(point1) var node = aFront.locate(point1)
val first = node val first = node
node = node.next
while(node.point != point2) { while(node.point != point2) {
points += node.point points += node.point
node = node.next node = node.next
} }
//assert(points.size == 1, "not implemented yet, points = " + points.size)
val endPoints = if(ahead) List(point2, point1) else List(point1, point2)
// STEP 3: Triangulate empty areas. // STEP 3: Triangulate empty areas.
val T = new ArrayBuffer[Triangle] val T = new ArrayBuffer[Triangle]
triangulate(points.toArray, List(point1, point2), T) triangulate(points.toArray, endPoints, T)
// Update advancing front // Update advancing front
first.triangle = T.first aFront -= (first, node.prev, T.first)
first.next = node
node.prev = first
// Mark constrained edge // Update neigbor pointers
val dEdge = new Segment(point1, point2) if(ahead) {
T.first mark dEdge T.first.neighbors(2) = node.prev.triangle;
T.first.neighbors(0) = first.triangle
node.prev.triangle.updateNeighbors(T.first.points(0), T.first.points(1), T.first, mesh.debug)
first.triangle.updateNeighbors(T.first.points(1), T.first.points(2), T.first, mesh.debug)
} else {
T.first.neighbors(2) = first.triangle;
T.first.neighbors(0) = node.prev.triangle
node.prev.triangle.updateNeighbors(T.first.points(1), T.first.points(2), T.first, mesh.debug)
first.triangle.updateNeighbors(T.first.points(0), T.first.points(1), T.first, mesh.debug)
} }
// Mark constrained edge // Mark constrained edge
if(contains) T.first mark(edge.p, edge.q)
firstTriangle mark edge
} else {
// Mark constrained edge
firstTriangle mark(edge.p, edge.q)
}
} }
// Marc Vigo Anglada's triangulate pseudo-polygon algo // Marc Vigo Anglada's triangulate pseudo-polygon algo
@ -347,7 +374,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
} }
// Scan left and right along AFront to fill holes // Scan left and right along AFront to fill holes
def scanAFront(n: Node) { private def scanAFront(n: Node) {
var node = n.next var node = n.next
// Update right // Update right
@ -371,7 +398,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 = { private 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))
@ -454,10 +481,4 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
} }
true true
} }
// Final step in the sweep-line CDT algo
private def finalization {
}
} }

View File

@ -44,7 +44,7 @@ class Mesh(initialTriangle: Triangle) {
// Recursively collect triangles // Recursively collect triangles
def clean(triangle: Triangle) { def clean(triangle: Triangle) {
if(triangle != null && triangle.clean == false) { if(triangle != null && !triangle.clean) {
triangle.clean = true triangle.clean = true
triangles += triangle triangles += triangle
if(!triangle.edges(0)) if(!triangle.edges(0))

View File

@ -56,7 +56,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
neighbors(2) = triangle neighbors(2) = triangle
else { else {
debug += triangle debug += triangle
throw new Exception("Neighbor pointer error, please report!") //throw new Exception("Neighbor pointer error, please report!")
} }
} }
@ -267,20 +267,35 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
ki = points(0) - points(2) ki = points(0) - points(2)
} }
def mark(e: Segment) { // Initial mark edges sweep
markEdge(e) def mark(p: Point, q: Point) {
markNeighbors(e) if(contains(p) && contains(q)) {
markEdge(p, q)
markNeighbors(p, q)
}
} }
private def markNeighbors(e: Segment) = neighbors.foreach(n => if(n != null) n.markEdge(e)) // Finalize edge marking
def markEdges {
for(i <- 0 to 2)
if(edges(i))
i match {
case 0 => if(neighbors(0) != null) neighbors(0).markEdge(points(1), points(2))
case 1 => if(neighbors(1) != null) neighbors(1).markEdge(points(0), points(2))
case _ => if(neighbors(2) != null) neighbors(2).markEdge(points(0), points(1))
}
}
// Mark neighbor's edge
private def markNeighbors(p: Point, q: Point) = neighbors.foreach(n => if(n != null) n.markEdge(p, q))
// Mark edge as constrained // Mark edge as constrained
private def markEdge(e: Segment) { private def markEdge(p: Point, q: Point) {
if((e.q == points(0) && e.p == points(1)) || (e.q == points(1) && e.p == points(0))) { if((q == points(0) && p == points(1)) || (q == points(1) && p == points(0))) {
edges(2) = true edges(2) = true
} else if ((e.q == points(0) && e.p == points(2)) || (e.q == points(2) && e.p == points(0))) { } else if ((q == points(0) && p == points(2)) || (q == points(2) && p == points(0))) {
edges(1) = true edges(1) = true
} else { } else if ((q == points(1) && p == points(2)) || (q == points(2) && p == points(1))){
edges(0) = true edges(0) = true
} }
} }