mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-12-27 21:23:30 +01:00
updated comments; optimizations
This commit is contained in:
parent
122b2d6f40
commit
5811c2c0d1
@ -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)
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user