mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-26 15:26:12 +01:00
updated demo framework
This commit is contained in:
parent
1f418be366
commit
6054e161da
@ -55,6 +55,12 @@ object Poly2Tri {
|
||||
|
||||
class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
|
||||
object Algo extends Enumeration {
|
||||
type Algo = Value
|
||||
val CDT, Seidel, EarClip = Value
|
||||
}
|
||||
import Algo._
|
||||
|
||||
// Sedidel Triangulator
|
||||
var seidel: Triangulator = null
|
||||
var segments: ArrayBuffer[Segment] = null
|
||||
@ -68,17 +74,10 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
// Sweep Line Constraied Delauney Triangulator (CDT)
|
||||
var slCDT: CDT = null
|
||||
|
||||
var polyX: ArrayBuffer[Float] = null
|
||||
var polyY: ArrayBuffer[Float] = null
|
||||
|
||||
var quit = false
|
||||
var debug = false
|
||||
var drawMap = false
|
||||
var drawSegs = true
|
||||
var hiLighter = 0
|
||||
var drawEarClip = false
|
||||
var drawCDT = true
|
||||
var drawcdtMesh = false
|
||||
var drawCDTMesh = false
|
||||
|
||||
val nazcaMonkey = "data/nazca_monkey.dat"
|
||||
val nazcaHeron = "data/nazca_heron_old.dat"
|
||||
@ -92,6 +91,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
|
||||
var currentModel = dude
|
||||
var doCDT = true
|
||||
// The current algorithm
|
||||
var algo = CDT
|
||||
|
||||
var mouseButton = 0
|
||||
var mousePressed = false
|
||||
@ -115,12 +116,11 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
|
||||
def render(container: GameContainer, g: Graphics) {
|
||||
|
||||
g.drawString("'1-9' to cycle models, mouse to pan & zoom", 10, 520)
|
||||
g.drawString("'SPACE' to show Seidel debug info", 10, 532)
|
||||
g.drawString("'m' to show trapezoidal map (Seidel debug mode)", 10, 544)
|
||||
g.drawString("'e' to switch Seidel / EarClip", 10, 556)
|
||||
g.drawString("'d' to switch CDT / Seidel", 10, 568)
|
||||
g.drawString("'c' to show CDT mesh, 's' to draw edges", 10, 580)
|
||||
g.drawString("'1-9' to cycle models, mouse to pan & zoom", 10, 522)
|
||||
g.drawString("'c,s,e' to switch CDT / Seidel / EarClip algos", 10, 537)
|
||||
g.drawString("'t' to show trapezoidal map (Seidel)", 10, 552)
|
||||
g.drawString("'m' to show triangle mesh (CDT)", 10, 567)
|
||||
g.drawString("'d' to draw edges", 10, 582)
|
||||
|
||||
g.scale(scaleFactor, scaleFactor)
|
||||
g.translate(deltaX, deltaY)
|
||||
@ -130,42 +130,34 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
val green = new Color(0f, 1f, 0f)
|
||||
val yellow = new Color(1f, 1f, 0f)
|
||||
|
||||
if(debug) {
|
||||
val draw = if(drawMap) seidel.trapezoidMap else seidel.trapezoids
|
||||
for(t <- draw) {
|
||||
val polygon = new Polygon()
|
||||
for(v <- t.vertices) {
|
||||
polygon.addPoint(v.x, v.y)
|
||||
}
|
||||
if(!drawMap) {
|
||||
val lCirc = new Circle(t.leftPoint.x, t.leftPoint.y, 4)
|
||||
g.setColor(blue); g.draw(lCirc); g.fill(lCirc)
|
||||
val rCirc = new Circle(t.rightPoint.x+5, t.rightPoint.y, 4)
|
||||
g.setColor(yellow); g.draw(rCirc); g.fill(rCirc)
|
||||
}
|
||||
g.setColor(red)
|
||||
g.draw(polygon)
|
||||
}
|
||||
}
|
||||
algo match {
|
||||
|
||||
if(!debug && !drawEarClip && !drawCDT) {
|
||||
var i = 0
|
||||
case Algo.Seidel => {
|
||||
for(t <- seidel.polygons) {
|
||||
val poly = new Polygon
|
||||
t.foreach(p => poly.addPoint(p.x, p.y))
|
||||
g.setColor(red)
|
||||
g.draw(poly)
|
||||
}
|
||||
} else if (debug && drawMap && !drawEarClip){
|
||||
if (drawMap) {
|
||||
for(t <- seidel.trapezoidMap) {
|
||||
val polygon = new Polygon()
|
||||
for(v <- t.vertices) {
|
||||
polygon.addPoint(v.x, v.y)
|
||||
}
|
||||
g.setColor(red)
|
||||
g.draw(polygon)
|
||||
}/*
|
||||
for(mp <- seidel.monoPolies) {
|
||||
val poly = new Polygon
|
||||
mp.foreach(p => poly.addPoint(p.x, p.y))
|
||||
g.setColor(yellow)
|
||||
g.draw(poly)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
if(drawEarClip)
|
||||
case Algo.EarClip => {
|
||||
earClipResults.foreach(t => {
|
||||
val triangle = new Polygon
|
||||
triangle.addPoint(t.x(0), t.y(0))
|
||||
@ -174,31 +166,17 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
g.setColor(red)
|
||||
g.draw(triangle)
|
||||
})
|
||||
|
||||
if(drawCDT) {
|
||||
|
||||
val draw = if(drawcdtMesh) slCDT.triangleMesh else slCDT.triangles
|
||||
|
||||
draw.foreach( t => {
|
||||
if(false) {
|
||||
for(i <- 0 to 2) {
|
||||
val s = t.points(i)
|
||||
val e = if(i == 2) t.points(0) else t.points(i + 1)
|
||||
val j = if(i == 0) 2 else if(i == 1) 0 else 1
|
||||
if(t.edges(j))
|
||||
g.setColor(yellow)
|
||||
else
|
||||
g.setColor(red)
|
||||
g.drawLine(s.x,s.y,e.x,e.y)
|
||||
}
|
||||
} else {
|
||||
|
||||
case Algo.CDT => {
|
||||
val draw = if(drawCDTMesh) slCDT.triangleMesh else slCDT.triangles
|
||||
draw.foreach( t => {
|
||||
val triangle = new Polygon
|
||||
triangle.addPoint(t.points(0).x, t.points(0).y)
|
||||
triangle.addPoint(t.points(1).x, t.points(1).y)
|
||||
triangle.addPoint(t.points(2).x, t.points(2).y)
|
||||
g.setColor(red)
|
||||
g.draw(triangle)
|
||||
}
|
||||
})
|
||||
|
||||
slCDT.debugTriangles.foreach( t => {
|
||||
@ -210,15 +188,16 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
g.draw(triangle)
|
||||
})
|
||||
|
||||
//slCDT.cList.foreach(c => {
|
||||
for(i <- 0 until slCDT.cList.size) {
|
||||
val circ = new Circle(slCDT.cList(i).x, slCDT.cList(i).y, 0.5f)
|
||||
g.setColor(blue); g.draw(circ); g.fill(circ)
|
||||
}
|
||||
//})
|
||||
|
||||
}
|
||||
|
||||
case _ =>
|
||||
}
|
||||
|
||||
if(drawSegs) {
|
||||
g.setColor(green)
|
||||
for(i <- 0 until segments.size) {
|
||||
@ -246,6 +225,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
* @param p The screen location that the mouse is down at.
|
||||
*/
|
||||
override def mousePressed(b: Int, x: Int, y: Int) {
|
||||
|
||||
mouseButton = b
|
||||
mousePressed = true
|
||||
mousePosOld = mousePos
|
||||
@ -296,23 +276,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
|
||||
// ESC
|
||||
if(key == 1) quit = true
|
||||
// SPACE
|
||||
if(key == 57) debug = !debug
|
||||
// UP
|
||||
if(key == 200) {
|
||||
hiLighter += 1
|
||||
if (hiLighter == seidel.polygons.size)
|
||||
hiLighter = 0
|
||||
}
|
||||
// DOWN
|
||||
if(key == 208) {
|
||||
hiLighter -= 1
|
||||
if (hiLighter == -1)
|
||||
hiLighter = seidel.polygons.size-1
|
||||
}
|
||||
|
||||
if(c == 'm') drawMap = !drawMap
|
||||
if(c == 'd') drawCDT = !drawCDT
|
||||
if(c == '1') selectModel(nazcaMonkey)
|
||||
if(c == '2') selectModel(bird)
|
||||
if(c == '3') selectModel(strange)
|
||||
@ -322,9 +286,16 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
if(c == '7') selectModel(nazcaHeron)
|
||||
if(c == '8') selectModel(tank)
|
||||
if(c == '9') selectModel(dude)
|
||||
if(c == 's') drawSegs = !drawSegs
|
||||
if(c == 'c') drawcdtMesh = !drawcdtMesh
|
||||
if(c == 'e') {drawEarClip = !drawEarClip; drawCDT = false; selectModel(currentModel)}
|
||||
|
||||
if(c == 'd') drawSegs = !drawSegs
|
||||
if(c == 'm') drawCDTMesh = !drawCDTMesh
|
||||
if(c == 't') drawMap = !drawMap
|
||||
|
||||
if(c == 's') {algo = Seidel; selectModel(currentModel) }
|
||||
if(c == 'c') {algo = CDT; selectModel(currentModel) }
|
||||
if(c == 'e') {algo = EarClip; selectModel(currentModel) }
|
||||
|
||||
// Experimental...
|
||||
if(c == 'r') slCDT.refine
|
||||
|
||||
}
|
||||
@ -359,8 +330,6 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
val clearPoint = Point(365, 427)
|
||||
loadModel(dude, -1f, Point(100f, -200f), 10, clearPoint)
|
||||
case _ =>
|
||||
assert(false)
|
||||
|
||||
}
|
||||
currentModel = model
|
||||
}
|
||||
@ -370,8 +339,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
println
|
||||
println("************** " + model + " **************")
|
||||
|
||||
polyX = new ArrayBuffer[Float]
|
||||
polyY = new ArrayBuffer[Float]
|
||||
val polyX = new ArrayBuffer[Float]
|
||||
val polyY = new ArrayBuffer[Float]
|
||||
var points = new ArrayBuffer[Point]
|
||||
|
||||
val angle = Math.Pi
|
||||
@ -398,7 +367,9 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
println("Number of points = " + polyX.size)
|
||||
println
|
||||
|
||||
if(doCDT) {
|
||||
algo match {
|
||||
|
||||
case Algo.CDT => {
|
||||
|
||||
val pts = points.toArray
|
||||
|
||||
@ -448,17 +419,19 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
println
|
||||
}
|
||||
|
||||
if(!drawEarClip) {
|
||||
case Algo.Seidel => {
|
||||
|
||||
// Sediel triangulation
|
||||
val t1 = System.nanoTime
|
||||
seidel = new Triangulator(points)
|
||||
val runTime = System.nanoTime - t1
|
||||
|
||||
println("Poly2Tri average (ms) = " + runTime*1e-6)
|
||||
println("Seidel average (ms) = " + runTime*1e-6)
|
||||
println("Number of triangles = " + seidel.polygons.size)
|
||||
|
||||
} else {
|
||||
}
|
||||
|
||||
case Algo.EarClip => {
|
||||
|
||||
// Earclip
|
||||
|
||||
@ -469,14 +442,19 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||
var xVerts = polyX.toArray
|
||||
var yVerts = polyY.toArray
|
||||
|
||||
val xv = if(currentModel != "data/strange.dat") xVerts.reverse.toArray else xVerts
|
||||
val yv = if(currentModel != "data/strange.dat") yVerts.reverse.toArray else yVerts
|
||||
|
||||
val t1 = System.nanoTime
|
||||
earClip.triangulatePolygon(xVerts, yVerts, xVerts.size, earClipResults)
|
||||
earClip.triangulatePolygon(xv, yv, xVerts.size, earClipResults)
|
||||
val runTime = System.nanoTime - t1
|
||||
|
||||
println
|
||||
println("Earclip average (ms) = " + runTime*1e-6)
|
||||
println("Number of triangles = " + earClip.numTriangles)
|
||||
}
|
||||
}
|
||||
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
@ -109,23 +109,19 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
|
||||
|
||||
// Create edges and connect end points; update edge event pointer
|
||||
private def initEdges(pts: Array[Point]) {
|
||||
|
||||
// Connect pts
|
||||
for(i <- 0 until pts.size-1) {
|
||||
val endPoints = validatePoints(pts(i), pts(i+1))
|
||||
val edge = new Segment(endPoints(0), endPoints(1))
|
||||
endPoints(1).edges += edge
|
||||
}
|
||||
|
||||
// Connect endpoints
|
||||
val endPoints = validatePoints(pts.first, pts.last)
|
||||
val edge = new Segment(endPoints(0), endPoints(1))
|
||||
endPoints(1).edges += edge
|
||||
|
||||
}
|
||||
|
||||
private def validatePoints(p1: Point, p2: Point): List[Point] = {
|
||||
|
||||
if(p1.y > p2.y) {
|
||||
// For CDT we want q to be the point with > y
|
||||
return List(p2, p1)
|
||||
@ -138,7 +134,6 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
|
||||
throw new Exception("Duplicate point")
|
||||
}
|
||||
}
|
||||
|
||||
List(p1, p2)
|
||||
}
|
||||
|
||||
@ -148,24 +143,19 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
|
||||
|
||||
// Implement sweep-line
|
||||
private def sweep {
|
||||
|
||||
val size = if(refined) 1 else points.size
|
||||
|
||||
for(i <- 1 until points.size) {
|
||||
|
||||
val point = points(i)
|
||||
// Process Point event
|
||||
val node = pointEvent(point)
|
||||
// Process edge events
|
||||
point.edges.foreach(e => edgeEvent(e, node))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Final step in the sweep-line CDT
|
||||
// Clean exterior triangles
|
||||
private def finalization {
|
||||
|
||||
var found = false
|
||||
mesh.map.foreach(m => {
|
||||
if(!found)
|
||||
@ -178,7 +168,6 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
|
||||
})
|
||||
// Collect interior triangles constrained by edges
|
||||
mesh clean cleanTri
|
||||
|
||||
}
|
||||
|
||||
// Delauney Refinement: Refine triangules using Steiner points
|
||||
@ -484,15 +473,12 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
|
||||
// Circumcircle test.
|
||||
// Determines if point d lies inside triangle abc's circumcircle
|
||||
private def illegal(a: Point, b: Point, c: Point, d: Point): Boolean = {
|
||||
|
||||
val ccw = Util.orient2d(a, b, c) > 0
|
||||
|
||||
// Make sure abc is oriented counter-clockwise
|
||||
if(ccw)
|
||||
Util.incircle(a, b, c, d)
|
||||
else
|
||||
Util.incircle(a, c, b, d)
|
||||
|
||||
}
|
||||
|
||||
// Ensure adjacent triangles are legal
|
||||
@ -545,7 +531,6 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
|
||||
aFront.insert(point, t1, node)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The triangle mesh
|
||||
|
@ -38,18 +38,7 @@ class EarClip {
|
||||
|
||||
var numTriangles = 0
|
||||
|
||||
def triangulatePolygon(x: Array[Float], y: Array[Float], vn: Int, results: Array[Triangle]): Int = {
|
||||
|
||||
/*
|
||||
val p1 = Point(x(0), y(0))
|
||||
val p2 = Point(x(1), y(1))
|
||||
val p3 = Point(x(2), y(2))
|
||||
|
||||
val ccw = Util.orient2d(p1, p2, p3) > 0
|
||||
*/
|
||||
|
||||
val xv = x.reverse.toArray
|
||||
val yv = y.reverse.toArray
|
||||
def triangulatePolygon(xv: Array[Float], yv: Array[Float], vn: Int, results: Array[Triangle]): Int = {
|
||||
|
||||
if (vn < 3) return 0
|
||||
var vNum = vn
|
||||
@ -133,6 +122,9 @@ class EarClip {
|
||||
|
||||
System.out.println("Couldn't find an ear, dumping remaining poly:\n");
|
||||
System.out.println("Please submit this dump to ewjordan at Box2d forums\n");
|
||||
|
||||
assert(false)
|
||||
|
||||
for (i <- 0 until bufferSize) {
|
||||
results(i).set(buffer(i));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user