mirror of
https://github.com/jhasse/poly2tri.git
synced 2024-11-26 15:26:12 +01:00
init CDT
This commit is contained in:
parent
f75a0a2974
commit
3ededbd3d0
@ -28,14 +28,75 @@
|
||||
* 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.cdt
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
import shapes.{Segment, Point}
|
||||
import utils.Util
|
||||
|
||||
/**
|
||||
* Sweep-line, Constrained Delauney Triangulation
|
||||
* See: Domiter, V. and Žalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
|
||||
* International Journal of Geographical Information Science,22:4,449 — 462
|
||||
*/
|
||||
package org.poly2tri.cdt
|
||||
|
||||
class CDT {
|
||||
class CDT(segments: ArrayBuffer[Segment]) {
|
||||
|
||||
// The point list
|
||||
val points = init
|
||||
// The triangle mesh
|
||||
val mesh = new Mesh
|
||||
|
||||
// Sweep points; build mesh
|
||||
sweep
|
||||
// Finalize triangulation
|
||||
finalization
|
||||
|
||||
// Initialize and sort point list
|
||||
private def init: List[Point] = {
|
||||
|
||||
var xmax, xmin = 0f
|
||||
var ymax, ymin = 0f
|
||||
val pts = new ArrayBuffer[Point]
|
||||
|
||||
for(i <- 0 until segments.size) {
|
||||
|
||||
val p = segments(i).p
|
||||
val q = segments(i).q
|
||||
|
||||
if(p.x > xmax) xmax = p.x
|
||||
if(q.x > xmax) xmax = q.x
|
||||
if(p.x < xmin) xmin = p.x
|
||||
if(q.x < xmin) xmin = q.x
|
||||
|
||||
if(p.y > ymax) ymax = p.x
|
||||
if(q.y > ymax) ymax = q.x
|
||||
if(p.y < ymin) ymin = p.x
|
||||
if(q.y < ymin) ymin = q.x
|
||||
|
||||
|
||||
pts += shearTransform(p)
|
||||
pts += shearTransform(q)
|
||||
}
|
||||
|
||||
if(pts.size < 10)
|
||||
// Insertion sort is one of the fastest algorithms for sorting arrays containing
|
||||
// fewer than ten elements, or for lists that are already mostly sorted.
|
||||
Util.insertSort((p1: Point, p2: Point) => p1 > p2)(pts).toList
|
||||
else
|
||||
// Merge sort: O(n log n)
|
||||
Util.msort((p1: Point, p2: Point) => p1 > p2)(pts.toList)
|
||||
}
|
||||
|
||||
// Implement sweep-line paradigm
|
||||
private def sweep {
|
||||
}
|
||||
|
||||
private def finalization {
|
||||
}
|
||||
|
||||
// Prevents any two distinct endpoints from lying on a common horizontal line, and avoiding
|
||||
// the degenerate case. See Mark de Berg et al, Chapter 6.3
|
||||
//val SHEER = 0.0001f
|
||||
def shearTransform(point: Point) = Point(point.x, point.y + point.x * 0.0001f)
|
||||
}
|
||||
|
@ -31,7 +31,9 @@
|
||||
package org.poly2tri.cdt
|
||||
|
||||
import scala.collection.mutable.HashSet
|
||||
|
||||
|
||||
import shapes.Point
|
||||
|
||||
class Mesh {
|
||||
|
||||
val map = HashSet.empty[Triangle]
|
||||
|
@ -158,7 +158,7 @@ class Triangulator(segments: ArrayBuffer[Segment]) {
|
||||
if(s.mPoints.size < 10)
|
||||
// Insertion sort is one of the fastest algorithms for sorting arrays containing
|
||||
// fewer than ten elements, or for lists that are already mostly sorted.
|
||||
k = Util.insertSort(s.mPoints).toList
|
||||
k = Util.insertSort((p1: Point, p2: Point) => p1 < p2)(s.mPoints).toList
|
||||
else
|
||||
k = Util.msort((p1: Point, p2: Point) => p1 < p2)(s.mPoints.toList)
|
||||
|
||||
|
@ -30,10 +30,18 @@
|
||||
*/
|
||||
package org.poly2tri.shapes
|
||||
|
||||
object Event extends Enumeration {
|
||||
val point, edge = Value
|
||||
}
|
||||
|
||||
case class Point(val x: Float, val y: Float) {
|
||||
|
||||
// Pointers to next and previous points in Monontone Mountain
|
||||
var next, prev: Point = null
|
||||
// The setment this point belongs to
|
||||
var segment: Segment = null
|
||||
// Point type for CDT
|
||||
var eventType: Event.Value = _
|
||||
|
||||
@inline def -(p: Point) = Point(x - p.x, y - p.y)
|
||||
@inline def +(p: Point) = Point(x + p.x, y + p.y)
|
||||
@ -45,7 +53,10 @@ case class Point(val x: Float, val y: Float) {
|
||||
@inline def dot(p: Point) = x * p.x + y * p.y
|
||||
@inline def length = Math.sqrt(x * x + y * y).toFloat
|
||||
@inline def normalize = this / length
|
||||
@inline def <(p: Point) = (x < p.x)
|
||||
// Sort along x axis
|
||||
@inline def <(p: Point) = (x < p.x)
|
||||
// Sort along y axis
|
||||
@inline def >(p: Point) = (y < p.y)
|
||||
@inline def !(p: Point) = !(p.x == x && p.y == y)
|
||||
@inline override def clone = Point(x, y)
|
||||
}
|
||||
|
@ -35,11 +35,13 @@ import scala.collection.mutable.{ArrayBuffer}
|
||||
// Represents a simple polygon's edge
|
||||
class Segment(var p: Point, var q: Point) {
|
||||
|
||||
p.segment = this
|
||||
q.segment = this
|
||||
|
||||
// Pointers used for building trapezoidal map
|
||||
var above, below: Trapezoid = null
|
||||
// Montone mountain points
|
||||
val mPoints = new ArrayBuffer[Point]
|
||||
|
||||
// Equation of a line: y = m*x + b
|
||||
// Slope of the line (m)
|
||||
val slope = (q.y - p.y)/(q.x - p.x)
|
||||
@ -50,5 +52,28 @@ class Segment(var p: Point, var q: Point) {
|
||||
def > (point: Point) = (Math.floor(point.y) < Math.floor(slope * point.x + b))
|
||||
// Determines if this segment lies below the given point
|
||||
def < (point: Point) = (Math.floor(point.y) > Math.floor(slope * point.x + b))
|
||||
|
||||
// Assign point type for CDT
|
||||
if(p.y > q.y)
|
||||
pEdge
|
||||
else if (p.y < q.y)
|
||||
pPoint
|
||||
else
|
||||
if(p.x < q.x)
|
||||
pPoint
|
||||
else if (p.x > q.x)
|
||||
pEdge
|
||||
else
|
||||
throw new Exception("Invalid segment")
|
||||
|
||||
private def pPoint {
|
||||
p.eventType = Event.point
|
||||
q.eventType = Event.edge
|
||||
}
|
||||
|
||||
private def pEdge {
|
||||
p.eventType = Event.edge
|
||||
q.eventType = Event.point
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,19 +19,19 @@ object Util {
|
||||
else merge(msort(less)(xs take n), msort(less)(xs drop n))
|
||||
}
|
||||
|
||||
def insertSort(list:ArrayBuffer[Point]) = {
|
||||
def insertSort[A](less: (A, A) => Boolean)(xs: ArrayBuffer[A]): ArrayBuffer[A] = {
|
||||
var j = 1
|
||||
while(j < list.size){
|
||||
val key = list(j)
|
||||
while(j < xs.size){
|
||||
val key = xs(j)
|
||||
var i = j-1
|
||||
while(i>=0 && list(i).x > key.x){
|
||||
list(i+1) = list(i)
|
||||
i=i-1
|
||||
while(i >= 0 && less(key, xs(i)) ){
|
||||
xs(i+1) = xs(i)
|
||||
i -= 1
|
||||
}
|
||||
list(i+1)=key
|
||||
j=j+1
|
||||
xs(i+1)=key
|
||||
j += 1
|
||||
}
|
||||
list
|
||||
xs
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user