def delaunay_triangulation(self): import voronoi from sets import Set vprovider = self.vlayer.dataProvider() allAttrs = vprovider.attributeIndexes() vprovider.select(allAttrs) fields = { 0: QgsField("POINTA", QVariant.Double), 1: QgsField("POINTB", QVariant.Double), 2: QgsField("POINTC", QVariant.Double) } writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields, QGis.WKBPolygon, vprovider.crs()) inFeat = QgsFeature() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 while vprovider.nextFeature(inFeat): geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x() y = point.y() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() if len(pts) < 3: return False uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet]) c.triangulate = True voronoi.voronoi(sl, c) triangles = c.triangles feat = QgsFeature() nFeat = len(triangles) nElement = 0 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) for triangle in triangles: indicies = list(triangle) indicies.append(indicies[0]) polygon = [] step = 0 for index in indicies: vprovider.featureAtId(ptDict[ids[index]], inFeat, True, allAttrs) geom = QgsGeometry(inFeat.geometry()) point = QgsPoint(geom.asPoint()) polygon.append(point) if step <= 3: feat.addAttribute(step, QVariant(ids[index])) step += 1 geometry = QgsGeometry().fromPolygon([polygon]) feat.setGeometry(geometry) writer.addFeature(feat) nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) del writer return True
def processAlgorithm(self, progress): vlayer = QGisLayers.getObjectFromUri( self.getParameterValue(Delaunay.INPUT)) vprovider = vlayer.dataProvider() allAttrs = vprovider.attributeIndexes() vprovider.select(allAttrs) fields = { 0: QgsField("POINTA", QVariant.Double), 1: QgsField("POINTB", QVariant.Double), 2: QgsField("POINTC", QVariant.Double) } writer = self.getOutputFromName(Delaunay.OUTPUT).getVectorWriter( fields, QGis.WKBPolygon, vprovider.crs()) inFeat = QgsFeature() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 while vprovider.nextFeature(inFeat): geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x() y = point.y() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() if len(pts) < 3: return False uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet]) c.triangulate = True voronoi.voronoi(sl, c) triangles = c.triangles feat = QgsFeature() nFeat = len(triangles) nElement = 0 for triangle in triangles: indicies = list(triangle) indicies.append(indicies[0]) polygon = [] step = 0 for index in indicies: vprovider.featureAtId(ptDict[ids[index]], inFeat, True, allAttrs) geom = QgsGeometry(inFeat.geometry()) point = QgsPoint(geom.asPoint()) polygon.append(point) if step <= 3: feat.addAttribute(step, QVariant(ids[index])) step += 1 geometry = QgsGeometry().fromPolygon([polygon]) feat.setGeometry(geometry) writer.addFeature(feat) nElement += 1 progress.setPercentage(nElement / nFeat * 100) del writer
def voronoi_polygons(self): vprovider = self.vlayer.dataProvider() writer = QgsVectorFileWriter(self.myName, self.myEncoding, vprovider.fields(), QGis.WKBPolygon, vprovider.crs()) inFeat = QgsFeature() outFeat = QgsFeature() extent = self.vlayer.extent() extraX = extent.height() * (self.myParam / 100.00) extraY = extent.width() * (self.myParam / 100.00) height = extent.height() width = extent.width() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 fit = vprovider.getFeatures() while fit.nextFeature(inFeat): geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x() - extent.xMinimum() y = point.y() - extent.yMinimum() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() self.vlayer = None if len(pts) < 3: return False uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([ voronoi.Site(i[0], i[1], sitenum=j) for j, i in enumerate(uniqueSet) ]) voronoi.voronoi(sl, c) inFeat = QgsFeature() nFeat = len(c.polygons) nElement = 0 self.emit(SIGNAL("runStatus( PyQt_PyObject )"), 0) self.emit(SIGNAL("runRange( PyQt_PyObject )"), (0, nFeat)) for site, edges in c.polygons.iteritems(): vprovider.getFeatures(QgsFeatureRequest().setFilterFid( ptDict[ids[site]])).nextFeature(inFeat) lines = self.clip_voronoi(edges, c, width, height, extent, extraX, extraY) geom = QgsGeometry.fromMultiPoint(lines) geom = QgsGeometry(geom.convexHull()) outFeat.setGeometry(geom) outFeat.setAttributes(inFeat.attributes()) writer.addFeature(outFeat) nElement += 1 self.emit(SIGNAL("runStatus( PyQt_PyObject )"), nElement) del writer return True
def processAlgorithm(self, progress): vlayer = QGisLayers.getObjectFromUri(self.getParameterValue(VoronoiPolygons.INPUT)) vprovider = vlayer.dataProvider() allAttrs = vprovider.attributeIndexes() vprovider.select( allAttrs ) writer = self.getOutputFromName(VoronoiPolygons.OUTPUT).getVectorWriter(vprovider.fields(), QGis.WKBPolygon, vprovider.crs() ) inFeat = QgsFeature() outFeat = QgsFeature() extent = vlayer.extent() height = extent.height() width = extent.width() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 while vprovider.nextFeature(inFeat): geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x()-extent.xMinimum() y = point.y()-extent.yMinimum() pts.append((x, y)) ptNdx +=1 ptDict[ptNdx] = inFeat.id() #self.vlayer = None if len(pts) < 3: return False uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([voronoi.Site(i[0], i[1], sitenum=j) for j, i in enumerate(uniqueSet)]) voronoi.voronoi(sl, c) inFeat = QgsFeature() nFeat = len(c.polygons) nElement = 0 for site, edges in c.polygons.iteritems(): vprovider.featureAtId(ptDict[ids[site]], inFeat, True, allAttrs) lines = self.clip_voronoi(edges, c, width, height, extent, 0, 0) geom = QgsGeometry.fromMultiPoint(lines) geom = QgsGeometry(geom.convexHull()) outFeat.setGeometry(geom) outFeat.setAttributeMap(inFeat.attributeMap()) writer.addFeature(outFeat) nElement += 1 progress.setPercentage(nElement/nFeat * 100) del writer return True
def VoronoiLineEdges(PointsMap): Sitepts = [] pts = {} #print CurrentDate, PointsMap[PointsMap.keys()[0]] for grid, stn in PointsMap.items(): x=float(stn[0]) y=float(stn[1]) station=grid #station.extend( stn[3:]) #print x,y,station pts[ (x,y) ]=station stncounts=len(pts.keys()) #print stncounts, "points" site_points=[] for pt in pts.keys(): Sitepts.append(voronoi.Site(pt[0],pt[1])) site_points.append( (pt[0],pt[1]) ) #print "Calculating Voronoi Lattice", siteList = voronoi.SiteList(Sitepts) context = voronoi.Context() voronoi.Edge.EDGE_NUM=0 voronoi.voronoi(siteList,context) vertices=context.vertices lines=context.lines edges=context.edges triangles=context.triangles has_edge=context.has_edge return vertices, lines, edges, has_edge
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) buf = self.getParameterValue(self.BUFFER) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.pendingFields().toList(), QGis.WKBPolygon, layer.crs()) inFeat = QgsFeature() outFeat = QgsFeature() extent = layer.extent() extraX = extent.height() * (buf / 100.0) extraY = extent.width() * (buf / 100.0) height = extent.height() width = extent.width() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 features = vector.features(layer) for inFeat in features: geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x() - extent.xMinimum() y = point.y() - extent.yMinimum() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() if len(pts) < 3: raise GeoAlgorithmExecutionException( 'Input file should contain at least 3 points. Choose \ another file and try again.') uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([ voronoi.Site(i[0], i[1], sitenum=j) for (j, i) in enumerate(uniqueSet) ]) voronoi.voronoi(sl, c) inFeat = QgsFeature() current = 0 total = 100.0 / float(len(c.polygons)) for (site, edges) in c.polygons.iteritems(): request = QgsFeatureRequest().setFilterFid(ptDict[ids[site]]) inFeat = layer.getFeatures(request).next() lines = self.clip_voronoi(edges, c, width, height, extent, extraX, extraY) geom = QgsGeometry.fromMultiPoint(lines) geom = QgsGeometry(geom.convexHull()) outFeat.setGeometry(geom) outFeat.setAttributes(inFeat.attributes()) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) fields = [ QgsField('POINTA', QVariant.Double, '', 24, 15), QgsField('POINTB', QVariant.Double, '', 24, 15), QgsField('POINTC', QVariant.Double, '', 24, 15) ] writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, QGis.WKBPolygon, layer.crs()) pts = [] ptDict = {} ptNdx = -1 c = voronoi.Context() features = vector.features(layer) for inFeat in features: geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x() y = point.y() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() if len(pts) < 3: raise GeoAlgorithmExecutionException( 'Input file should contain at least 3 points. Choose \ another file and try again.') uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet]) c.triangulate = True voronoi.voronoi(sl, c) triangles = c.triangles feat = QgsFeature() current = 0 total = 100.0 / float(len(triangles)) for triangle in triangles: indicies = list(triangle) indicies.append(indicies[0]) polygon = [] attrs = [] step = 0 for index in indicies: request = QgsFeatureRequest().setFilterFid(ptDict[ids[index]]) inFeat = layer.getFeatures(request).next() geom = QgsGeometry(inFeat.geometry()) point = QgsPoint(geom.asPoint()) polygon.append(point) if step <= 3: attrs.append(ids[index]) step += 1 feat.setAttributes(attrs) geometry = QgsGeometry().fromPolygon([polygon]) feat.setGeometry(geometry) writer.addFeature(feat) current += 1 progress.setPercentage(int(current * total)) del writer
def effect(self): if not self.options.ids: inkex.errormsg(_("Please select an object")) exit() scale = self.unittouu('1px') # convert to document units self.options.size *= scale self.options.border *= scale q = {'x':0,'y':0,'width':0,'height':0} # query the bounding box of ids[0] for query in q.keys(): p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query, self.options.ids[0], self.args[-1]), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = scale*float(p.stdout.read()) mat = simpletransform.composeParents(self.selected[self.options.ids[0]], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) defs = self.xpathSingle('/svg:svg//svg:defs') pattern = inkex.etree.SubElement(defs ,inkex.addNS('pattern','svg')) pattern.set('id', 'Voronoi' + str(random.randint(1, 9999))) pattern.set('width', str(q['width'])) pattern.set('height', str(q['height'])) pattern.set('patternTransform', 'translate(%s,%s)' % (q['x'] - mat[0][2], q['y'] - mat[1][2])) pattern.set('patternUnits', 'userSpaceOnUse') # generate random pattern of points c = voronoi.Context() pts = [] b = float(self.options.border) # width of border for i in range(int(q['width']*q['height']/self.options.size/self.options.size)): x = random.random()*q['width'] y = random.random()*q['height'] if b > 0: # duplicate border area pts.append(voronoi.Site(x, y)) if x < b: pts.append(voronoi.Site(x + q['width'], y)) if y < b: pts.append(voronoi.Site(x + q['width'], y + q['height'])) if y > q['height'] - b: pts.append(voronoi.Site(x + q['width'], y - q['height'])) if x > q['width'] - b: pts.append(voronoi.Site(x - q['width'], y)) if y < b: pts.append(voronoi.Site(x - q['width'], y + q['height'])) if y > q['height'] - b: pts.append(voronoi.Site(x - q['width'], y - q['height'])) if y < b: pts.append(voronoi.Site(x, y + q['height'])) if y > q['height'] - b: pts.append(voronoi.Site(x, y - q['height'])) elif x > -b and y > -b and x < q['width'] + b and y < q['height'] + b: pts.append(voronoi.Site(x, y)) # leave border area blank # dot = inkex.etree.SubElement(pattern, inkex.addNS('rect','svg')) # dot.set('x', str(x-1)) # dot.set('y', str(y-1)) # dot.set('width', '2') # dot.set('height', '2') if len(pts) < 3: inkex.errormsg("Please choose a larger object, or smaller cell size") exit() # plot Voronoi diagram sl = voronoi.SiteList(pts) voronoi.voronoi(sl, c) path = "" for edge in c.edges: if edge[1] >= 0 and edge[2] >= 0: # two vertices [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], c.vertices[edge[2]][0], c.vertices[edge[2]][1], q['width'], q['height']) elif edge[1] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2]/c.lines[edge[0]][0] if c.vertices[edge[1]][1] > q['height']/2: ytemp = q['height'] else: ytemp = 0 else: xtemp = q['width'] ytemp = (c.lines[edge[0]][2] - q['width']*c.lines[edge[0]][0])/c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], xtemp, ytemp, q['width'], q['height']) elif edge[2] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2]/c.lines[edge[0]][0] if c.vertices[edge[2]][1] > q['height']/2: ytemp = q['height'] else: ytemp = 0 else: xtemp = 0 ytemp = c.lines[edge[0]][2]/c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(xtemp, ytemp, c.vertices[edge[2]][0], c.vertices[edge[2]][1], q['width'], q['height']) if x1 or x2 or y1 or y2: path += 'M %.3f,%.3f %.3f,%.3f ' % (x1, y1, x2, y2) patternstyle = {'stroke': '#000000', 'stroke-width': str(scale)} attribs = {'d': path, 'style': simplestyle.formatStyle(patternstyle)} inkex.etree.SubElement(pattern, inkex.addNS('path', 'svg'), attribs) # link selected object to pattern obj = self.selected[self.options.ids[0]] style = {} if obj.attrib.has_key('style'): style = simplestyle.parseStyle(obj.attrib['style']) style['fill'] = 'url(#%s)' % pattern.get('id') obj.attrib['style'] = simplestyle.formatStyle(style) if obj.tag == inkex.addNS('g', 'svg'): for node in obj: style = {} if node.attrib.has_key('style'): style = simplestyle.parseStyle(node.attrib['style']) style['fill'] = 'url(#%s)' % pattern.get('id') node.attrib['style'] = simplestyle.formatStyle(style)
def effect(self): if not self.options.ids: inkex.errormsg(_("Please select an object")) exit() scale = self.unittouu('1px') # convert to document units self.options.size *= scale self.options.border *= scale q = { 'x': 0, 'y': 0, 'width': 0, 'height': 0 } # query the bounding box of ids[0] for query in q.keys(): p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query, self.options.ids[0], self.args[-1]), shell=True, stdout=PIPE, stderr=PIPE) rc = p.wait() q[query] = scale * float(p.stdout.read()) # generate random pattern of points node = self.selected.values()[0] path_string = node.attrib[u'd'] svg_path = simplepath.parsePath(path_string) pts = self.generatePoints(svg_path, self.options.size) self.display_pts(pts) c = voronoi.Context() pts_to_trig = [] for point in pts: pts_to_trig.append(voronoi.Site(point.loc[0], point.loc[1])) # triangulate with library sl = voronoi.SiteList(pts_to_trig) c.triangulate = True voronoi.voronoi(sl, c) edge_to_triangle = {} triangle_timestamps = [0] * len(c.triangles) triangle_used = [False] * len(c.triangles) quads = [] def getTriangularMidPoint(pt1, pt2, pt3): mid_2_3 = pt2.loc + 0.5 * (pt3.loc - pt2.loc) mid_1_3 = pt1.loc + 0.5 * (pt3.loc - pt1.loc) return curve_utils.intersect_line_line([pt1.loc, mid_2_3], [pt2.loc, mid_1_3])[0] def rejectOutofRangeTringl(): for trngl_indx in range(len(c.triangles)): triangle = c.triangles[trngl_indx] if pts[triangle[0]].type != 3 and pts[ triangle[1]].type != 3 and pts[triangle[2]].type != 3: triangle_midpt = getTriangularMidPoint( pts[triangle[0]], pts[triangle[1]], pts[triangle[2]]) if not pointInPath(self.paths, triangle_midpt): triangle_used[trngl_indx] = True rejectOutofRangeTringl() for trngl_indx in range(len(c.triangles)): triangle = c.triangles[trngl_indx] # compute timestamp for each triangle verts = [pts[triangle[i]] for i in range(3)] min_tstmp = min([vert.timestamp for vert in verts]) triangle_timestamps[trngl_indx] = min_tstmp # build edge_to_triangle for j in range(0, 3): id1 = triangle[j] id2 = triangle[(j + 1) % 3] if id1 < id2: edge = (id1, id2) else: edge = (id2, id1) if edge in edge_to_triangle: edge_to_triangle[edge].append(trngl_indx) else: edge_to_triangle[edge] = [trngl_indx] def getThirdInkex(triangle, edge): for id in triangle: if id not in edge: return id def getEdgeLen(pt1, pt2): return np.linalg.norm(pt1.loc - pt2.loc) def getAngle(pt1, pt2, pt3): vec1 = pt1.loc - pt2.loc vec2 = pt3.loc - pt2.loc angle = np.dot( vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2)) return math.acos(angle) def matchLongestEdge(matchTimestamp): # process triangles for edge in edge_to_triangle: if len(edge_to_triangle[edge]) == 2: tringl1, tringl2 = edge_to_triangle[edge] # skip if either triangle used if triangle_used[tringl1] or triangle_used[tringl2]: continue if matchTimestamp and triangle_timestamps[ tringl1] != triangle_timestamps[tringl2]: continue # get third index of triangle third_id1 = getThirdInkex(c.triangles[tringl1], edge) third_id2 = getThirdInkex(c.triangles[tringl2], edge) # get edge length edge_len = getEdgeLen(pts[edge[0]], pts[edge[1]]) # get other edges length trigl1_edge_len = [ getEdgeLen(pts[edge[0]], pts[third_id1]), getEdgeLen(pts[edge[1]], pts[third_id1]) ] trigl2_edge_len = [ getEdgeLen(pts[edge[0]], pts[third_id2]), getEdgeLen(pts[edge[1]], pts[third_id2]) ] # check if the connecting edge is longest edge of both triangles if all(edge_len >= el for el in trigl1_edge_len) and all( edge_len >= el for el in trigl2_edge_len): # if yes, create quadrilateral quads.append([edge[0], third_id1, edge[1], third_id2]) triangle_used[tringl1] = True triangle_used[tringl2] = True def createNiceQuads(matchTimestamp): # process triangles for edge in edge_to_triangle: if len(edge_to_triangle[edge]) == 2: tringl1, tringl2 = edge_to_triangle[edge] # skip if either triangle used if triangle_used[tringl1] or triangle_used[tringl2]: continue if matchTimestamp and triangle_timestamps[ tringl1] != triangle_timestamps[tringl2]: continue # get third index of triangle third_id1 = getThirdInkex(c.triangles[tringl1], edge) third_id2 = getThirdInkex(c.triangles[tringl2], edge) # get edge length quad_lens = [] edge_len = getEdgeLen(pts[edge[0]], pts[edge[1]]) # get other edges length quad_lens.extend([ getEdgeLen(pts[edge[0]], pts[third_id1]), getEdgeLen(pts[edge[1]], pts[third_id1]) ]) quad_lens.extend([ getEdgeLen(pts[edge[0]], pts[third_id2]), getEdgeLen(pts[edge[1]], pts[third_id2]) ]) avg_quad_len = sum(quad_lens) / len(quad_lens) len_diff = 0 for quad_len in quad_lens: len_diff += abs(quad_len - avg_quad_len) / avg_quad_len angles = [] angles.append( getAngle(pts[edge[0]], pts[third_id1], pts[edge[1]])) angles.append( getAngle(pts[third_id1], pts[edge[1]], pts[third_id2])) angles.append( getAngle(pts[edge[1]], pts[third_id2], pts[edge[0]])) angles.append( getAngle(pts[third_id2], pts[edge[0]], pts[third_id1])) angle_diff = 0 for angle in angles: angle_diff += abs(angle - 3.14159 / 2.0) / (3.14159 / 2) # check if the connecting edge is longest edge of both triangles if len_diff + angle_diff <= threshold: # if yes, create quadrilateral quads.append([edge[0], third_id1, edge[1], third_id2]) triangle_used[tringl1] = True triangle_used[tringl2] = True matchLongestEdge(True) matchLongestEdge(False) createNiceQuads(True) createNiceQuads(False) self.display_triangles(pts, triangle_used, c.triangles) self.display_quads(pts, quads)
def VoronoiPolygons(PointsMap, BoundingBox="W", PlotMap=False): global PlotIt global WorldRange global WorldRanges if type(BoundingBox) == type([]): if len(BoundingBox) == 4: WorldRange = BoundingBox else: return "Error in Bounding Box" else: WorldRange = WorldRanges[BoundingBox] PlotIt = PlotMap currenttime = time.time() Sitepts = [] pts = {} #print CurrentDate, PointsMap[PointsMap.keys()[0]] for grid, stn in PointsMap.items(): x = float(stn[0]) y = float(stn[1]) station = grid #station.extend( stn[3:]) #print x,y,station pts[(x, y)] = station stncounts = len(pts.keys()) #print stncounts, "points" site_points = [] for pt in pts.keys(): Sitepts.append(voronoi.Site(pt[0], pt[1])) site_points.append((pt[0], pt[1])) #print "Calculating Voronoi Lattice", siteList = voronoi.SiteList(Sitepts) context = voronoi.Context() voronoi.Edge.EDGE_NUM = 0 voronoi.voronoi(siteList, context) vertices = context.vertices lines = context.lines edges = context.edges #print edges #For Faster Access edge_dic = {} for edge in edges: edge_dic[edge[0]] = edge[1:] triangles = context.triangles has_edge = context.has_edge voronoi_lattice = {} m_range = {} m_range["max_x"] = -9999999999 m_range["max_y"] = -9999999999 m_range["min_x"] = 9999999999 m_range["min_y"] = 9999999999 #Get the range!! for pnt in site_points: m_range = update_maxmin(m_range, pnt[0], pnt[1]) #print "Getting the Polygons" prev_percent = 0 for station, ls in has_edge.items(): voronoi_lattice[station] = {} voronoi_lattice[station]["coordinate"] = site_points[station] voronoi_lattice[station]["info"] = pts[site_points[station]] polygon = [] prev_extreme = [] Verbose = True if Verbose: current_percent = int(station / float(stncounts) * 100) if current_percent != prev_percent: #print station,"/", stncounts, current_percent, "% Done" timeelapse = time.time() - currenttime #print station, timeelapse currenttime = time.time() prev_percent = current_percent #For every lines that the station owns for l in ls: e = edge_dic[l] v1 = vertices[e[0]] v2 = vertices[e[1]] if e[0] < 0 and checkInRange(WorldRange, v2[0], v2[1]) == False: continue if e[1] < 0 and checkInRange(WorldRange, v1[0], v1[1]) == False: continue if e[0] > -1 and e[1] > -1 and checkInRange( WorldRange, v1[0], v1[1]) == False and checkInRange( WorldRange, v2[0], v2[1]) == False: continue if e[0] < 0 or checkInRange(WorldRange, v1[0], v1[1]) == False: v1 = getExtreme(lines[l], v2, LR=0) if len(prev_extreme) == 0: prev_extreme = v1 else: extreme_points = linkExtremes(prev_extreme, v1, m_range) for extreme_pair in extreme_points: polygon.append(extreme_pair) if e[1] < 0 or checkInRange(WorldRange, v2[0], v2[1]) == False: v2 = getExtreme(lines[l], v1, LR=1) if len(prev_extreme) == 0: prev_extreme = v2 else: extreme_points = linkExtremes(prev_extreme, v2, m_range) for extreme_pair in extreme_points: polygon.append(extreme_pair) if v1 != v2: polygon.append((v1, v2)) if len(polygon) == 0: sys.stderr.write( "\nThis station does not have meaningful polygon:") sys.stderr.write( str(pts[site_points[station]]) + " at " + str(site_points[station]) + "\n") for l in ls: e = edge_dic[l] v1 = vertices[e[0]] v2 = vertices[e[1]] sys.stderr.write(str(e[0]) + "," + str(e[1]) + "\n") sys.stderr.write(str(v1) + "," + str(v2) + "\n") voronoi_lattice.pop(station) continue #print polygon try: result = list(polygonize(polygon)) except ValueError: #print "Wrong:", polygon #Delete invisible short lines point_to_replace = [] for line in polygon: d = math.hypot(line[0][0] - line[1][0], line[0][1] - line[1][1]) if d < 1: polygon.remove(line) point_to_replace = line i = 0 New_Lines = [] for line in polygon: New_Lines.append(list(line)) j = 0 for point in line: if point == point_to_replace[0]: #print line, point_to_replace New_Lines[i][j] = point_to_replace[1] j += 1 i += 1 polygon = tuple(New_Lines) #I could not figure out why sometimes it fails to draw a polygon. try: result = list(polygonize(polygon)) except: voronoi_lattice.pop(station) continue finalpoly = result[0] #print list(finalpoly.exterior.coords) #voronoi_lattice[station]["polygon"]=list(finalpoly.exterior.coords) voronoi_lattice[station]["obj_polygon"] = finalpoly #print polygon if (PlotIt): for station, data in voronoi_lattice.items(): x = [] y = [] #print data try: polygon_data = data["obj_polygon"] #print polygon_data for point in list(polygon_data.exterior.coords): x.append(point[0]) y.append(point[1]) except: print "Error", data["name"] #if station == 8 : #plot(x,y) fill(x, y, alpha=0.6) plot(data["coordinate"][0], data["coordinate"][1]) #text(data["coordinate"][0],data["coordinate"][1],data["info"]) show() return voronoi_lattice
def Fortune(self, points): """Generate polygons. points: Input point sets return list is: vertices: All vertices of all the polygon polygons: A list of lists, where polygons[i] is a list of vertices for station i.""" voronoi.Edge.LE = 0 voronoi.Edge.RE = 1 voronoi.Edge.EDGE_NUM = 0 voronoi.Edge.DELETED = {} # marker value siteList = voronoi.SiteList(points) context = voronoi.Context() voronoi.voronoi(siteList, context) vertices = context.vertices lines = context.lines edges = context.edges has_edge = context.has_edge #print(vertices) #print(lines) #print(edges) #Empty vertices if len(lines) == 0: vts = [(points[0].x, points[0].y)] polygons = [[(0, 0), (1000, 0), (1000, 1000), (0, 1000)]] self.edges = edges self.lines = lines self.has_edge = has_edge self.vertices = list(vts) self.polygons = polygons self.points = points return edgedict = dict() for e in edges: edgedict[e[0]] = (e[1], e[2], True) vts = set() #Delete edges that are outside the bounding box for v in vertices: if self.Inrange(v): vts.add(v) polygons = list() for i in range(len(points)): cand = set() pset = set() #Add to candidates. -1 means does not associate with a line cand.add((self.rec[0], self.rec[1])) cand.add((self.rec[0], self.rec[3])) cand.add((self.rec[2], self.rec[1])) cand.add((self.rec[2], self.rec[3])) #print(has_edge[i]) for j in range(len(has_edge[i])): #Scanning over the lines to determine intersects or candidates edge = edgedict[has_edge[i][j]] line = lines[has_edge[i][j]] #Edge endpoints outside and points to outside where #if edge[0] == -1 and edge[1] != -1 and not self.Inrange(vertices[edge[1]]) or (edge[0] != -1 and edge[1] == -1 and not self.Inrange(vertices[edge[0]])): #continue #Edge endpoints outside if edge[0] != -1 and (not self.Inrange(vertices[edge[0]])): edge = (-1, edge[1]) if edge[1] != -1 and (not self.Inrange(vertices[edge[1]])): edge = (edge[0], -1) if edge[0] == -1 and edge[1] == -1: #Add to point sets because this is the right one pt1, pt2 = self.Intersect(line) #print((points[i],line,edge,pt1,pt2)) cand.add(pt1) cand.add(pt2) elif edge[0] == -1 or edge[1] == -1: #Add to candidates because one has to be gone. With edge index. pt1, pt2 = self.Intersect(line) #print((points[i],line,edge,pt1,pt2)) cand.add(pt1) cand.add(pt2) if edge[0] == -1: cand.add(vertices[edge[1]]) else: cand.add(vertices[edge[0]]) else: #Add both points to cand, if both the points are valid cand.add(vertices[edge[0]]) cand.add(vertices[edge[1]]) #Iterate over all the candidates, determine whether they can be saved for c in cand: valid = True #Iterate through all the lines associated with point i for j in range(len(has_edge[i])): line = lines[has_edge[i][j]] if not Voronoi.Sameside(line, (points[i].x, points[i].y), c): valid = False #print((points[i],line,c,valid)) break #print((points[i],line,c,valid)) if valid == True: pset.add(c) vts.add(c) #Update polygons polygons.append( sorted(list(pset), key=lambda p: Voronoi.Direction( (points[i].x, points[i].y), p))) self.edges = edges self.lines = lines self.has_edge = has_edge self.vertices = list(vts) self.polygons = polygons self.points = points
def effect(self): if not self.options.ids: return inkex.errormsg(_("Please select an object")) scale = self.svg.unittouu('1px') # convert to document units self.options.size *= scale self.options.border *= scale obj = self.svg.selection.first() bbox = obj.bounding_box() mat = obj.composed_transform().matrix pattern = self.svg.defs.add(Pattern()) pattern.set_random_id('Voronoi') pattern.set('width', str(bbox.width)) pattern.set('height', str(bbox.height)) pattern.set('patternUnits', 'userSpaceOnUse') pattern.patternTransform.add_translate(bbox.left - mat[0][2], bbox.top - mat[1][2]) # generate random pattern of points c = voronoi.Context() pts = [] b = float(self.options.border) # width of border for i in range(int(bbox.width * bbox.height / self.options.size / self.options.size)): x = random.random() * bbox.width y = random.random() * bbox.height if b > 0: # duplicate border area pts.append(voronoi.Site(x, y)) if x < b: pts.append(voronoi.Site(x + bbox.width, y)) if y < b: pts.append(voronoi.Site(x + bbox.width, y + bbox.height)) if y > bbox.height - b: pts.append(voronoi.Site(x + bbox.width, y - bbox.height)) if x > bbox.width - b: pts.append(voronoi.Site(x - bbox.width, y)) if y < b: pts.append(voronoi.Site(x - bbox.width, y + bbox.height)) if y > bbox.height - b: pts.append(voronoi.Site(x - bbox.width, y - bbox.height)) if y < b: pts.append(voronoi.Site(x, y + bbox.height)) if y > bbox.height - b: pts.append(voronoi.Site(x, y - bbox.height)) elif x > -b and y > -b and x < bbox.width + b and y < bbox.height + b: pts.append(voronoi.Site(x, y)) # leave border area blank # dot = pattern.add(inkex.Rectangle()) # dot.set('x', str(x-1)) # dot.set('y', str(y-1)) # dot.set('width', '2') # dot.set('height', '2') if len(pts) < 3: return inkex.errormsg("Please choose a larger object, or smaller cell size") # plot Voronoi diagram sl = voronoi.SiteList(pts) voronoi.voronoi(sl, c) path = "" for edge in c.edges: if edge[1] >= 0 and edge[2] >= 0: # two vertices [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], c.vertices[edge[2]][0], c.vertices[edge[2]][1], bbox.width, bbox.height) elif edge[1] >= 0: # only one vertex if c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0] if c.vertices[edge[1]][1] > bbox.height / 2: ytemp = bbox.height else: ytemp = 0 else: xtemp = bbox.width ytemp = (c.lines[edge[0]][2] - bbox.width * c.lines[edge[0]][0]) / c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(c.vertices[edge[1]][0], c.vertices[edge[1]][1], xtemp, ytemp, bbox.width, bbox.height) elif edge[2] >= 0: # only one vertex if edge[0] >= len(c.lines): xtemp = 0 ytemp = 0 elif c.lines[edge[0]][1] == 0: # vertical line xtemp = c.lines[edge[0]][2] / c.lines[edge[0]][0] if c.vertices[edge[2]][1] > bbox.height / 2: ytemp = bbox.height else: ytemp = 0 else: xtemp = 0 ytemp = c.lines[edge[0]][2] / c.lines[edge[0]][1] [x1, y1, x2, y2] = clip_line(xtemp, ytemp, c.vertices[edge[2]][0], c.vertices[edge[2]][1], bbox.width, bbox.height) if x1 or x2 or y1 or y2: path += 'M %.3f,%.3f %.3f,%.3f ' % (x1, y1, x2, y2) patternstyle = {'stroke': '#000000', 'stroke-width': str(scale)} attribs = {'d': path, 'style': str(inkex.Style(patternstyle))} pattern.append(PathElement(**attribs)) # link selected object to pattern style = {} if 'style' in obj.attrib: style = dict(inkex.Style.parse_str(obj.attrib['style'])) style['fill'] = 'url(#%s)' % pattern.get('id') obj.attrib['style'] = str(inkex.Style(style)) if isinstance(obj, inkex.Group): for node in obj: style = {} if 'style' in node.attrib: style = dict(inkex.Style.parse_str(node.attrib['style'])) style['fill'] = 'url(#%s)' % pattern.get('id') node.attrib['style'] = str(inkex.Style(style))
def GenerateVoronoi(CurrentDate, PointsMap): currenttime=time.time() Sitepts = [] pts = {} #print CurrentDate, PointsMap[PointsMap.keys()[0]] for grid, stations in PointsMap.items(): for stn in stations: x=int(stn[2]) y=int(stn[1]) station=[stn[0]] station.extend( stn[3:]) #print x,y,station if checkInRange(WorldRange,x,y)==False: #print x,y continue pts[ (x,y) ]=station stncounts=len(pts.keys()) #print stncounts, "points" site_points=[] for pt in pts.keys(): Sitepts.append(voronoi.Site(pt[0],pt[1])) site_points.append( (pt[0],pt[1]) ) #print "Calculating Voronoi Lattice", siteList = voronoi.SiteList(Sitepts) context = voronoi.Context() voronoi.Edge.EDGE_NUM=0 #what the hell why should I initialize it? voronoi.voronoi(siteList,context) vertices=context.vertices lines=context.lines edges=context.edges #print edges #For Faster Access edge_dic={} for edge in edges: edge_dic[edge[0]]=edge[1:] triangles=context.triangles has_edge=context.has_edge voronoi_lattice={} m_range={} m_range["max_x"]=-9999999999 m_range["max_y"]=-9999999999 m_range["min_x"]=9999999999 m_range["min_y"]=9999999999 #Get the range!! for pnt in site_points: m_range=update_maxmin(m_range, pnt[0], pnt[1]) #print "Getting the Polygons" prev_percent=0 for station, ls in has_edge.items(): voronoi_lattice[station]={} voronoi_lattice[station]["coordinate"]=site_points[station] voronoi_lattice[station]["info"]=pts[ site_points[station] ] polygon=[] prev_extreme=[] Verbose=True if Verbose: current_percent=int(station/float(stncounts)*100) if current_percent!=prev_percent: #print station,"/", stncounts, current_percent, "% Done" timeelapse=time.time()-currenttime #print station, timeelapse currenttime=time.time() prev_percent=current_percent #For every lines that the station owns for l in ls: e=edge_dic[l] v1=vertices[e[0]] v2=vertices[e[1]] if e[0] < 0 and checkInRange(WorldRange,v2[0],v2[1])==False: continue if e[1] < 0 and checkInRange(WorldRange,v1[0],v1[1])==False: continue if e[0] > -1 and e[1] > -1 and checkInRange(WorldRange,v1[0],v1[1])==False and checkInRange(WorldRange,v2[0],v2[1])==False: continue if e[0] < 0 or checkInRange(WorldRange,v1[0],v1[1])==False: v1=getExtreme(lines[l],v2, LR=0) if len(prev_extreme)==0: prev_extreme=v1 else: extreme_points=linkExtremes(prev_extreme, v1, m_range) for extreme_pair in extreme_points: polygon.append(extreme_pair) if e[1] < 0 or checkInRange(WorldRange,v2[0],v2[1])==False : v2=getExtreme(lines[l],v1, LR=1) if len(prev_extreme)==0: prev_extreme=v2 else: extreme_points=linkExtremes(prev_extreme, v2, m_range) for extreme_pair in extreme_points: polygon.append(extreme_pair) if v1!=v2: polygon.append( (v1,v2) ) #This happened only once for 195612: ['999999-68601', 'BEARDMORE CAMP', 'AY', 'AY'] at (-164667, -85033) if len(polygon)==0: voronoi_lattice.pop(station) continue #print polygon try: result = list(polygonize( polygon )) except ValueError: #print "Wrong:", polygon #Delete invisible short lines point_to_replace=[] for line in polygon: d=math.hypot( line[0][0]-line[1][0], line[0][1]-line[1][1]) if d<1: polygon.remove(line) point_to_replace=line i=0 New_Lines=[] for line in polygon: New_Lines.append(list(line)) j=0 for point in line: if point==point_to_replace[0]: #print line, point_to_replace New_Lines[i][j]=point_to_replace[1] j+=1 i+=1 sys.stderr.write(str(polygon)) polygon=tuple(New_Lines) sys.stderr.write(str(polygon)) result = list(polygonize( polygon )) finalpoly=result[0] #print list(finalpoly.exterior.coords) #voronoi_lattice[station]["polygon"]=list(finalpoly.exterior.coords) voronoi_lattice[station]["obj_polygon"]=finalpoly #print polygon return voronoi_lattice