def cdtFromPSLG(pslg, onlyInner = False): """cdtFromPSLG(pslg, onlyInner) -> GeoMap Return a CDT for the given planar straight line graph. `pslg` should be a GeoMap whose node positions are simple input points and edges define constraint segments. FIXME: ATM, this function may crash if the input contains duplicate points (e.g. within the same edge). This is due to a limitation of the triangle module, i.e. J. Shewchuck's code. """ # return constrainedDelaunayMap( # list(pslg.edgeIter()), pslg.imageSize(), # [node.position() for node in pslg.nodeIter() if node.isIsolated()], # onlyInner = False) points = [] segments = [] holes = [] nodes = [None] * pslg.maxNodeLabel() for node in pslg.nodeIter(): nodes[node.label()] = len(points) points.append(node.position()) for edge in pslg.edgeIter(): l = len(points) edgeSegments = [(l+i-1, l+i) for i in range(len(edge)-1)] edgeSegments[0] = (nodes[edge.startNodeLabel()], edgeSegments[0][1]) edgeSegments[-1] = (edgeSegments[-1][0], nodes[edge.endNodeLabel()]) points.extend(edge[1:-1]) # for i in range(1, len(edge)-1): # assert edge[i] not in points, "%s[%d] = ..%s,%s,%s,.. is already present!" % ( # edge, i, edge[i-1], edge[i], edge[i+1]) # points.append(edge[i]) segments.extend(edgeSegments) for face in pslg.faceIter(skipInfinite = True): if face.flag(OUTER_FACE): # FIXME: re-use available scanlines for face: holes.append(_pointInHole(contourPoly(face.contour()))) print "- performing Constrained Delaunay Triangulation..." print " (%d points, %s segments, %d holes)" % ( len(points), len(segments), len(holes)) nodePositions, edgeData = triangle.constrainedDelaunay( points, segments, onlyInner, holes) print "- storing result in a GeoMap..." result = _delaunayMapFromData(nodePositions, edgeData, pslg.imageSize()) for edge in result.edgeIter(): if edgeData[edge.label()][2]: edge.setFlag(CONTOUR_SEGMENT) result.face(0).setFlag(OUTER_FACE) for holePoint in holes: result.faceAt(holePoint).setFlag(OUTER_FACE) return result
def constrainedDelaunayMap(polygons, imageSize, extraPoints = [], onlyInner = True): """constrainedDelaunayMap(polygons, imageSize, extraPoints, onlyInner) -> GeoMap Returns a new `GeoMap` containing a Constrained Delaunay Triangulation of all points of the polygons plus the extraPoints if given. The segments of the polygons will be constrained segments of the CDT. If the optional `onlyInner` parameter is True (default), then all edge segments in the 'outside' will be removed. (This assumes that all closed polygons with a negative partialArea() are holes.) **NOTE**: You probably want to use `cdtFromPSLG` or `faceCDTMap` instead, both of which have a much simpler API.""" assert triangle, """For correct CDT, you need to compile the triangle module (vigra/experiments/triangle). You might want to try the home-made fakedConstrainedDelaunayMap instead, which will give a correct result if possible, but may just throw an exception if it has to give up or even go into an infinite loop.""" points = list(extraPoints) segments = [] holes = [] for polygon in polygons: l = len(points) partPoints = list(polygon) partSegments = [(l+i, l+i+1) for i in range(len(partPoints)-1)] if polygon[-1] == polygon[0]: del partPoints[-1] if partPoints[0] in points: for i, (s, e) in enumerate(partSegments): partSegments[i] = (s-1, e-1) # partPoints[0] will be deleted partSegments[0] = (points.index(partPoints[0]), partSegments[0][1]) del partPoints[0] partSegments[-1] = (partSegments[-1][0], partSegments[0][0]) if onlyInner and polygon.partialArea() < 0: holes.append(_pointInHole(polygon)) else: if partPoints[-1] in points: partSegments[-1] = (partSegments[-1][0], points.index(partPoints[-1])) del partPoints[-1] if partPoints[0] in points: for i, (s, e) in enumerate(partSegments): partSegments[i] = (s-1, e-1) # partPoints[0] will be deleted partSegments[0] = (points.index(partPoints[0]), partSegments[0][1]) del partPoints[0] points.extend(partPoints) segments.extend(partSegments) print "- performing Constrained Delaunay Triangulation..." print " (%d points, %s segments, %d holes)" % ( len(points), len(segments), len(holes)) nodePositions, edgeData = triangle.constrainedDelaunay( points, segments, onlyInner, holes) print "- storing result in a GeoMap..." result = _delaunayMapFromData(nodePositions, edgeData, imageSize) for edge in result.edgeIter(): if edgeData[edge.label()][2]: edge.setFlag(CONTOUR_SEGMENT) result.face(0).setFlag(OUTER_FACE) for holePoint in holes: result.faceAt(holePoint).setFlag(OUTER_FACE) return result