mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-30 01:03:30 +01:00
influence region
This commit is contained in:
parent
54b7fbd009
commit
6228342454
@ -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
|
||||||
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,29 +133,6 @@ class MonotoneMountain(buildTriangles: Boolean) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
@ -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,21 +170,12 @@ 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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user