influence region

This commit is contained in:
zzzzrrr 2009-08-02 20:39:20 -04:00
parent 54b7fbd009
commit 6228342454
6 changed files with 66 additions and 65 deletions

View File

@ -75,7 +75,6 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
var drawSegs = true var drawSegs = true
var hiLighter = 0 var hiLighter = 0
var drawEarClip = false var drawEarClip = false
var hertelMehlhorn = false
var drawCDT = false var drawCDT = false
val nazcaMonkey = "data/nazca_monkey.dat" val nazcaMonkey = "data/nazca_monkey.dat"
@ -201,7 +200,6 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
if(c == '6') selectModel(i18) if(c == '6') selectModel(i18)
if(c == 's') drawSegs = !drawSegs if(c == 's') drawSegs = !drawSegs
if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)} if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)}
if(c == 'h') {hertelMehlhorn = !hertelMehlhorn; selectModel(currentModel)}
} }
def selectModel(model: String) { def selectModel(model: String) {
@ -262,7 +260,6 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
// Sediel triangulation // Sediel triangulation
seidel = new Triangulator(segments) seidel = new Triangulator(segments)
seidel.buildTriangles = hertelMehlhorn
val t1 = System.nanoTime val t1 = System.nanoTime
seidel.process seidel.process

View File

@ -122,13 +122,13 @@ 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 9 /*points.size*/) { for(i <- 1 until points.size) {
val point = points(i) val point = points(i)
println(point)
// Process Point event // Process Point event
val triangle = pointEvent(point) //val triangle =
pointEvent(point)
// Process edge events // Process edge events
point.edges.foreach(e => edgeEvent(e, triangle)) //point.edges.foreach(e => edgeEvent(e, triangle))
} }
} }
@ -164,12 +164,40 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
// EdgeEvent // EdgeEvent
private def edgeEvent(edge: Segment, triangle: Triangle) { private def edgeEvent(edge: Segment, triangle: Triangle) {
// STEP 1: Locate the first intersected triangle // STEP 1: Locate the first intersected triangle
val first = triangle.locateFirst(edge) val firstTriangle = triangle.locateFirst(edge)
println(first)
if(first != null && first != triangle && !first.contains(edge))
mesh.map -= first
// STEP 2: Remove intersected triangles // STEP 2: Remove intersected triangles
if(firstTriangle != null && !firstTriangle.contains(edge)) {
// Collect intersected triangles
val triangles = new ArrayBuffer[Triangle]
triangles += firstTriangle
while(!triangles.last.contains(edge.p))
triangles += triangles.last.findNeighbor(edge.p - edge.q)
// Remove from the mesh
triangles.foreach(t => mesh.map -= t)
} else if(firstTriangle == null) {
// Traverse the AFront, and build triangle list
var node = aFront.locate(edge.q)
if(edge.p.x > edge.q.x) {
// Search right
while(node.point != edge.p) {
// Collect points
node = node.next
}
} else {
// Search left
while(node.point != edge.p) {
// Collect points
node = node.prev
}
}
}
// STEP 3: Triangulate empty areas. // STEP 3: Triangulate empty areas.
} }

View File

@ -35,7 +35,7 @@ import scala.collection.mutable.{ArrayBuffer, Queue}
import shapes.Point import shapes.Point
// Doubly linked list // Doubly linked list
class MonotoneMountain(buildTriangles: Boolean) { class MonotoneMountain {
var tail, head: Point = null var tail, head: Point = null
var size = 0 var size = 0
@ -108,10 +108,7 @@ class MonotoneMountain(buildTriangles: Boolean) {
p = p.next p = p.next
} }
if(buildTriangles) triangulate
triangulate
else
hertelMehlhorn
} }
@ -135,30 +132,7 @@ class MonotoneMountain(buildTriangles: Boolean) {
assert(size <= 3, "Triangulation bug, please report") assert(size <= 3, "Triangulation bug, please report")
} }
private def hertelMehlhorn {
while(!convexPoints.isEmpty) {
val ear = convexPoints.remove(0)
val a = ear.prev
val b = ear
val c = ear.next
val triangle = Array(a, b, c)
convexPolies += triangle
// Remove ear, update angles and convex list
remove(ear)
}
val polygon = new Array[Point](size)
var p = head
for(i <- 0 until size) {
polygon(i) = p
p = p.next
}
convexPolies += polygon
}
private def valid(p: Point) = (p != head && p != tail && convex(p)) private def valid(p: Point) = (p != head && p != tail && convex(p))
// Create the monotone polygon // Create the monotone polygon

