mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-30 01:03:30 +01:00
edge event work
This commit is contained in:
parent
552cc3f564
commit
7d87363ba7
@ -76,6 +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 = true
|
||||||
|
|
||||||
val nazcaMonkey = "data/nazca_monkey.dat"
|
val nazcaMonkey = "data/nazca_monkey.dat"
|
||||||
val bird = "data/bird.dat"
|
val bird = "data/bird.dat"
|
||||||
@ -84,7 +85,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
val strange = "data/strange.dat"
|
val strange = "data/strange.dat"
|
||||||
val i18 = "data/i.18"
|
val i18 = "data/i.18"
|
||||||
|
|
||||||
var currentModel = star
|
var currentModel = i18
|
||||||
|
|
||||||
var mouseButton = 0
|
var mouseButton = 0
|
||||||
var mousePressed = false
|
var mousePressed = false
|
||||||
@ -167,7 +168,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if(drawCDT) {
|
if(drawCDT) {
|
||||||
slCDT.triangles.foreach( t => {
|
val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles
|
||||||
|
draw.foreach( t => {
|
||||||
val triangle = new Polygon
|
val triangle = new Polygon
|
||||||
triangle.addPoint(t.points(0).x, t.points(0).y)
|
triangle.addPoint(t.points(0).x, t.points(0).y)
|
||||||
triangle.addPoint(t.points(1).x, t.points(1).y)
|
triangle.addPoint(t.points(1).x, t.points(1).y)
|
||||||
@ -264,6 +266,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
if(c == '5') selectModel(star)
|
if(c == '5') selectModel(star)
|
||||||
if(c == '6') selectModel(i18)
|
if(c == '6') selectModel(i18)
|
||||||
if(c == 's') drawSegs = !drawSegs
|
if(c == 's') drawSegs = !drawSegs
|
||||||
|
if(c == 'c') drawcdtMesh = !drawcdtMesh
|
||||||
//if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)}
|
//if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ object CDT {
|
|||||||
class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Triangle) {
|
class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Triangle) {
|
||||||
|
|
||||||
// Triangle list
|
// Triangle list
|
||||||
def triangles = mesh.map
|
def triangles = mesh.triangles
|
||||||
def triangleMesh = mesh.map
|
def triangleMesh = mesh.map
|
||||||
def debugTriangles = mesh.debug
|
def debugTriangles = mesh.debug
|
||||||
|
|
||||||
@ -119,6 +119,9 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
private val PI_2 = Math.Pi/2
|
private val PI_2 = Math.Pi/2
|
||||||
private val PI_34 = Math.Pi*3/4
|
private val PI_34 = Math.Pi*3/4
|
||||||
|
|
||||||
|
// Triangle used to clean interior
|
||||||
|
var cleanTri: Triangle = null
|
||||||
|
|
||||||
// Sweep points; build mesh
|
// Sweep points; build mesh
|
||||||
sweep
|
sweep
|
||||||
// Finalize triangulation
|
// Finalize triangulation
|
||||||
@ -126,7 +129,6 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
|
|
||||||
// Implement sweep-line
|
// Implement sweep-line
|
||||||
private def sweep {
|
private def sweep {
|
||||||
//var cTri: Triangle = null
|
|
||||||
for(i <- 1 until points.size) {
|
for(i <- 1 until points.size) {
|
||||||
val point = points(i)
|
val point = points(i)
|
||||||
// Process Point event
|
// Process Point event
|
||||||
@ -139,12 +141,18 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
}
|
}
|
||||||
// Process edge events
|
// Process edge events
|
||||||
point.edges.foreach(e => edgeEvent(e, triangle))
|
point.edges.foreach(e => edgeEvent(e, triangle))
|
||||||
//if(i == 7) {cTri = triangle; mesh.debug += cTri}
|
//if(i == 7) {cleanTri = triangle; mesh.debug += cleanTri}
|
||||||
}
|
}
|
||||||
//mesh clean cTri
|
|
||||||
//mesh.map.foreach(m => m.edges.foreach(e => if(e) mesh.debug += m))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Final step in the sweep-line CDT algo
|
||||||
|
// Clean exterior triangles
|
||||||
|
private def finalization {
|
||||||
|
mesh.map.foreach(m => m.markEdges)
|
||||||
|
mesh clean cleanTri
|
||||||
|
//mesh.map.foreach(m => m.edges.foreach(e => if(e) mesh.debug += m))
|
||||||
|
}
|
||||||
|
|
||||||
// Point event
|
// Point event
|
||||||
private def pointEvent(point: Point): Triangle = {
|
private def pointEvent(point: Point): Triangle = {
|
||||||
|
|
||||||
@ -276,11 +284,14 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
|
|
||||||
// Mark constrained edges
|
// Mark constrained edges
|
||||||
val dEdge = new Segment(point1, point2)
|
val dEdge = new Segment(point1, point2)
|
||||||
T1.first mark dEdge
|
T1.first mark(point1, point2)
|
||||||
T2.first mark dEdge
|
T2.first mark(point1, point2)
|
||||||
|
|
||||||
|
//TODO update neighbor pointers
|
||||||
|
|
||||||
} else if(firstTriangle == null) {
|
} else if(firstTriangle == null) {
|
||||||
|
|
||||||
|
// NOTE: So far this only works for single triangles
|
||||||
// No triangles are intersected by the edge; edge must lie outside the mesh
|
// No triangles are intersected by the edge; edge must lie outside the mesh
|
||||||
// Apply constraint; traverse the AFront, and build triangles
|
// Apply constraint; traverse the AFront, and build triangles
|
||||||
|
|
||||||
@ -292,29 +303,45 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
var node = aFront.locate(point1)
|
var node = aFront.locate(point1)
|
||||||
val first = node
|
val first = node
|
||||||
|
|
||||||
|
node = node.next
|
||||||
|
|
||||||
while(node.point != point2) {
|
while(node.point != point2) {
|
||||||
points += node.point
|
points += node.point
|
||||||
node = node.next
|
node = node.next
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//assert(points.size == 1, "not implemented yet, points = " + points.size)
|
||||||
|
|
||||||
|
val endPoints = if(ahead) List(point2, point1) else List(point1, point2)
|
||||||
|
|
||||||
// STEP 3: Triangulate empty areas.
|
// STEP 3: Triangulate empty areas.
|
||||||
val T = new ArrayBuffer[Triangle]
|
val T = new ArrayBuffer[Triangle]
|
||||||
triangulate(points.toArray, List(point1, point2), T)
|
triangulate(points.toArray, endPoints, T)
|
||||||
|
|
||||||
// Update advancing front
|
// Update advancing front
|
||||||
first.triangle = T.first
|
aFront -= (first, node.prev, T.first)
|
||||||
first.next = node
|
|
||||||
node.prev = first
|
// Update neigbor pointers
|
||||||
|
if(ahead) {
|
||||||
|
T.first.neighbors(2) = node.prev.triangle;
|
||||||
|
T.first.neighbors(0) = first.triangle
|
||||||
|
node.prev.triangle.updateNeighbors(T.first.points(0), T.first.points(1), T.first, mesh.debug)
|
||||||
|
first.triangle.updateNeighbors(T.first.points(1), T.first.points(2), T.first, mesh.debug)
|
||||||
|
} else {
|
||||||
|
T.first.neighbors(2) = first.triangle;
|
||||||
|
T.first.neighbors(0) = node.prev.triangle
|
||||||
|
node.prev.triangle.updateNeighbors(T.first.points(1), T.first.points(2), T.first, mesh.debug)
|
||||||
|
first.triangle.updateNeighbors(T.first.points(0), T.first.points(1), T.first, mesh.debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark constrained edge
|
||||||
|
T.first mark(edge.p, edge.q)
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
// Mark constrained edge
|
// Mark constrained edge
|
||||||
val dEdge = new Segment(point1, point2)
|
firstTriangle mark(edge.p, edge.q)
|
||||||
T.first mark dEdge
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Mark constrained edge
|
|
||||||
if(contains)
|
|
||||||
firstTriangle mark edge
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marc Vigo Anglada's triangulate pseudo-polygon algo
|
// Marc Vigo Anglada's triangulate pseudo-polygon algo
|
||||||
@ -347,7 +374,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Scan left and right along AFront to fill holes
|
// Scan left and right along AFront to fill holes
|
||||||
def scanAFront(n: Node) {
|
private def scanAFront(n: Node) {
|
||||||
|
|
||||||
var node = n.next
|
var node = n.next
|
||||||
// Update right
|
// Update right
|
||||||
@ -371,7 +398,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill empty space with a triangle
|
// Fill empty space with a triangle
|
||||||
def fill(node: Node): Double = {
|
private def fill(node: Node): Double = {
|
||||||
val a = (node.prev.point - node.point)
|
val a = (node.prev.point - node.point)
|
||||||
val b = (node.next.point - node.point)
|
val b = (node.next.point - node.point)
|
||||||
val angle = Math.abs(Math.atan2(a cross b, a dot b))
|
val angle = Math.abs(Math.atan2(a cross b, a dot b))
|
||||||
@ -423,7 +450,7 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
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
|
// Prevent creation of collinear traingles
|
||||||
val c1 = t1.collinear(oPoint)
|
val c1 = t1.collinear(oPoint)
|
||||||
val c2 = t2.collinear(oPoint, t1.points(0))
|
val c2 = t2.collinear(oPoint, t1.points(0))
|
||||||
@ -453,11 +480,5 @@ class CDT(val points: List[Point], val segments: List[Segment], iTriangle: Trian
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Final step in the sweep-line CDT algo
|
|
||||||
private def finalization {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ class Mesh(initialTriangle: Triangle) {
|
|||||||
|
|
||||||
// Recursively collect triangles
|
// Recursively collect triangles
|
||||||
def clean(triangle: Triangle) {
|
def clean(triangle: Triangle) {
|
||||||
if(triangle != null && triangle.clean == false) {
|
if(triangle != null && !triangle.clean) {
|
||||||
triangle.clean = true
|
triangle.clean = true
|
||||||
triangles += triangle
|
triangles += triangle
|
||||||
if(!triangle.edges(0))
|
if(!triangle.edges(0))
|
||||||
|
@ -56,7 +56,7 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
|
|||||||
neighbors(2) = triangle
|
neighbors(2) = triangle
|
||||||
else {
|
else {
|
||||||
debug += triangle
|
debug += triangle
|
||||||
throw new Exception("Neighbor pointer error, please report!")
|
//throw new Exception("Neighbor pointer error, please report!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,22 +267,37 @@ class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) {
|
|||||||
ki = points(0) - points(2)
|
ki = points(0) - points(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
def mark(e: Segment) {
|
// Initial mark edges sweep
|
||||||
markEdge(e)
|
def mark(p: Point, q: Point) {
|
||||||
markNeighbors(e)
|
if(contains(p) && contains(q)) {
|
||||||
|
markEdge(p, q)
|
||||||
|
markNeighbors(p, q)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def markNeighbors(e: Segment) = neighbors.foreach(n => if(n != null) n.markEdge(e))
|
// Finalize edge marking
|
||||||
|
def markEdges {
|
||||||
|
for(i <- 0 to 2)
|
||||||
|
if(edges(i))
|
||||||
|
i match {
|
||||||
|
case 0 => if(neighbors(0) != null) neighbors(0).markEdge(points(1), points(2))
|
||||||
|
case 1 => if(neighbors(1) != null) neighbors(1).markEdge(points(0), points(2))
|
||||||
|
case _ => if(neighbors(2) != null) neighbors(2).markEdge(points(0), points(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark neighbor's edge
|
||||||
|
private def markNeighbors(p: Point, q: Point) = neighbors.foreach(n => if(n != null) n.markEdge(p, q))
|
||||||
|
|
||||||
// Mark edge as constrained
|
// Mark edge as constrained
|
||||||
private def markEdge(e: Segment) {
|
private def markEdge(p: Point, q: Point) {
|
||||||
if((e.q == points(0) && e.p == points(1)) || (e.q == points(1) && e.p == points(0))) {
|
if((q == points(0) && p == points(1)) || (q == points(1) && p == points(0))) {
|
||||||
edges(2) = true
|
edges(2) = true
|
||||||
} else if ((e.q == points(0) && e.p == points(2)) || (e.q == points(2) && e.p == points(0))) {
|
} else if ((q == points(0) && p == points(2)) || (q == points(2) && p == points(0))) {
|
||||||
edges(1) = true
|
edges(1) = true
|
||||||
} else {
|
} else if ((q == points(1) && p == points(2)) || (q == points(2) && p == points(1))){
|
||||||
edges(0) = true
|
edges(0) = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user