diff --git a/python/framework/triangulator.pyx b/python/framework/triangulator.pyx index 2fd71f7..ffef7ef 100644 --- a/python/framework/triangulator.pyx +++ b/python/framework/triangulator.pyx @@ -29,6 +29,7 @@ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # +from random import shuffle ### ### Based on Raimund Seidel'e paper "A simple and fast incremental randomized @@ -42,14 +43,112 @@ cdef extern from 'math.h': double floor(double) double sqrt(double) +class Triangulator: + + def __init__(self, points): + self.polygons = [] + self.edge_list = self.init_edges(points) + self.trapezoids = [] + self.trapezoidal_map = TrapezoidalMap() + boundingBox = self.trapezoidal_map.boundingBox(self.edge_list) + self.query_graph = QueryGraph(Sink(boundingBox)) + self.xmono_poly = [] + self.process() + + def trapezoidMap(self): + return self.trapezoidal_map.map + + # Build the trapezoidal map and query graph + def process(self): + for e in self.edge_list: + traps = self.query_graph.followSegment(e) + for t in traps: + self.trapezoidal_map.map.remove(t) + for t in traps: + tlist = [] + cp = t.contains(e.p) + cq = t.contains(e.q) + if cp and cq: + tlist = self.trapezoidal_map.case1(t, e) + self.query_graph.case1(t.sink, e, tlist) + elif cp and not cq: + tlist = self.trapezoidal_map.case2(t, e) + self.query_graph.case2(t.sink, e, tlist) + elif not cp and not cq: + tlist = self.trapezoidal_map.case3(t, e) + self.query_graph.case3(t.sink, e, tlist) + else: + tlist = self.trapezoidal_map.case4(t, e) + self.query_graph.case4(t.sink, e, tlist) + + # Add new trapezoids to map + for t in tlist: + self.trapezoidal_map.map.append(t) + + self.trapezoidal_map.clear() + + # Mark outside trapezoids + for t in self.trapezoidal_map.map: + self.mark_outside(t) + + # Collect interior trapezoids + for t in self.trapezoidal_map.map: + if t.inside(): + self.trapezoids.append(t) + t.add_points() + + self.create_mountains() + + def mono_polies(self): + polies = [] + for x in self.xmono_poly: + polies.append(x.monoPoly) + return polies + + def create_mountains(self): + for s in self.edge_list: + if len(s.mpoints) > 0: + mountain = MonotoneMountain() + k = merge_sort(s.mpoints) + points = [s.p] + k + [s.q] + for p in points: + mountain.append(p) + mountain.process() + for t in mountain.triangles: + self.polygons.append(t) + self.xmono_poly.append(mountain) + + def mark_outside(self, t): + if t.top is self.boundingBox.top or t.bottom is self.boundingBox.bottom: + t.trimNeighbors() + + def init_edges(self, points): + edges = [] + for i in range(len(points)-1): + edges.append(Edge(points[i], points[i+1])) + edges.append(Edge(points[0], points[-1])) + return self.order_edges(edges) + + def order_edges(self, edges): + segs = [] + for s in edges: + p = self.shearTransform(s.p) + q = self.shearTransform(s.q) + if p.x > q.x: segs.append(Edge(q, p)) + elif p.x < q.x: segs.append(Edge(p, q)) + shuffle(segs) + return segs + + def shearTransform(self, point): + return Point(point.x + 1e-4 * point.y, point.y) + cdef list merge_sort(list l): cdef list lleft, lright cdef int p1, p2, p if len(l)>1 : lleft = merge_sort(l[:len(l)/2]) lright = merge_sort(l[len(l)/2:]) - #do merge here - p1,p2,p = 0,0,0 + p1, p2, p = 0, 0, 0 while p1= self.point.x: - return self.right.locate(e) - else: - return self.left.locate(e) + if e.p.x >= self.point.x: return self.right.locate(e) + else: return self.left.locate(e) class YNode(Node): @@ -438,15 +529,11 @@ class YNode(Node): self.rchild = rchild def locate(self, e): - if self.edge.is_above(e.p): - return self.right.locate(e) - elif self.edge.is_below(e.p): - return self.left.locate(e) + if self.edge.is_above(e.p): return self.right.locate(e) + elif self.edge.is_below(e.p): return self.left.locate(e) else: - if e.slope < self.edge.slope: - return self.right.locate(e) - else: - return self.left.locate(e) + if e.slope < self.edge.slope: return self.right.locate(e) + else: return self.left.locate(e) class QueryGraph: