mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-30 01:03:30 +01:00
restructure code
This commit is contained in:
parent
d48d3f4fc0
commit
328d8e4962
@ -76,7 +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 = false
|
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"
|
||||||
|
@ -67,12 +67,9 @@ class AFront(iTriangle: Triangle) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
def insert(tuple: Tuple3[Point, Triangle, Node]) = {
|
def insert(point: Point, triangle: Triangle, nNode: Node) = {
|
||||||
val (point, triangle, nNode) = tuple
|
|
||||||
val node = new Node(point, triangle)
|
val node = new Node(point, triangle)
|
||||||
// Update pointer
|
|
||||||
nNode.triangle = triangle
|
nNode.triangle = triangle
|
||||||
// Insert new node into advancing front
|
|
||||||
nNode.next.prev = node
|
nNode.next.prev = node
|
||||||
node.next = nNode.next
|
node.next = nNode.next
|
||||||
node.prev = nNode
|
node.prev = nNode
|
||||||
@ -80,6 +77,17 @@ class AFront(iTriangle: Triangle) {
|
|||||||
node
|
node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def insertLegalized(point: Point, triangle: Triangle, nNode: Node) = {
|
||||||
|
val node = new Node(triangle.points(1), triangle)
|
||||||
|
val rNode = nNode.next
|
||||||
|
rNode.prev = node
|
||||||
|
node.next = rNode
|
||||||
|
nNode.next = node
|
||||||
|
node.prev = nNode
|
||||||
|
node
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def -=(tuple: Tuple3[Node, Node, Triangle]) {
|
def -=(tuple: Tuple3[Node, Node, Triangle]) {
|
||||||
val (node, kNode, triangle) = tuple
|
val (node, kNode, triangle) = tuple
|
||||||
kNode.next.prev = node
|
kNode.next.prev = node
|
||||||
|
@ -137,7 +137,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
var triangle = pointEvent(point)
|
var triangle = pointEvent(point)
|
||||||
// Process edge events
|
// Process edge events
|
||||||
point.edges.foreach(e => triangle = edgeEvent(e, triangle))
|
point.edges.foreach(e => triangle = edgeEvent(e, triangle))
|
||||||
if(i == CDT.clearPoint) {cleanTri = triangle; mesh.debug += cleanTri}
|
if(i == CDT.clearPoint) {cleanTri = triangle; /*mesh.debug += cleanTri*/}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,72 +153,20 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
private def pointEvent(point: Point): Triangle = {
|
private def pointEvent(point: Point): Triangle = {
|
||||||
|
|
||||||
val node = aFront.locate(point)
|
val node = aFront.locate(point)
|
||||||
/*
|
|
||||||
// Projected point coincides with existing point; create two triangles
|
|
||||||
if(point.x == node.point.x && node.prev != null) {
|
|
||||||
|
|
||||||
val rPts = Array(point, node.point, node.next.point)
|
// Projected point hits advancing front; create new triangle
|
||||||
val rNeighbors = Array(node.triangle, null, null)
|
val pts = Array(point, node.point, node.next.point)
|
||||||
val rTriangle = new Triangle(rPts, rNeighbors)
|
val neighbors = Array(node.triangle, null, null)
|
||||||
|
val triangle = new Triangle(pts, neighbors)
|
||||||
|
mesh.map += triangle
|
||||||
|
|
||||||
val lPts = Array(point, node.prev.point, node.point)
|
// Legalize
|
||||||
val lNeighbors = Array(node.prev.triangle, rTriangle, null)
|
val newNode = legalization(triangle, node)
|
||||||
val lTriangle = new Triangle(lPts, lNeighbors)
|
|
||||||
|
|
||||||
rTriangle.neighbors(2) = lTriangle
|
// Fill in adjacent triangles if required
|
||||||
mesh.map += lTriangle
|
scanAFront(newNode)
|
||||||
mesh.map += rTriangle
|
newNode.triangle
|
||||||
|
|
||||||
// TODO: check to see of legalization is necessary here
|
|
||||||
|
|
||||||
// Update neighbors
|
|
||||||
node.triangle.markNeighbor(rTriangle.points(1), rTriangle.points(2), rTriangle, mesh.debug)
|
|
||||||
node.prev.triangle.markNeighbor(lTriangle.points(1), lTriangle.points(2), lTriangle, mesh.debug)
|
|
||||||
|
|
||||||
// Update advancing front
|
|
||||||
val newNode = aFront.insert(point, rTriangle, node)
|
|
||||||
node.prev.next = newNode
|
|
||||||
newNode.prev = node.prev
|
|
||||||
node.prev.triangle = lTriangle
|
|
||||||
|
|
||||||
// Fill in adjacent triangles if required
|
|
||||||
scanAFront(newNode)
|
|
||||||
newNode.triangle
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*/
|
|
||||||
// Projected point hits advancing front; create new triangle
|
|
||||||
val cwPoint = node.next.point
|
|
||||||
val ccwPoint = node.point
|
|
||||||
val nTri = node.triangle
|
|
||||||
|
|
||||||
val pts = Array(point, ccwPoint, cwPoint)
|
|
||||||
val neighbors = Array(nTri, null, null)
|
|
||||||
val triangle = new Triangle(pts, neighbors)
|
|
||||||
mesh.map += triangle
|
|
||||||
|
|
||||||
// Legalize
|
|
||||||
val legal = legalization(triangle, nTri)
|
|
||||||
var newNode: Node = null
|
|
||||||
|
|
||||||
// Update advancing front
|
|
||||||
if(legal) {
|
|
||||||
newNode = aFront.insert(point, triangle, node)
|
|
||||||
// Update neighbors
|
|
||||||
nTri.markNeighbor(cwPoint, ccwPoint, triangle, mesh.debug)
|
|
||||||
} else {
|
|
||||||
newNode = new Node(triangle.points(1), triangle)
|
|
||||||
val rNode = node.next
|
|
||||||
rNode.prev = newNode
|
|
||||||
newNode.next = rNode
|
|
||||||
node.next = newNode
|
|
||||||
newNode.prev = node
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in adjacent triangles if required
|
|
||||||
scanAFront(newNode)
|
|
||||||
newNode.triangle
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EdgeEvent
|
// EdgeEvent
|
||||||
@ -478,15 +426,13 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
|
|
||||||
if(cosA < 0 && cosB < 0)
|
if(cosA < 0 && cosB < 0)
|
||||||
return true
|
return true
|
||||||
else if(cosA > 0 && cosB > 0)
|
if(cosA > 0 && cosB > 0)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
val sinA = v1 cross v2
|
val sinA = v1 cross v2
|
||||||
val sinB = v3 cross v4
|
val sinB = v3 cross v4
|
||||||
|
|
||||||
// Small negative number to prevent swapping
|
if((cosA*sinB + sinA*cosB) < 0f)
|
||||||
// in nearly neutral cases
|
|
||||||
if((cosA*sinB + sinA*cosB) < -0.01f)
|
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
@ -494,40 +440,41 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
|
|
||||||
// Ensure adjacent triangles are legal
|
// Ensure adjacent triangles are legal
|
||||||
// If illegal, flip edges and update triangle's pointers
|
// If illegal, flip edges and update triangle's pointers
|
||||||
private def legalization(t1: Triangle, t2: Triangle): Boolean = {
|
private def legalization(t1: Triangle, node: Node): Node = {
|
||||||
|
|
||||||
|
val t2 = node.triangle
|
||||||
|
|
||||||
val oPoint = t2 oppositePoint t1
|
val oPoint = t2 oppositePoint t1
|
||||||
|
|
||||||
if(illegal(t1.points(1), oPoint, t1.points(2), t1.points(0))) {
|
if(illegal(t1.points(1), oPoint, t1.points(2), t1.points(0))) {
|
||||||
|
|
||||||
// Prevent creation of collinear traingles
|
// Flip edges and rotate everything clockwise
|
||||||
val c1 = t1.collinear(oPoint)
|
val point = t1.points(0)
|
||||||
val c2 = t2.collinear(oPoint, t1.points(0))
|
t1.legalize(oPoint)
|
||||||
|
t2.legalize(oPoint, point)
|
||||||
|
|
||||||
if(!c1 && !c2) {
|
// Update neighbor pointers
|
||||||
|
val neighbors = List(t2.neighbors(0), t2.neighbors(1), t2.neighbors(2))
|
||||||
|
for(n <- neighbors) {
|
||||||
|
if(n != null) {
|
||||||
|
t2.markNeighbor(n)
|
||||||
|
t1.markNeighbor(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t2.markNeighbor(t1)
|
||||||
|
|
||||||
// Update neighbor pointers
|
// Update advancing front
|
||||||
val ccwNeighbor = t2.neighborCCW(oPoint)
|
aFront.insertLegalized(point, t1, node)
|
||||||
|
|
||||||
if(ccwNeighbor != null) {
|
|
||||||
ccwNeighbor.markNeighbor(oPoint, t1.points(2), t1, mesh.debug)
|
|
||||||
t1.neighbors(1) = ccwNeighbor
|
|
||||||
}
|
|
||||||
|
|
||||||
t2.rotateNeighborsCW(oPoint, t1)
|
|
||||||
|
|
||||||
t1.neighbors(0) = t2
|
|
||||||
t1.neighbors(2) = null
|
|
||||||
|
|
||||||
// Flip edges and rotate everything clockwise
|
|
||||||
val point = t1.points(0)
|
|
||||||
t1.legalize(oPoint)
|
|
||||||
t2.legalize(oPoint, point)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
true
|
|
||||||
|
// Update neighbor
|
||||||
|
node.triangle.markNeighbor(t1)
|
||||||
|
// Update advancing front
|
||||||
|
aFront.insert(t1.points(0), t1, node)
|
||||||
|
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -88,13 +88,19 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def oppositePoint(t: Triangle) = {
|
def oppositePoint(t: Triangle): Point = {
|
||||||
if(points(0) == t.points(1))
|
if(points(0) == t.points(1))
|
||||||
points(1)
|
points(1)
|
||||||
else if(points(0) == t.points(2))
|
else if(points(0) == t.points(2))
|
||||||
points(2)
|
points(2)
|
||||||
else
|
else if((points(2) == t.points(1) && points(1) == t.points(2)) || (points(1) == t.points(1) && points(2) == t.points(2)))
|
||||||
points(0)
|
points(0)
|
||||||
|
else {
|
||||||
|
println("**********************")
|
||||||
|
t.printDebug
|
||||||
|
printDebug
|
||||||
|
throw new Exception("point location error")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
||||||
@ -176,10 +182,10 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The neighbor counter-clockwise to given point
|
// The neighbor counter-clockwise to given point
|
||||||
def neighborCCW(point: Point): Triangle = {
|
def neighborCCW(oPoint: Point): Triangle = {
|
||||||
if(point == points(0)) {
|
if(oPoint == points(0)) {
|
||||||
neighbors(2)
|
neighbors(2)
|
||||||
}else if(point == points(1)) {
|
}else if(oPoint == points(1)) {
|
||||||
neighbors(0)
|
neighbors(0)
|
||||||
} else
|
} else
|
||||||
neighbors(1)
|
neighbors(1)
|
||||||
|
@ -40,18 +40,9 @@ object Util {
|
|||||||
// Tests if the given points are collinear
|
// Tests if the given points are collinear
|
||||||
def collinear(p1: Point, p2: Point, p3: Point): Boolean = {
|
def collinear(p1: Point, p2: Point, p3: Point): Boolean = {
|
||||||
|
|
||||||
// 3x2 matrix
|
val d = (p2 - p1) cross (p1 - p3)
|
||||||
val a11 = p1.x
|
|
||||||
val a12 = p1.y
|
|
||||||
val a21 = p2.x
|
|
||||||
val a22 = p2.y
|
|
||||||
val a31 = p3.x
|
|
||||||
val a32 = p3.y
|
|
||||||
|
|
||||||
// Determinant
|
if(Math.abs(d) <= COLLINEAR_SLOP)
|
||||||
val d = a11*(a22-a32) - a12*(a21-a31) + (a21*a32-a31*a22)
|
|
||||||
|
|
||||||
if(d <= COLLINEAR_SLOP)
|
|
||||||
true
|
true
|
||||||
else
|
else
|
||||||
false
|
false
|
||||||
|
Loading…
Reference in New Issue
Block a user