fixed Python Seidel algo

This commit is contained in:
zzzzrrr 2009-11-18 13:58:59 -05:00
parent bdcfc0eb04
commit 48805d55db
7 changed files with 152 additions and 133 deletions

5
data/basic.dat Normal file
View File

@ -0,0 +1,5 @@
100.0 100.0
-100.0 100.0
-100.0 -100.0
0.0 0.0
100.0 -100.0

View File

@ -14,7 +14,7 @@ SEGMENTS = 25
INCREMENT = 2.0 * PI / SEGMENTS INCREMENT = 2.0 * PI / SEGMENTS
def init_gl(width, height): def init_gl(width, height):
#glEnable(GL_LINE_SMOOTH) glEnable(GL_LINE_SMOOTH)
glEnable(GL_BLEND) glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glClearColor(0.0, 0.0, 0.0, 0.0) glClearColor(0.0, 0.0, 0.0, 0.0)

View File

@ -5,22 +5,24 @@ from seidel import Triangulator
class Poly2Tri(Game): class Poly2Tri(Game):
#Screen size
screen_size = 800.0, 600.0 screen_size = 800.0, 600.0
def __init__(self): def __init__(self):
super(Poly2Tri, self).__init__(*self.screen_size) super(Poly2Tri, self).__init__(*self.screen_size)
# Load point set # Load point set
file_name = "../data/star.dat" file_name = "../data/dude.dat"
points = self.load_points(file_name) self.points = self.load_points(file_name)
# Triangulate # Triangulate
t1 = self.time t1 = self.time
seidel = Triangulator(points) seidel = Triangulator(self.points)
dt = (self.time - t1) * 1000.0
self.triangles = seidel.triangles() self.triangles = seidel.triangles()
dt = self.time - t1 self.trapezoids = seidel.trapezoids
print "time = %f , num triangles = %d" % (dt, len(self.triangles)) #self.trapezoids = seidel.trapezoidal_map.map
print "time (ms) = %f , num triangles = %d" % (dt, len(self.triangles))
self.main_loop() self.main_loop()
@ -28,11 +30,20 @@ class Poly2Tri(Game):
pass pass
def render(self): def render(self):
reset_zoom(1.0, (0,0), self.screen_size) reset_zoom(2.0, (400, 500), self.screen_size)
red = 255, 0, 0 red = 255, 0, 0
for t in self.triangles: for t in self.triangles:
draw_polygon(t, red) draw_polygon(t, red)
green = 0, 255, 0
#draw_polygon(self.points, green)
'''
yellow = 255, 255, 0
for t in self.trapezoids:
#verts = self.trapezoids[key].vertices()
verts = t.vertices()
draw_polygon(verts, yellow)
'''
def load_points(self, file_name): def load_points(self, file_name):
infile = open(file_name, "r") infile = open(file_name, "r")
points = [] points = []

View File