View File

@ -43,9 +43,6 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
// Convex polygon list // Convex polygon list
var polygons = new ArrayBuffer[Array[Point]] var polygons = new ArrayBuffer[Array[Point]]
// Generate triangles vs non-convex polygons
// On by default
var buildTriangles = true
// Order and randomize the segments // Order and randomize the segments
val segmentList = orderSegments val segmentList = orderSegments
@ -149,7 +146,7 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
if(s.mPoints.size > 0) { if(s.mPoints.size > 0) {
val mountain = new MonotoneMountain(buildTriangles) val mountain = new MonotoneMountain
var k: List[Point] = null var k: List[Point] = null
// Sorting is a perfromance hit. Literature says this can be accomplised in // Sorting is a perfromance hit. Literature says this can be accomplised in
@ -173,20 +170,11 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
// Triangulate monotone mountain // Triangulate monotone mountain
mountain process mountain process
if(buildTriangles) { // Extract the triangles into a single list
// Extract the triangles into a single list j = 0
j = 0 while(j < mountain.triangles.size) {
while(j < mountain.triangles.size) { polygons += mountain.triangles(j)
polygons += mountain.triangles(j) j += 1
j += 1
}
} else {
// Extract the convex polygons into a single list
j = 0
while(j < mountain.convexPolies.size) {
polygons += mountain.convexPolies(j)
j += 1
}
} }
xMonoPoly += mountain xMonoPoly += mountain

View File

@ -53,13 +53,14 @@ class Segment(var p: Point, var q: Point) {
// Update point edge list for CDT // Update point edge list for CDT
def updateEdge { def updateEdge {
if(p.y > q.y) { if(q.y > p.y) {
// For CDT we want q to be the point with > y // For CDT we want q to be the point with > y
val tmp = p // val tmp = p
p = q //p = q
q = tmp //q = tmp
q.edges += this
} }
q.edges += this
} }
} }

View File

@ -30,6 +30,8 @@
*/ */
package org.poly2tri.shapes package org.poly2tri.shapes
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
// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator"
// "Triangulations in CGAL" // "Triangulations in CGAL"
@ -65,7 +67,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
} }
def contains(p: Point): Boolean = (p == points(0) || p == points(1) || p == points(2)) def contains(p: Point): Boolean = (p == points(0) || p == points(1) || p == points(2))
def contains(e: Segment): Boolean = (contains(e.p) || contains(e.q)) def contains(e: Segment): Boolean = (contains(e.p) && contains(e.q))
// Fast point in triangle test // Fast point in triangle test
def pointIn(point: Point): Boolean = { def pointIn(point: Point): Boolean = {
@ -86,7 +88,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
val p = edge.p val p = edge.p
if(contains(p)) return this if(contains(p)) return this
val q = edge.q val q = edge.q
val e = q - p val e = p - q
if(q == points(0)) { if(q == points(0)) {
val sameSign = Math.signum(ik cross e) == Math.signum(ij cross e) val sameSign = Math.signum(ik cross e) == Math.signum(ij cross e)
if(!sameSign) return this if(!sameSign) return this
@ -105,4 +107,15 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
} }
throw new Exception("location error") throw new Exception("location error")
} }
def findNeighbor(e: Point): Triangle = {
var sameSign = Math.signum(ik cross e) == Math.signum(ij cross e)
if(!sameSign) return neighbors(0)
sameSign = Math.signum(jk cross e) == Math.signum(ji cross e)
if(!sameSign) return neighbors(1)
sameSign = Math.signum(kj cross e) == Math.signum(ki cross e)
if(!sameSign) return neighbors(2)
this
}
} }