fixed collinear points bug

This commit is contained in:
zzzrrr 2009-07-16 07:48:57 -04:00
parent 2a27491146
commit 4b40deb5db
2 changed files with 28 additions and 16 deletions

View File

@ -43,8 +43,10 @@ class MonotoneMountain {
val monoPoly = new ArrayBuffer[Point] val monoPoly = new ArrayBuffer[Point]
// Triangles that constitute the mountain // Triangles that constitute the mountain
val triangles = new ArrayBuffer[Array[Point]] val triangles = new ArrayBuffer[Array[Point]]
// Used to track which side of the line we are on
var slop = 0.0f var positive = false
// Almost Pi!
val SLOP = 3.1
// Append a point to the list // Append a point to the list
def +=(point: Point) { def +=(point: Point) {
@ -83,10 +85,15 @@ class MonotoneMountain {
lastTriangle lastTriangle
} else { } else {
// Initialize internal angles at each nonbase vertex // Initialize internal angles at each nonbase vertex
// Link strictly convex vertices into a list, ignore reflex vertices
var p = head.next var p = head.next
while(p != tail) { while(p != tail) {
// Link strictly convex vertices into a list val a = angle(p)
if(convex(p)) convexPoints.enqueue(p) // If the point is almost colinear with it's neighbor, remove it!
if(a >= SLOP || a <= -SLOP)
remove(p)
else
if(convex(p)) convexPoints.enqueue(p)
p = p.next p = p.next
} }
@ -97,6 +104,7 @@ class MonotoneMountain {
val b = ear.clone val b = ear.clone
val c = ear.next.clone val c = ear.next.clone
val triangle = Array(a, b, c) val triangle = Array(a, b, c)
triangles += triangle triangles += triangle
// Remove ear, update angles and convex list // Remove ear, update angles and convex list
@ -105,17 +113,12 @@ class MonotoneMountain {
if(c.prev != null && convex(c)) convexPoints.enqueue(c) if(c.prev != null && convex(c)) convexPoints.enqueue(c)
} }
if(size >= 4) {
println("Size = " + size)
println(convex(head.next) + ", Angle: " + slop)
println(convex(head.next.next) + ", Angle: " + slop)
}
assert(size <= 3, "Triangulation bug") assert(size <= 3, "Triangulation bug")
if(size == 3)lastTriangle if(size == 3)lastTriangle
} }
} }
// Return the monotone polygon // Create the monotone polygon
private def genMonoPoly { private def genMonoPoly {
var p = head var p = head
while(p != null) { while(p != null) {
@ -124,13 +127,21 @@ class MonotoneMountain {
} }
} }
// Determines if the inslide angle between edge v2-v3 and edge v2-v1 is convex def angle(p: Point) = {
val a = (p.next - p)
val b = (p.prev - p)
Math.atan2(a cross b, a dot b)
}
// Determines if the inslide angle is convex or reflex
private def convex(p: Point) = { private def convex(p: Point) = {
val a = (p.next - p).normalize val cvx = (angle(p) >= 0)
val b = (p.prev - p).normalize if(p.prev == head)
slop = a dot b positive = cvx
slop = 0.1f * Math.round( slop * 10.0f) if(positive != cvx)
(slop >= 0f || slop == -1f || slop == 1f) false
else
true
} }
private def lastTriangle { private def lastTriangle {

View File

@ -45,6 +45,7 @@ class Point(val x: Float, val y: Float, var segment: Segment) {
def +(f: Float) = new Point(x + f, y + f) def +(f: Float) = new Point(x + f, y + f)
def *(f: Float) = new Point(x * f, y * f) def *(f: Float) = new Point(x * f, y * f)
def /(a: Float) = new Point(x / a, y / a) def /(a: Float) = new Point(x / a, y / a)
def cross(p: Point) = x * p.y - y * p.x
def dot(p: Point) = x * p.x + y * p.y def dot(p: Point) = x * p.x + y * p.y
def length = Math.sqrt(x * x + y * y).toFloat def length = Math.sqrt(x * x + y * y).toFloat
def normalize = this / length def normalize = this / length