def decimetritzar_lines(self): """ Edit the lines' geometry in order to round the endpoint's coordinates decimals """ with edit(self.line_layer): for line in self.line_layer.getFeatures(): tram = line.geometry().asMultiPolyline() verts = tram[0] # Comprovar si el primer i últim vertex del tram ja estan decimetritzats i per tant no s'han # de decimetritzar first_vert_decim, last_vert_decim = self.check_tram_decimals( verts) if first_vert_decim and last_vert_decim: continue first_vertex = verts[0] last_vertex = verts[-1] if len(verts) > 2: if first_vert_decim and not last_vert_decim: tram_vertex = verts[:-1] elif not first_vert_decim and last_vert_decim: tram_vertex = verts[1:] else: tram_vertex = verts[1:-1] # Round first and last vertex # First if not first_vert_decim: first_coord_x = first_vertex.x() first_coord_y = first_vertex.y() first_x, first_y = round_coordinates( first_coord_x, first_coord_y) rounded_first_vert = QgsPointXY(first_x, first_y) # Last if not last_vert_decim: last_coord_x = last_vertex.x() last_coord_y = last_vertex.y() last_x, last_y = round_coordinates(last_coord_x, last_coord_y) rounded_last_vert = QgsPointXY(last_x, last_y) # Create new geometry if len(verts) > 2: if not first_vert_decim: tram_vertex.insert(0, rounded_first_vert) if not last_vert_decim: tram_vertex.insert(len(tram_vertex), rounded_last_vert) rounded_geom = QgsGeometry.fromMultiPolylineXY( [tram_vertex]) else: pairs_vertex = [rounded_first_vert, rounded_last_vert] rounded_geom = QgsGeometry.fromMultiPolylineXY( [pairs_vertex]) # Set new geometry self.line_layer.changeGeometry(line.id(), rounded_geom)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) srcCRS = source.sourceCrs() (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.MultiLineString, srcCRS) # Set up CRS transformations if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 iterator = source.getFeatures() for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: if feature.geometry().isMultipart(): seg = feature.geometry().asMultiPolyline() else: seg = [feature.geometry().asPolyline()] numseg = len(seg) if numseg < 1 or len(seg[0]) < 2: continue outseg = [] for pts in seg: if srcCRS != epsg4326: for x, pt in enumerate(pts): pts[x] = geomTo4326.transform(pt) normalizeLongitude(pts) newseg = checkIdlCrossings(pts) outseg.extend(newseg) if srcCRS != epsg4326: # Convert each point to the output CRS for y in range(len(outseg)): for x, pt in enumerate(outseg[y]): outseg[y][x] = toSinkCrs.transform(pt) f = QgsFeature() f.setGeometry(QgsGeometry.fromMultiPolylineXY(outseg)) f.setAttributes(feature.attributes()) sink.addFeature(f) except Exception: '''s = traceback.format_exc() feedback.pushInfo(s)''' pass if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) return {self.PrmOutputLayer: dest_id}
def _swap_qgs_geometry(qgsgeom): if qgsgeom.wkbType() == QgsWkbTypes.Point: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0])) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint: mp = qgsgeom.asMultiPoint() qgsgeom = QgsGeometry.fromMultiPointXY( [QgsPointXY(p[1], p[0]) for p in mp]) elif qgsgeom.wkbType() == QgsWkbTypes.LineString: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolylineXY( [QgsPointXY(p[1], p[0]) for p in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString: mls = qgsgeom.asMultiPolyline() qgsgeom = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p[1], p[0]) for p in pl] for pl in mls]) elif qgsgeom.wkbType() == QgsWkbTypes.Polygon: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygonXY( [[QgsPointXY(p[1], p[0]) for p in r] for r in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon: mp = qgsgeom.asMultiPolygon() qgsgeom = QgsGeometry.fromMultiPolygonXY( [[[QgsPointXY(p[1], p[0]) for p in r] for r in pl] for pl in mp]) return qgsgeom
def testQgsMultilineStringRepr(self): ml = QgsGeometry.fromMultiPolylineXY( [ [QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 0), ], [QgsPointXY(3, 0), QgsPointXY(3, 1), QgsPointXY(5, 1), QgsPointXY(5, 0), QgsPointXY(6, 0), ] ] ) self.assertEqual(ml.constGet().__repr__(), '<QgsMultiLineString: MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0),(3 0, 3 1, 5 1, 5 0, 6 0))>')
def TestQgsMultilineStringRepr(self): ml = QgsGeometry.fromMultiPolylineXY( [ [QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 0), ], [QgsPointXY(3, 0), QgsPointXY(3, 1), QgsPointXY(5, 1), QgsPointXY(5, 0), QgsPointXY(6, 0), ] ] ) self.assertEqual(ml.constGet().__repr__(), '<QgsMultiLineString: MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0),(3 0, 3 1, 5 1, 5 0, 6 0))>')
def reprojectPoints(self, geom, xform): if geom.type() == 0: #Point if geom.isMultipart(): pnts = geom.asMultiPoint() newPnts = [] for pnt in pnts: newPnts += [xform.transform(pnt)] newGeom = QgsGeometry.fromMultiPointXY(newPnts) return newGeom else: pnt = geom.asPoint() newPnt = xform.transform(pnt) newGeom = QgsGeometry.fromPointXY(newPnt) return newGeom elif geom.type() == 1: #Line if geom.isMultipart(): linhas = geom.asMultiPolyline() newLines = [] for linha in linhas: newLine = [] for pnt in linha: newLine += [xform.transform(pnt)] newLines += [newLine] newGeom = QgsGeometry.fromMultiPolylineXY(newLines) return newGeom else: linha = geom.asPolyline() newLine = [] for pnt in linha: newLine += [xform.transform(pnt)] newGeom = QgsGeometry.fromPolylineXY(newLine) return newGeom elif geom.type() == 2: #Polygon if geom.isMultipart(): poligonos = geom.asMultiPolygon() newPolygons = [] for pol in poligonos: newPol = [] for anel in pol: newAnel = [] for pnt in anel: newAnel += [xform.transform(pnt)] newPol += [newAnel] newPolygons += [newPol] newGeom = QgsGeometry.fromMultiPolygonXY(newPolygons) return newGeom else: pol = geom.asPolygon() newPol = [] for anel in pol: newAnel = [] for pnt in anel: newAnel += [xform.transform(pnt)] newPol += [newAnel] newGeom = QgsGeometry.fromPolygonXY(newPol) return newGeom else: return None
def flipFeature(self, layer, feature, geomType=None, refreshCanvas=False): """ Inverts the flow from a given feature. THE GIVEN FEATURE IS ALTERED. Standard behaviour is to not refresh canvas map. :param layer: layer containing the target feature for flipping. :param feature: feature to be flipped. :param geomType: if layer geometry type is not given, it'll calculate it (0,1 or 2) :param refreshCanvas: indicates whether the canvas should be refreshed after flipping feature. :returns: flipped feature as of [layer, feature, geometry_type]. """ if not geomType: geomType = layer.geometryType() # getting whether geometry is multipart or not # features not yet commited to layer always have SINGLE geometry isMulti = QgsWkbTypes.isMultiType(int( layer.wkbType())) and feature.id() > 0 geom = feature.geometry() if geomType == 0: if isMulti: nodes = geom.asMultiPoint() # inverting the point list by parts for idx, part in enumerate(nodes): nodes[idx] = part[::-1] # setting flipped geometry flippedFeatureGeom = QgsGeometry.fromMultiPointXY(nodes) else: # inverting the point list nodes = geom.asPoint() nodes = nodes[::-1] flippedFeatureGeom = QgsGeometry.fromPoint(nodes) elif geomType == 1: if isMulti: nodes = geom.asMultiPolyline() for idx, part in enumerate(nodes): nodes[idx] = part[::-1] flippedFeatureGeom = QgsGeometry.fromMultiPolylineXY(nodes) else: nodes = geom.asPolyline() nodes = nodes[::-1] flippedFeatureGeom = QgsGeometry.fromPolylineXY(nodes) elif geomType == 2: if isMulti: nodes = geom.asMultiPolygon() for idx, part in enumerate(nodes): nodes[idx] = part[::-1] flippedFeatureGeom = QgsGeometry.fromMultiPolygonXY(nodes) else: nodes = geom.asPolygon() nodes = nodes[::-1] flippedFeatureGeom = QgsGeometry.fromPolygonXY(nodes) # setting feature geometry to the flipped one # feature.setGeometry(flippedFeatureGeom) # layer.updateFeature(feature) layer.changeGeometry(feature.id(), flippedFeatureGeom) if refreshCanvas: self.iface.mapCanvas().refresh() return [layer, feature, geomType]
def testAddFeatures(self): # test adding features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertEqual(layer.editBuffer().allAddedOrEditedFeatures(), []) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1])) self.assertCountEqual(layer.editBuffer().allAddedOrEditedFeatures(), [new_feature_ids[0], new_feature_ids[1]]) # check if error in case adding not adaptable geometry # eg. a Multiline in a Line layer = createEmptyLinestringLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) self.assertEqual(layer.editBuffer().allAddedOrEditedFeatures(), []) # add a features with a multi line geometry of not touched lines => # cannot be forced to be linestring multiline = [ [QgsPointXY(1, 1), QgsPointXY(2, 2)], [QgsPointXY(3, 3), QgsPointXY(4, 4)], ] f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromMultiPolylineXY(multiline)) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeatures([f1])) self.assertFalse(layer.commitChanges())
def toQgsGeometry(self): count = len(self.lines) if count > 1: lines = [lineToQgsPolyline(line) for line in self.lines] return QgsGeometry.fromMultiPolylineXY(lines) if count == 1: return QgsGeometry.fromPolylineXY(lineToQgsPolyline(self.lines[0])) return QgsGeometry()
def accept(self): try: distance = float(self.distLineEdit.text()) azimuth = float(self.azimuthLineEdit.text()) units = self.unitsComboBox.currentIndex() # 0 km, 1 m, 2 nm, 3 miles, 4 yards, 5 ft, 6 inches, 7 cm start = self.checkBox.isChecked() except Exception: self.iface.messageBar().pushMessage("", tr("Either distance or azimuth were invalid"), level=Qgis.Warning, duration=4) return layer = self.iface.activeLayer() if layer is None: self.iface.messageBar().pushMessage("", tr("No point or line layer selected"), level=Qgis.Warning, duration=4) return measureFactor = conversionToMeters(units) distance = distance * measureFactor pt = self.pt destCRS = layer.crs() transform = QgsCoordinateTransform(epsg4326, destCRS, QgsProject.instance()) if layer.wkbType() == QgsWkbTypes.Point: g = geod.Direct(pt.y(), pt.x(), azimuth, distance, Geodesic.LATITUDE | Geodesic.LONGITUDE) if start: ptStart = transform.transform(self.pt.x(), self.pt.y()) feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(ptStart)) layer.addFeature(feat) pt = transform.transform(g['lon2'], g['lat2']) feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(pt)) layer.addFeature(feat) else: # It will either be a LineString or MultiLineString maxseglen = settings.maxSegLength * 1000.0 # Needs to be in meters maxSegments = settings.maxSegments gline = geod.Line(pt.y(), pt.x(), azimuth) n = int(math.ceil(distance / maxseglen)) if n > maxSegments: n = maxSegments seglen = distance / n pts = [] for i in range(0, n + 1): s = seglen * i g = gline.Position(s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) ptc = transform.transform(g['lon2'], g['lat2']) pts.append(ptc) feat = QgsFeature(layer.fields()) if layer.wkbType() == QgsWkbTypes.LineString: feat.setGeometry(QgsGeometry.fromPolylineXY(pts)) else: feat.setGeometry(QgsGeometry.fromMultiPolylineXY([pts])) layer.addFeatures([feat]) layer.updateExtents() self.iface.mapCanvas().refresh() self.close()
def toQgsGeometry(self): count = len(self.lines) if count > 1: lines = [[QgsPointXY(x, y) for x, y, z in line] for line in self.lines] return QgsGeometry.fromMultiPolylineXY(lines) if count == 1: pts = [QgsPointXY(x, y) for x, y, z in self.lines[0]] return QgsGeometry.fromPolylineXY(pts) return QgsGeometry()
def testAddFeatures(self): # test adding features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1])) # check if error in case adding not adaptable geometry # eg. a Multiline in a Line layer = createEmptyLinestringLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add a features with a multi line geometry of not touched lines => # cannot be forced to be linestring multiline = [ [QgsPointXY(1, 1), QgsPointXY(2, 2)], [QgsPointXY(3, 3), QgsPointXY(4, 4)], ] f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromMultiPolylineXY(multiline)) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeatures([f1])) self.assertFalse(layer.commitChanges())
def testMeasureMultiLine(self): # +-+ +-+-+ # | | | | # +-+ + + +-+ linestring = QgsGeometry.fromMultiPolylineXY( [ [QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 0), ], [QgsPointXY(3, 0), QgsPointXY(3, 1), QgsPointXY(5, 1), QgsPointXY(5, 0), QgsPointXY(6, 0), ] ] ) da = QgsDistanceArea() length = da.measureLength(linestring) myMessage = ('Expected:\n%f\nGot:\n%f\n' % (9, length)) assert length == 9, myMessage
def create_path_feature_from_Multipolyline(MultipolyLine, ID, flux, roadType, fields): # We create the geometry of the polyline polyline = QgsGeometry.fromMultiPolylineXY(MultipolyLine) # We retrieve the fields and add them to the feature feature = QgsFeature(fields) id_index = feature.fieldNameIndex("id") feature.setAttribute(id_index, ID) flux_index = feature.fieldNameIndex("flux") feature.setAttribute(flux_index, flux) road_type_index = feature.fieldNameIndex("road_type") feature.setAttribute(road_type_index, roadType) # We add the geometry to the feature feature.setGeometry(polyline) return feature
def testMeasureMultiLine(self): # +-+ +-+-+ # | | | | # +-+ + + +-+ linestring = QgsGeometry.fromMultiPolylineXY( [ [QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 0), ], [QgsPointXY(3, 0), QgsPointXY(3, 1), QgsPointXY(5, 1), QgsPointXY(5, 0), QgsPointXY(6, 0), ] ] ) da = QgsDistanceArea() length = da.measureLength(linestring) myMessage = ('Expected:\n%f\nGot:\n%f\n' % (9, length)) assert length == 9, myMessage
def addLinkReverse(self): offset = 5 #Loop over the links """ try: layer = QgsProject.instance().mapLayersByName("Liens")[0] except IndexError: print("No link layer...") with edit(layer): features = layer.selectedFeatures() for feature in features: print("Feature ID: ", feature.id()) geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type()==QgsWkbTypes.LineGeometry: if geomSingleType: print("Dev Notes : maybe useless here but if you see it in the console, this case has to be handled") else: x = geom.asMultiPolyline() newPoints = [] # first point X = x[0][0][0] + offset*(x[0][0][1]-x[0][1][1])/((x[0][1][0]-x[0][0][0])**2 + (x[0][1][1]-x[0][0][1])**2)**0.5 Y = x[0][0][1] + offset*(x[0][1][0]-x[0][0][0])/((x[0][1][0]-x[0][0][0])**2 + (x[0][1][1]-x[0][0][1])**2)**0.5 newPoints.append(QgsPointXY(X,Y)) #last point N = len(x[0]) - 1 for i in range(1,N): x1 = x[0][i][0] + offset*(x[0][i-1][1]-x[0][i][1])/((x[0][i][0]-x[0][i-1][0])**2 + (x[0][i][1]-x[0][i-1][1])**2)**0.5 y1 = x[0][i][1] + offset*(x[0][i][0]-x[0][i-1][0])/((x[0][i][0]-x[0][i-1][0])**2 + (x[0][i][1]-x[0][i-1][1])**2)**0.5 x2 = x[0][i][0] + offset*(x[0][i][1]-x[0][i+1][1])/((x[0][i+1][0]-x[0][i][0])**2 + (x[0][i+1][1]-x[0][i][1])**2)**0.5 y2 = x[0][i][1] + offset*(x[0][i+1][0]-x[0][i][0])/((x[0][i+1][0]-x[0][i][0])**2 + (x[0][i+1][1]-x[0][i][1])**2)**0.5 X = (x1 + x2)/2 Y = (y1 + y2)/2 # TODO !! Faire quand Etienne sera parti newPoints.append(QgsPointXY(X,Y)) #last point X = x[0][N][0] + offset*(x[0][N-1][1]-x[0][N][1])/((x[0][N][0]-x[0][N-1][0])**2 + (x[0][N][1]-x[0][N-1][1])**2)**0.5 Y = x[0][N][1] + offset*(x[0][N][0]-x[0][N-1][0])/((x[0][N][0]-x[0][N-1][0])**2 + (x[0][N][1]-x[0][N-1][1])**2)**0.5 newPoints.append(QgsPointXY(X,Y)) # reverse newPoints.reverse() newgeom = QgsGeometry.fromMultiPolylineXY([newPoints]) feat = QgsFeature(layer.fields()) feat.setGeometry(newgeom) (res, outFeats) = layer.dataProvider().addFeatures([feat])
def contours_ind(self, grille, p, q, s, novalue, mini, maxi, ll, pixel_size_x, pixel_size_y, nx, ny, poles_dict): p1 = ll[0] + (p) * pixel_size_x p2 = ll[0] + (p + 1) * pixel_size_x q1 = ll[1] + (q) * pixel_size_y q2 = ll[1] + (q + 1) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY([[ QgsPointXY(p1, q1), QgsPointXY(p2, q1), QgsPointXY(p2, q2), QgsPointXY(p1, q2), QgsPointXY(p1, q1) ]]) f1 = QgsFeature() f1.setAttributes([poles_dict[str(int(grille[p][q]))]]) f1.setGeometry(ligne1) self.polys[poles_dict[str(int(grille[p][q]))], p, q] = [f1.geometry().asMultiPolyline()]
def find_geometry(self, g): if self.output_type == "Poly": stat = g.area() if g.isMultipart(): geometry = QgsGeometry.fromMultiPolygonXY(g.asMultiPolygon()) else: geometry = QgsGeometry.fromPolygonXY(g.asPolygon()) elif self.output_type == "Line": stat = g.length() if g.isMultipart(): geometry = QgsGeometry.fromMultiPolylineXY(g.asMultiPolyLine()) else: geometry = QgsGeometry.fromPolyline(g.asPoly()) else: stat = 1 if g.isMultipart(): geometry = QgsGeometry.fromMultiPointXY(g.asMultiPoint()) else: geometry = QgsGeometry.fromPointXY(g.asPoint()) return geometry, stat
def _swap_qgs_geometry(qgsgeom): if qgsgeom.wkbType() == QgsWkbTypes.Point: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPointXY(QgsPointXY(p[1], p[0])) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPoint: mp = qgsgeom.asMultiPoint() qgsgeom = QgsGeometry.fromMultiPointXY([QgsPointXY(p[1], p[0]) for p in mp]) elif qgsgeom.wkbType() == QgsWkbTypes.LineString: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolylineXY([QgsPointXY(p[1],p[0]) for p in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiLineString: mls = qgsgeom.asMultiPolyline() qgsgeom = QgsGeometry.fromMultiPolylineXY([[QgsPointXY(p[1],p[0]) for p in pl] for pl in mls]) elif qgsgeom.wkbType() == QgsWkbTypes.Polygon: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygonXY([[QgsPointXY(p[1],p[0]) for p in r] for r in pl]) elif qgsgeom.wkbType() == QgsWkbTypes.MultiPolygon: mp = qgsgeom.asMultiPolygon() qgsgeom = QgsGeometry.fromMultiPolygonXY([[[QgsPointXY(p[1],p[0]) for p in r] for r in pl] for pl in mp]) return qgsgeom
def reverseSelectedLinks(self): try: layer = QgsProject.instance().mapLayersByName("Liens")[0] except IndexError: print("No link layer...") return with edit(layer): features = layer.selectedFeatures() for feature in features: geom = feature.geometry() geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) if geom.type()==QgsWkbTypes.LineGeometry: if geomSingleType: #TODO print("Dev Notes : maybe useless here but if you see it in the console, this case has to be handled") else: x = geom.asMultiPolyline() x[0].reverse() newgeom = QgsGeometry.fromMultiPolylineXY(x) layer.changeGeometry(feature.id(),newgeom)
def paint_model_division(self): if self.rect_Params is None: return if self.divisions: self.canvas.scene().removeItem(self.divisions) self.divisions = [] x_models = int(self.ui.ColPartsSpinBox.value()) y_models = int(self.ui.RowPartsSpinBox.value()) points = getPointsFromRectangleParams(self.rect_Params) lines = [] if y_models > 1: model_height = self.rect_Params["height"] / y_models custRot = self.rect_Params['rotation'] - math.pi * 0.5 for i in range(1, y_models): p1 = getPolarPoint(points[0][0], points[0][1], custRot, model_height * i) p2 = getPolarPoint(points[1][0], points[1][1], custRot, model_height * i) lines.append( [QgsPointXY(p1[0], p1[1]), QgsPointXY(p2[0], p2[1])]) if x_models > 1: model_width = self.rect_Params["width"] / x_models for i in range(1, x_models): p1 = getPolarPoint(points[3][0], points[3][1], self.rect_Params['rotation'], model_width * i) p2 = getPolarPoint(points[0][0], points[0][1], self.rect_Params['rotation'], model_width * i) lines.append( [QgsPointXY(p1[0], p1[1]), QgsPointXY(p2[0], p2[1])]) if lines: self.divisions = QgsRubberBand(self.canvas, False) self.divisions.setColor(QColor(227, 26, 28, 255)) self.divisions.setWidth(3) self.divisions.setLineStyle(Qt.PenStyle(Qt.DashDotLine)) self.divisions.setToGeometry( QgsGeometry.fromMultiPolylineXY(lines), None)
def getSegmentDict(self, lineLyr): segmentDict = dict() geomList = [] if lineLyr.featureCount() > 0: toLineAlias = lambda geom : geom.asMultiPolyline()[0] if next(lineLyr.getFeatures()).geometry().isMultipart() \ else geom.asPolyline() fromLineAlias = lambda x : QgsGeometry.fromMultiPolylineXY([x]) if next(lineLyr.getFeatures()).geometry().isMultipart() \ else QgsGeometry.fromPolyline(x[0], x[1]) for feat in lineLyr.getFeatures(): geom = feat.geometry() if geom not in geomList: geomList.append(geom) lineList = toLineAlias(geom) if lineList[0] not in segmentDict: segmentDict[lineList[0]] = [] segmentDict[lineList[0]].append( fromLineAlias([lineList[0], lineList[1]])) if lineList[-1] not in segmentDict: segmentDict[lineList[-1]] = [] segmentDict[lineList[-1]].append( fromLineAlias([lineList[-1], lineList[-2]])) return segmentDict
def getTree(self, node_id: str): """ Does the work. Tracks the graph up- or downstream. :param node_id: The node from which the tracking should be started """ QApplication.setOverrideCursor(Qt.WaitCursor) upstream = self.direction == "upstream" self.rubberBand.reset() nodes, edges = self.network_analyzer.getTree(node_id, upstream) polylines = self.network_analyzer.getEdgeGeometry([edge[2]['feature'] for edge in edges]) # Fix for QGIS < 2.0 filtered_polylines = [pl for pl in polylines if pl] self.rubberBand.addGeometry(QgsGeometry.fromMultiPolylineXY(filtered_polylines), self.network_analyzer.getNodeLayer()) self.treeChanged.emit(nodes, edges) QApplication.restoreOverrideCursor()
def inv_vertex_order(self, geom): if geom.type() == 1: #Line if geom.isMultipart(): linhas = geom.asMultiPolyline() newLines = [] for linha in linhas: newLine = linha[::-1] newLines += [newLine] newGeom = QgsGeometry.fromMultiPolylineXY(newLines) return newGeom else: linha = geom.asPolyline() newLine = linha[::-1] newGeom = QgsGeometry.fromPolylineXY(newLine) return newGeom elif geom.type() == 2: #Polygon if geom.isMultipart(): poligonos = geom.asMultiPolygon() newPolygons = [] for pol in poligonos: newPol = [] for anel in pol: newAnel = anel[::-1] newPol += [newAnel] newPolygons += [newPol] newGeom = QgsGeometry.fromMultiPolygonXY(newPolygons) return newGeom else: pol = geom.asPolygon() newPol = [] for anel in pol: newAnel = anel[::-1] newPol += [newAnel] newGeom = QgsGeometry.fromPolygonXY(newPol) return newGeom else: return None
def lineContourFeatures(self): x,y,z=self.data() levels = self.levels() usegrid=self.isGridded() and self._useGrid try: if usegrid: gx,gy,gz=self.gridContourData() cs = contour(gx, gy, gz, levels ) else: trig,z=self.trigContourData() cs = tricontour(trig, z, levels ) except: raise ContourGenerationError.fromException(sys.exc_info()) fields = self.fields() zfield=self.zFieldName() dx,dy=self._origin for i, line in enumerate(cs.collections): level=float(cs.levels[i]) glines = [] try: for path in line.get_paths(): if len(path.vertices) > 1: points=[QgsPointXY(x,y) for x,y in path.vertices] glines.append(points) geom=QgsGeometry.fromMultiPolylineXY(glines) geom.translate(dx,dy) feat = QgsFeature(fields) feat.setGeometry(geom) feat['index']=i feat[zfield]=level feat['label']=self._levelLabel(level) yield feat except: message=sys.exc_info()[1] self._feedback.reportError(message)
def lineContourFeatures(self): x,y,z=self.data() levels = self.levels() usegrid=self.isGridded() and self._useGrid try: if usegrid: gx,gy,gz=self.gridContourData() cs = contour(gx, gy, gz, levels ) else: trig,z=self.trigContourData() cs = tricontour(trig, z, levels ) except: raise ContourGenerationError.fromException(sys.exc_info()) fields = self.fields() zfield=self.zFieldName() dx,dy=self._origin for i, line in enumerate(cs.collections): level=float(cs.levels[i]) glines = [] try: for path in line.get_paths(): if len(path.vertices) > 1: points=[QgsPointXY(x,y) for x,y in path.vertices] glines.append(points) geom=QgsGeometry.fromMultiPolylineXY(glines) geom.translate(dx,dy) feat = QgsFeature(fields) feat.setGeometry(geom) feat['index']=i feat[zfield]=level feat['label']=self._levelLabel(level) yield feat except: message=sys.exc_info()[1] self._feedback.reportError(message)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shape_type = self.parameterAsInt(parameters, self.PrmShapeType, context) outer_col = self.parameterAsString(parameters, self.PrmOuterRadiusField, context) inner_col = self.parameterAsString(parameters, self.PrmInnerRadiusField, context) def_outer_radius = self.parameterAsDouble(parameters, self.PrmDefaultOuterRadius, context) def_inner_radius = self.parameterAsDouble(parameters, self.PrmDefaultInnerRadius, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) measure_factor = conversionToMeters(units) def_inner_radius *= measure_factor def_outer_radius *= measure_factor pt_spacing = 360.0 / segments src_crs = source.sourceCrs() fields = source.fields() if export_geom: names = fields.names() name_x, name_y = settings.getGeomNames(names) fields.append(QgsField(name_x, QVariant.Double)) fields.append(QgsField(name_y, QVariant.Double)) if shape_type == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, src_crs) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.MultiLineString, src_crs) if src_crs != epsg4326: geom_to_4326 = QgsCoordinateTransform(src_crs, epsg4326, QgsProject.instance()) to_sink_crs = QgsCoordinateTransform(epsg4326, src_crs, QgsProject.instance()) feature_count = source.featureCount() total = 100.0 / feature_count if feature_count else 0 iterator = source.getFeatures() num_bad = 0 for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: pts_in = [] pts_out = [] pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() # make sure the coordinates are in EPSG:4326 if src_crs != epsg4326: pt = geom_to_4326.transform(pt.x(), pt.y()) lat = pt.y() lon = pt.x() if inner_col: inner_radius = float(feature[inner_col]) * measure_factor else: inner_radius = def_inner_radius if outer_col: outer_radius = float(feature[outer_col]) * measure_factor else: outer_radius = def_outer_radius angle = 0 while angle < 360: if inner_radius != 0: g = geod.Direct(lat, lon, angle, inner_radius, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts_in.append(QgsPointXY(g['lon2'], g['lat2'])) g = geod.Direct(lat, lon, angle, outer_radius, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts_out.append(QgsPointXY(g['lon2'], g['lat2'])) angle += pt_spacing if inner_radius != 0: pts_in.append(pts_in[0]) pts_out.append(pts_out[0]) crosses_idl = hasIdlCrossing(pts_out) if crosses_idl: if inner_radius != 0: makeIdlCrossingsPositive(pts_in, True) makeIdlCrossingsPositive(pts_out, True) # If the Output crs is not 4326 transform the points to the proper crs if src_crs != epsg4326: if inner_radius != 0: for x, pt_out in enumerate(pts_in): pts_in[x] = to_sink_crs.transform(pt_out) for x, pt_out in enumerate(pts_out): pts_out[x] = to_sink_crs.transform(pt_out) f = QgsFeature() if shape_type == 0: if inner_radius == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts_out])) else: f.setGeometry( QgsGeometry.fromPolygonXY([pts_out, pts_in])) else: if inner_radius == 0: f.setGeometry( QgsGeometry.fromMultiPolylineXY([pts_out])) else: f.setGeometry( QgsGeometry.fromMultiPolylineXY([pts_out, pts_in])) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) except Exception: num_bad += 1 feedback.setProgress(int(cnt * total)) if num_bad > 0: feedback.pushInfo( tr("{} out of {} features had invalid parameters and were ignored." .format(num_bad, feature_count))) return {self.PrmOutputLayer: dest_id}
def updateRubberGeom(self): if self.pA is None: return self.zoneWidth = self.pA.distance(self.pB) self.zoneDepth = self.pA.distance(self.pD) self.pM = QgsPointXY((self.pC.x() + self.pD.x()) / 2, (self.pC.y() + self.pD.y()) / 2) self.d0 = self.pM.distance(self.pY) # self.widget.updateZ(self.pY) self.rb.setToGeometry( QgsGeometry.fromPolygonXY( [[self.pD, self.pA, self.pB, self.pC, self.pD]])) self.rbFoc.setToGeometry( QgsGeometry.fromPolylineXY([self.pD, self.pY, self.pC])) for p, rb in [ [self.pA, self.rbPA], [self.pB, self.rbPB], [self.pC, self.rbPC], [self.pD, self.rbPD], [self.pY, self.rbPY], [self.pH, self.rbPH], [self.pL, self.rbPL], ]: rb.setToGeometry(QgsGeometry.fromPointXY(p)) leftEdge = (QgsGeometry.fromPolylineXY([ self.pA, self.pD ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.pB, self.pC ]).densifyByCount(self.widget.rowCount.value() - 1).asPolyline()) # Plot edges lines polyline = list(zip(leftEdge, rightEdge)) backSide = (QgsGeometry.fromPolylineXY([ self.pA, self.pB ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.pD, self.pC ]).densifyByCount(self.widget.columnCount.value() - 1).asPolyline()) polylineX = list(zip(frontSide[:], backSide[:])) self.finalWidth = self.zoneWidth self.rowLines = polyline self.columnLines = polylineX self.allLines = polyline + polylineX self.rbLines.setToGeometry( QgsGeometry.fromMultiPolylineXY( polylineX + polyline + polyline[::max(1, 1 + len(polyline))])) if self.widget.cbReverseRows.isChecked(): if self.widget.cbReverseColumns.isChecked(): self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPA.setColor(Qt.red) self.rbPB.setColor(QColor(0, 200, 150, 255)) else: self.rbPC.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPA.setColor(QColor(0, 200, 150, 255)) else: if self.widget.cbReverseColumns.isChecked(): self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPD.setColor(Qt.red) self.rbPC.setColor(QColor(0, 200, 150, 255)) else: self.rbPA.setColor(Qt.red) self.rbPB.setColor(Qt.red) self.rbPC.setColor(Qt.red) self.rbPD.setColor(QColor(0, 200, 150, 255)) self.widget.alert.setText("Total plots: {}".format( self.widget.columnCount.value() * self.widget.rowCount.value()))
def on_btnSave_released(self): layer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Lines", "memory", ) #QgsProject.instance().addMapLayer(layer) layer.startEditing() layer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) layer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) layer.dataProvider().addAttributes([QgsField("column", QVariant.Int)]) layer.updateFields() feats = [] columnGap = self.columnGap.value() rowGap = self.rowGap.value() fid = 0 lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines) feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(lin) feats.append(feature) g = feature.geometry() rowBuffer = g.buffer(rowGap / 2, 5) fid = 1 lin = QgsGeometry.fromMultiPolylineXY(self.mt.columnLines) feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(lin) feats.append(feature) columnBuffer = lin.buffer(columnGap / 2, 5) layer.dataProvider().addFeatures(feats) # layer.loadNamedStyle(self.plugin_dir + "/lines.qml") layer.commitChanges() # Generate index lines if self.cbReverseRows.isChecked(): leftEdge = (QgsGeometry.fromPolylineXY([ self.mt.pA, self.mt.pD ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.mt.pB, self.mt.pC ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) else: leftEdge = (QgsGeometry.fromPolylineXY([ self.mt.pD, self.mt.pA ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) rightEdge = (QgsGeometry.fromPolylineXY([ self.mt.pC, self.mt.pB ]).densifyByCount(self.rowCount.value() * 2 - 1).asPolyline()) # Plot edges lines polyline_rows = list(zip(leftEdge[1::2], rightEdge[1::2])) if self.cbReverseColumns.isChecked(): backSide = (QgsGeometry.fromPolylineXY([ self.mt.pB, self.mt.pA ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.mt.pC, self.mt.pD ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) else: backSide = (QgsGeometry.fromPolylineXY([ self.mt.pA, self.mt.pB ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) frontSide = (QgsGeometry.fromPolylineXY([ self.mt.pD, self.mt.pC ]).densifyByCount(self.columnCount.value() * 2 - 1).asPolyline()) polyline_columns = list(zip(backSide[1::2], frontSide[1::2])) # Generate Row lines iRowLayer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Index Rows", "memory", ) #QgsProject.instance().addMapLayer(iRowLayer) iRowLayer.startEditing() iRowLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) iRowLayer.updateFields() feats = [] row = 1 lines_rows = QgsGeometry.fromMultiPolylineXY(polyline_rows) for p in lines_rows.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([row]) feature.setGeometry(p) feats.append(feature) row += 1 iRowLayer.dataProvider().addFeatures(feats) iRowLayer.commitChanges() # Generate Column lines iColLayer = QgsVectorLayer( "MultiLineString?crs={}".format( QgsProject.instance().crs().authid()), "Index Columns", "memory", ) #QgsProject.instance().addMapLayer(iColLayer) iColLayer.startEditing() iColLayer.dataProvider().addAttributes( [QgsField("column", QVariant.Int)]) iColLayer.updateFields() feats = [] column = 1 lines_columns = QgsGeometry.fromMultiPolylineXY(polyline_columns) for p in lines_columns.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([column]) feature.setGeometry(p) feats.append(feature) column += 1 iColLayer.dataProvider().addFeatures(feats) iColLayer.commitChanges() pLayer = QgsVectorLayer( "Polygon?crs={}".format(QgsProject.instance().crs().authid()), "Polygons", "memory", ) #QgsProject.instance().addMapLayer(pLayer) pLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) pLayer.dataProvider().addAttributes([QgsField("row", QVariant.Int)]) pLayer.dataProvider().addAttributes([QgsField("column", QVariant.Int)]) pLayer.startEditing() pLayer.updateFields() feats = [] feature = QgsFeature(0) feature.setAttributes([str(fid), 0, 0]) line_list = [f.geometry() for f in layer.getFeatures()] lines = QgsGeometry.unaryUnion(line_list) polygons = QgsGeometry.polygonize([lines]) fid = 0 for p in polygons.asGeometryCollection(): feature = QgsFeature(fid) feature.setAttributes([str(fid), 0, 0]) feature.setGeometry(p) feats.append(feature) fid += 1 pLayer.dataProvider().addFeatures(feats) pLayer.commitChanges() pcLayer = QgsVectorLayer( "Polygon?crs={}".format(QgsProject.instance().crs().authid()), "Plots", "memory", ) QgsProject.instance().addMapLayer(pcLayer) pcLayer.dataProvider().addAttributes(pLayer.fields()) pcLayer.startEditing() pcLayer.updateFields() pcLayer.dataProvider().addFeatures( self.clip_polygons(pLayer, rowBuffer, columnBuffer, iRowLayer, iColLayer)) pcLayer.commitChanges() ptLayer = QgsVectorLayer( "Point?crs={}".format(QgsProject.instance().crs().authid()), "Points", "memory") QgsProject.instance().addMapLayer(ptLayer) ptLayer.startEditing() ptLayer.dataProvider().addAttributes([QgsField("num", QVariant.Int)]) ptLayer.updateFields() feats = [] fid = 0 lin = QgsGeometry.fromMultiPolylineXY(self.mt.rowLines) for line in lin.asGeometryCollection(): poly = line.densifyByCount(self.rowCount.value() * 2).asPolyline() for part in poly: feature = QgsFeature(fid) feature.setAttributes([str(fid)]) feature.setGeometry(QgsPoint(part)) feats.append(feature) fid += 1 # ptLayer.dataProvider().addFeatures(sorted(feats, key=lambda f: f['num'])) ptLayer.dataProvider().addFeatures(feats) ptLayer.commitChanges()
def getLines(self): return QgsGeometry.fromMultiPolylineXY(self.rowLines)
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. raster = self.parameterAsRasterLayer(parameters, self.RASTER, context) bande = self.parameterAsInt(parameters, self.BANDE, context) mini = self.parameterAsDouble(parameters, self.MINI, context) maxi = self.parameterAsDouble(parameters, self.MAXI, context) intervalle = self.parameterAsDouble(parameters, self.INTERVALLE, context) novalue = self.parameterAsDouble(parameters, self.NOVALUE, context) polygones = self.parameterAsBool(parameters, self.POLYGONS, context) # get features from source novalue = novalue layer = raster #fichier_resultat=resultat if not layer == None: if layer.type() == QgsMapLayer.RasterLayer: provider = layer.dataProvider() filePath = str(provider.dataSourceUri()) raster_or = gdal.Open(filePath) nb_bands = layer.bandCount() champs2 = QgsFields() champs2.append(QgsField("id", QVariant.Double)) if polygones == True: (resultat, dest_id) = self.parameterAsSink( parameters, self.CONTOURS, context, champs2, QgsWkbTypes.Polygon, raster.crs() ) # Compute the number of steps to display within the progress bar and else: (resultat, dest_id) = self.parameterAsSink( parameters, self.CONTOURS, context, champs2, QgsWkbTypes.LineString, raster.crs() ) # Compute the number of steps to display within the progress bar and sortie = os.path.splitext(dest_id) nom_sortie = os.path.basename(sortie[0]) rep_sortie = os.path.dirname(sortie[0]) grille = raster_or.GetRasterBand(nb_bands).ReadAsArray() grille = numpy.rot90(grille, 3) self.polys = {} #if polygones==True: # table_lignes=QgsVectorFileWriter(resultat,"UTF-8",champs2,QGis.WKBMultiPolygon,iface.activeLayer().crs(),"ESRI Shapefile") #else: # table_lignes=QgsVectorFileWriter(resultat,"UTF-8",champs2,QGis.WKBMultiLineString,iface.activeLayer().crs(),"ESRI Shapefile") fenetre = layer.extent() a = fenetre.toString().split(":") p1 = a[0].split(',') p2 = a[1].split(',') ll = (float(p1[0]), float(p1[1])) hauteur = float(p2[1]) - float(p1[1]) largeur = float(p2[0]) - float(p1[0]) nx = int(layer.width()) ny = int(layer.height()) pixel_size_x = round(largeur / nx, 2) pixel_size_y = round(hauteur / ny, 2) feedback.setProgressText(self.tr('Grid interpolation...')) for p in range(nx - 1): feedback.setProgress(50 * p / nx) for q in range(ny - 1): self.contours(grille, p, q, intervalle, novalue, mini, maxi, ll, pixel_size_x, pixel_size_y, nx, ny) conn = db.connect(':memory:') conn.enable_load_extension(True) conn.execute("select load_extension('mod_spatialite')") c = conn.cursor() texte = 'drop table if exists "' + nom_sortie + '_polys"' rs = c.execute(texte) conn.commit() texte = 'drop table if exists "' + nom_sortie + '_polys2"' rs = c.execute(texte) conn.commit() texte = 'drop table if exists "' + nom_sortie + '"' rs = c.execute(texte) conn.commit() texte = 'drop table if exists "' + nom_sortie + '_2"' rs = c.execute(texte) conn.commit() texte = 'create table ' + nom_sortie + ' (id double,p integer,q integer, geom geometry)' rs = c.execute(texte) conn.commit() texte = 'SELECT RecoverGeometryColumn(\'' + nom_sortie + '\',\'geom\',' + str( layer.crs().postgisSrid( )) + ', \'MULTILINESTRING\', \'XY\')' rs = c.execute(texte) conn.commit() for k, ff in enumerate(self.polys): feedback.setProgress(51 + (k * 50 / len(self.polys))) li = self.polys[ff] liste1 = [QgsGeometry.fromMultiPolylineXY(l1) for l1 in li] for j, i in enumerate(liste1): texte = 'insert into ' + nom_sortie + ' values(' + str( float(ff[0])) + ',' + str(ff[1]) + ',' + str( ff[2]) + ',st_geomfromtext(\'' + i.asWkt( ) + '\',2154))' rs = c.execute(texte) conn.commit() tlignes = NULL db_filename = rep_sortie + "/" + nom_sortie + ".sqlite" feedback.setProgressText( self.tr("Generating isovalue polygons...")) feedback.setProgress(0) if polygones == True: texte = 'create table \"' + nom_sortie + "_polys\" as SELECT id, casttomultipolygon(polygonize(" + nom_sortie + '.geom)) AS geom FROM \"' + nom_sortie + '\" GROUP BY id,p,q;' rs = c.execute(texte) conn.commit() feedback.setProgress(20) texte = 'create table \"' + nom_sortie + '_polys2" as SELECT id,st_union(geom) AS geom FROM \"' + nom_sortie + '_polys\" GROUP BY id;' rs = c.execute(texte) conn.commit() feedback.setProgress(60) texte = 'SELECT RecoverGeometryColumn(\"' + nom_sortie + "_polys2\"," + '\'geom\',' + str( layer.crs().postgisSrid( )) + ', \'MULTIPOLYGON\', \'XY\')' rs = c.execute(texte) conn.commit() else: texte = 'create table \"' + nom_sortie + "_polys2" + '\" as SELECT "' + nom_sortie + '_2".\'id\' as Id, casttomultilinestring(st_union("' + nom_sortie + '_2".\'GEOMETRY\')) AS Geometry FROM \"' + nom_sortie + '_2\" GROUP BY "' + nom_sortie + '_2".\'id\' ;' rs = c.execute(texte) conn.commit() feedback.setProgress(20) texte = 'SELECT RecoverGeometryColumn(\"' + nom_sortie + "_polys2\"," + '\'geom\',' + str( layer.crs().postgisSrid( )) + ', \'MULTILINESTRING\', \'XY\')' rs = c.execute(texte) conn.commit() feedback.setProgress(60) texte = 'select id, asWkt(geom) from ' + nom_sortie + "_polys2" rs = c.execute(texte) feedback.setProgress(80) resultat2 = c.fetchall() conn.commit() for r0, r in enumerate(resultat2): f1 = QgsFeature(champs2) geom = QgsGeometry.fromWkt(r[1]) f1.setGeometry(geom) f1.setAttributes([float(r[0])]) resultat.addFeature(f1) feedback.setProgress(80 + (r0 * 20 / len(resultat2))) conn.close() del c del conn return {self.CONTOURS: dest_id}
def contours(self, grille, p, q, s, novalue, mini, maxi, ll, pixel_size_x, pixel_size_y, nx, ny): lignes = {} points = {} bords = {} cadreu = {} cadred = {} cadrel = {} cadrer = {} cadre = {} bordu = {} bordd = {} bordl = {} bordr = {} lu = grille[p, q] ld = grille[p, q + 1] ru = grille[p + 1, q] rd = grille[p + 1, q + 1] if lu > novalue: ilu = int(math.floor(lu / s)) else: ilu = novalue if ld > novalue: ild = int(math.floor(ld / s)) else: ild = novalue if ru > novalue: iru = int(math.floor(ru / s)) else: iru = novalue if rd > novalue: ird = int(math.floor(rd / s)) else: ird = novalue if ilu > novalue: ilu = min(max(ilu, int(math.floor(mini / s))), int(math.floor(maxi / s))) if ild > novalue: ild = min(max(ild, int(math.floor(mini / s))), int(math.floor(maxi / s))) if iru > novalue: iru = min(max(iru, int(math.floor(mini / s))), int(math.floor(maxi / s))) if ird > novalue: ird = min(max(ird, int(math.floor(mini / s))), int(math.floor(maxi / s))) if ilu == ild and ilu != novalue: if ilu not in bordl: bordl[ilu] = [] bordl[ilu].append([p, q]) if ilu + 1 not in bordl: bordl[ilu + 1] = [] bordl[ilu + 1].append([p, q + 1]) if ild == ird and ild != novalue: if ild not in bordd: bordd[ild] = [] bordd[ild].append([p, q + 1]) if ild + 1 not in bordd: bordd[ild + 1] = [] bordd[ild + 1].append([p + 1, q + 1]) if iru == ird and iru != novalue: if ird not in bordr: bordr[ird] = [] bordr[ird].append([p + 1, q]) if ird + 1 not in bordr: bordr[ird + 1] = [] bordr[ird + 1].append([p + 1, q + 1]) if ilu == iru and ilu != novalue: if ilu not in bordu: bordu[ilu] = [] bordu[ilu].append([p, q]) if ilu + 1 not in bordu: bordu[ilu + 1] = [] bordu[ilu + 1].append([p + 1, q]) if ilu < ild: if lu == novalue: if ild not in bordl: bordl[ild] = [] bordl[ild].append([p, q]) bordl[ild].append([p, q + 1]) else: for i in range(ilu, ild): if i not in points: points[i] = [] points[i].append([p, q + ((i + 1) * s - lu) / (ld - lu)]) if i == ilu: if i not in bordl: bordl[i] = [] bordl[i].append([p, q]) if i + 1 not in bordl: bordl[i + 1] = [] bordl[i + 1].append( [p, q + ((i + 1) * s - lu) / (ld - lu)]) if i == ild - 1: if i + 2 not in bordl: bordl[i + 2] = [] bordl[i + 2].append([p, q + 1]) if ilu > ild: if ld == novalue: if ilu not in bordl: bordl[ilu] = [] bordl[ilu].append([p, q]) bordl[ilu].append([p, q + 1]) else: for i in range(ild, ilu): if i not in points: points[i] = [] points[i].append([p, q + (lu - (i + 1) * s) / (lu - ld)]) if i == ild: if i - 1 not in bordl: bordl[i - 1] = [] bordl[i - 1].append([p, q + 1]) if i not in bordl: bordl[i] = [] bordl[i].append([p, q + (lu - (i + 1) * s) / (lu - ld)]) if i == ilu - 1: if i + 1 not in bordl: bordl[i + 1] = [] bordl[i + 1].append([p, q]) if ild < ird: if ld == novalue: if ird not in bordd: bordd[ird] = [] bordd[ird].append([p, q + 1]) bordd[ird].append([p + 1, q + 1]) else: for i in range(ild, ird): if i not in points: points[i] = [] points[i].append( [p + ((i + 1) * s - ld) / (rd - ld), q + 1]) if i == ild: if i not in bordd: bordd[i] = [] bordd[i].append([p, q + 1]) if i + 1 not in bordd: bordd[i + 1] = [] bordd[i + 1].append( [p + ((i + 1) * s - ld) / (rd - ld), q + 1]) if i == ird - 1: if i + 2 not in bordd: bordd[i + 2] = [] bordd[i + 2].append([p + 1, q + 1]) if ild > ird: if rd == novalue: if ild not in bordd: bordd[ild] = [] bordd[ild].append([p, q + 1]) bordd[ild].append([p + 1, q + 1]) else: for i in range(ird, ild): if i not in points: points[i] = [] points[i].append( [p + (ld - (i + 1) * s) / (ld - rd), q + 1]) if i == ird: if i - 1 not in bordd: bordd[i - 1] = [] bordd[i - 1].append([p + 1, q + 1]) if i not in bordd: bordd[i] = [] bordd[i].append( [p + (ld - (i + 1) * s) / (ld - rd), q + 1]) if i == ild - 1: if i + 1 not in bordd: bordd[i + 1] = [] bordd[i + 1].append([p, q + 1]) if ird < iru: if rd == novalue: if iru not in bordr: bordr[iru] = [] bordr[iru].append([p + 1, q]) bordr[iru].append([p + 1, q + 1]) else: for i in range(ird, iru): if i not in points: points[i] = [] points[i].append( [p + 1, q + (ru - (i + 1) * s) / (ru - rd)]) if i == iru - 1: if i + 1 not in bordr: bordr[i + 1] = [] bordr[i + 1].append([p + 1, q]) if i == ird: if i - 1 not in bordr: bordr[i - 1] = [] bordr[i - 1].append([p + 1, q + 1]) if i not in bordr: bordr[i] = [] bordr[i].append( [p + 1, q + (ru - (i + 1) * s) / (ru - rd)]) if ird > iru: if ru == novalue: if ird not in bordr: bordr[ird] = [] bordr[ird].append([p + 1, q]) bordr[ird].append([p + 1, q + 1]) else: for i in range(iru, ird): if i not in points: points[i] = [] points[i].append( [p + 1, q + ((i + 1) * s - ru) / (rd - ru)]) if i == iru: if i not in bordr: bordr[i] = [] bordr[i].append([p + 1, q]) if i + 1 not in bordr: bordr[i + 1] = [] bordr[i + 1].append( [p + 1, q + ((i + 1) * s - ru) / (rd - ru)]) if i == ird - 1: if i + 2 not in bordr: bordr[i + 2] = [] bordr[i + 2].append([p + 1, q + 1]) if iru < ilu: if ru == novalue: if ilu not in bordu: bordu[ilu] = [] bordu[ilu].append([p, q]) bordu[ilu].append([p + 1, q]) else: for i in range(iru, ilu): if i not in points: points[i] = [] points[i].append([p + (lu - (i + 1) * s) / (lu - ru), q]) if i == iru: if i - 1 not in bordu: bordu[i - 1] = [] bordu[i - 1].append([p + 1, q]) if i == ilu - 1: if i + 1 not in bordu: bordu[i + 1] = [] bordu[i + 1].append([p, q]) if i not in bordu: bordu[i] = [] bordu[i].append([p + (lu - (i + 1) * s) / (lu - ru), q]) if iru > ilu: if lu == novalue: if iru not in bordu: bordu[iru] = [] bordu[iru].append([p, q]) bordu[iru].append([p + 1, q]) else: for i in range(ilu, iru): if i not in points: points[i] = [] points[i].append([p + ((i + 1) * s - lu) / (ru - lu), q]) if i == ilu: if i not in bordu: bordu[i] = [] bordu[i].append([p, q]) if i + 1 not in bordu: bordu[i + 1] = [] bordu[i + 1].append( [p + ((i + 1) * s - lu) / (ru - lu), q]) if i == iru - 1: if i + 2 not in bordu: bordu[i + 2] = [] bordu[i + 2].append([p + 1, q]) for pt in points: mx = sum(float(points[pt][j][0]) for j in range(len(points[pt]))) / len(points[pt]) my = sum(float(points[pt][j][1]) for j in range(len(points[pt]))) / len(points[pt]) for j in range(len(points[pt])): n = len(points[pt]) if n > 2: p1x = ll[0] + (p + 1 - 0.02 * ((-1)**(int(j / 2)))) * pixel_size_x p2x = ll[0] + (points[pt][j][0] + 0.5) * pixel_size_x q1y = ll[1] + (q + 1 - 0.02 * ((-1)**(int(j / 2)))) * pixel_size_y q2y = ll[1] + (points[pt][j][1] + 0.5) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p1x, q1y), QgsPointXY(p2x, q2y)]]) else: p1x = ll[0] + (mx + 0.5) * pixel_size_x p2x = ll[0] + (points[pt][j][0] + 0.5) * pixel_size_x q1y = ll[1] + (my + 0.5) * pixel_size_y q2y = ll[1] + (points[pt][j][1] + 0.5) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p1x, q1y), QgsPointXY(p2x, q2y)]]) f1 = QgsFeature() f1.setAttributes([pt * s]) f1.setGeometry(ligne1) f2 = QgsFeature() f2.setAttributes([(pt + 1) * s]) f2.setGeometry(ligne1) if min(lu, ld, ru, rd) > novalue: if (pt * s, p, q) not in self.polys: self.polys[pt * s, p, q] = [] self.polys[pt * s, p, q].append(f1.geometry().asMultiPolyline()) if ((pt + 1) * s, p, q) not in self.polys: self.polys[(pt + 1) * s, p, q] = [] self.polys[(pt + 1) * s, p, q].append(f2.geometry().asMultiPolyline()) if len(bordu) > 0: bords = sorted(bordu.items(), key=lambda x: x[1][0]) for pt in range(len(bords) - 1): p1 = ll[0] + (bords[pt][1][0][0] + 0.5) * pixel_size_x p2 = ll[0] + (bords[pt + 1][1][0][0] + 0.5) * pixel_size_x q1 = ll[1] + (bords[pt][1][0][1] + 0.5) * pixel_size_y q2 = ll[1] + (bords[pt + 1][1][0][1] + 0.5) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p1, q1), QgsPointXY(p2, q2)]]) f1 = QgsFeature() f1.setAttributes([bords[pt][0] * s]) f1.setGeometry(ligne1) if q > 0: if q < ny - 1: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) else: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) if len(bordl) > 0: bords = sorted(bordl.items(), key=lambda x: x[1][0][1]) for pt in range(len(bords) - 1): p1 = ll[0] + (bords[pt][1][0][0] + 0.5) * pixel_size_x p2 = ll[0] + (bords[pt + 1][1][0][0] + 0.5) * pixel_size_x q1 = ll[1] + (bords[pt][1][0][1] + 0.5) * pixel_size_y q2 = ll[1] + (bords[pt + 1][1][0][1] + 0.5) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p1, q1), QgsPointXY(p2, q2)]]) f1 = QgsFeature() f1.setAttributes([bords[pt][0] * s]) f1.setGeometry(ligne1) if p > 0: if p < nx - 1: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) else: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) if len(bordr) > 0: bords = sorted(bordr.items(), key=lambda x: x[1][0][1]) for pt in range(len(bords) - 1): p1 = ll[0] + (bords[pt][1][0][0] + 0.5) * pixel_size_x p2 = ll[0] + (bords[pt + 1][1][0][0] + 0.5) * pixel_size_x q1 = ll[1] + (bords[pt][1][0][1] + 0.5) * pixel_size_y q2 = ll[1] + (bords[pt + 1][1][0][1] + 0.5) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p1, q1), QgsPointXY(p2, q2)]]) f1 = QgsFeature() f1.setAttributes([bords[pt][0] * s]) f1.setGeometry(ligne1) if p < nx - 2: if q > -1: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) else: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) if len(bordd) > 0: bords = sorted(bordd.items(), key=lambda x: x[1][0]) for pt in range(len(bords) - 1): p1 = ll[0] + (bords[pt][1][0][0] + 0.5) * pixel_size_x p2 = ll[0] + (bords[pt + 1][1][0][0] + 0.5) * pixel_size_x q1 = ll[1] + (bords[pt][1][0][1] + 0.5) * pixel_size_y q2 = ll[1] + (bords[pt + 1][1][0][1] + 0.5) * pixel_size_y ligne1 = QgsGeometry.fromMultiPolylineXY( [[QgsPointXY(p1, q1), QgsPointXY(p2, q2)]]) f1 = QgsFeature() f1.setAttributes([bords[pt][0] * s]) f1.setGeometry(ligne1) if q < ny - 2: if q > -1: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline()) else: if (bords[pt][0] * s, p, q) not in self.polys: self.polys[bords[pt][0] * s, p, q] = [] self.polys[bords[pt][0] * s, p, q].append(f1.geometry().asMultiPolyline())
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) startPoints = self.parameterAsSource(parameters, self.START_POINTS, context) if startPoints is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.START_POINTS)) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) include_bounds = True # default to true to maintain 3.0 API if self.INCLUDE_BOUNDS in parameters: include_bounds = self.parameterAsBoolean(parameters, self.INCLUDE_BOUNDS, context) fields = startPoints.fields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Loading start points…')) request = QgsFeatureRequest() request.setDestinationCrs(network.sourceCrs(), context.transformContext()) features = startPoints.getFeatures(request) total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0 points = [] source_attributes = {} i = 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): continue for p in f.geometry().vertices(): points.append(QgsPointXY(p)) source_attributes[i] = f.attributes() i += 1 feedback.setProgress(int(current * total)) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Building graph…')) snappedPoints = director.makeGraph(builder, points, feedback) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…')) graph = builder.graph() (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context, fields, QgsWkbTypes.MultiLineString, network.sourceCrs()) total = 100.0 / len(snappedPoints) if snappedPoints else 1 for i, p in enumerate(snappedPoints): if feedback.isCanceled(): break idxStart = graph.findVertex(snappedPoints[i]) origPoint = points[i].toString() tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = set() area_points = [] lines = [] for vertex, start_vertex_cost in enumerate(cost): inbound_edge_index = tree[vertex] if inbound_edge_index == -1 and vertex != idxStart: # unreachable vertex continue if start_vertex_cost > travelCost: # vertex is too expensive, discard continue vertices.add(vertex) start_point = graph.vertex(vertex).point() # find all edges coming from this vertex for edge_id in graph.vertex(vertex).outgoingEdges(): edge = graph.edge(edge_id) end_vertex_cost = start_vertex_cost + edge.cost(0) end_point = graph.vertex(edge.toVertex()).point() if end_vertex_cost <= travelCost: # end vertex is cheap enough to include vertices.add(edge.toVertex()) lines.append([start_point, end_point]) else: # travelCost sits somewhere on this edge, interpolate position interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue(start_point.x(), start_point.y(), start_vertex_cost, end_point.x(), end_point.y(), end_vertex_cost, travelCost) area_points.append(interpolated_end_point) lines.append([start_point, interpolated_end_point]) for v in vertices: area_points.append(graph.vertex(v).point()) feat = QgsFeature() if point_sink is not None: geomPoints = QgsGeometry.fromMultiPointXY(area_points) feat.setGeometry(geomPoints) attrs = source_attributes[i] attrs.extend(['within', origPoint]) feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if include_bounds: upperBoundary = [] lowerBoundary = [] vertices = [] for vertex, c in enumerate(cost): if c > travelCost and tree[vertex] != -1: vertexId = graph.edge(tree[vertex]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(vertex) for v in vertices: upperBoundary.append(graph.vertex(graph.edge(tree[v]).toVertex()).point()) lowerBoundary.append(graph.vertex(graph.edge(tree[v]).fromVertex()).point()) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) feat.setGeometry(geomUpper) attrs[-2] = 'upper' feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) attrs[-2] = 'lower' feat.setAttributes(attrs) point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if line_sink is not None: geom_lines = QgsGeometry.fromMultiPolylineXY(lines) feat.setGeometry(geom_lines) attrs = source_attributes[i] attrs.extend(['lines', origPoint]) feat.setAttributes(attrs) line_sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(i * total)) results = {} if point_sink is not None: results[self.OUTPUT] = dest_id if line_sink is not None: results[self.OUTPUT_LINES] = line_dest_id return results
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. source = self.parameterAsSource(parameters, self.INPUT, context) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) # Compute the number of steps to display within the progress bar and # get features from source total = 100.0 / source.featureCount() if source.featureCount() else 0 features = source.getFeatures() print(features) for current, feature in enumerate(features): # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): break # sshuair begin geom = feature.geometry() attrs = feature.attributes() geom_type = geom.wkbType() feature_new = QgsFeature() # Point if geom_type == 1: vertices = geom.asPoint() vert_new = bd2gcj(vertices[0], vertices[1]) feature_new.setGeometry( QgsGeometry.fromPointXY( QgsPointXY(vert_new[0], vert_new[1]))) # LineString elif geom_type == 2: vert_new = [] vertices = geom.asPolyline() for pt in vertices: pt_new = bd2gcj(pt[0], pt[1]) vert_new.append(QgsPointXY(pt_new[0], pt_new[1])) feature_new.setGeometry(QgsGeometry.fromPolylineXY(vert_new)) # Polygon elif geom_type == 3: vertices = geom.asPolygon() vert_new = [] for ring in vertices: ring_vert = [] for pt in ring: pt_new = bd2gcj(pt[0], pt[1]) ring_vert.append(QgsPointXY(pt_new[0], pt_new[1])) vert_new.append(ring_vert) feature_new.setGeometry(QgsGeometry.fromPolygonXY(vert_new)) # MultiPoint elif geom_type == 4: vert_new = [] vertices = geom.asMultiPoint() for pt in vertices: pt_new = bd2gcj(pt[0], pt[1]) vert_new.append(QgsPointXY(pt_new[0], pt_new[1])) feature_new.setGeometry(QgsGeometry.fromMultiPointXY(vert_new)) # MultiLineString elif geom_type == 5: vertices = geom.asMultiPolyline() vert_new = [] for part in vertices: linestring = [] for pt in part: pt_new = bd2gcj(pt[0], pt[1]) linestring.append(QgsPointXY(pt_new[0], pt_new[1])) vert_new.append(linestring) feature_new.setGeometry( QgsGeometry.fromMultiPolylineXY(vert_new)) # MultiPolygon elif geom_type == 6: vertices = geom.asMultiPolygon() vert_new = [] for part in vertices: poly = [] for ring in part: ring_vert = [] for pt in ring: pt_new = bd2gcj(pt[0], pt[1]) ring_vert.append(QgsPointXY(pt_new[0], pt_new[1])) poly.append(ring_vert) vert_new.append(poly) feature_new.setGeometry( QgsGeometry.fromMultiPolygonXY(vert_new)) else: continue feature_new.setAttributes(attrs) # sshuair end # feature = feature+0.1 # Add a feature in the sink sink.addFeature(feature_new, QgsFeatureSink.FastInsert) # Update the progress bar feedback.setProgress(int(current * total)) print(feature) # Return the results of the algorithm. In this case our only result is # the feature sink which contains the processed features, but some # algorithms may return multiple feature sinks, calculated numeric # statistics, etc. These should all be included in the returned # dictionary, with keys matching the feature corresponding parameter # or output names. return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): network = self.parameterAsSource(parameters, self.INPUT, context) if network is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs()) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context) directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) include_bounds = True # default to true to maintain 3.0 API if self.INCLUDE_BOUNDS in parameters: include_bounds = self.parameterAsBool(parameters, self.INCLUDE_BOUNDS, context) directionField = -1 if directionFieldName: directionField = network.fields().lookupField(directionFieldName) speedField = -1 if speedFieldName: speedField = network.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(network, directionField, forwardValue, backwardValue, bothValue, defaultDirection) distUnit = context.project().crs().mapUnits() multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters) if strategy == 0: strategy = QgsNetworkDistanceStrategy() else: strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed, multiplier * 1000.0 / 3600.0) director.addStrategy(strategy) builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Building graph…')) snappedPoints = director.makeGraph(builder, [startPoint], feedback) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Calculating service area…')) graph = builder.graph() idxStart = graph.findVertex(snappedPoints[0]) tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) vertices = set() points = [] lines = [] for vertex, start_vertex_cost in enumerate(cost): inbound_edge_index = tree[vertex] if inbound_edge_index == -1 and vertex != idxStart: # unreachable vertex continue if start_vertex_cost > travelCost: # vertex is too expensive, discard continue vertices.add(vertex) start_point = graph.vertex(vertex).point() # find all edges coming from this vertex for edge_id in graph.vertex(vertex).outgoingEdges(): edge = graph.edge(edge_id) end_vertex_cost = start_vertex_cost + edge.cost(0) end_point = graph.vertex(edge.toVertex()).point() if end_vertex_cost <= travelCost: # end vertex is cheap enough to include vertices.add(edge.toVertex()) lines.append([start_point, end_point]) else: # travelCost sits somewhere on this edge, interpolate position interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue(start_point.x(), start_point.y(), start_vertex_cost, end_point.x(), end_point.y(), end_vertex_cost, travelCost) points.append(interpolated_end_point) lines.append([start_point, interpolated_end_point]) for i in vertices: points.append(graph.vertex(i).point()) feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Writing results…')) fields = QgsFields() fields.append(QgsField('type', QVariant.String, '', 254, 0)) fields.append(QgsField('start', QVariant.String, '', 254, 0)) feat = QgsFeature() feat.setFields(fields) (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.MultiPoint, network.sourceCrs()) results = {} if point_sink is not None: results[self.OUTPUT] = dest_id geomPoints = QgsGeometry.fromMultiPointXY(points) feat.setGeometry(geomPoints) feat['type'] = 'within' feat['start'] = startPoint.toString() point_sink.addFeature(feat, QgsFeatureSink.FastInsert) if include_bounds: upperBoundary = [] lowerBoundary = [] vertices = [] for i, v in enumerate(cost): if v > travelCost and tree[i] != -1: vertexId = graph.edge(tree[i]).fromVertex() if cost[vertexId] <= travelCost: vertices.append(i) for i in vertices: upperBoundary.append(graph.vertex(graph.edge(tree[i]).toVertex()).point()) lowerBoundary.append(graph.vertex(graph.edge(tree[i]).fromVertex()).point()) geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary) geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary) feat.setGeometry(geomUpper) feat['type'] = 'upper' feat['start'] = startPoint.toString() point_sink.addFeature(feat, QgsFeatureSink.FastInsert) feat.setGeometry(geomLower) feat['type'] = 'lower' feat['start'] = startPoint.toString() point_sink.addFeature(feat, QgsFeatureSink.FastInsert) (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context, fields, QgsWkbTypes.MultiLineString, network.sourceCrs()) if line_sink is not None: results[self.OUTPUT_LINES] = line_dest_id geom_lines = QgsGeometry.fromMultiPolylineXY(lines) feat.setGeometry(geom_lines) feat['type'] = 'lines' feat['start'] = startPoint.toString() line_sink.addFeature(feat, QgsFeatureSink.FastInsert) return results
def getLinesSelectionModeLines(self, selectBehaviour: SelectBehaviour, rect: QgsRectangle) -> typing.Tuple: assert self.simplifiedSegmentsLayer rect = self.__getCoordinateTransform( self.simplifiedSegmentsLayer).transform(rect) self.simplifiedSegmentsLayer.selectByRect(rect, selectBehaviour) if self.simplifiedSegmentsLayer.selectedFeatureCount() == 0: return () selectedLinesLayer = utils.selected_features_to_layer( self.simplifiedSegmentsLayer) dissolvedLinesLayer = utils.dissolve_layer(selectedLinesLayer) mergedLinesLayer = utils.merge_lines_layer(dissolvedLinesLayer) singlepartsLayer = utils.multipart_to_singleparts(mergedLinesLayer) # INFO: this is disabled, it causes the selecteBehaviour to be ignored. # Could be written in much more clever way, but does not worth it # self.simplifiedSegmentsLayer.deselect(list(self.simplifiedSegmentsLayer.selectedFeatureIds())) enclosingLineFeatures = list(dissolvedLinesLayer.getFeatures()) points_dict = dict() for f in singlepartsLayer.getFeatures(): points_dict[f.id()] = utils.lines_unique_vertices( singlepartsLayer, [f.id()]) points = list(points_dict.values()) if len(points) == 1 and len(points[0]) == 2: pointX1 = points[0][0] pointY1 = points[0][0] pointX2 = points[0][1] pointY2 = points[0][1] elif len(points) == 2 and len(points[0]) == 2 and len(points[1]) == 2: pointX1 = points[0][0] pointY1 = points[0][1] pointX2 = points[1][0] pointY2 = points[1][1] else: show_info( __('Selected lines can have exactly two or four unconnected endpoints' )) return tuple(enclosingLineFeatures) selectedLinesLayer.startEditing() f1 = QgsFeature(selectedLinesLayer.fields()) f2 = QgsFeature(selectedLinesLayer.fields()) if pointX1.distance(pointX2) + pointY1.distance( pointY2) < pointX1.distance(pointY2) + pointY1.distance( pointX2): # x1->x2 y1->y2 f1.setGeometry( QgsGeometry.fromMultiPolylineXY([[pointX1, pointX2]])) f2.setGeometry( QgsGeometry.fromMultiPolylineXY([[pointY1, pointY2]])) else: # x1->y2 y1->x f1.setGeometry( QgsGeometry.fromMultiPolylineXY([[pointX1, pointY2]])) f2.setGeometry( QgsGeometry.fromMultiPolylineXY([[pointY1, pointX2]])) selectedLinesLayer.addFeatures([f1, f2]) selectedLinesLayer.commitChanges() dissolvedLinesLayer2 = utils.dissolve_layer(selectedLinesLayer) return tuple(dissolvedLinesLayer2.getFeatures())