mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-12-02 02:03:30 +01:00
added slick2D rendering
This commit is contained in:
parent
236155e6ed
commit
89866779da
@ -30,9 +30,93 @@
|
|||||||
*/
|
*/
|
||||||
package org.poly2tri
|
package org.poly2tri
|
||||||
|
|
||||||
|
// Based on Raimund Seidel's paper "A simple and fast incremental randomized
|
||||||
|
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
|
||||||
|
// See also: "Computational Geometry", 3rd edition, by Mark de Berg et al, Chapter 6.2
|
||||||
|
// "Computational Geometry in C", 2nd edition, by Joseph O'Rourke
|
||||||
|
|
||||||
|
import org.newdawn.slick.{BasicGame, GameContainer, Graphics, Color, AppGameContainer}
|
||||||
|
import org.newdawn.slick.geom.Polygon
|
||||||
|
|
||||||
|
import collection.jcl.ArrayList
|
||||||
|
|
||||||
|
// TODO: Lots of documentation!
|
||||||
|
|
||||||
object Poly2Tri {
|
object Poly2Tri {
|
||||||
|
|
||||||
def main(args: Array[String]) {
|
def main(args: Array[String]) {
|
||||||
|
val container = new AppGameContainer(new Poly2TriDemo())
|
||||||
|
container.setDisplayMode(800,600,false)
|
||||||
|
container.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
||||||
|
|
||||||
|
var tesselator: Triangulator = null
|
||||||
|
var quit = false
|
||||||
|
|
||||||
|
def init(container: GameContainer) {
|
||||||
|
testTesselator
|
||||||
|
}
|
||||||
|
|
||||||
|
def update(gc: GameContainer, delta: Int) {
|
||||||
|
if(quit) gc exit
|
||||||
|
}
|
||||||
|
|
||||||
|
def render(container: GameContainer, g: Graphics) {
|
||||||
|
|
||||||
|
val red = new Color(1f,0.0f,0.0f)
|
||||||
|
val blue = new Color(0f, 0f, 1f)
|
||||||
|
val green = new Color(0f, 1f, 0f)
|
||||||
|
|
||||||
|
//for(t <- tesselator.allTrapezoids) {
|
||||||
|
for(t <- tesselator.trapezoids) {
|
||||||
|
val polygon = new Polygon()
|
||||||
|
for(v <- t.vertices) {
|
||||||
|
polygon.addPoint(v.x, v.y)
|
||||||
|
}
|
||||||
|
//g.setColor(red)
|
||||||
|
//g.draw(polygon)
|
||||||
|
}
|
||||||
|
|
||||||
|
for(x <- tesselator.xMonoPoly) {
|
||||||
|
var t = x.triangles
|
||||||
|
for(t <- x.triangles) {
|
||||||
|
val triangle = new Polygon()
|
||||||
|
t.foreach(p => triangle.addPoint(p.x, p.y))
|
||||||
|
g.setColor(green)
|
||||||
|
g.draw(triangle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def keyPressed(key:Int, c:Char) {
|
||||||
|
if(key == 1) quit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
def testTesselator {
|
||||||
|
|
||||||
|
val scale = 1.0f
|
||||||
|
val p1 = new Point(100,300)*scale
|
||||||
|
val p2 = new Point(400,500)*scale
|
||||||
|
val p3 = new Point(260,200)*scale
|
||||||
|
val p4 = new Point(600,175)*scale
|
||||||
|
val p5 = new Point(400,300)*scale
|
||||||
|
val p6 = new Point(650,250)*scale
|
||||||
|
|
||||||
|
val segments = new ArrayList[Segment]
|
||||||
|
segments += new Segment(p1, p2)
|
||||||
|
segments += new Segment(p3, p4)
|
||||||
|
segments += new Segment(p1, p3)
|
||||||
|
segments += new Segment(p5, p2)
|
||||||
|
segments += new Segment(p5, p6)
|
||||||
|
segments += new Segment(p4, p6)
|
||||||
|
|
||||||
|
tesselator = new Triangulator(segments)
|
||||||
|
tesselator.process
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -40,7 +40,7 @@ class TrapezoidalMap {
|
|||||||
// Trapezoid associated array
|
// Trapezoid associated array
|
||||||
val map = HashSet.empty[Trapezoid]
|
val map = HashSet.empty[Trapezoid]
|
||||||
// AABB margin
|
// AABB margin
|
||||||
var margin = 2f
|
var margin = 20f
|
||||||
|
|
||||||
// Bottom segment that spans multiple trapezoids
|
// Bottom segment that spans multiple trapezoids
|
||||||
private var bCross: Segment = null
|
private var bCross: Segment = null
|
||||||
|
@ -33,8 +33,6 @@ package org.poly2tri
|
|||||||
import collection.jcl.ArrayList
|
import collection.jcl.ArrayList
|
||||||
import scala.collection.mutable.{HashSet, Map, Stack, ListBuffer}
|
import scala.collection.mutable.{HashSet, Map, Stack, ListBuffer}
|
||||||
|
|
||||||
import utils.Random
|
|
||||||
|
|
||||||
// Based on Raimund Seidel's paper "A simple and fast incremental randomized
|
// Based on Raimund Seidel's paper "A simple and fast incremental randomized
|
||||||
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
|
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
|
||||||
class Triangulator(var segments: ArrayList[Segment]) {
|
class Triangulator(var segments: ArrayList[Segment]) {
|
||||||
@ -144,6 +142,7 @@ class Triangulator(var segments: ArrayList[Segment]) {
|
|||||||
segs += s
|
segs += s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// This is actually important: See Seidel's paper
|
||||||
Random.shuffle(segs)
|
Random.shuffle(segs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,124 +1,13 @@
|
|||||||
/* Poly2Tri
|
|
||||||
* Copyright (c) 2009, Mason Green
|
|
||||||
* http://code.google.com/p/poly2tri/
|
|
||||||
*
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* * Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* * Neither the name of Poly2Tri nor the names of its contributors may be
|
|
||||||
* used to endorse or promote products derived from this software without specific
|
|
||||||
* prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
||||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
||||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
package org.poly2tri
|
package org.poly2tri
|
||||||
|
|
||||||
import collection.jcl.ArrayList
|
import collection.jcl.ArrayList
|
||||||
|
|
||||||
import org.villane.vecmath.Vector2
|
|
||||||
|
|
||||||
object Util {
|
|
||||||
|
|
||||||
final def rotateLeft90(v:Vector2) = new Vector2( -v.y, v.x )
|
|
||||||
|
|
||||||
final def rotateRight90(v:Vector2) = new Vector2(v.y, -v.x )
|
|
||||||
|
|
||||||
final def rotate(v:Vector2, angle:Float) = {
|
|
||||||
val cos = Math.cos(angle).asInstanceOf[Float]
|
|
||||||
val sin = Math.sin(angle).asInstanceOf[Float]
|
|
||||||
val u = new Vector2((cos * v.x) - (sin * v.y), (cos * v.y) + (sin * v.x))
|
|
||||||
u
|
|
||||||
}
|
|
||||||
|
|
||||||
final def clamp(a: Float, low: Float, high: Float) =
|
|
||||||
if (a < low) low
|
|
||||||
else if (a > high) high
|
|
||||||
else a
|
|
||||||
|
|
||||||
final def left(a: Vector2, b: Vector2, c: Vector2) =
|
|
||||||
((b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y) > 0)
|
|
||||||
|
|
||||||
/** Melkman's Algorithm
|
|
||||||
* www.ams.sunysb.edu/~jsbm/courses/345/melkman.pdf
|
|
||||||
* Return a convex hull in ccw order
|
|
||||||
*/
|
|
||||||
def hull(V: Array[Vector2]) = {
|
|
||||||
|
|
||||||
val n = V.length
|
|
||||||
val D = new Array[Vector2](2 * n + 1)
|
|
||||||
var bot = n - 2
|
|
||||||
var top = bot + 3
|
|
||||||
|
|
||||||
D(bot) = V(2)
|
|
||||||
D(top) = V(2)
|
|
||||||
|
|
||||||
if (left(V(0), V(1), V(2))) {
|
|
||||||
D(bot+1) = V(0)
|
|
||||||
D(bot+2) = V(1)
|
|
||||||
} else {
|
|
||||||
D(bot+1) = V(1)
|
|
||||||
D(bot+2) = V(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = 3
|
|
||||||
while(i < n) {
|
|
||||||
while (left(D(bot), D(bot+1), V(i)) && left(D(top-1), D(top), V(i))) {
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
while (!left(D(top-1), D(top), V(i))) top -= 1
|
|
||||||
top += 1; D(top) = V(i)
|
|
||||||
while (!left(D(bot), D(bot+1), V(i))) bot += 1
|
|
||||||
bot -= 1; D(bot) = V(i)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
val H = new Array[Vector2](top - bot)
|
|
||||||
var h = 0
|
|
||||||
while(h < (top - bot)) {
|
|
||||||
H(h) = D(bot + h)
|
|
||||||
h += 1
|
|
||||||
}
|
|
||||||
H
|
|
||||||
}
|
|
||||||
|
|
||||||
def svgToWorld(points: Array[Float], scale: Float) = {
|
|
||||||
val verts = new Array[Vector2](points.length/2)
|
|
||||||
var i = 0
|
|
||||||
while(i < verts.length) {
|
|
||||||
verts(i) = worldPoint(points(i*2), points(i*2+1), scale)
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
verts
|
|
||||||
}
|
|
||||||
|
|
||||||
def worldPoint(x: Float, y: Float, scale: Float) = {
|
|
||||||
val p = Vector2(x*scale, y*scale)
|
|
||||||
p
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The object <code>Random</code> offers a default implementation
|
/** The object <code>Random</code> offers a default implementation
|
||||||
* of scala.util.Random and random-related convenience methods.
|
* of scala.util.Random and random-related convenience methods.
|
||||||
*
|
*
|
||||||
* @since 2.8
|
* @since 2.8
|
||||||
|
* From Scala 2.8 standard library
|
||||||
*/
|
*/
|
||||||
object Random extends scala.util.Random {
|
object Random extends scala.util.Random {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user