@ -32,10 +32,11 @@
from random import shuffle from random import shuffle
from math import atan2, floor from math import atan2, floor
### ##
### Based on Raimund Seidel'e paper "A simple and fast incremental randomized ## Based on Raimund Seidel'e 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"
### (Ported from poly2tri) ## (Ported from poly2tri)
##
class Point(object): class Point(object):
@ -76,23 +77,21 @@ class Point(object):
def less(self, p): def less(self, p):
return self.x < p.x return self.x < p.x
def not_equal(self, p):
return not (p.x == self.x and p.y == self.y)
def clone(self): def clone(self):
return Point(self.x, self.y) return Point(self.x, self.y)
class Edge(object): class Edge(object):
mpoints = []
above, below = None, None
def __init__(self, p, q): def __init__(self, p, q):
self.p = p self.p = p
self.q = q self.q = q
self.slope = 0.0 if (q.x - p.x) == 0 else (q.y - p.y)/(q.x - p.x) self.slope = 0.0 if (q.x - p.x) == 0.0 else (q.y - p.y)/(q.x - p.x)
self.b = p.y - (p.x * self.slope) self.b = p.y - (p.x * self.slope)
self.above, self.below = None, None
self.mpoints = []
self.mpoints.append(p)
self.mpoints.append(q)
def is_above(self, point): def is_above(self, point):
return (floor(point.y) < floor(self.slope * point.x + self.b)) return (floor(point.y) < floor(self.slope * point.x + self.b))
@ -105,10 +104,10 @@ class Edge(object):
b = self.q b = self.q
a1 = self.signed_area(a, b, d) a1 = self.signed_area(a, b, d)
a2 = self.signed_area(a, b, c) a2 = self.signed_area(a, b, c)
if a1 != 0 and a2 != 0 and (a1 * a2) < 0: if a1 != 0.0 and a2 != 0.0 and (a1 * a2) < 0.0:
a3 = self.signed_area(c, d, a) a3 = self.signed_area(c, d, a)
a4 = a3 + a2 - a1 a4 = a3 + a2 - a1
if a3 * a4 < 0: if a3 * a4 < 0.0:
t = a3 / (a3 - a4) t = a3 / (a3 - a4)
return a + ((b - a) * t) return a + ((b - a) * t)
return 0.0 return 0.0
@ -117,12 +116,13 @@ class Edge(object):
return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x) return (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x)
class Trapezoid(object): class Trapezoid(object):
def __init__(self, left_point, right_point, top, bottom): def __init__(self, left_point, right_point, top, bottom):
self.left_point = left_point self.left_point = left_point
self.right_point = right_point self.right_point = right_point
self.top = top self.top = top
self.bottom = bottom self.bottom = bottom
self.hash = hash(self)
self.upper_left = None self.upper_left = None
self.upper_right = None self.upper_right = None
self.lower_left = None self.lower_left = None
@ -132,26 +132,26 @@ class Trapezoid(object):
def update_left(self, ul, ll): def update_left(self, ul, ll):
self.upper_left = ul self.upper_left = ul
self.lower_left = ll
if ul != None: ul.upper_right = self if ul != None: ul.upper_right = self
if ll != None: ll.lower_right = self self.lower_left = ll
if ll != None: ll.lower_right = self
def update_right(self, ur, lr): def update_right(self, ur, lr):
self.upper_right = ur self.upper_right = ur
self.lower_right = lr
if ur != None: ur.upper_left = self if ur != None: ur.upper_left = self
if lr != None: lr.lower_left = self self.lower_right = lr
if lr != None: lr.lower_left = self
def update_left_right(self, ul, ll, ur, lr): def update_left_right(self, ul, ll, ur, lr):
self.upper_left = ul self.upper_left = ul
self.lower_left = ll
self.upper_right = ur
self.lower_right = lr
if ul != None: ul.upper_right = self if ul != None: ul.upper_right = self
self.lower_left = ll
if ll != None: ll.lower_right = self if ll != None: ll.lower_right = self
self.upper_right = ur
if ur != None: ur.upper_left = self if ur != None: ur.upper_left = self
self.lower_right = lr
if lr != None: lr.lower_left = self if lr != None: lr.lower_left = self
def trim_neighbors(self): def trim_neighbors(self):
if self.inside: if self.inside:
self.inside = False self.inside = False
@ -165,12 +165,11 @@ class Trapezoid(object):
self.top.is_above(point) and self.bottom.is_below(point)) self.top.is_above(point) and self.bottom.is_below(point))
def vertices(self): def vertices(self):
verts = [] v1 = line_intersect(self.top, self.left_point.x)
verts.append(line_intersect(self.top, self.left_point.x)) v2 = line_intersect(self.bottom, self.left_point.x)
verts.append(line_intersect(self.bottom, self.left_point.x)) v3 = line_intersect(self.bottom, self.right_point.x)
verts.append(line_intersect(self.bottom, self.right_point.x)) v4 = line_intersect(self.top, self.right_point.x)
verts.append(line_intersect(self.top, self.right_point.x)) return v1, v2, v3, v4
return verts
def add_points(self): def add_points(self):
if self.left_point != self.bottom.p: if self.left_point != self.bottom.p:
@ -184,19 +183,19 @@ class Trapezoid(object):
def line_intersect(edge, x): def line_intersect(edge, x):
y = edge.slope * x + edge.b y = edge.slope * x + edge.b
return Point(x, y) return x, y
class Triangulator(object): class Triangulator(object):
def __init__(self, poly_line): def __init__(self, poly_line):
self.polygons = [] self.polygons = []
self.edge_list = self.init_edges(poly_line)
self.trapezoids = [] self.trapezoids = []
self.xmono_poly = []
self.edge_list = self.init_edges(poly_line)
self.trapezoidal_map = TrapezoidalMap() self.trapezoidal_map = TrapezoidalMap()
self.bounding_box = self.trapezoidal_map.bounding_box(self.edge_list) self.bounding_box = self.trapezoidal_map.bounding_box(self.edge_list)
self.query_graph = QueryGraph(isink(self.bounding_box)) self.query_graph = QueryGraph(isink(self.bounding_box))
self.xmono_poly = []
self.process() self.process()
def triangles(self): def triangles(self):
@ -214,13 +213,11 @@ class Triangulator(object):
# Build the trapezoidal map and query graph # Build the trapezoidal map and query graph
def process(self): def process(self):
for edge in self.edge_list: for edge in self.edge_list:
traps = self.query_graph.follow_edge(edge) traps = self.query_graph.follow_edge(edge)
for t in traps:
try:
self.trapezoidal_map.map.remove(t)
except:
pass
for t in traps: for t in traps:
# Remove old trapezods
del self.trapezoidal_map.map[t.hash]
# Bisect old trapezoids and create new
cp = t.contains(edge.p) cp = t.contains(edge.p)
cq = t.contains(edge.q) cq = t.contains(edge.q)
if cp and cq: if cp and cq:
@ -237,19 +234,22 @@ class Triangulator(object):
self.query_graph.case4(t.sink, edge, tlist) self.query_graph.case4(t.sink, edge, tlist)
# Add new trapezoids to map # Add new trapezoids to map
for t in tlist: for t in tlist:
self.trapezoidal_map.map.append(t) self.trapezoidal_map.map[t.hash] = t
self.trapezoidal_map.clear() self.trapezoidal_map.clear()
#TODO remove invalid/extra trapezoids
#print len(self.trapezoidal_map.map)
# Mark outside trapezoids # Mark outside trapezoids w/ depth-first search
for t in self.trapezoidal_map.map: for k, t in self.trapezoidal_map.map.items():
self.mark_outside(t) self.mark_outside(t)
# Collect interior trapezoids # Collect interior trapezoids
for t in self.trapezoidal_map.map: for k, t in self.trapezoidal_map.map.items():
if t.inside: if t.inside:
self.trapezoids.append(t) self.trapezoids.append(t)
t.add_points() t.add_points()
# Generate the triangles # Generate the triangles
self.create_mountains() self.create_mountains()
@ -260,11 +260,10 @@ class Triangulator(object):
return polies return polies
def create_mountains(self): def create_mountains(self):
for edge in self.edge_list: for edge in self.edge_list:
if len(edge.mpoints) > 0: if len(edge.mpoints) > 2:
mountain = MonotoneMountain() mountain = MonotoneMountain()
k = merge_sort(edge.mpoints) points = merge_sort(edge.mpoints)
points = [edge.p] + k + [edge.q]
for p in points: for p in points:
mountain.add(p) mountain.add(p)
mountain.process() mountain.process()
@ -296,7 +295,7 @@ class Triangulator(object):
edges.append(Edge(q, p)) edges.append(Edge(q, p))
elif p.x < q.x: elif p.x < q.x:
edges.append(Edge(p, q)) edges.append(Edge(p, q))
shuffle(edges) #shuffle(edges)
return edges return edges
def shear_transform(self, point): def shear_transform(self, point):
@ -323,18 +322,17 @@ def merge_sort(l):
class TrapezoidalMap(object): class TrapezoidalMap(object):
map = [] def __init__(self):
margin = 50 self.map = {}
bcross = None self.margin = 50.0
tcross = None self.bcross = None
self.tcross = None
def clear(self): def clear(self):
self.bcross = None self.bcross = None
self.tcross = None self.tcross = None
map = []
def case1(self, t, e):
def case1(self, trapezoid, edge):
t = trapezoid; e = edge
trapezoids = [] trapezoids = []
trapezoids.append(Trapezoid(t.left_point, e.p, t.top, t.bottom)) trapezoids.append(Trapezoid(t.left_point, e.p, t.top, t.bottom))
trapezoids.append(Trapezoid(e.p, e.q, t.top, e)) trapezoids.append(Trapezoid(e.p, e.q, t.top, e))
@ -346,8 +344,7 @@ class TrapezoidalMap(object):
trapezoids[3].update_right(t.upper_right, t.lower_right) trapezoids[3].update_right(t.upper_right, t.lower_right)
return trapezoids return trapezoids
def case2(self, trapezoid, edge): def case2(self, t, e):
t = trapezoid; e = edge
rp = e.q if e.q.x == t.right_point.x else t.right_point rp = e.q if e.q.x == t.right_point.x else t.right_point
trapezoids = [] trapezoids = []
trapezoids.append(Trapezoid(t.left_point, e.p, t.top, t.bottom)) trapezoids.append(Trapezoid(t.left_point, e.p, t.top, t.bottom))
@ -362,8 +359,7 @@ class TrapezoidalMap(object):
e.below = trapezoids[2] e.below = trapezoids[2]
return trapezoids return trapezoids
def case3(self, trapezoid, edge): def case3(self, t, e):
t = trapezoid; e = edge
lp = e.p if e.p.x == t.left_point.x else t.left_point lp = e.p if e.p.x == t.left_point.x else t.left_point
rp = e.q if e.q.x == t.right_point.x else t.right_point rp = e.q if e.q.x == t.right_point.x else t.right_point
trapezoids = [] trapezoids = []
@ -387,8 +383,7 @@ class TrapezoidalMap(object):
e.below = trapezoids[1] e.below = trapezoids[1]
return trapezoids return trapezoids
def case4(self, trapezoid, edge): def case4(self, t, e):
t = trapezoid; e = edge
lp = e.p if e.p.x == t.left_point.x else t.left_point lp = e.p if e.p.x == t.left_point.x else t.left_point
trapezoids = [] trapezoids = []
if self.tcross is t.top: if self.tcross is t.top:
@ -411,21 +406,23 @@ class TrapezoidalMap(object):
margin = self.margin margin = self.margin
max = edges[0].p + margin max = edges[0].p + margin
min = edges[0].q - margin min = edges[0].q - margin
for edge in edges: for e in edges:
if edge.p.x > max.x: max = Point(edge.p.x + margin, max.y) if e.p.x > max.x: max = Point(e.p.x + margin, max.y)
if edge.p.y > max.y: max = Point(max.x, edge.p.y + margin) if e.p.y > max.y: max = Point(max.x, e.p.y + margin)
if edge.q.x > max.x: max = Point(edge.q.x + margin, max.y) if e.q.x > max.x: max = Point(e.q.x + margin, max.y)
if edge.q.y > max.y: max = Point(max.x, edge.q.y + margin) if e.q.y > max.y: max = Point(max.x, e.q.y + margin)
if edge.p.x < min.x: min = Point(edge.p.x - margin, min.y) if e.p.x < min.x: min = Point(e.p.x - margin, min.y)
if edge.p.y < min.y: min = Point(min.x, edge.p.y - margin) if e.p.y < min.y: min = Point(min.x, e.p.y - margin)
if edge.q.x < min.x: min = Point(edge.q.x - margin, min.y) if e.q.x < min.x: min = Point(e.q.x - margin, min.y)
if edge.q.y < min.y: min = Point(min.x, edge.q.y - margin) if e.q.y < min.y: min = Point(min.x, e.q.y - margin)
top = Edge(Point(min.x, max.y), Point(max.x, max.y)) top = Edge(Point(min.x, max.y), Point(max.x, max.y))
bottom = Edge(Point(min.x, min.y), Point(max.x, min.y)) bottom = Edge(Point(min.x, min.y), Point(max.x, min.y))
left = bottom.p left = bottom.p
right = top.q right = top.q
return Trapezoid(left, right, top, bottom) trap = Trapezoid(left, right, top, bottom)
self.map[hash(trap)] = trap
return trap
class Node(object): class Node(object):
def __init__(self, left, right): def __init__(self, left, right):
@ -533,9 +530,8 @@ class QueryGraph:
qNode = XNode(edge.q, yNode, isink(tlist[2])) qNode = XNode(edge.q, yNode, isink(tlist[2]))
self.replace(sink, qNode) self.replace(sink, qNode)
PI_SLOP = 3.1 PI_SLOP = 3.1
class MonotoneMountain: class MonotoneMountain:
def __init__(self): def __init__(self):
@ -549,17 +545,17 @@ class MonotoneMountain:
self.convex_polies = [] self.convex_polies = []
def add(self, point): def add(self, point):
if self.size == 0: if self.size is 0:
self.head = point self.head = point
self.size += 1 self.size = 1
elif self.size == 1: elif self.size is 1:
if point.not_equal(self.head): if point != self.head:
self.tail = point self.tail = point
self.tail.prev = self.head self.tail.prev = self.head
self.head.next = self.tail self.head.next = self.tail
self.size += 1 self.size = 2
else: else:
if point.not_equal(self.tail): if point != self.tail:
self.tail.next = point self.tail.next = point
point.prev = self.tail point.prev = self.tail
self.tail = point self.tail = point
@ -576,9 +572,9 @@ class MonotoneMountain:
self.positive = self.angle_sign() self.positive = self.angle_sign()
self.gen_mono_poly() self.gen_mono_poly()
p = self.head.next p = self.head.next
while p is not self.tail: while p != self.tail:
a = self.angle(p) a = self.angle(p)
if a >= PI_SLOP or a <= -PI_SLOP: if a >= PI_SLOP or a <= -PI_SLOP or a == 0:
self.remove(p) self.remove(p)
elif self.is_convex(p): elif self.is_convex(p):
self.convex_points.append(p) self.convex_points.append(p)
@ -586,16 +582,18 @@ class MonotoneMountain:
self.triangulate() self.triangulate()
def triangulate(self): def triangulate(self):
while len(self.convex_points) > 0: while self.convex_points:
ear = self.convex_points.pop(0) ear = self.convex_points.pop(0)
a = ear.prev a = ear.prev
b = ear b = ear
c = ear.next c = ear.next
triangle = [a, b, c] triangle = (a, b, c)
self.triangles.append(triangle) self.triangles.append(triangle)
self.remove(ear) self.remove(ear)
if self.valid(a): self.convex_points.append(a) if self.valid(a):
if self.valid(c): self.convex_points.append(c) self.convex_points.append(a)
if self.valid(c):
self.convex_points.append(c)
assert(self.size <= 3, "Triangulation bug, please report") assert(self.size <= 3, "Triangulation bug, please report")
def valid(self, p): def valid(self, p):
@ -618,5 +616,6 @@ class MonotoneMountain:
return atan2(a.cross(b), a.dot(b)) >= 0 return atan2(a.cross(b), a.dot(b)) >= 0
def is_convex(self, p): def is_convex(self, p):
if self.positive != (self.angle(p) >= 0): return False if self.positive != (self.angle(p) >= 0):
return True return False
return True

