mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-12-29 06:03:31 +01:00
fixed rounding bug
This commit is contained in:
parent
c67d9d1b86
commit
a131fa7866
@ -42,8 +42,8 @@
|
|||||||
-7.61308 2.03218
|
-7.61308 2.03218
|
||||||
-7.18844 1.45589
|
-7.18844 1.45589
|
||||||
-6.79414 1.12225
|
-6.79414 1.12225
|
||||||
-6.64248.788605
|
-6.64248 0.788605
|
||||||
-6.36951.242648
|
-6.36951 0.242648
|
||||||
-6.24818 -0.212317
|
-6.24818 -0.212317
|
||||||
-6.00553 -0.515627
|
-6.00553 -0.515627
|
||||||
-5.73255 -0.818936
|
-5.73255 -0.818936
|
||||||
|
@ -57,17 +57,21 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
|
|
||||||
var tesselator: Triangulator = null
|
var tesselator: Triangulator = null
|
||||||
var segments: ArrayBuffer[Segment] = null
|
var segments: ArrayBuffer[Segment] = null
|
||||||
val earClip = new EarClip
|
|
||||||
|
|
||||||
|
val earClip = new EarClip
|
||||||
|
var earClipResults: Array[Triangle] = null
|
||||||
|
|
||||||
|
var polyX: ArrayBuffer[Float] = null
|
||||||
|
var polyY: ArrayBuffer[Float] = null
|
||||||
|
|
||||||
var quit = false
|
var quit = false
|
||||||
var debug = false
|
var debug = false
|
||||||
var drawMap = false
|
var drawMap = false
|
||||||
var drawSegs = true
|
var drawSegs = true
|
||||||
var hiLighter = 0
|
var hiLighter = 0
|
||||||
|
var drawEarClip = false
|
||||||
|
|
||||||
def init(container: GameContainer) {
|
def init(container: GameContainer) {
|
||||||
poly
|
|
||||||
earClipPoly
|
|
||||||
bird
|
bird
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +104,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!debug) {
|
if(!debug && !drawEarClip) {
|
||||||
var i = 0
|
var i = 0
|
||||||
for(t <- tesselator.triangles) {
|
for(t <- tesselator.triangles) {
|
||||||
val triangle = new Polygon
|
val triangle = new Polygon
|
||||||
@ -108,7 +112,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
g.setColor(red)
|
g.setColor(red)
|
||||||
g.draw(triangle)
|
g.draw(triangle)
|
||||||
}
|
}
|
||||||
} else if (debug && drawMap){
|
} else if (debug && drawMap && !drawEarClip){
|
||||||
for(mp <- tesselator.monoPolies) {
|
for(mp <- tesselator.monoPolies) {
|
||||||
val poly = new Polygon
|
val poly = new Polygon
|
||||||
mp.foreach(p => poly.addPoint(p.x, p.y))
|
mp.foreach(p => poly.addPoint(p.x, p.y))
|
||||||
@ -117,22 +121,24 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(drawEarClip)
|
||||||
|
earClipResults.foreach(t => {
|
||||||
|
val triangle = new Polygon
|
||||||
|
triangle.addPoint(t.x(0), t.y(0))
|
||||||
|
triangle.addPoint(t.x(1), t.y(1))
|
||||||
|
triangle.addPoint(t.x(2), t.y(2))
|
||||||
|
g.setColor(red)
|
||||||
|
g.draw(triangle)
|
||||||
|
})
|
||||||
|
|
||||||
if(drawSegs) {
|
if(drawSegs) {
|
||||||
g.setColor(green)
|
g.setColor(green)
|
||||||
for(s <- segments)
|
for(i <- 0 until segments.size) {
|
||||||
g.drawLine(s.p.x,s.p.y,s.q.x,s.q.y)
|
val s = segments(i)
|
||||||
|
g.drawLine(s.p.x,s.p.y,s.q.x,s.q.y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
earClipResults.foreach(t => {
|
|
||||||
val triangle = new Polygon
|
|
||||||
triangle.addPoint(t.x(0), t.y(0))
|
|
||||||
triangle.addPoint(t.x(1), t.y(1))
|
|
||||||
triangle.addPoint(t.x(2), t.y(2))
|
|
||||||
g.setColor(red)
|
|
||||||
g.draw(triangle)
|
|
||||||
})*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override def keyPressed(key:Int, c:Char) {
|
override def keyPressed(key:Int, c:Char) {
|
||||||
@ -153,11 +159,12 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
hiLighter = tesselator.triangles.size-1
|
hiLighter = tesselator.triangles.size-1
|
||||||
}
|
}
|
||||||
if(c == 'm') drawMap = !drawMap
|
if(c == 'm') drawMap = !drawMap
|
||||||
if(c == '1') {poly; earClipPoly; hiLighter = 0}
|
if(c == '1') bird
|
||||||
if(c == '2') {snake; hiLighter = 0}
|
if(c == '2') {poly; earClipPoly}
|
||||||
if(c == '3') {star; hiLighter = 0}
|
if(c == '3') snake
|
||||||
|
if(c == '4') star
|
||||||
if(c == 's') drawSegs = !drawSegs
|
if(c == 's') drawSegs = !drawSegs
|
||||||
|
if(c == 'e') drawEarClip = !drawEarClip
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test #1
|
// Test #1
|
||||||
@ -204,7 +211,6 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
val t2 = System.nanoTime
|
val t2 = System.nanoTime
|
||||||
println
|
println
|
||||||
println("**Poly1**")
|
println("**Poly1**")
|
||||||
println("Poly2Tri core (ms) = " + tesselator.coreTime*1e-6)
|
|
||||||
println("Poly2Tri total (ms) = " + (t2-t1)*1e-6)
|
println("Poly2Tri total (ms) = " + (t2-t1)*1e-6)
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -240,7 +246,6 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
val t2 = System.nanoTime
|
val t2 = System.nanoTime
|
||||||
println
|
println
|
||||||
println("**Star**")
|
println("**Star**")
|
||||||
println("Poly2Tri core (ms) = " + tesselator.coreTime*1e-6)
|
|
||||||
println("Poly2Tri total (ms) = " + (t2-t1)*1e-6)
|
println("Poly2Tri total (ms) = " + (t2-t1)*1e-6)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,15 +287,82 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
|
|||||||
val t2 = System.nanoTime
|
val t2 = System.nanoTime
|
||||||
println
|
println
|
||||||
println("**Snake**")
|
println("**Snake**")
|
||||||
println("Poly2Tri core (ms) = " + tesselator.coreTime*1e-6)
|
|
||||||
println("Poly2Tri total (ms) = " + (t2-t1)*1e-6)
|
println("Poly2Tri total (ms) = " + (t2-t1)*1e-6)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def bird {
|
def bird {
|
||||||
|
|
||||||
for (line <- Source.fromFile("data/bird.dat").getLines)
|
println("*** Bird ***")
|
||||||
print(line)
|
|
||||||
|
polyX = new ArrayBuffer[Float]
|
||||||
|
polyY = new ArrayBuffer[Float]
|
||||||
|
|
||||||
|
val scale = 25.0f
|
||||||
|
val center = Point(400, 300)
|
||||||
|
val angle = Math.Pi
|
||||||
|
for (line <- Source.fromFile("data/bird.dat").getLines) {
|
||||||
|
val s = line.replaceAll("\n", "")
|
||||||
|
val tokens = s.split("[ ]+")
|
||||||
|
if(tokens.size == 2) {
|
||||||
|
var x = tokens(0).toFloat
|
||||||
|
var y = tokens(1).toFloat
|
||||||
|
// Transform the shape
|
||||||
|
polyX += (Math.cos(angle)*x - Math.sin(angle)*y).toFloat * scale + center.x
|
||||||
|
polyY += (Math.sin(angle)*x + Math.cos(angle)*y).toFloat * scale + center.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
segments = new ArrayBuffer[Segment]
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
val numPoints = polyX.size
|
||||||
|
while(i < polyX.size-2) {
|
||||||
|
val p1 = new Point(polyX(i), polyY(i))
|
||||||
|
val p2 = new Point(polyX(i+1), polyY(i+1))
|
||||||
|
segments += new Segment(p1, p2)
|
||||||
|
i += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the end points
|
||||||
|
val p1 = segments(0).p
|
||||||
|
val p2 = segments(segments.length-1).q
|
||||||
|
segments += new Segment(p2, p1)
|
||||||
|
|
||||||
|
var t1: Float = 0f
|
||||||
|
var t2: Float = 0f
|
||||||
|
var runTime: Float = 0
|
||||||
|
val iterations = 100
|
||||||
|
|
||||||
|
println("Iteration count = " + iterations)
|
||||||
|
println("Seidel triangulation:")
|
||||||
|
|
||||||
|
for(i <- 0 until iterations) {
|
||||||
|
// Run benchmarks
|
||||||
|
tesselator = new Triangulator(segments)
|
||||||
|
t1 = System.nanoTime
|
||||||
|
tesselator.process
|
||||||
|
runTime += System.nanoTime - t1
|
||||||
|
}
|
||||||
|
println("Poly2Tri average (ms) = " + runTime*1e-6/iterations)
|
||||||
|
println("Number of triangles = " + tesselator.triangles.size)
|
||||||
|
|
||||||
|
println("Earclip triangulation:")
|
||||||
|
// Earclip
|
||||||
|
earClipResults = new Array[Triangle](500)
|
||||||
|
for(i <- 0 until earClipResults.size) earClipResults(i) = new Triangle
|
||||||
|
val xVerts = polyX.toArray.reverse
|
||||||
|
val yVerts = polyY.toArray.reverse
|
||||||
|
|
||||||
|
runTime = 0
|
||||||
|
for(i <- 0 until iterations) {
|
||||||
|
t1 = System.nanoTime
|
||||||
|
earClip.triangulatePolygon(xVerts, yVerts, xVerts.size, earClipResults)
|
||||||
|
runTime += System.nanoTime - t1
|
||||||
|
}
|
||||||
|
println("Earclip average (ms) = " + runTime*1e-6/iterations)
|
||||||
|
val numTriangles = earClip.triangulatePolygon(xVerts, yVerts, xVerts.size, earClipResults)
|
||||||
|
println("Number of triangles = " + numTriangles)
|
||||||
}
|
}
|
||||||
|
|
||||||
def earClipPoly {
|
def earClipPoly {
|
||||||
|
@ -47,8 +47,8 @@ class Segment(var p: Point, var q: Point) {
|
|||||||
val b = p.y - (p.x * slope)
|
val b = p.y - (p.x * slope)
|
||||||
|
|
||||||
// Determines if this segment lies above the given point
|
// Determines if this segment lies above the given point
|
||||||
def > (point: Point) = (point.y < Math.round(slope * point.x + b))
|
def > (point: Point) = (Math.floor(point.y) < Math.floor(slope * point.x + b))
|
||||||
// Determines if this segment lies below the given point
|
// Determines if this segment lies below the given point
|
||||||
def < (point: Point) = (point.y > Math.round(slope * point.x + b))
|
def < (point: Point) = (Math.floor(point.y) > Math.floor(slope * point.x + b))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,6 @@ import scala.collection.mutable.ArrayBuffer
|
|||||||
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
|
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
|
||||||
class Triangulator(segments: ArrayBuffer[Segment]) {
|
class Triangulator(segments: ArrayBuffer[Segment]) {
|
||||||
|
|
||||||
var sortTime = 0.0
|
|
||||||
var coreTime = 0.0
|
|
||||||
var trapezoidTime = 0.0
|
|
||||||
var markTime = 0.0
|
|
||||||
|
|
||||||
// Triangle decomposition list
|
// Triangle decomposition list
|
||||||
var triangles = new ArrayBuffer[Array[Point]]
|
var triangles = new ArrayBuffer[Array[Point]]
|
||||||
|
|
||||||
@ -49,14 +44,11 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
|
|||||||
|
|
||||||
// Build the trapezoidal map and query graph
|
// Build the trapezoidal map and query graph
|
||||||
def process {
|
def process {
|
||||||
|
|
||||||
val t1 = System.nanoTime
|
|
||||||
|
|
||||||
var i = 0
|
var i = 0
|
||||||
while(i < segmentList.size) {
|
while(i < segmentList.size) {
|
||||||
|
|
||||||
val s = segmentList(i)
|
val s = segmentList(i)
|
||||||
|
|
||||||
var traps = queryGraph.followSegment(s)
|
var traps = queryGraph.followSegment(s)
|
||||||
|
|
||||||
// Remove trapezoids from trapezoidal Map
|
// Remove trapezoids from trapezoidal Map
|
||||||
@ -104,8 +96,6 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
coreTime = System.nanoTime - t1
|
|
||||||
|
|
||||||
// Mark outside trapezoids
|
// Mark outside trapezoids
|
||||||
for(t <- trapezoidalMap.map)
|
for(t <- trapezoidalMap.map)
|
||||||
markOutside(t)
|
markOutside(t)
|
||||||
@ -174,9 +164,7 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Triangulate monotone mountain
|
// Triangulate monotone mountain
|
||||||
val t1 = System.nanoTime
|
|
||||||
mountain.triangulate
|
mountain.triangulate
|
||||||
coreTime += System.nanoTime - t1
|
|
||||||
|
|
||||||
// Extract the triangles into a single list
|
// Extract the triangles into a single list
|
||||||
j = 0
|
j = 0
|
||||||
|
@ -33,6 +33,7 @@ package org.poly2tri
|
|||||||
class XNode(point: Point, lChild: Node, rChild: Node) extends Node(lChild, rChild) {
|
class XNode(point: Point, lChild: Node, rChild: Node) extends Node(lChild, rChild) {
|
||||||
|
|
||||||
override def locate(s: Segment): Sink = {
|
override def locate(s: Segment): Sink = {
|
||||||
|
|
||||||
if(s.p.x >= point.x) {
|
if(s.p.x >= point.x) {
|
||||||
// Move to the right in the graph
|
// Move to the right in the graph
|
||||||
return right.locate(s)
|
return right.locate(s)
|
||||||
|
Loading…
Reference in New Issue
Block a user