updated comments; optimizations

This commit is contained in:
zzzzrrr 2009-08-21 22:28:49 -04:00
parent 122b2d6f40
commit 5811c2c0d1
6 changed files with 46 additions and 16 deletions

View File

@ -413,9 +413,10 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
headSegs = new ArrayBuffer[Segment]
for(i <- 0 until headHole.size-1)
chestSegs += new Segment(headHole(i), headHole(i+1))
chestSegs += new Segment(headHole.first, headHole.last)
headSegs += new Segment(headHole(i), headHole(i+1))
headSegs += new Segment(headHole.first, headHole.last)
// Add the holes
slCDT.addHole(headHole)
slCDT.addHole(chestHole)
}

View File

@ -99,6 +99,7 @@ class AFront(iTriangle: Triangle) {
val point2 = edge.p
// Scan the advancing front and update Node triangle pointers
// TODO: Make this more efficient
while(node != null && node != eNode.next) {
T2.foreach(t => {
if(t.contains(node.point, node.next.point))

View File

@ -45,6 +45,7 @@ import utils.Util
// and triangle traversal respectively. See figure 14(a) from Domiter et al.
// Although it may not be necessary for simple polygons....
// clearPoint is any interior point inside the polygon
class CDT(polyLine: Array[Point], clearPoint: Point) {
// Triangle list
@ -140,6 +141,7 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
private def sweep {
for(i <- 1 until points.size) {
val point = points(i)
// Process Point event
val node = pointEvent(point)
@ -149,18 +151,21 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
}
// Final step in the sweep-line CDT algo
// Final step in the sweep-line CDT
// Clean exterior triangles
private def finalization {
var found = false
mesh.map.foreach(m => {
if(!found)
// Mark the originating clean triangle
if(m.pointIn(clearPoint)) {
found = true
cleanTri = m
}
m.markNeighborEdges
})
// Collect interior triangles constrained by edges
mesh clean cleanTri
}
@ -367,7 +372,7 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
do {
angle = fill(node1)
node1 = node1.next
} while(angle <= PI_2 && node1.next != null)
} while(angle <= PI_2 && angle >= -PI_2 && node1.next != null)
}
var node2 = n.prev
@ -377,17 +382,19 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
do {
angle = fill(node2)
node2 = node2.prev
} while(angle <= PI_2 && node2.prev != null)
} while(angle <= PI_2 && angle >= -PI_2 && node2.prev != null)
}
}
// Fill empty space with a triangle
private def fill(node: Node): Double = {
val a = (node.prev.point - node.point)
val b = (node.next.point - node.point)
val angle = Math.abs(Math.atan2(a cross b, a dot b))
if(angle <= PI_2) {
val angle = Math.atan2(a cross b, a dot b)
// Is the angle acute?
if(angle <= PI_2 && angle >= -PI_2) {
val points = Array(node.prev.point, node.point, node.next.point)
val triangle = new Triangle(points)
// Update neighbor pointers

View File

@ -30,20 +30,23 @@
*/
package org.poly2tri.cdt
import scala.collection.mutable.{HashSet, ArrayBuffer}
import scala.collection.mutable.ArrayBuffer
import shapes.{Point, Triangle}
class Mesh {
// Triangles that constitute the mesh
val map = HashSet.empty[Triangle]
val map = new ArrayBuffer[Triangle]
// Debug triangles
val debug = HashSet.empty[Triangle]
val debug = new ArrayBuffer[Triangle]
val triangles = new ArrayBuffer[Triangle]
// Recursively collect triangles
// Recursively collect interior triangles and clean the mesh
// Excludes exterior triangles outside constrained edges
// TODO: Investigate depth first search as an alternative
def clean(triangle: Triangle) {
if(triangle != null && !triangle.interior) {
triangle.interior = true
triangles += triangle

View File

@ -30,7 +30,6 @@
*/
package org.poly2tri.shapes
import scala.collection.mutable.HashSet
import scala.collection.mutable.ArrayBuffer
import utils.Util
@ -80,6 +79,7 @@ class Triangle(val points: Array[Point]) {
neighbors(2) = t
t.markNeighbor(points(0), points(1), this)
}
}
def clearNeighbors {
@ -87,6 +87,7 @@ class Triangle(val points: Array[Point]) {
}
def oppositePoint(t: Triangle): Point = {
assert(t != this, "self-pointer error")
if(points(0) == t.points(1))
points(1)
@ -123,6 +124,7 @@ class Triangle(val points: Array[Point]) {
// Locate first triangle crossed by constrained edge
def locateFirst(edge: Segment): Triangle = {
if(contains(edge)) this
if(edge.q == points(0))
search(points(1), points(2), edge, neighbors(2))
@ -171,6 +173,7 @@ class Triangle(val points: Array[Point]) {
// The neighbor clockwise to given point
def neighborCW(point: Point): Triangle = {
if(point == points(0)) {
neighbors(1)
}else if(point == points(1)) {
@ -181,6 +184,7 @@ class Triangle(val points: Array[Point]) {
// The neighbor counter-clockwise to given point
def neighborCCW(oPoint: Point): Triangle = {
if(oPoint == points(0)) {
neighbors(2)
}else if(oPoint == points(1)) {
@ -191,6 +195,7 @@ class Triangle(val points: Array[Point]) {
// The neighbor clockwise to given point
def neighborAcross(point: Point): Triangle = {
if(point == points(0)) {
neighbors(0)
}else if(point == points(1)) {
@ -201,6 +206,7 @@ class Triangle(val points: Array[Point]) {
// The point counter-clockwise to given point
def pointCCW(point: Point): Point = {
if(point == points(0)) {
points(1)
} else if(point == points(1)) {
@ -214,6 +220,7 @@ class Triangle(val points: Array[Point]) {
// The point counter-clockwise to given point
def pointCW(point: Point): Point = {
if(point == points(0)) {
points(2)
} else if(point == points(1)) {
@ -227,6 +234,7 @@ class Triangle(val points: Array[Point]) {
// Legalized triangle by rotating clockwise around point(0)
def legalize(oPoint: Point) {
points(1) = points(0)
points(0) = points(2)
points(2) = oPoint
@ -234,6 +242,7 @@ class Triangle(val points: Array[Point]) {
// Legalize triagnle by rotating clockwise around oPoint
def legalize(oPoint: Point, nPoint: Point) {
if(oPoint == points(0)) {
points(1) = points(0)
points(0) = points(2)
@ -257,6 +266,7 @@ class Triangle(val points: Array[Point]) {
// Check if legalized triangle will be collinear
def collinear(oPoint: Point, nPoint: Point): Boolean = {
if(oPoint == points(0)) {
Util.collinear(points(0), points(2), nPoint)
} else if (oPoint == points(1)) {
@ -268,6 +278,7 @@ class Triangle(val points: Array[Point]) {
// Rotate neighbors clockwise around give point. Share diagnal with triangle
def rotateNeighborsCW(oPoint: Point, triangle: Triangle) {
if(oPoint == points(0)) {
neighbors(2) = neighbors(1)
neighbors(1) = null
@ -289,6 +300,7 @@ class Triangle(val points: Array[Point]) {
// Finalize edge marking
def markNeighborEdges {
for(i <- 0 to 2)
if(edges(i))
i match {
@ -299,6 +311,7 @@ class Triangle(val points: Array[Point]) {
}
def markEdge(triangle: Triangle) {
for(i <- 0 to 2)
if(edges(i))
i match {
@ -309,6 +322,7 @@ class Triangle(val points: Array[Point]) {
}
def markEdge(T: ArrayBuffer[Triangle]) {
for(t <- T) {
for(i <- 0 to 2)
if(t.edges(i))
@ -322,6 +336,7 @@ class Triangle(val points: Array[Point]) {
// Mark edge as constrained
def markEdge(p: Point, q: Point) {
if((q == points(0) && p == points(1)) || (q == points(1) && p == points(0))) {
finalized = true
edges(2) = true
@ -335,12 +350,14 @@ class Triangle(val points: Array[Point]) {
}
def area = {
val b = points(0).x - points(1).x
val h = points(2).y - points(1).y
(b*h*0.5f)
}
def centroid: Point = {
val cx = (points(0).x + points(1).x + points(2).x)/3f
val cy = (points(0).y + points(1).y + points(2).y)/3f
Point(cx, cy)

View File

@ -14,7 +14,7 @@ object Util {
val ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon
val iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon
// From "Scala By Example," by Martin Odersky
// Refursive merge sort, from "Scala By Example," by Martin Odersky
def msort[A](less: (A, A) => Boolean)(xs: List[A]): List[A] = {
def merge(xs1: List[A], xs2: List[A]): List[A] =
if (xs1.isEmpty) xs2
@ -26,6 +26,7 @@ object Util {
else merge(msort(less)(xs take n), msort(less)(xs drop n))
}
// Insertion sort - best for lists <= 10 elements
def insertSort[A](less: (A, A) => Boolean)(xs: ArrayBuffer[A]): ArrayBuffer[A] = {
var j = 1
while(j < xs.size){
@ -46,7 +47,7 @@ object Util {
val d = Math.abs((p2-p1) cross (p1-p3))
if(Math.abs(d) <= COLLINEAR_SLOP)
if(d <= COLLINEAR_SLOP)
true
else
false
@ -157,7 +158,7 @@ object Util {
(center, radius)
}
def det(p1: Point, p2: Point, p3: Point): Float = {
private def det(p1: Point, p2: Point, p3: Point): Float = {
val a11 = p1.x
val a12 = p1.y
@ -171,7 +172,7 @@ object Util {
}
def detC(p1: Point, p2: Point, p3: Point): Float = {
private def detC(p1: Point, p2: Point, p3: Point): Float = {
val a11 = p1.x*p1.x + p1.y*p1.y
val a12 = p1.x