View File

@ -79,16 +79,17 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
var drawSegs = true var drawSegs = true
var drawCDTMesh = false var drawCDTMesh = false
val nazcaMonkey = "data/nazca_monkey.dat" val nazcaMonkey = "../data/nazca_monkey.dat"
val nazcaHeron = "data/nazca_heron_old.dat" val nazcaHeron = "../data/nazca_heron_old.dat"
val bird = "data/bird.dat" val bird = "../data/bird.dat"
val snake = "data/i.snake" val snake = "../data/i.snake"
val star = "data/star.dat" val star = "../data/star.dat"
val strange = "data/strange.dat" val strange = "../data/strange.dat"
val i18 = "data/i.18" val i18 = "../data/i.18"
val tank = "data/tank.dat" val tank = "../data/tank.dat"
val dude = "data/dude.dat" val dude = "../data/dude.dat"
val basic = "../data/basic.dat"
var currentModel = dude var currentModel = dude
var doCDT = true var doCDT = true
// The current algorithm // The current algorithm
@ -207,7 +208,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
} }
} }
if(currentModel == "data/dude.dat" && drawSegs) { if(currentModel == "../data/dude.dat" && drawSegs) {
g.setColor(green) g.setColor(green)
for(i <- 0 until chestSegs.size) { for(i <- 0 until chestSegs.size) {
val s = chestSegs(i) val s = chestSegs(i)
@ -287,7 +288,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
if(c == '7') selectModel(nazcaHeron) if(c == '7') selectModel(nazcaHeron)
if(c == '8') selectModel(tank) if(c == '8') selectModel(tank)
if(c == '9') selectModel(dude) if(c == '9') selectModel(dude)
if(c == '0') selectModel(basic)
if(c == 'd') drawSegs = !drawSegs if(c == 'd') drawSegs = !drawSegs
if(c == 'm') drawCDTMesh = !drawCDTMesh if(c == 'm') drawCDTMesh = !drawCDTMesh
if(c == 't') drawMap = !drawMap if(c == 't') drawMap = !drawMap
@ -303,33 +305,36 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
def selectModel(model: String) { def selectModel(model: String) {
model match { model match {
case "data/nazca_monkey.dat" => case "../data/nazca_monkey.dat" =>
val clearPoint = Point(418, 282) val clearPoint = Point(418, 282)
loadModel(nazcaMonkey, 4.5f, Point(400, 300), 1500, clearPoint) loadModel(nazcaMonkey, 4.5f, Point(400, 300), 1500, clearPoint)
case "data/bird.dat" => case "../data/bird.dat" =>
val clearPoint = Point(400, 300) val clearPoint = Point(400, 300)
loadModel(bird, 25f, Point(400, 300), 350, clearPoint) loadModel(bird, 25f, Point(400, 300), 350, clearPoint)
case "data/i.snake" => case "../data/i.snake" =>
val clearPoint = Point(336f, 196f) val clearPoint = Point(336f, 196f)
loadModel(snake, 10f, Point(600, 300), 10, clearPoint) loadModel(snake, 10f, Point(600, 300), 10, clearPoint)
case "data/star.dat" => case "../data/star.dat" =>
val clearPoint = Point(400, 204) val clearPoint = Point(400, 204)
loadModel(star, -1f, Point(0f, 0f), 10, clearPoint) loadModel(star, -1f, Point(0f, 0f), 10, clearPoint)
case "data/strange.dat" => case "../data/strange.dat" =>
val clearPoint = Point(400, 268) val clearPoint = Point(400, 268)
loadModel(strange, -1f, Point(0f, 0f), 15, clearPoint) loadModel(strange, -1f, Point(0f, 0f), 15, clearPoint)
case "data/i.18" => case "../data/i.18" =>
val clearPoint = Point(510, 385) val clearPoint = Point(510, 385)
loadModel(i18, 20f, Point(600f, 500f), 20, clearPoint) loadModel(i18, 20f, Point(600f, 500f), 20, clearPoint)
case "data/nazca_heron_old.dat" => case "../data/nazca_heron_old.dat" =>
val clearPoint = Point(85, 290) val clearPoint = Point(85, 290)
loadModel(nazcaHeron, 4.2f, Point(400f, 300f), 1500, clearPoint) loadModel(nazcaHeron, 4.2f, Point(400f, 300f), 1500, clearPoint)
case "data/tank.dat" => case "../data/tank.dat" =>
val clearPoint = Point(450, 350) val clearPoint = Point(450, 350)
loadModel(tank, -1f, Point(100f, 0f), 10, clearPoint) loadModel(tank, -1f, Point(100f, 0f), 10, clearPoint)
case "data/dude.dat" => case "../data/dude.dat" =>
val clearPoint = Point(365, 427) val clearPoint = Point(365, 427)
loadModel(dude, -1f, Point(100f, -200f), 10, clearPoint) loadModel(dude, -1f, Point(100f, -200f), 10, clearPoint)
case "../data/basic.dat" =>
val clearPoint = Point(365, 427)
loadModel(basic, -1f, Point(400f, 300f), 10, clearPoint)
case _ => case _ =>
} }
currentModel = model currentModel = model
@ -378,7 +383,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
slCDT = new CDT(pts, clearPoint) slCDT = new CDT(pts, clearPoint)
// Add some holes.... // Add some holes....
if(model == "data/dude.dat") { if(model == "../data/dude.dat") {
val headHole = Array(Point(325f,437f), Point(320f,423f), Point(329f,413f), Point(332f,423f)) val headHole = Array(Point(325f,437f), Point(320f,423f), Point(329f,413f), Point(332f,423f))
val chestHole = Array(Point(320.72342f,480f), Point(338.90617f,465.96863f), val chestHole = Array(Point(320.72342f,480f), Point(338.90617f,465.96863f),
@ -443,8 +448,8 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
var xVerts = polyX.toArray var xVerts = polyX.toArray
var yVerts = polyY.toArray var yVerts = polyY.toArray
val xv = if(currentModel != "data/strange.dat") xVerts.reverse.toArray else xVerts val xv = if(currentModel != "../data/strange.dat") xVerts.reverse.toArray else xVerts
val yv = if(currentModel != "data/strange.dat") yVerts.reverse.toArray else yVerts val yv = if(currentModel != "../data/strange.dat") yVerts.reverse.toArray else yVerts
val t1 = System.nanoTime val t1 = System.nanoTime
earClip.triangulatePolygon(xv, yv, xVerts.size, earClipResults) earClip.triangulatePolygon(xv, yv, xVerts.size, earClipResults)

View File

@ -101,10 +101,10 @@ class MonotoneMountain {
while(p != tail) { while(p != tail) {
val a = angle(p) val a = angle(p)
// If the point is almost colinear with it's neighbor, remove it! // If the point is almost colinear with it's neighbor, remove it!
if(a >= PI_SLOP || a <= -PI_SLOP) if(a >= PI_SLOP || a <= -PI_SLOP || a == 0.0)
remove(p) remove(p)
else else if(convex(p))
if(convex(p)) convexPoints += p convexPoints += p
p = p.next p = p.next
} }

View File

@ -112,7 +112,7 @@ class Triangulator(points: ArrayBuffer[Point]) {
i += 1 i += 1
} }
// Mark outside trapezoids // Mark outside trapezoids
for(t <- trapezoidalMap.map) for(t <- trapezoidalMap.map)
markOutside(t) markOutside(t)
@ -147,7 +147,7 @@ class Triangulator(points: ArrayBuffer[Point]) {
val s = segmentList(i) val s = segmentList(i)
if(s.mPoints.size > 0) { if(s.mPoints.size > 0) {
val mountain = new MonotoneMountain val mountain = new MonotoneMountain
var k: List[Point] = null var k: List[Point] = null
@ -162,7 +162,6 @@ class Triangulator(points: ArrayBuffer[Point]) {
k = Util.msort((p1: Point, p2: Point) => p1 < p2)(s.mPoints.toList) k = Util.msort((p1: Point, p2: Point) => p1 < p2)(s.mPoints.toList)
val points = s.p :: k ::: List(s.q) val points = s.p :: k ::: List(s.q)
var j = 0 var j = 0
while(j < points.size) { while(j < points.size) {
mountain += points(j) mountain += points(j)