diff --git a/src/org/poly2tri/Poly2Tri.scala b/src/org/poly2tri/Poly2Tri.scala index 679ef54..e9ddcd5 100644 --- a/src/org/poly2tri/Poly2Tri.scala +++ b/src/org/poly2tri/Poly2Tri.scala @@ -82,7 +82,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { var currentModel = nazcaMonkey def init(container: GameContainer) { - selectModel + selectModel(currentModel) } def update(gc: GameContainer, delta: Int) { @@ -109,10 +109,10 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { 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) + 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) @@ -175,19 +175,19 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { hiLighter = tesselator.polygons.size-1 } if(c == 'm') drawMap = !drawMap - if(c == '1') {currentModel = nazcaMonkey; selectModel} - if(c == '2') {currentModel = bird; selectModel} - if(c == '3') {currentModel = strange; selectModel} - if(c == '4') {currentModel = snake; selectModel} - if(c == '5') {currentModel = star; selectModel} - if(c == '6') {currentModel = i18; selectModel} + if(c == '1') selectModel(nazcaMonkey) + if(c == '2') selectModel(bird) + if(c == '3') selectModel(strange) + if(c == '4') selectModel(snake) + if(c == '5') selectModel(star) + if(c == '6') selectModel(i18) if(c == 's') drawSegs = !drawSegs - if(c == 'e') {drawEarClip = !drawEarClip; selectModel} - if(c == 'h') {hertelMehlhorn = !hertelMehlhorn; selectModel} + if(c == 'e') {drawEarClip = !drawEarClip; selectModel(currentModel)} + if(c == 'h') {hertelMehlhorn = !hertelMehlhorn; selectModel(currentModel)} } - def selectModel { - currentModel match { + def selectModel(model: String) { + model match { case "data/nazca_monkey.dat" => loadModel(nazcaMonkey, 4.5f, Point(400, 300), 1500) case "data/bird.dat" => @@ -199,10 +199,11 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { case "data/strange.dat" => loadModel(strange, -1f, Point(0f, 0f), 15) case "data/i.18" => - loadModel(i18, 15f, Point(500f, 400f), 20) + loadModel(i18, 20f, Point(600f, 500f), 20) case _ => assert(false) } + currentModel = model } def loadModel(model: String, scale: Float, center: Point, maxTriangles: Int) { @@ -228,15 +229,13 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") { throw new Exception("Bad input file") } } - points.foreach(println) + segments = new ArrayBuffer[Segment] for(i <- 0 until polyX.size-1) segments += new Segment(points(i), points(i+1)) - // Connect the end points segments += new Segment(points.first, points.last) - val cdt = CDT.init(points) - println(cdt.points.size + "," + cdt.segments.size) + //val cdt = CDT.init(points) println("Number of points = " + polyX.size) println diff --git a/src/org/poly2tri/cdt/AFront.scala b/src/org/poly2tri/cdt/AFront.scala index b03e165..f8fe122 100644 --- a/src/org/poly2tri/cdt/AFront.scala +++ b/src/org/poly2tri/cdt/AFront.scala @@ -30,7 +30,34 @@ */ package org.poly2tri.cdt -// Advancing front -class AFront { +import shapes.{Point, Triangle} +// Advancing front +class AFront(iTriangle: Triangle) { + + // Doubly linked list + var head = new Node(iTriangle.points(0), iTriangle) + var tail = new Node(iTriangle.points(2), iTriangle) + + head.next = new Node(iTriangle.points(1), iTriangle) + head.next.next = tail + tail.prev = head.next + + def locate(point: Point): Tuple2[List[Point], Triangle] = { + var node = head + while(node != tail) { + if(point.x > node.point.x && point.x < node.next.point.x) + return (List(node.point, node.next.point), node.triangle) + node = node.next + } + null + } + + } + +class Node(val point: Point, val triangle: Triangle) { + + var next: Node = null + var prev: Node = null +} \ No newline at end of file diff --git a/src/org/poly2tri/cdt/CDT.scala b/src/org/poly2tri/cdt/CDT.scala index 5774f50..8b6f43e 100644 --- a/src/org/poly2tri/cdt/CDT.scala +++ b/src/org/poly2tri/cdt/CDT.scala @@ -45,10 +45,11 @@ object CDT { // Inital triangle factor val ALPHA = 0.3f + // Triangulate simple polygon def init(points: ArrayBuffer[Point]): CDT = { - var xmax, xmin = 0f - var ymax, ymin = 0f + var xmax, xmin = shearTransform(points.first).x + var ymax, ymin = shearTransform(points.first).y // Calculate bounds for(i <- 0 until points.size) { @@ -56,27 +57,32 @@ object CDT { val p = points(i) if(p.x > xmax) xmax = p.x if(p.x < xmin) xmin = p.x - if(p.y > ymax) ymax = p.x - if(p.y < ymin) ymin = p.x + if(p.y > ymax) ymax = p.y + if(p.y < ymin) ymin = p.y } val deltaX = ALPHA * (xmax - xmin) val deltaY = ALPHA * (ymax - ymin) val p1 = Point(xmin - deltaX, ymin - deltaY) - val p2 = Point(xmax - deltaX, ymin - deltaY) + val p2 = Point(xmax + deltaX, ymin - deltaY) - val initialTriangle = new Triangle(Array(p2, points(0), p1), null) val segments = initSegments(points) val sortedPoints = pointSort(points) + val initialTriangle = new Triangle(Array(p1, sortedPoints(0), p2), null) new CDT(sortedPoints, segments, initialTriangle) } - // Create segments and connect end points + // Create segments and connect end points; update edge event pointer private def initSegments(points: ArrayBuffer[Point]): List[Segment] = { var segments = List[Segment]() - for(i <- 0 until points.size-1) - segments = new Segment(points(i), points(i+1)) :: segments - segments = new Segment(points.first, points.last) :: segments + for(i <- 0 until points.size-1) { + val segment = new Segment(points(i), points(i+1)) + points(i+1).eEvent = segment + segments = segment :: segments + } + val segment = new Segment(points.first, points.last) + points.first.eEvent = segment + segments = segment :: segments segments } @@ -101,7 +107,9 @@ class CDT(val points: List[Point], val segments: List[Segment], initialTriangle: // The triangle mesh val mesh = new Mesh(initialTriangle) - + // Advancing front + val aFront = new AFront(initialTriangle) + // Sweep points; build mesh sweep // Finalize triangulation @@ -109,6 +117,14 @@ class CDT(val points: List[Point], val segments: List[Segment], initialTriangle: // Implement sweep-line paradigm private def sweep { + + for(i <- 1 until points.size) { + val point = points(i) + val triangle = aFront.locate(point) + val (nPoints, nTriangle) = triangle + println(nPoints) + } + } private def finalization { diff --git a/src/org/poly2tri/shapes/Point.scala b/src/org/poly2tri/shapes/Point.scala index dd98ad3..a81c1b0 100644 --- a/src/org/poly2tri/shapes/Point.scala +++ b/src/org/poly2tri/shapes/Point.scala @@ -38,8 +38,6 @@ case class Point(val x: Float, val y: Float) { var segment: Segment = null // Edge event pointer for CDT var eEvent: Segment = null - // Point event pointer for CDT - var pEvent: Segment = null @inline def -(p: Point) = Point(x - p.x, y - p.y) @inline def +(p: Point) = Point(x + p.x, y + p.y) diff --git a/src/org/poly2tri/shapes/Triangle.scala b/src/org/poly2tri/shapes/Triangle.scala index b0097c7..0708367 100644 --- a/src/org/poly2tri/shapes/Triangle.scala +++ b/src/org/poly2tri/shapes/Triangle.scala @@ -33,7 +33,7 @@ package org.poly2tri.shapes // Triangle-based data structures are know to have better performance than quad-edge structures // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" // "Triangulations in CGAL" -class Triangle(points: Array[Point], neighbors: Array[Triangle]) { +class Triangle(val points: Array[Point], val neighbors: Array[Triangle]) { // Flags to determine if an edge is the final Delauney edge val edges = new Array[Boolean](3)