From 4b40deb5dbbb2e002459a6289dfaa4a284ada716 Mon Sep 17 00:00:00 2001 From: zzzrrr Date: Thu, 16 Jul 2009 07:48:57 -0400 Subject: [PATCH] fixed collinear points bug --- src/org/poly2tri/MonoToneMountain.scala | 43 ++++++++++++++++--------- src/org/poly2tri/Point.scala | 1 + 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/org/poly2tri/MonoToneMountain.scala b/src/org/poly2tri/MonoToneMountain.scala index eec657e..c93346d 100644 --- a/src/org/poly2tri/MonoToneMountain.scala +++ b/src/org/poly2tri/MonoToneMountain.scala @@ -43,8 +43,10 @@ class MonotoneMountain { val monoPoly = new ArrayBuffer[Point] // Triangles that constitute the mountain val triangles = new ArrayBuffer[Array[Point]] - - var slop = 0.0f + // Used to track which side of the line we are on + var positive = false + // Almost Pi! + val SLOP = 3.1 // Append a point to the list def +=(point: Point) { @@ -83,10 +85,15 @@ class MonotoneMountain { lastTriangle } else { // Initialize internal angles at each nonbase vertex + // Link strictly convex vertices into a list, ignore reflex vertices var p = head.next while(p != tail) { - // Link strictly convex vertices into a list - if(convex(p)) convexPoints.enqueue(p) + val a = angle(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 } @@ -97,6 +104,7 @@ class MonotoneMountain { val b = ear.clone val c = ear.next.clone val triangle = Array(a, b, c) + triangles += triangle // Remove ear, update angles and convex list @@ -105,17 +113,12 @@ class MonotoneMountain { 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") if(size == 3)lastTriangle } } - // Return the monotone polygon + // Create the monotone polygon private def genMonoPoly { var p = head 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) = { - val a = (p.next - p).normalize - val b = (p.prev - p).normalize - slop = a dot b - slop = 0.1f * Math.round( slop * 10.0f) - (slop >= 0f || slop == -1f || slop == 1f) + val cvx = (angle(p) >= 0) + if(p.prev == head) + positive = cvx + if(positive != cvx) + false + else + true } private def lastTriangle { diff --git a/src/org/poly2tri/Point.scala b/src/org/poly2tri/Point.scala index 6e32b5c..438c3d7 100644 --- a/src/org/poly2tri/Point.scala +++ b/src/org/poly2tri/Point.scala @@ -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 /(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 length = Math.sqrt(x * x + y * y).toFloat def normalize = this / length