def ovals(self, sink, source, width, height, rotation, segments, feedback): features = source.getFeatures() ft = QgsFeature() xOffset = width / 2.0 yOffset = height / 2.0 total = 100.0 / source.featureCount() if source.featureCount() else 0 if rotation is not None: phi = rotation * math.pi / 180 for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue point = feat.geometry().asPoint() x = point.x() y = point.y() points = [] for t in [(2 * math.pi) / segments * i for i in range(segments)]: points.append((xOffset * math.cos(t), yOffset * math.sin(t))) polygon = [[QgsPointXY(i[0] * math.cos(phi) + i[1] * math.sin(phi) + x, -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) else: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue point = feat.geometry().asPoint() x = point.x() y = point.y() points = [] for t in [(2 * math.pi) / segments * i for i in range(segments)]: points.append((xOffset * math.cos(t), yOffset * math.sin(t))) polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total))
def testQgsPolygonRepr(self): p = QgsGeometry.fromPolygonXY( [[QgsPointXY(0, 0), QgsPointXY(2, 0), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0)]]) self.assertEqual(p.constGet().__repr__(), '<QgsPolygon: Polygon ((0 0, 2 0, 2 2, 0 2, 0 0))>')
def createLayerWithOnePolygon(): layer = QgsVectorLayer("Polygon?crs=epsg:3111&field=pk:int", "vl", "memory") assert layer.isValid() f1 = QgsFeature(layer.dataProvider().fields(), 1) f1.setAttribute("pk", 1) f1.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(2484588, 2425722), QgsPointXY(2482767, 2398853), QgsPointXY(2520109, 2397715), QgsPointXY(2520792, 2425494), QgsPointXY(2484588, 2425722)]])) assert layer.dataProvider().addFeatures([f1]) return layer
def _diamondGrid(self, sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback): ft = QgsFeature() halfHSpacing = hSpacing / 2 halfVSpacing = vSpacing / 2 halfHOverlay = hOverlay / 2 halfVOverlay = vOverlay / 2 columns = int(math.ceil(float(width) / (halfHSpacing - halfHOverlay))) rows = int(math.ceil(float(height) / (vSpacing - halfVOverlay))) cells = rows * columns count_update = cells * 0.05 id = 1 count = 0 for col in range(columns): if feedback.isCanceled(): break x = originX - (col * halfHOverlay) x1 = x + ((col + 0) * halfHSpacing) x2 = x + ((col + 1) * halfHSpacing) x3 = x + ((col + 2) * halfHSpacing) for row in range(rows): y = originY + (row * halfVOverlay) if (col % 2) == 0: y1 = y - (((row * 2) + 0) * halfVSpacing) y2 = y - (((row * 2) + 1) * halfVSpacing) y3 = y - (((row * 2) + 2) * halfVSpacing) else: y1 = y - (((row * 2) + 1) * halfVSpacing) y2 = y - (((row * 2) + 2) * halfVSpacing) y3 = y - (((row * 2) + 3) * halfVSpacing) polyline = [] polyline.append(QgsPointXY(x1, y2)) polyline.append(QgsPointXY(x2, y1)) polyline.append(QgsPointXY(x3, y2)) polyline.append(QgsPointXY(x2, y3)) polyline.append(QgsPointXY(x1, y2)) ft.setGeometry(QgsGeometry.fromPolygonXY([polyline])) ft.setAttributes([x1, y1, x3, y3, id]) sink.addFeature(ft, QgsFeatureSink.FastInsert) id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(int(count / cells * 100))
def create_cell(self, centroid, from_deg, to_deg, radius): step = abs(to_deg - from_deg) / self.DEFAULT_SEGS outer_ring = [] outer_ring.append(centroid) # second outer for index in range(self.DEFAULT_SEGS, -1, -1): radian = math.radians(from_deg + (index * step)) outer_ring.append(self.create_point(centroid, radian, radius)) return QgsGeometry.fromPolygonXY([outer_ring])
def rotation_test(self): # We will create a polygon layer with a rotated rectangle. # Then we will make it the object layer for the atlas, # rotate the map and test that the bounding rectangle # is smaller than the bounds without rotation. polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.fields()) points = [(10, 15), (15, 10), (45, 40), (40, 45)] poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]])) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) # Recreating the layout locally composition = QgsPrintLayout(QgsProject.instance()) composition.initializeDefaults() # the atlas map atlasMap = QgsLayoutItemMap(composition) atlasMap.attemptSetSceneRect(QRectF(20, 20, 130, 130)) atlasMap.setFrameEnabled(True) atlasMap.setLayers([polygonLayer]) atlasMap.setExtent(QgsRectangle(0, 0, 100, 50)) composition.addLayoutItem(atlasMap) # the atlas atlas = composition.atlas() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) atlasMap.setAtlasDriven(True) atlasMap.setAtlasScalingMode(QgsLayoutItemMap.Auto) atlasMap.setAtlasMargin(0.0) # Testing atlasMap.setMapRotation(0.0) atlas.beginRender() atlas.first() nonRotatedExtent = QgsRectangle(atlasMap.extent()) atlasMap.setMapRotation(45.0) atlas.first() rotatedExtent = QgsRectangle(atlasMap.extent()) self.assertLess(rotatedExtent.width(), nonRotatedExtent.width() * 0.9) self.assertLess(rotatedExtent.height(), nonRotatedExtent.height() * 0.9) QgsProject.instance().removeMapLayer(polygonLayer)
def create_ring_cell(self, centroid, from_deg, to_deg, from_radius, to_radius): step = abs(to_deg - from_deg) / self.DEFAULT_SEGS radian = 0.0 outer_ring = [] # first interior for index in range(self.DEFAULT_SEGS + 1 - self.GAPS): radian = math.radians(from_deg + (index * step)) outer_ring.append(self.create_point(centroid, radian, from_radius)) # second outer for index in range(self.DEFAULT_SEGS - self.GAPS, -1, -1): radian = math.radians(from_deg + (index * step)) outer_ring.append(self.create_point(centroid, radian, to_radius)) return QgsGeometry.fromPolygonXY([outer_ring])
def rotation_test(self): # We will create a polygon layer with a rotated rectangle. # Then we will make it the object layer for the atlas, # rotate the map and test that the bounding rectangle # is smaller than the bounds without rotation. polygonLayer = QgsVectorLayer('Polygon', 'test_polygon', 'memory') poly = QgsFeature(polygonLayer.pendingFields()) points = [(10, 15), (15, 10), (45, 40), (40, 45)] poly.setGeometry(QgsGeometry.fromPolygonXY([[QgsPointXY(x[0], x[1]) for x in points]])) polygonLayer.dataProvider().addFeatures([poly]) QgsProject.instance().addMapLayer(polygonLayer) # Recreating the composer locally composition = QgsComposition(QgsProject.instance()) composition.setPaperSize(297, 210) # the atlas map atlasMap = QgsComposerMap(composition, 20, 20, 130, 130) atlasMap.setFrameEnabled(True) atlasMap.setLayers([polygonLayer]) atlasMap.setNewExtent(QgsRectangle(0, 0, 100, 50)) composition.addComposerMap(atlasMap) # the atlas atlas = composition.atlasComposition() atlas.setCoverageLayer(polygonLayer) atlas.setEnabled(True) composition.setAtlasMode(QgsComposition.ExportAtlas) atlasMap.setAtlasDriven(True) atlasMap.setAtlasScalingMode(QgsComposerMap.Auto) atlasMap.setAtlasMargin(0.0) # Testing atlasMap.setMapRotation(0.0) atlas.firstFeature() nonRotatedExtent = QgsRectangle(atlasMap.currentMapExtent()) atlasMap.setMapRotation(45.0) atlas.firstFeature() rotatedExtent = QgsRectangle(atlasMap.currentMapExtent()) assert rotatedExtent.width() < nonRotatedExtent.width() * 0.9 assert rotatedExtent.height() < nonRotatedExtent.height() * 0.9 QgsProject.instance().removeMapLayer(polygonLayer)
def testMeasurePolygon(self): # +-+-+ # | | # + +-+ # | | # +-+ polygon = QgsGeometry.fromPolygonXY( [[ QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0), ]] ) da = QgsDistanceArea() area = da.measureArea(polygon) assert area == 3, 'Expected:\n%f\nGot:\n%f\n' % (3, area) perimeter = da.measurePerimeter(polygon) assert perimeter == 8, 'Expected:\n%f\nGot:\n%f\n' % (8, perimeter)
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 testMeasurePolygonWithHole(self): # +-+-+-+ # | | # + +-+ + # | | | | # + +-+ + # | | # +-+-+-+ polygon = QgsGeometry.fromPolygonXY( [ [QgsPointXY(0, 0), QgsPointXY(3, 0), QgsPointXY(3, 3), QgsPointXY(0, 3), QgsPointXY(0, 0)], [QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(1, 2), QgsPointXY(1, 1)], ] ) da = QgsDistanceArea() area = da.measureArea(polygon) assert area == 8, "Expected:\n%f\nGot:\n%f\n" % (8, area) # MH150729: Changed behavior to consider inner rings for perimeter calculation. Therefore, expected result is 16. perimeter = da.measurePerimeter(polygon) assert perimeter == 16, "Expected:\n%f\nGot:\n%f\n" % (16, perimeter)
def _rectangleGrid(self, sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback): ft = QgsFeature() columns = int(math.ceil(float(width) / (hSpacing - hOverlay))) rows = int(math.ceil(float(height) / (vSpacing - vOverlay))) cells = rows * columns count_update = cells * 0.05 id = 1 count = 0 for col in range(columns): if feedback.isCanceled(): break x1 = originX + (col * hSpacing - col * hOverlay) x2 = x1 + hSpacing for row in range(rows): y1 = originY - (row * vSpacing - row * vOverlay) y2 = y1 - vSpacing polyline = [] polyline.append(QgsPointXY(x1, y1)) polyline.append(QgsPointXY(x2, y1)) polyline.append(QgsPointXY(x2, y2)) polyline.append(QgsPointXY(x1, y2)) polyline.append(QgsPointXY(x1, y1)) ft.setGeometry(QgsGeometry.fromPolygonXY([polyline])) ft.setAttributes([x1, y1, x2, y2, id]) sink.addFeature(ft, QgsFeatureSink.FastInsert) id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(int(count / cells * 100))
def processEllipse(self, layer, outname, shapetype, semimajorcol, semiminorcol, orientcol, unitOfMeasure, defSemiMajor, defSemiMinor, defOrientation): measureFactor = conversionToMeters(unitOfMeasure) fields = layer.fields() if shapetype == 0: self.outLayer = QgsVectorLayer( "Polygon?crs={}".format(self.outputCRS.authid()), outname, "memory") else: self.outLayer = QgsVectorLayer( "LineString?crs={}".format(self.outputCRS.authid()), outname, "memory") dp = self.outLayer.dataProvider() dp.addAttributes(fields) self.outLayer.updateFields() iter = layer.getFeatures() num_features = 0 num_good = 0 for feature in iter: num_features += 1 try: if semimajorcol != -1: semi_major = float(feature[semimajorcol]) else: semi_major = defSemiMajor if semiminorcol != -1: semi_minor = float(feature[semiminorcol]) else: semi_minor = defSemiMinor if orientcol != -1: orient = float(feature[orientcol]) else: orient = defOrientation pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) pts = geodesicEllipse(geod, pt.y(), pt.x(), semi_major * measureFactor, semi_minor * measureFactor, orient, 64) # If the Output crs is not 4326 transform the points to the proper crs if self.outputCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = self.transformOut.transform(ptout) featureout = QgsFeature() featureout.setAttributes(feature.attributes()) if shapetype == 0: featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: featureout.setGeometry(QgsGeometry.fromPolylineXY(pts)) dp.addFeatures([featureout]) num_good += 1 except: # Just skip any lines that are badly formed #traceback.print_exc() pass self.outLayer.updateExtents() QgsProject.instance().addMapLayer(self.outLayer) self.iface.messageBar().pushMessage( "", "{} Ellipses created from {} records".format( num_good, num_features), level=Qgis.Info, duration=3)
def getPointsCaptured(self): TOMsMessageLog.logMessage(("In CreateRestrictionTool - getPointsCaptured"), level=Qgis.Info) # Check the number of points self.nrPoints = self.size() TOMsMessageLog.logMessage(("In CreateRestrictionTool - getPointsCaptured; Stopping: " + str(self.nrPoints)), level=Qgis.Info) self.sketchPoints = self.points() for point in self.sketchPoints: TOMsMessageLog.logMessage(("In CreateRestrictionTool - getPointsCaptured X:" + str(point.x()) + " Y: " + str(point.y())), level=Qgis.Info) # stop capture activity self.stopCapturing() if self.nrPoints > 0: # take points from the rubber band and copy them into the "feature" fields = self.layer.dataProvider().fields() feature = QgsFeature() feature.setFields(fields) TOMsMessageLog.logMessage(("In CreateRestrictionTool. getPointsCaptured, layerType: " + str(self.layer.geometryType())), level=Qgis.Info) if self.layer.geometryType() == 0: # Point feature.setGeometry(QgsGeometry.fromPointXY(self.sketchPoints[0])) elif self.layer.geometryType() == 1: # Line feature.setGeometry(QgsGeometry.fromPolylineXY(self.sketchPoints)) elif self.layer.geometryType() == 2: # Polygon feature.setGeometry(QgsGeometry.fromPolygonXY([self.sketchPoints])) #feature.setGeometry(QgsGeometry.fromPolygonXY(self.sketchPoints)) else: TOMsMessageLog.logMessage(("In CreateRestrictionTool - no geometry type found"), level=Qgis.Info) return TOMsMessageLog.logMessage(("In Create - getPointsCaptured; geometry prepared; " + str(feature.geometry().asWkt())), level=Qgis.Info) if self.layer.name() == "ConstructionLines": self.layer.addFeature(feature) else: # set any geometry related attributes ... self.setDefaultFieldRestrictionDetails(feature, self.layer, QDate.currentDate()) self.layer.addFeature(feature) # TH (added for v3) #self.layer.reload() TOMsMessageLog.logMessage("In CreateRestrictionTool - getPointsCaptured. currRestrictionLayer: " + str(self.layer.name()), level=Qgis.Info) #newRestrictionID = str(uuid.uuid4()) #feature[self.layer.fields().indexFromName("GeometryID")] = newRestrictionID dialog = self.iface.getFeatureForm(self.layer, feature) self.setupFieldRestrictionDialog(dialog, self.layer, feature) # connects signals, etc self.inProcess = False dialog.show() pass
def updateborn(self): if (self.lineEditNum.text() != ""): if (self.lineEditIndice.text() != ""): if (self.tableWidgetBornes.rowCount() >= 3): print("'--INFO--' : Filter Passed Successfully") cmbnature = self.comboBoxNature.currentText() fieldnum = self.lineEditNum.text() fieldindice = self.lineEditIndice.text() typocomb = self.comboBoxType.currentText() nbbornes = self.tableWidgetBornes.rowCount() mapfield = self.comboBoxMap.currentText() titreref = "" + cmbnature + fieldnum + fieldindice conn = psycopg2.connect( "dbname='postgres' user='******' password='******'") print("'--INFO--' : Data Saved to Database") try: bornes = [] for x in range(0, nbbornes): name = self.tableWidgetBornes.item(x, 0).text() psx = self.tableWidgetBornes.item(x, 1).text() psy = self.tableWidgetBornes.item(x, 2).text() bornes.append(QgsPointXY(float(psx), float(psy))) geometryborne = QgsGeometry.fromPointXY( QgsPointXY(float(psx), float(psy))).asWkt() try: pt = QgsPointXY(float(psx), float(psy)) print("'--INFO--': name:" + name + " x:" + psx + " y:" + psy) rb = QgsRubberBand(iface.mapCanvas(), True) rb.reset(QgsWkbTypes.PointGeometry) rb.addPoint(pt) print("'--INFO--': the born '" + name + "' was added.") except: print( "'--INFO--': You need to enter a number not text in X, Y Fields" ) try: sql = ("UPDATE public.bornes SET x = " + psx + ", y = " + psy + ", the_geom = ST_GeomFromText('" + geometryborne + "', 26191) WHERE titref = '" + titreref + "' AND name = '" + name + "';") print(sql) cur = conn.cursor() cur.execute(sql) conn.commit() except: print( "'--ERROR--': Error while sending querry") self.ErrorLabel.setText("Error on Querry") except: print("'--INFO--': PLZ Fill all fields") self.ErrorLabel.setText("Fields empty detected") geometry = QgsGeometry.fromPolygonXY([bornes]) geometrypolygon = geometry.asWkt() # thegeomshape = "ST_GeomFromText('"+geometry+"', 26191)) try: sql = ( "UPDATE public.titres SET the_geom = ST_GeomFromText('" + geometrypolygon + "', 26191) WHERE titref = '" + titreref + "';") print(sql) cur = conn.cursor() cur.execute(sql) conn.commit() except: print("'--INFO--': Can''t edit titre") self.ErrorLabel.setText("Can't Edit titre") else: self.ErrorLabel.setText("Bornes < 3") else: self.ErrorLabel.setText("No Indice detected") else: self.ErrorLabel.setText("No Number detected")
def ovals(self, sink, source, width, height, rotation, segments, feedback): features = source.getFeatures() ft = QgsFeature() total = 100.0 / source.featureCount() if source.featureCount() else 0 if rotation >= 0: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] angle = feat[rotation] # block 0/NULL width or height, but allow 0 as angle value if not w or not h: feedback.pushInfo( QCoreApplication.translate( 'RectanglesOvalsDiamondsVariable', 'Feature {} has empty ' 'width or height. ' 'Skipping…').format(feat.id())) continue if angle == NULL: feedback.pushInfo( QCoreApplication.translate( 'RectanglesOvalsDiamondsVariable', 'Feature {} has empty ' 'angle. ' 'Skipping…').format(feat.id())) continue xOffset = w / 2.0 yOffset = h / 2.0 phi = angle * math.pi / 180 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [] for t in [(2 * math.pi) / segments * i for i in range(segments)]: points.append( (xOffset * math.cos(t), yOffset * math.sin(t))) polygon = [[ QgsPointXY( i[0] * math.cos(phi) + i[1] * math.sin(phi) + x, -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points ]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) else: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] if not w or not h: feedback.pushInfo( QCoreApplication.translate( 'RectanglesOvalsDiamondsVariable', 'Feature {} has empty ' 'width or height. ' 'Skipping…').format(feat.id())) continue xOffset = w / 2.0 yOffset = h / 2.0 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [] for t in [(2 * math.pi) / segments * i for i in range(segments)]: points.append( (xOffset * math.cos(t), yOffset * math.sin(t))) polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total))
def run(self): try: inputlayer = self.inputvectorlayer if inputlayer is None: self.error.emit(self.tr('No input layer defined')) self.finished.emit(False, None) return # Get and check the geometry type of the input layer geometryType = self.inputvectorlayer.geometryType() if not (geometryType == QgsWkbTypes.LineGeometry or geometryType == QgsWkbTypes.PolygonGeometry): self.error.emit('Only line and polygon layers are supported!') self.finished.emit(False, None) return self.processed = 0 self.percentage = 0 if self.selectedfeaturesonly: self.feature_count = inputlayer.selectedFeatureCount() else: self.feature_count = inputlayer.featureCount() if self.feature_count == 0: self.error.emit("No features in layer") self.finished.emit(False, None) return self.increment = self.feature_count // 1000 # Initialise the result list statistics = [] # Initialise the bins for the over all result mybins = [] for i in range(self.bins): mybins.append([0.0, 0]) # Add the over all bins statistics.append(mybins) # Get the features (iterator) if self.selectedfeaturesonly: features = inputlayer.getSelectedFeatures() # features = inputlayer.selectedFeaturesIterator() else: features = inputlayer.getFeatures() # Create a list for the (possible) tile (Polygon) # geometries tilegeoms = [] if self.tilelayer is not None: self.status.emit("Using tiles!") for tilefeat in self.tilelayer.getFeatures(): tilegeoms.append(tilefeat.geometry()) # Initialise and add bins for all the tiles for i in range(len(tilegeoms)): mybins = [] for j in range(self.bins): mybins.append([0.0, 0]) statistics.append(mybins) # Go through the features for feat in features: # Allow user abort if self.abort is True: break # Prepare for the histogram creation by extracting # line geometries (QgsGeometry) from the input layer # First we do all the lines of the layer. Later we # will do the lines per tile # We use a list of line geometries to be able to # handle MultiPolylines and Polygons inputlines = [] geom = feat.geometry() # QgsGeometry if geometryType == QgsWkbTypes.LineGeometry: # Lines! if geom.isMultipart(): theparts = geom.constParts() # QgsGeometryConstPartIterator # Go through the parts of the multigeometry for part in theparts: # QgsAbstractGeometry - QgsLineString partgeom = QgsGeometry.fromPolyline(part) inputlines.append(partgeom) # QgsGeometry else: inputlines.append(geom) # There are only two possibilites for geometry type, so # this elif: could be replaced with an else: elif geometryType == QgsWkbTypes.PolygonGeometry: # Polygons! # We use a list of polygon geometries to be able to # handle MultiPolygons inputpolygons = [] if geom.isMultipart(): # Multi polygon multipoly = geom.asMultiPolygon() for geompoly in multipoly: # list of list of QgsPointXY # abstract geometry -> QgsGeometry polygon polygeometry = QgsGeometry.fromPolygonXY(geompoly) inputpolygons.append(polygeometry) else: # Non-multi polygon # Make sure it is a QgsGeometry polygon singlegeom = geom.asPolygon() polygeometry = QgsGeometry.fromPolygonXY(singlegeom) inputpolygons.append(polygeometry) # QgsGeometry # Add the polygon rings for polygon in inputpolygons: # create a list of list of QgsPointXY poly = polygon.asPolygon() for ring in poly: # list of QgsPointXY # Create a QgsGeometry line geometryring = QgsGeometry.fromPolylineXY(ring) inputlines.append(geometryring) # QgsGeometry else: # We should never end up here self.status.emit("Unexpected geometry type!") # We introduce a list of line geometries for the tiling tilelinecoll = [None] * (len(tilegeoms) + 1) # Use the first element to store all the input lines # (for the over all histogram) tilelinecoll[0] = inputlines # Clip the lines based on the tile layer if self.tilelayer is not None: i = 1 # The first one is used for the complete dataset for tile in tilegeoms: # Go through the tiles # Create a list for the lines in the tile newlines = [] for linegeom in inputlines: # QgsGeometry # Clip clipres = linegeom.intersection(tile) if clipres.isEmpty(): continue if clipres.isMultipart(): # MultiLineString clipresparts = clipres.constParts() for clipline in clipresparts: # Create a QgsGeometry line linegeom = QgsGeometry.fromPolyline(clipline) newlines.append(linegeom) # QgsGeometry else: # ? newlines.append(clipres) tilelinecoll[i] = newlines i = i + 1 # Do calculations (line length and directions) j = 0 # Counter for the tiles for tilelines in tilelinecoll: # Handling the tiles for inputlinegeom in tilelines: # Handling the lines # QgsGeometry line - wkbType 2 if inputlinegeom is None: continue numvert = 0 for v in inputlinegeom.vertices(): numvert = numvert + 1 if numvert == 0: continue if numvert < 2: self.status.emit("Less than two vertices!") continue # Go through all the segments of this line thispoint = inputlinegeom.vertexAt(0) # QgsPoint first = True for v in inputlinegeom.vertices(): if first: first = False continue nextpoint = v linelength = sqrt(thispoint.distanceSquared(nextpoint)) # Find the angle of the line segment lineangle = thispoint.azimuth(nextpoint) if lineangle < 0: lineangle = 360 + lineangle if self.directionneutral: if lineangle >= 180.0: lineangle = lineangle - 180 # Find the bin if lineangle > self.offsetangle: fitbin = (int((lineangle - self.offsetangle) / self.binsize) % self.bins) else: fitbin = (int((360 + lineangle - self.offsetangle) / self.binsize) % self.bins) # Have to handle special case to keep index in range? if fitbin == self.bins: self.status.emit("fitbin == self.bins") fitbin = 0 # Add to the length of the bin of this tile (j) statistics[j][fitbin][0] = (statistics[j][fitbin][0] + linelength) # Add to the number of line segments in the bin statistics[j][fitbin][1] = (statistics[j][fitbin][1] + 1) thispoint = nextpoint # advance to the next point j = j + 1 # Next tile self.calculate_progress() except Exception as e: self.status.emit("Exception occurred - " + str()) self.error.emit(str(e)) self.finished.emit(False, None) else: if self.abort: self.status.emit("Aborted") self.finished.emit(False, None) else: self.status.emit("Completed") self.finished.emit(True, statistics)
def processPoly(self, layer, outname, shapetype, sidescol, anglecol, distcol, sides, angle, defaultDist, unitOfDist): measureFactor = conversionToMeters(unitOfDist) defaultDist *= measureFactor fields = layer.fields() if shapetype == 0: outLayer = QgsVectorLayer( "Polygon?crs={}".format(self.outputCRS.authid()), outname, "memory") else: outLayer = QgsVectorLayer( "LineString?crs={}".format(self.outputCRS.authid()), outname, "memory") dp = outLayer.dataProvider() dp.addAttributes(fields) outLayer.updateFields() iter = layer.getFeatures() for feature in iter: try: pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) if sidescol != -1: s = int(feature[sidescol]) else: s = sides if anglecol != -1: startangle = float(feature[anglecol]) else: startangle = angle if distcol != -1: d = float(feature[distcol]) * measureFactor else: d = defaultDist pts = [] i = s while i >= 0: a = (i * 360.0 / s) + startangle i -= 1 g = geod.Direct(pt.y(), pt.x(), a, d, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) # If the Output crs is not 4326 transform the points to the proper crs if self.outputCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = self.transformOut.transform(ptout) featureout = QgsFeature() if shapetype == 0: featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: featureout.setGeometry(QgsGeometry.fromPolylineXY(pts)) featureout.setAttributes(feature.attributes()) dp.addFeatures([featureout]) except: pass outLayer.updateExtents() QgsProject.instance().addMapLayer(outLayer)
def diamonds(self, sink, source, width, height, rotation, feedback): features = source.getFeatures() ft = QgsFeature() total = 100.0 / source.featureCount() if source.featureCount() else 0 if rotation >= 0: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] angle = feat[rotation] if not w or not h or not angle: feedback.pushInfo( self.tr('Feature {} has empty ' 'width, height or angle. ' 'Skipping...'.format(feat.id()))) continue xOffset = w / 2.0 yOffset = h / 2.0 phi = angle * math.pi / 180 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)] polygon = [[ QgsPointXY( i[0] * math.cos(phi) + i[1] * math.sin(phi) + x, -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points ]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) else: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] if not w or not h: feedback.pushInfo( self.tr('Feature {} has empty ' 'width or height. ' 'Skipping...'.format(feat.id()))) continue xOffset = w / 2.0 yOffset = h / 2.0 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)] polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total))
def addPolygonsToMap(self, polygons): if not QgsProject.instance().mapLayersByName( 'Location Lab - catchments'): vl = QgsVectorLayer('Polygon?crs=EPSG:4326', 'Location Lab - catchments', 'memory') pr = vl.dataProvider() vl.startEditing() pr.addAttributes([ QgsField('id', QVariant.Int), QgsField(self.tr('provider'), QVariant.String), QgsField(self.tr('mode'), QVariant.String), QgsField(self.tr('value'), QVariant.Int), QgsField(self.tr('units'), QVariant.String), QgsField(self.tr('lat'), QVariant.Double), QgsField(self.tr('lon'), QVariant.Double), QgsField('params', QVariant.String) ]) vl.commitChanges() QgsProject.instance().addMapLayer(vl) vl = QgsProject.instance().mapLayersByName( 'Location Lab - catchments')[0] pr = vl.dataProvider() next_id = len(vl.allFeatureIds()) + 1 id_field = self.fieldsComboBox.currentField() if id_field: layer = self.layerComboBox.currentLayer() new_ids = [ feature.attribute(id_field) for feature in list(layer.getFeatures()) ] for index, p in enumerate(polygons): feature = QgsFeature() points = [] if p['source'] == 'HERE' or p['source'] == 'OpenRouteService': coordinates = [c.split(',') for c in p['coordinates']] for xy in coordinates: points.append(QgsPointXY(float(xy[1]), float(xy[0]))) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolygonXY([points])) lat, lon = p['coords'].split(',') for key in ['key', 'url', 'coordinates', 'start']: #unnecessary params if key in p.keys(): p.pop(key) feature.setAttributes([ next_id if not id_field else new_ids[index], self.providersComboBox.currentText(), self.modesComboBox.currentText().lower(), self.valueSpinBox.value(), self.unitsComboBox.currentText(), float(lat), float(lon), str(p) ]) pr.addFeatures([feature]) next_id += 1 vl.updateExtents() self.iface.mapCanvas().setExtent( QgsCoordinateTransform( vl.crs(), self.iface.mapCanvas().mapSettings().destinationCrs(), QgsProject().instance()).transform(vl.extent())) self.iface.mapCanvas().refresh()
def get_transformed_polygon(self, feature, distance_area, xform): """Returns transformd polygon geometry""" # TODO: distance_area and xform should probably be class variables points = feature.geometry().asPolygon() transformed = [self.transform_point(xform, point) for point in points[0]] return QgsGeometry.fromPolygonXY([transformed])
def _ignitePerimeters(self, layer): perimeters = self._perimeter_layer.getFeatures() perimeters_features = [ f for f in perimeters if f.attributes()[1] == self._tnow.strftime('%Y-%m-%dT%H:%M:%S') ] perimeters = list() for perimeter_feature in perimeters_features: new_perimeter = list() geom = perimeter_feature.geometry().asPolygon() points = list() for pt in geom[0]: feat = QgsFeature() feat.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(pt.x(), pt.y()))) ip = IgnitionPoint(feat, pt.x(), pt.y(), self._tnow.strftime('%Y-%m-%dT%H:%M:%S')) points.append(ip) self._assignFuel(points) new_points = self._propagatePerimeter(points[-2::-1]) new_perimeter.append( [QgsPointXY(pt[0], pt[1]) for pt in new_points]) if len(geom) > 1: for i in range(1, len(geom)): points = list() for pt in geom[i]: feat = QgsFeature() feat.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(pt.x(), pt.y()))) ip = IgnitionPoint( feat, pt.x(), pt.y(), self._tnow.strftime('%Y-%m-%dT%H:%M:%S')) points.append(ip) self._assignFuel(points) new_points = self._propagatePerimeter(points[-2::-1]) new_perimeter.append( [[QgsPointXY(pt[0], pt[1]) for pt in new_points], geom[i]]) perimeters.append(new_perimeter) for perimeter in perimeters: # Create a line layer to calculate rings layer_in = self._createMemoryLayer( 'Polygon', QgsProject.instance().crs().authid(), 'outer_perimeter') self._addPerimeterToLayer(layer_in, [perimeter[0]]) params = {'INPUT': layer_in, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:fixgeometries', params, feedback=feedback, is_child_algorithm=False) fixed_layer = result['OUTPUT'] params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:polygonstolines', params, feedback=feedback, is_child_algorithm=False) line_layer = result['OUTPUT'] params = { 'INPUT': line_layer, 'LINES': line_layer, 'OUTPUT': 'memory:' } feedback = QgsProcessingFeedback() result = processing.run('native:splitwithlines', params, feedback=feedback, is_child_algorithm=False) split_layer = result['OUTPUT'] params = {'INPUT': split_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('qgis:linestopolygons', params, feedback=feedback, is_child_algorithm=False) polygon_layer = result['OUTPUT'] params = {'INPUT': polygon_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False) correct_plygons = result['OUTPUT'] island_layer = None if correct_plygons.featureCount() > 1: island_layer = self._findRing(correct_plygons) #params = {'INPUT': polygon_layer, 'OUTPUT': 'memory:'} #feedback = QgsProcessingFeedback() #result = processing.run('native:dissolve', params, feedback=feedback, is_child_algorithm=False) #dissolved_layer = result['OUTPUT'] #if island_layer is None: # params = {'INPUT': polygon_layer, 'OUTPUT': 'memory:'} #else: # params = {'INPUT': island_layer, 'OUTPUT': 'memory:'} #feedback = QgsProcessingFeedback() #result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False) #correct_plygons = result['OUTPUT'] if island_layer is None: rings_layer = correct_plygons else: rings_layer = island_layer feats = [f for f in rings_layer.getFeatures()] elements = feats[0].geometry().asPolygon() new_perimeter = list() for element in elements: new_perimeter.append( [QgsPointXY(pt.x(), pt.y()) for pt in element]) del (layer_in) del (fixed_layer) del (line_layer) del (split_layer) del (polygon_layer) if not (island_layer is None): del (island_layer) del (correct_plygons) if len(perimeter) > 1: for i in range(1, len(perimeter)): # Create layer fromprevious perimeter geom = perimeter[i][1] feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolygonXY([geom])) previous_ring = self._createMemoryLayer( 'Polygon', QgsProject.instance().crs().authid(), 'previous_ring') previous_ring.dataProvider().addFeatures([feature]) actual_ring = self._createMemoryLayer( 'Polygon', QgsProject.instance().crs().authid(), 'actual_ring') self._addPerimeterToLayer(actual_ring, [perimeter[i][0]]) params = {'INPUT': actual_ring, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:fixgeometries', params, feedback=feedback, is_child_algorithm=False) fixed_layer = result['OUTPUT'] params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:polygonstolines', params, feedback=feedback, is_child_algorithm=False) line_layer = result['OUTPUT'] params = { 'INPUT': line_layer, 'LINES': line_layer, 'OUTPUT': 'memory:' } feedback = QgsProcessingFeedback() result = processing.run('native:splitwithlines', params, feedback=feedback, is_child_algorithm=False) split_layer = result['OUTPUT'] params = {'INPUT': split_layer, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('qgis:linestopolygons', params, feedback=feedback, is_child_algorithm=False) polygon_layer = result['OUTPUT'] params = { 'INPUT': polygon_layer, 'PREDICATE': [6], 'INTERSECT': previous_ring, 'OUTPUT': 'memory:' } feedback = QgsProcessingFeedback() result = processing.run('native:extractbylocation', params, feedback=feedback, is_child_algorithm=False) rings_inside = result['OUTPUT'] params = {'INPUT': rings_inside, 'OUTPUT': 'memory:'} feedback = QgsProcessingFeedback() result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False) correct_rings = result['OUTPUT'] for feature in correct_rings.getFeatures(): geom = feature.geometry().asPolygon() for elem in geom: new_perimeter.append( [QgsPointXY(pt.x(), pt.y()) for pt in elem]) del (previous_ring) del (actual_ring) del (fixed_layer) del (line_layer) del (split_layer) del (rings_inside) del (correct_rings) self._addPerimeterToLayer(layer, new_perimeter)
def UpdateFootPrintData(packet, cornerPointUL, cornerPointUR, cornerPointLR, cornerPointLL, ele): """ Update Footprint Values """ global crtSensorSrc, groupName imgSS = packet.ImageSourceSensor footprintLyr = selectLayerByName(Footprint_lyr, groupName) try: if all(v is not None for v in [ footprintLyr, cornerPointUL, cornerPointUR, cornerPointLR, cornerPointLL, ]) and all(v >= 2 for v in [ len(cornerPointUL), len(cornerPointUR), len(cornerPointLR), len(cornerPointLL), ]): if imgSS != crtSensorSrc: SetDefaultFootprintStyle(footprintLyr, imgSS) crtSensorSrc = imgSS footprintLyr.startEditing() if footprintLyr.featureCount() == 0: feature = QgsFeature() feature.setAttributes([ cornerPointUL[1], cornerPointUL[0], cornerPointUR[1], cornerPointUR[0], cornerPointLR[1], cornerPointLR[0], cornerPointLL[1], cornerPointLL[0], ]) surface = QgsGeometry.fromPolygonXY([[ QgsPointXY(cornerPointUL[1], cornerPointUL[0]), QgsPointXY(cornerPointUR[1], cornerPointUR[0]), QgsPointXY(cornerPointLR[1], cornerPointLR[0]), QgsPointXY(cornerPointLL[1], cornerPointLL[0]), QgsPointXY(cornerPointUL[1], cornerPointUL[0]), ]]) feature.setGeometry(surface) footprintLyr.addFeatures([feature]) else: fetId = 1 attrib = { 0: cornerPointUL[1], 1: cornerPointUL[0], 2: cornerPointUR[1], 3: cornerPointUR[0], 4: cornerPointLR[1], 5: cornerPointLR[0], 6: cornerPointLL[1], 7: cornerPointLL[0], } footprintLyr.dataProvider().changeAttributeValues( {fetId: attrib}) footprintLyr.dataProvider().changeGeometryValues({ fetId: QgsGeometry.fromPolygonXY([[ QgsPointXY(cornerPointUL[1], cornerPointUL[0]), QgsPointXY(cornerPointUR[1], cornerPointUR[0]), QgsPointXY(cornerPointLR[1], cornerPointLR[0]), QgsPointXY(cornerPointLL[1], cornerPointLL[0]), QgsPointXY(cornerPointUL[1], cornerPointUL[0]), ]]) }) CommonLayer(footprintLyr) # 3D Style if ele: SetDefaultFootprint3DStyle(footprintLyr) except Exception as e: qgsu.showUserAndLogMessage( QCoreApplication.translate("QgsFmvLayers", "Failed Update FootPrint Layer! : "), str(e), )
def _addPerimeterToLayer(self, layer, perimeter): feat = QgsFeature() geom = QgsGeometry.fromPolygonXY(perimeter) feat.setGeometry(geom) (res, outFeats) = layer.dataProvider().addFeatures([feat])
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) outerCol = self.parameterAsString(parameters, self.PrmOuterRadiusField, context) innerCol = self.parameterAsString(parameters, self.PrmInnerRadiusField, context) starPointsCol = self.parameterAsString(parameters, self.PrmStarPointsField, context) startAngleCol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) outerRadius = self.parameterAsDouble(parameters, self.PrmDefaultOuterRadius, context) innerRadius = self.parameterAsDouble(parameters, self.PrmDefaultInnerRadius, context) startAngle = self.parameterAsDouble(parameters, self.PrmDefaultStartingAngle, context) numPoints = self.parameterAsInt(parameters, self.PrmDefaultStarPoints, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) measureFactor = conversionToMeters(units) innerRadius *= measureFactor outerRadius *= measureFactor srcCRS = source.sourceCrs() if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.LineString, srcCRS) 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 half = (360.0 / numPoints) / 2.0 numbad = 0 iterator = source.getFeatures() for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) if outerCol: oradius = float(feature[outerCol]) * measureFactor else: oradius = outerRadius if innerCol: iradius = float(feature[innerCol]) * measureFactor else: iradius = innerRadius if startAngleCol: sangle = float(feature[startAngleCol]) else: sangle = startAngle if starPointsCol: spoints = float(feature[starPointsCol]) shalf = (360.0 / spoints) / 2.0 else: spoints = numPoints shalf = half i = spoints - 1 while i >= 0: i -= 1 angle = (i * 360.0 / spoints) + sangle g = geod.Direct(pt.y(), pt.x(), angle, oradius, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) g = geod.Direct(pt.y(), pt.x(), angle-shalf, iradius, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) f.setAttributes(feature.attributes()) sink.addFeature(f) except: '''s = traceback.format_exc() feedback.pushInfo(s)''' numbad += 1 if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) if numbad > 0: feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shape_type = self.parameterAsInt(parameters, self.PrmShapeType, context) semi_major_col = self.parameterAsString(parameters, self.PrmSemiMajorAxisField, context) semi_minor_col = self.parameterAsString(parameters, self.PrmSemiMinorAxisField, context) orientation_col = self.parameterAsString(parameters, self.PrmOrientationField, context) default_semi_major = self.parameterAsDouble( parameters, self.PrmDefaultSemiMajorAxis, context) default_semi_minor = self.parameterAsDouble( parameters, self.PrmDefaultSemiMinorAxis, context) def_orientation = self.parameterAsDouble(parameters, self.PrmDefaultOrientation, 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) default_semi_major *= measure_factor default_semi_minor *= measure_factor 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.LineString, 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 = [] 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 semi_major_col: sma = float(feature[semi_major_col]) * measure_factor else: sma = default_semi_major if semi_minor_col: smi = float(feature[semi_minor_col]) * measure_factor else: smi = default_semi_minor if orientation_col: orient = float(feature[orientation_col]) else: orient = def_orientation pts = geodesicEllipse(geod, lat, lon, sma, smi, orient, segments) # If the Output crs is not 4326 transform the points to the proper crs if src_crs != epsg4326: for x, ptout in enumerate(pts): pts[x] = to_sink_crs.transform(ptout) f = QgsFeature() if shape_type == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) 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 '''s = traceback.format_exc() feedback.pushInfo(s)''' 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 processPie(self, layer, outname, shapetype, azimuthMode, startanglecol, endanglecol, distcol, unitOfDist, startangle, endangle, defaultDist, segments): measureFactor = conversionToMeters(unitOfDist) defaultDist *= measureFactor arcPtSpacing = 360.0 / segments fields = layer.fields() if shapetype == 0: outLayer = QgsVectorLayer( "Polygon?crs={}".format(self.outputCRS.authid()), outname, "memory") else: outLayer = QgsVectorLayer( "LineString?crs={}".format(self.outputCRS.authid()), outname, "memory") dp = outLayer.dataProvider() dp.addAttributes(fields) outLayer.updateFields() iter = layer.getFeatures() for feature in iter: try: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) pts.append(pt) if startanglecol == -1: sangle = startangle else: sangle = float(feature[startanglecol]) if endanglecol == -1: eangle = endangle else: eangle = float(feature[endanglecol]) if azimuthMode == 1: width = abs(eangle) / 2.0 eangle = sangle + width sangle -= width if distcol == -1: dist = defaultDist else: dist = float(feature[distcol]) * measureFactor sangle = sangle % 360 eangle = eangle % 360 if sangle > eangle: # We are crossing the 0 boundry so lets just subtract # 360 from it. sangle -= 360.0 while sangle < eangle: g = geod.Direct(pt.y(), pt.x(), sangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) sangle += arcPtSpacing # add this number of degrees to the angle g = geod.Direct(pt.y(), pt.x(), eangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(pt) # If the Output crs is not 4326 transform the points to the proper crs if self.outputCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = self.transformOut.transform(ptout) featureout = QgsFeature() if shapetype == 0: featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: featureout.setGeometry(QgsGeometry.fromPolylineXY(pts)) featureout.setAttributes(feature.attributes()) dp.addFeatures([featureout]) except: pass outLayer.updateExtents() QgsProject.instance().addMapLayer(outLayer)
def testAreaMeasureAndUnits(self): """Test a variety of area measurements in different CRS and ellipsoid modes, to check that the calculated areas and units are always consistent """ da = QgsDistanceArea() da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext()) da.setEllipsoid("NONE") polygon = QgsGeometry.fromPolygonXY( [[ QgsPointXY(0, 0), QgsPointXY(1, 0), QgsPointXY(1, 1), QgsPointXY(2, 1), QgsPointXY(2, 2), QgsPointXY(0, 2), QgsPointXY(0, 0), ]] ) # We check both the measured area AND the units, in case the logic regarding # ellipsoids and units changes in future area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or (abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters)) da.setEllipsoid("WGS84") area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) # should always be in Meters Squared self.assertAlmostEqual(area, 37416879192.9, delta=0.1) self.assertEqual(units, QgsUnitTypes.AreaSquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareMiles) self.assertAlmostEqual(area, 14446.7378, delta=0.001) # now try with a source CRS which is in feet polygon = QgsGeometry.fromPolygonXY( [[ QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000) ]] ) da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext()) da.setEllipsoid("NONE") # measurement should be in square feet area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(area, 2000000, delta=0.001) self.assertEqual(units, QgsUnitTypes.AreaSquareFeet) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards) self.assertAlmostEqual(area, 222222.2222, delta=0.001) da.setEllipsoid("WGS84") # now should be in Square Meters again area = da.measureArea(polygon) units = da.areaUnits() print(("measured {} in {}".format(area, QgsUnitTypes.toString(units)))) self.assertAlmostEqual(area, 184149.37, delta=1.0) self.assertEqual(units, QgsUnitTypes.AreaSquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards) self.assertAlmostEqual(area, 220240.8172549, delta=1.0)
def processDonut(self, layer, outname, shapetype, innerCol, outerCol, defInnerRadius, defOuterRadius, units, segments): measureFactor = conversionToMeters(units) defInnerRadius *= measureFactor defOuterRadius *= measureFactor ptSpacing = 360.0 / segments fields = layer.fields() if shapetype == 0: outLayer = QgsVectorLayer( "Polygon?crs={}".format(self.outputCRS.authid()), outname, "memory") else: outLayer = QgsVectorLayer( "MultiLineString?crs={}".format(self.outputCRS.authid()), outname, "memory") dp = outLayer.dataProvider() dp.addAttributes(fields) outLayer.updateFields() iter = layer.getFeatures() for feature in iter: try: ptsi = [] ptso = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) lat = pt.y() lon = pt.x() angle = 0 while angle < 360: if innerCol == -1: iRadius = defInnerRadius else: iRadius = float(feature[innerCol]) * measureFactor if outerCol == -1: oRadius = defOuterRadius else: oRadius = float(feature[outerCol]) * measureFactor if iRadius != 0: g = geod.Direct(lat, lon, angle, iRadius, Geodesic.LATITUDE | Geodesic.LONGITUDE) ptsi.append(QgsPointXY(g['lon2'], g['lat2'])) g = geod.Direct(lat, lon, angle, oRadius, Geodesic.LATITUDE | Geodesic.LONGITUDE) ptso.append(QgsPointXY(g['lon2'], g['lat2'])) angle += ptSpacing if iRadius != 0: ptsi.append(ptsi[0]) ptso.append(ptso[0]) # If the Output crs is not 4326 transform the points to the proper crs if self.outputCRS != epsg4326: if iRadius != 0: for x, ptout in enumerate(ptsi): ptsi[x] = self.transformOut.transform(ptout) for x, ptout in enumerate(ptso): ptso[x] = self.transformOut.transform(ptout) featureout = QgsFeature() if shapetype == 0: if iRadius == 0: featureout.setGeometry( QgsGeometry.fromPolygonXY([ptso])) else: featureout.setGeometry( QgsGeometry.fromPolygonXY([ptso, ptsi])) else: if iRadius == 0: featureout.setGeometry( QgsGeometry.fromMultiPolylineXY([ptso])) else: featureout.setGeometry( QgsGeometry.fromMultiPolylineXY([ptso, ptsi])) featureout.setAttributes(feature.attributes()) dp.addFeatures([featureout]) except: pass outLayer.updateExtents() QgsProject.instance().addMapLayer(outLayer)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) radius = self.parameterAsDouble(parameters, self.PrmRadius, context) startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context) k = self.parameterAsInt(parameters, self.PrmPetals, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) measureFactor = conversionToMeters(units) radius *= measureFactor srcCRS = 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 shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.LineString, srcCRS) if srcCRS != epsg4326: geomTo4326 = QgsCoordinateTransform(srcCRS, epsg4326, QgsProject.instance()) toSinkCrs = QgsCoordinateTransform(epsg4326, srcCRS, QgsProject.instance()) dist = [] if k == 1: dist.append(0.0) step = 1 angle = -90.0 + step while angle < 90.0: a = math.radians(angle) r = math.cos(a) dist.append(r) angle += step cnt = len(dist) featureCount = source.featureCount() total = 100.0 / featureCount if featureCount else 0 iterator = source.getFeatures() for item, feature in enumerate(iterator): if feedback.isCanceled(): break pts = [] pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) arange = 360.0 / k angle = -arange / 2.0 astep = arange / cnt for i in range(k): aoffset = arange * (k - 1) index = 0 while index < cnt: r = dist[index] * radius g = geod.Direct(pt.y(), pt.x(), angle + aoffset + startAngle, r, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += astep index += 1 # repeat the very first point to close the polygon pts.append(pts[0]) # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) if item % 100 == 0: feedback.setProgress(int(item * total)) return {self.PrmOutputLayer: dest_id}
def processRose(self, layer, outname, shapetype, startAngle, k, radius, unitOfDist): measureFactor = conversionToMeters(unitOfDist) radius *= measureFactor fields = layer.fields() if shapetype == 0: outLayer = QgsVectorLayer( "Polygon?crs={}".format(self.outputCRS.authid()), outname, "memory") else: outLayer = QgsVectorLayer( "LineString?crs={}".format(self.outputCRS.authid()), outname, "memory") dp = outLayer.dataProvider() dp.addAttributes(fields) outLayer.updateFields() iter = layer.getFeatures() dist = [] if k == 1: dist.append(0.0) step = 1 angle = -90.0 + step while angle < 90.0: a = math.radians(angle) r = math.cos(a) dist.append(r) angle += step cnt = len(dist) for feature in iter: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 pt = self.transform.transform(pt.x(), pt.y()) arange = 360.0 / k angle = -arange / 2.0 astep = arange / cnt for i in range(k): aoffset = arange * (k - 1) index = 0 while index < cnt: r = dist[index] * radius g = geod.Direct(pt.y(), pt.x(), angle + aoffset + startAngle, r, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += astep index += 1 # repeat the very first point to close the polygon pts.append(pts[0]) # If the Output crs is not 4326 transform the points to the proper crs if self.outputCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = self.transformOut.transform(ptout) featureout = QgsFeature() if shapetype == 0: featureout.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: featureout.setGeometry(QgsGeometry.fromPolylineXY(pts)) featureout.setAttributes(feature.attributes()) dp.addFeatures([featureout]) outLayer.updateExtents() QgsProject.instance().addMapLayer(outLayer)
def processAlgorithm(self, parameters, context, feedback): # inputs rasters = self.parameterAsLayerList(parameters, self.RASTERLIST, context) if rasters is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.RASTERLIST)) reamostragem = self.parameterAsEnum(parameters, self.RESAMPLING, context) reamostragem = ['nearest', 'bilinear', 'bicubic'][reamostragem] sobrep = self.parameterAsEnum(parameters, self.OVERLAP, context) muda_res = self.parameterAsBool(parameters, self.CHANGERESOLUTION, context) resolucao = self.parameterAsDouble(parameters, self.RESOLUTION, context) valor_nulo = self.parameterAsDouble(parameters, self.NULLVALUE, context) moldura = self.parameterAsDouble(parameters, self.CLIP, context) if moldura: vlayer = self.parameterAsVectorLayer(parameters, self.FRAME, context) if vlayer is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.FRAME)) # output Output = self.parameterAsFileOutput(parameters, self.MOSAIC, context) Carregar = self.parameterAsBool(parameters, self.OPEN, context) lista = [] for raster_lyr in rasters: lista += [raster_lyr.dataProvider().dataSourceUri()] if len(lista) < 1: raise QgsProcessingException( self.tr('At least one raster must be selected!', 'Pelo menos um raster deve ser selecionado!')) if len(lista) == 1: sobrep = 0 # apenas um raster (sem sobreposicao) # Gerar geometria para cada raster geoms = [] SRC = [] n_bands = [] GDT = [] nulos = [] XRES, YRES = [], [] for item in lista: image = gdal.Open(item) SRC += [QgsCoordinateReferenceSystem(image.GetProjection())] # wkt ulx, xres, xskew, uly, yskew, yres = image.GetGeoTransform() cols = image.RasterXSize rows = image.RasterYSize n_bands += [image.RasterCount] GDT += [image.GetRasterBand(1).DataType] nulos += [image.GetRasterBand(1).GetNoDataValue()] XRES += [xres] YRES += [yres] image = None # Close image # Creating BBox coord = [[ QgsPointXY(ulx, uly), QgsPointXY(ulx + cols * xres, uly), QgsPointXY(ulx + cols * xres, uly + rows * yres), QgsPointXY(ulx, uly + rows * yres), QgsPointXY(ulx, uly) ]] geom = QgsGeometry.fromPolygonXY(coord) geoms += [geom] ## Validar dados de entrada # Mesmo numero de bandas if not n_bands.count(n_bands[0]) == len(n_bands): raise QgsProcessingException( self.tr('The images must have the same number of bands!', 'As imagens devem ter o mesmo número de bandas!')) # Mesmo SRC if not SRC.count(SRC[0]) == len(SRC): raise QgsProcessingException( self.tr('The images must have the same CRS!', 'As imagens devem ter o mesmo SRC!')) # Mesmo GDT if not GDT.count(GDT[0]) == len(GDT): raise QgsProcessingException( self.tr('The images must have the same data type!', 'As imagens devem ter o tipo de dado!')) # Mesmo valor nulo if not nulos.count(nulos[0]) == len(nulos): raise QgsProcessingException( self.tr( 'The images must have the same definied null value!', 'As imagens devem ter o mesmo valor para definir pixel nulo!' )) # Dados para o raster de saída prj = SRC[0].toWkt() n_bands = n_bands[0] GDT = GDT[0] xres = np.mean(XRES) yres = np.mean(YRES) NULO = valor_nulo if valor_nulo == -1: valor_nulo = nulos[0] if nulos[0] is not None else 0 if moldura: # Pegar extensão X e Y da moldura # SRC da moldura deve ser o mesmo dos raster if vlayer.sourceCrs() != QgsCoordinateReferenceSystem(prj): raise QgsProcessingException( self.tr( "The frame's CRS must be iqual to the rasters' CRS!", 'O SRC da moldura deve ser igual ao SRC dos rasters!')) for feat in vlayer.getFeatures(): moldura_geom = feat.geometry() break moldura_rect = moldura_geom.boundingBox() y_min = moldura_rect.yMinimum() y_max = moldura_rect.yMaximum() x_min = moldura_rect.xMinimum() x_max = moldura_rect.xMaximum() else: # Mesclar geometrias e obter a extensão new_geom = QgsGeometry() new_geom = new_geom.unaryUnion(geoms) extensao = new_geom.boundingBox() # Coodenadas máxima e mínima da extensão y_min = extensao.yMinimum() y_max = extensao.yMaximum() x_min = extensao.xMinimum() x_max = extensao.xMaximum() # Transformar resolucao de metros para graus, se o SRC for Geográfico src_qgis = QgsCoordinateReferenceSystem(prj) if src_qgis.isGeographic(): EPSG = int(src_qgis.authid().split(':')[-1]) proj_crs = CRS.from_epsg(EPSG) a = proj_crs.ellipsoid.semi_major_metre f = 1 / proj_crs.ellipsoid.inverse_flattening e2 = f * (2 - f) N = a / np.sqrt(1 - e2 * (np.sin( (y_min + y_max) / 2))**2) # Raio de curvatura 1º vertical M = a * (1 - e2) / (1 - e2 * (np.sin((y_min + y_max) / 2))**2)**( 3 / 2.) # Raio de curvatura meridiana R = np.sqrt(M * N) # Raio médio de Gauss theta = resolucao / R resolucao = np.degrees(theta) # Radianos para graus # Definir n_col, n_lin e resolucao if moldura: if muda_res: n_lin = round((y_max - y_min) / abs(resolucao)) n_col = round((x_max - x_min) / abs(resolucao)) else: n_lin = round((y_max - y_min) / abs(yres)) n_col = round((x_max - x_min) / abs(xres)) xres = (x_max - x_min) / n_col yres = -(y_max - y_min) / n_lin else: if muda_res: n_lin = round((y_max - y_min) / abs(resolucao)) n_col = round((x_max - x_min) / abs(resolucao)) xres = resolucao yres = -resolucao else: n_lin = round((y_max - y_min) / abs(yres)) n_col = round((x_max - x_min) / abs(xres)) xres = (x_max - x_min) / n_col yres = -(y_max - y_min) / n_lin feedback.pushInfo( self.tr('Resolution: ', 'Resolução: ') + str(n_lin) + 'x' + str(n_col)) # Geotransform do Mosaico ulx = x_min uly = y_max xskew, yskew = 0, 0 geotransform = [ulx, xres, xskew, uly, yskew, yres] origem = (ulx, uly) resol_X = abs(xres) resol_Y = abs(yres) # Numeração das Imagens valores = list(range(1, len(lista) + 1)) # Definição de áreas de varredura feedback.pushInfo( self.tr('Defining mosaic filling areas...', 'Definindo áreas de preenchimento do mosaico...')) # Gerar combinações dos Rasters if sobrep != 0: combs = [] feedback.pushInfo( self.tr('Creating combinations...', 'Gerando combinações...')) for k in range(1, 5): combs += list(combinations(valores, k)) if feedback.isCanceled(): break # Armazenar geometrias exclusivas de cada combinação classes = {} feedback.pushInfo( self.tr('Indentifying combinations...', 'Identificando combinações...')) Percent = 100.0 / (len(combs)) current = 0 for comb in combs: if len(comb) == 1: geom1 = geoms[comb[0] - 1] lista_outras = [] for geom in geoms: if geom1 != geom: lista_outras += [geom] outras = QgsGeometry() outras = outras.unaryUnion(lista_outras) diferença = geom1.difference(outras) if not diferença.isEmpty(): classes[comb] = {'geom': diferença} elif len(comb) < len(valores): intersecao = geoms[comb[0] - 1] sentinela = True for ind in comb[1:]: geom = geoms[ind - 1] if geom.intersects(intersecao): intersecao = intersecao.intersection(geom) else: sentinela = False continue lista_outras = [] for valor in valores: if valor not in comb: lista_outras += [geoms[valor - 1]] outras = QgsGeometry() outras = outras.unaryUnion(lista_outras) if sentinela: diferença = intersecao.difference(outras) if not diferença.isEmpty(): classes[comb] = {'geom': diferença} else: intersecao = geoms[comb[0] - 1] sentinela = True for ind in comb[1:]: geom = geoms[ind - 1] if geom.intersects(intersecao): intersecao = intersecao.intersection(geom) else: sentinela = False continue if sentinela: classes[comb] = {'geom': intersecao} if feedback.isCanceled(): break current += 1 feedback.setProgress(int(current * Percent)) else: # Gerar geometrias por área sem cálculo de sobreposição ("first") combs = np.array(valores)[:, np.newaxis] classes = {} acumulado = geoms[combs[0][0] - 1] classes[(1, )] = {'geom': acumulado} for k in range(1, len(combs)): comb = combs[k] geom = geoms[comb[0] - 1] diferenca = geom.difference(acumulado) classes[(comb[0], )] = {'geom': diferenca} acumulado = acumulado.combine(geom) if feedback.isCanceled(): break # Gerar lista com os valores classificados Percent = 100.0 / (len(classes)) current = 0 for classe in classes: feedback.pushInfo( (self.tr('Classifying class {}...', 'Classificando classe {}...')).format(str(classe))) geom = classes[classe]['geom'] if moldura: geom = geom.intersection(moldura_geom) if geom.type() == 2: if geom.isMultipart(): coords = geom.asMultiPolygon()[0][0] else: coords = geom.asPolygon()[0] else: del classes[classe] continue caminho = [] for ponto in coords: linha = (origem[1] - ponto.y()) / resol_Y coluna = (ponto.x() - origem[0]) / resol_X caminho += [(linha, coluna)] p = path.Path(caminho) box = geom.boundingBox() uly = box.yMaximum() lry = box.yMinimum() ulx = box.xMinimum() lrx = box.xMaximum() # Limites de Varredura row_ini = int(round((origem[1] - uly) / resol_Y - 0.5)) - 1 row_fim = int(round((origem[1] - lry) / resol_Y - 0.5)) + 1 col_ini = int(round((ulx - origem[0]) / resol_X - 0.5)) - 1 col_fim = int(round((lrx - origem[0]) / resol_X - 0.5)) + 1 lin, col = np.meshgrid(np.arange(row_ini, row_fim), np.arange(col_ini, col_fim)) LIN = lin.flatten()[:, np.newaxis] + 0.5 # centro do pixel COL = col.flatten()[:, np.newaxis] + 0.5 pixels_center = np.hstack((LIN, COL)) # Verificando pixels dentro de poligono flags = p.contains_points(pixels_center) pixels_x = LIN.flatten() * flags pixels_y = COL.flatten() * flags pixels_x = (pixels_x[pixels_x > 0] - 0.5).astype('int')[:, np.newaxis] pixels_y = (pixels_y[pixels_y > 0] - 0.5).astype('int')[:, np.newaxis] pixels = np.hstack((pixels_x, pixels_y)) classes[classe]['pixels'] = pixels current += 1 feedback.setProgress(int(current * Percent)) # Criar Raster Driver = gdal.GetDriverByName('GTiff').Create(Output, n_col, n_lin, n_bands, GDT) Driver.SetGeoTransform(geotransform) Driver.SetProjection(prj) # Mosaicar por banda Percent = 100.0 / (n_lin * n_col * n_bands) current = 0 for k in range(n_bands): feedback.pushInfo( (self.tr('Creating band {}...', 'Criando banda {}...')).format(str(k + 1))) # Criar Array do mosaico tipo = gdal_array.GDALTypeCodeToNumericTypeCode(GDT) inteiro = True if GDT in (gdal.GDT_Byte, gdal.GDT_UInt16, gdal.GDT_Int16, gdal.GDT_UInt32, gdal.GDT_Int32) else False banda = np.ones( (n_lin, n_col), dtype=tipo) * (int(valor_nulo) if inteiro else valor_nulo) imgs = {} # Para cada classe abrir banda da(s) imagem(ns) for classe in classes: # Deixando somente imagens a serem utilizadas for item in valores: if (item not in classe) and (item in imgs): del imgs[item] # Preenchendo dados da imagem no dicionário for img in classe: if img not in imgs or len(lista) == 1: img_path = lista[img - 1] image = gdal.Open(img_path) ulx, xres, xskew, uly, yskew, yres = image.GetGeoTransform( ) img_origem = (ulx, uly) img_resol_X = abs(xres) img_resol_Y = abs(yres) img_band = image.GetRasterBand(k + 1).ReadAsArray() imgs[img] = { 'band': img_band, 'xres': img_resol_X, 'yres': img_resol_Y, 'origem': img_origem } image = None if sobrep == 0: # Se for "primeiro", interpolar apenas da primeira img da comb, caso contrário img = classe[0] # Para cada pixel da classe for px in classes[classe]['pixels']: lin, col = px X = origem[0] + resol_X * (col + 0.5) Y = origem[1] - resol_Y * (lin + 0.5) Interpolado = self.Interpolar(X, Y, imgs[img]['band'], imgs[img]['origem'], imgs[img]['xres'], imgs[img]['yres'], reamostragem, valor_nulo) if Interpolado != valor_nulo: banda[lin][col] = round( Interpolado) if inteiro else Interpolado if feedback.isCanceled(): break current += 1 feedback.setProgress(int(current * Percent)) else: # Para cada pixel da classe interpolar o valor da banda de cada img for px in classes[classe]['pixels']: lin, col = px X = origem[0] + resol_X * (col + 0.5) Y = origem[1] - resol_Y * (lin + 0.5) interp_values = [] for img in imgs: Interpolado = self.Interpolar( X, Y, imgs[img]['band'], imgs[img]['origem'], imgs[img]['xres'], imgs[img]['yres'], reamostragem, valor_nulo) if Interpolado != valor_nulo: interp_values += [Interpolado] # Calcular o valor agregado (0:first, 1:average, 2:median, 3:min, 4:max) e inserir na banda (se byte, arredondar) if interp_values: if sobrep == 1: result = np.mean(interp_values) elif sobrep == 2: result = np.median(interp_values) elif sobrep == 3: result = np.min(interp_values) elif sobrep == 4: result = np.max(interp_values) banda[lin][col] = round( result) if inteiro else result if feedback.isCanceled(): break current += 1 feedback.setProgress(int(current * Percent)) # Salvar banda outband = Driver.GetRasterBand(k + 1) feedback.pushInfo( self.tr('Writing Band {}...'.format(k + 1), 'Escrevendo Banda {}...'.format(k + 1))) outband.WriteArray(banda) if NULO != -1: outband.SetNoDataValue(valor_nulo) # Salvar e Fechar Raster Driver.FlushCache() # Escrever no disco Driver = None # Salvar e fechar feedback.pushInfo( self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) feedback.pushInfo('Leandro França - Eng Cart') self.CAMINHO = Output self.CARREGAR = Carregar return {self.MOSAIC: Output}
def _hexagonGrid(self, sink, width, height, originX, originY, hSpacing, vSpacing, hOverlay, vOverlay, feedback): ft = QgsFeature() # To preserve symmetry, hspacing is fixed relative to vspacing xVertexLo = 0.288675134594813 * vSpacing xVertexHi = 0.577350269189626 * vSpacing hSpacing = xVertexLo + xVertexHi hOverlay = hSpacing - hOverlay if hOverlay < 0: raise QgsProcessingException( self. tr('To preserve symmetry, hspacing is fixed relative to vspacing\n \ hspacing is fixed at: {0} and hoverlay is fixed at: {1}\n \ hoverlay cannot be negative. Increase hoverlay.' ).format(hSpacing, hOverlay)) halfVSpacing = vSpacing / 2.0 columns = int(math.ceil(float(width) / hOverlay)) rows = int(math.ceil(float(height) / (vSpacing - vOverlay))) cells = rows * columns count_update = cells * 0.05 id = 1 count = 0 for col in range(columns): if feedback.isCanceled(): break # (column + 1) and (row + 1) calculation is used to maintain # topology between adjacent shapes and avoid overlaps/holes # due to rounding errors x1 = originX + (col * hOverlay) # far left x2 = x1 + (xVertexHi - xVertexLo) # left x3 = originX + (col * hOverlay) + hSpacing # right x4 = x3 + (xVertexHi - xVertexLo) # far right for row in range(rows): if (col % 2) == 0: y1 = originY + (row * vOverlay) - ( ((row * 2) + 0) * halfVSpacing) # hi y2 = originY + (row * vOverlay) - ( ((row * 2) + 1) * halfVSpacing) # mid y3 = originY + (row * vOverlay) - ( ((row * 2) + 2) * halfVSpacing) # lo else: y1 = originY + (row * vOverlay) - ( ((row * 2) + 1) * halfVSpacing) # hi y2 = originY + (row * vOverlay) - ( ((row * 2) + 2) * halfVSpacing) # mid y3 = originY + (row * vOverlay) - ( ((row * 2) + 3) * halfVSpacing) # lo polyline = [] polyline.append(QgsPointXY(x1, y2)) polyline.append(QgsPointXY(x2, y1)) polyline.append(QgsPointXY(x3, y1)) polyline.append(QgsPointXY(x4, y2)) polyline.append(QgsPointXY(x3, y3)) polyline.append(QgsPointXY(x2, y3)) polyline.append(QgsPointXY(x1, y2)) ft.setGeometry(QgsGeometry.fromPolygonXY([polyline])) ft.setAttributes([x1, y1, x4, y3, id]) sink.addFeature(ft, QgsFeatureSink.FastInsert) id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(int(count / cells * 100))
def draw_circle(self, circle): # destination = self.layer.crs() destination = self.get_destination_crs() source = self.get_project_crs() xform_to_latlon = self.crs_transform(source, destination) # project to latlon xform = self.crs_transform(source, self.layer.crs()) # project to layer polygon = [ self.transform_point(xform, QgsPointXY(*point)) for point in circle.to_polygon() ] print(circle) print(polygon) print(type(polygon)) #gPnt = QgsGeometry.fromPointXY(QgsPointXY(1,1)) #gLine = QgsGeometry.fromPolyline([QgsPoint(1, 1), QgsPoint(2, 2)]) #gPolygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 1), QgsPointXY(2, 2), QgsPointXY(2, 1)]]) #geometry = QgsGeometry.fromPolygon([polygon]) geometry = QgsGeometry.fromPolygonXY([polygon]) feature = QgsFeature() feature.setGeometry(geometry) feature.setFields(self.layer.fields()) #print circle.center.x, circle.center.y #print(circle.center.x, circle.center.y) line = [ QgsPointXY(circle.center.x, circle.center.y), QgsPointXY(circle.center.x, circle.center.y + circle.radius), ] transformed = [ self.transform_point(xform, line[0]), self.transform_point(xform, line[1]), ] print("****", transformed) #new_line_geometry = QgsGeometry.fromPolyline( [ QgsGeometry.fromPointXY(transformed[0]), QgsGeometry.fromPointXY(transformed[1]) ] ) new_line_geometry = QgsGeometry.fromPolyline([ QgsPoint(transformed[0][0], transformed[0][1]), QgsPoint(transformed[1][0], transformed[1][1]) ]) distance_area = self.get_distance_area(self.layer) actual_line_distance = distance_area.convertLengthMeasurement( distance_area.measureLength(new_line_geometry), QgsUnitTypes.DistanceMeters) # TODO: still cannot convert to meters when layer is geo crs. If a ellips is set to distance_area, the diameter is multiplied a radii when layer is projected crs # Translate circle center to units of degrees center_in_degrees = xform_to_latlon.transform(circle.center.x, circle.center.y) # circle_feature.id() is NULL for .shp file # and assigned automaticly for .gpkg # order is id, diameter, lon, lat feature.setAttribute('diameter', actual_line_distance * 2) feature.setAttribute('center_lon', center_in_degrees[0]) feature.setAttribute('center_lat', center_in_degrees[1]) self.layer.startEditing() self.layer.dataProvider().addFeatures([feature]) #self.layer.addFeature(feature, True) self.layer.commitChanges() # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer self.layer.updateExtents()
def drawEllipse(self): # self.showInfo('Result: ' + str(self.result)) meanx = self.result[0] meany = self.result[1] angle1 = self.result[2] angle2 = self.result[3] SD1 = self.result[4] SD2 = self.result[5] if self.method == 2: # CrimeStat SD1 = SD1 * (sqrt(2) * sqrt(self.featureCount) / sqrt(self.featureCount - 2)) SD2 = SD2 * (sqrt(2) * sqrt(self.featureCount) / sqrt(self.featureCount - 2)) if self.crimestatCorr and self.method != 2: SD1 = SD1 * sqrt(2) SD2 = SD2 * sqrt(2) if self.degfreedCorr and self.method != 2: SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 2) SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 2) # SD1 = SD1 * sqrt(self.featureCount) / sqrt(self.featureCount - 1) # SD2 = SD2 * sqrt(self.featureCount) / sqrt(self.featureCount - 1) # Find the major and minor axis majoraxisangle = angle1 minoraxisangle = angle2 majorSD = SD2 minorSD = SD1 if SD2 < SD1: majoraxisangle = angle2 minoraxisangle = angle1 majorSD = SD1 minorSD = SD2 # Calculate the "compass" direction angle (clockwise from north) direction = 90.0 - majoraxisangle * 180 / pi # Calculte the eccentricity eccentricity = sqrt(1 - pow(minorSD, 2) / pow(majorSD, 2)) # Create the memory layer for the ellipse sdefields = [] sdefields.append(QgsField("meanx", QVariant.Double)) sdefields.append(QgsField("meany", QVariant.Double)) sdefields.append(QgsField("majoranglerad", QVariant.Double)) # sdefields.append(QgsField("minoranglerad", QVariant.Double)) sdefields.append(QgsField("directiondeg", QVariant.Double)) sdefields.append(QgsField("majorsd", QVariant.Double)) sdefields.append(QgsField("minorsd", QVariant.Double)) sdefields.append(QgsField("eccentricity", QVariant.Double)) layeruri = 'Polygon?' layeruri = (layeruri + 'crs=' + str(self.SDLayer.dataProvider().crs().authid())) memSDlayer = QgsVectorLayer(layeruri, self.OutputLayerName.text(), "memory") # Set the CRS to the original CRS object memSDlayer.setCrs(self.SDLayer.dataProvider().crs()) memSDlayer.startEditing() # ? for field in sdefields: memSDlayer.dataProvider().addAttributes([field]) sdfeature = QgsFeature() theta1 = majoraxisangle points = [] step = pi / 180 # 360 points to draw the ellipse t = 0.0 while t < 2 * pi: p1 = QPointF(meanx + majorSD * cos(t) * cos(majoraxisangle) - minorSD * sin(t) * sin(majoraxisangle), meany + majorSD * cos(t) * sin(majoraxisangle) + minorSD * sin(t) * cos(majoraxisangle)) points.append(QgsPointXY(p1)) t = t + step # Close the polygon p1 = QPointF(meanx + majorSD * cos(majoraxisangle), meany + majorSD * sin(majoraxisangle)) points.append(QgsPointXY(p1)) sdfeature.setGeometry(QgsGeometry.fromPolygonXY([points])) attrs = [meanx, meany, majoraxisangle, direction, majorSD, minorSD, eccentricity] sdfeature.setAttributes(attrs) memSDlayer.dataProvider().addFeatures([sdfeature]) memSDlayer.commitChanges() # ? memSDlayer.updateExtents() QgsProject.instance().addMapLayers([memSDlayer])
def processPoly(layer, writerLines, isProcessing): layercrs = layer.crs() if layercrs != epsg4326: transto4326 = QgsCoordinateTransform(layercrs, epsg4326, QgsProject.instance()) transfrom4326 = QgsCoordinateTransform(epsg4326, layercrs, QgsProject.instance()) iterator = layer.getFeatures() num_features = 0 num_bad = 0 maxseglen = settings.maxSegLength*1000.0 maxSegments = settings.maxSegments for feature in iterator: num_features += 1 try: wkbtype = feature.geometry().wkbType() if wkbtype == QgsWkbTypes.Polygon: poly = feature.geometry().asPolygon() numpolygons = len(poly) if numpolygons < 1: continue ptset = [] for points in poly: numpoints = len(points) if numpoints < 2: continue # If the input is not 4326 we need to convert it to that and then back to the output CRS ptStart = QgsPointXY(points[0][0], points[0][1]) if layercrs != epsg4326: # Convert to 4326 ptStart = transto4326.transform(ptStart) pts = [ptStart] for x in range(1,numpoints): ptEnd = QgsPointXY(points[x][0], points[x][1]) if layercrs != epsg4326: # Convert to 4326 ptEnd = transto4326.transform(ptEnd) l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x()) n = int(math.ceil(l.s13 / maxseglen)) if n > maxSegments: n = maxSegments seglen = l.s13 / n for i in range(1,n): s = seglen * i g = l.Position(s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append( QgsPointXY(g['lon2'], g['lat2']) ) pts.append(ptEnd) ptStart = ptEnd if layercrs != epsg4326: # Convert each point to the output CRS for x, pt in enumerate(pts): pts[x] = transfrom4326.transform(pt) ptset.append(pts) if len(ptset) > 0: featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY(ptset)) featureout.setAttributes(feature.attributes()) if isProcessing: writerLines.addFeature(featureout) else: writerLines.addFeatures([featureout]) else: multipoly = feature.geometry().asMultiPolygon() multiset = [] for poly in multipoly: ptset = [] for points in poly: numpoints = len(points) if numpoints < 2: continue # If the input is not 4326 we need to convert it to that and then back to the output CRS ptStart = QgsPointXY(points[0][0], points[0][1]) if layercrs != epsg4326: # Convert to 4326 ptStart = transto4326.transform(ptStart) pts = [ptStart] for x in range(1,numpoints): ptEnd = QgsPointXY(points[x][0], points[x][1]) if layercrs != epsg4326: # Convert to 4326 ptEnd = transto4326.transform(ptEnd) l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x()) n = int(math.ceil(l.s13 / maxseglen)) if n > maxSegments: n = maxSegments seglen = l.s13 / n for i in range(1,n): s = seglen * i g = l.Position(s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append( QgsPointXY(g['lon2'], g['lat2']) ) pts.append(ptEnd) ptStart = ptEnd if layercrs != epsg4326: # Convert each point to the output CRS for x, pt in enumerate(pts): pts[x] = transfrom4326.transform(pt) ptset.append(pts) multiset.append(ptset) if len(multiset) > 0: featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromMultiPolygonXY(multiset)) featureout.setAttributes(feature.attributes()) if isProcessing: writerLines.addFeature(featureout) else: writerLines.addFeatures([featureout]) except: num_bad += 1 #traceback.print_exc() pass return num_bad
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) azimuthmode = self.parameterAsInt(parameters, self.PrmAzimuthMode, context) startanglecol = self.parameterAsString(parameters, self.PrmAzimuth1Field, context) endanglecol = self.parameterAsString(parameters, self.PrmAzimuth2Field, context) radiusCol = self.parameterAsString(parameters, self.PrmRadiusField, context) startangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth1, context) endangle = self.parameterAsDouble(parameters, self.PrmDefaultAzimuth2, context) radius = self.parameterAsDouble(parameters, self.PrmDefaultRadius, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) measureFactor = conversionToMeters(units) radius *= measureFactor ptSpacing = 360.0 / segments srcCRS = source.sourceCrs() if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.LineString, srcCRS) 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 numbad = 0 iterator = source.getFeatures() for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: pts = [] pt = feature.geometry().asPoint() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) pts.append(pt) if startanglecol: sangle = float(feature[startanglecol]) else: sangle = startangle if endanglecol: eangle = float(feature[endanglecol]) else: eangle = endangle if azimuthmode == 1: width = abs(eangle) / 2.0 eangle = sangle + width sangle -= width if radiusCol: dist = float(feature[radiusCol]) * measureFactor else: dist = radius sangle = sangle % 360 eangle = eangle % 360 if sangle > eangle: # We are crossing the 0 boundry so lets just subtract # 360 from it. sangle -= 360.0 while sangle < eangle: g = geod.Direct(pt.y(), pt.x(), sangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) sangle += ptSpacing # add this number of degrees to the angle g = geod.Direct(pt.y(), pt.x(), eangle, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(pt) # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) f.setAttributes(feature.attributes()) sink.addFeature(f) except: numbad += 1 if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) if numbad > 0: feedback.pushInfo( tr("{} out of {} features had invalid parameters and were ignored." .format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def canvasPressEvent(self, e): if e.button() == Qt.RightButton and len(self.mousePoints) > 0: poligon = QgsVectorLayer('Polygon', 'poly', "memory") pr = poligon.dataProvider() poly = QgsFeature() if len(self.mousePoints) > 3: self.mousePoints.remove(self.mousePoints[-1]) poly.setGeometry(QgsGeometry.fromPolygonXY([self.mousePoints])) pr.addFeatures([poly]) layers = self.canvas.layers() try: for layer in layers: if layer.type() == QgsMapLayer.RasterLayer: continue modifiers = QApplication.keyboardModifiers() if modifiers == Qt.ShiftModifier: processing.run( 'qgis:selectbylocation', { 'INPUT': layer, 'PREDICATE': [0], 'INTERSECT': poligon, 'METHOD': 3 }) # Remove elif modifiers == Qt.ControlModifier: processing.run( 'qgis:selectbylocation', { 'INPUT': layer, 'PREDICATE': [0], 'INTERSECT': poligon, 'METHOD': 1 }) # Add else: processing.run( 'qgis:selectbylocation', { 'INPUT': layer, 'PREDICATE': [0], 'INTERSECT': poligon, 'METHOD': 0 }) # Set except Exception: self.iface.messageBar().pushMessage( "Warning", "Polygon not valid for selecting elements", level=1, duration=5) self.reset() poligon = None return elif e.button() == Qt.RightButton: self.canvas.unsetMapTool(self) self.deactivate() return # Rectangle if len(self.mousePoints) == 0: self.initialPoint = self.toMapCoordinates(e.pos()) self.finalPoint = self.initialPoint self.isSelecting = True self.showRectangle(self.initialPoint, self.finalPoint) # Poliline point = self.toMapCoordinates(e.pos()) self.mousePoints.append(point) if len(self.mousePoints) == 1: self.mousePoints.append(point)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) anglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) radiuscol = self.parameterAsString(parameters, self.PrmRadiusField, context) radius = self.parameterAsDouble(parameters, self.PrmRadius, context) startAngle = self.parameterAsDouble(parameters, self.PrmStartingAngle, context) segments = self.parameterAsInt(parameters, self.PrmDrawingSegments, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) export_geom = self.parameterAsBool(parameters, self.PrmExportInputGeometry, context) # The algorithm creates the heart on its side so this rotates # it so that it is upright. startAngle -= 90.0 measureFactor = conversionToMeters(units) radius *= measureFactor srcCRS = 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 shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, fields, QgsWkbTypes.LineString, srcCRS) 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 step = 360.0 / segments numbad = 0 iterator = source.getFeatures() for index, feature in enumerate(iterator): if feedback.isCanceled(): break try: if anglecol: sangle = float(feature[anglecol]) - 90 else: sangle = startAngle if radiuscol: radius2 = float(feature[radiuscol]) * measureFactor else: radius2 = radius except: numbad += 1 continue pts = [] pt = feature.geometry().asPoint() pt_orig_x = pt.x() pt_orig_y = pt.y() # make sure the coordinates are in EPSG:4326 if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) angle = 0.0 while angle <= 360.0: a = math.radians(angle) sina = math.sin(a) x = 16 * sina * sina * sina y = 13 * math.cos(a) - 5 * math.cos(2*a) - 2 * math.cos(3 * a)- math.cos(4*a) dist = math.sqrt(x*x + y*y) * radius2 / 17.0 a2 = math.degrees(math.atan2(y,x))+sangle g = geod.Direct(pt.y(), pt.x(), a2, dist, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) angle += step # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) attr = feature.attributes() if export_geom: attr.append(pt_orig_x) attr.append(pt_orig_y) f.setAttributes(attr) sink.addFeature(f) if index % 100 == 0: feedback.setProgress(int(index * total)) if numbad > 0: feedback.pushInfo(tr("{} out of {} features had invalid parameters and were ignored.".format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def diamonds(self, sink, source, width, height, rotation, feedback): features = source.getFeatures() ft = QgsFeature() total = 100.0 / source.featureCount() if source.featureCount() else 0 if rotation >= 0: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] angle = feat[rotation] if not w or not h or not angle: feedback.pushInfo(self.tr('Feature {} has empty ' 'width, height or angle. ' 'Skipping...'.format(feat.id()))) continue xOffset = w / 2.0 yOffset = h / 2.0 phi = angle * math.pi / 180 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)] polygon = [[QgsPointXY(i[0] * math.cos(phi) + i[1] * math.sin(phi) + x, -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) else: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] if not w or not h: feedback.pushInfo(self.tr('Feature {} has empty ' 'width or height. ' 'Skipping...'.format(feat.id()))) continue xOffset = w / 2.0 yOffset = h / 2.0 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)] polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) shapetype = self.parameterAsInt(parameters, self.PrmShapeType, context) sidescol = self.parameterAsString(parameters, self.PrmNumberOfSidesField, context) anglecol = self.parameterAsString(parameters, self.PrmStartingAngleField, context) distcol = self.parameterAsString(parameters, self.PrmRadiusField, context) sides = self.parameterAsInt(parameters, self.PrmDefaultNumberOfSides, context) angle = self.parameterAsDouble(parameters, self.PrmDefaultStartingAngle, context) defaultDist = self.parameterAsInt(parameters, self.PrmDefaultRadius, context) unitOfDist = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) measureFactor = conversionToMeters(unitOfDist) defaultDist *= measureFactor srcCRS = source.sourceCrs() if shapetype == 0: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.Polygon, srcCRS) else: (sink, dest_id) = self.parameterAsSink(parameters, self.PrmOutputLayer, context, source.fields(), QgsWkbTypes.LineString, srcCRS) 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() numbad = 0 for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: pt = feature.geometry().asPoint() if srcCRS != epsg4326: pt = geomTo4326.transform(pt.x(), pt.y()) if sidescol: s = int(feature[sidescol]) else: s = sides if anglecol: startangle = float(feature[anglecol]) else: startangle = angle if distcol: d = float(feature[distcol]) * measureFactor else: d = defaultDist pts = [] i = s while i >= 0: a = (i * 360.0 / s) + startangle i -= 1 g = geod.Direct(pt.y(), pt.x(), a, d, Geodesic.LATITUDE | Geodesic.LONGITUDE) pts.append(QgsPointXY(g['lon2'], g['lat2'])) # If the Output crs is not 4326 transform the points to the proper crs if srcCRS != epsg4326: for x, ptout in enumerate(pts): pts[x] = toSinkCrs.transform(ptout) f = QgsFeature() if shapetype == 0: f.setGeometry(QgsGeometry.fromPolygonXY([pts])) else: f.setGeometry(QgsGeometry.fromPolylineXY(pts)) f.setAttributes(feature.attributes()) sink.addFeature(f) except: numbad += 1 if cnt % 100 == 0: feedback.setProgress(int(cnt * total)) if numbad > 0: feedback.pushInfo( tr("{} out of {} features had invalid parameters and were ignored." .format(numbad, featureCount))) return {self.PrmOutputLayer: dest_id}
def addEntitySetToPolygon(self, entitySet, removeOriginals=False): """ Aggiunge il set di entità al poligono da modificare """ geom = self.poligonEntity.getGeometry() layerList = [] layerList.append(self.poligonEntity.layer) for layerEntitySet in entitySet.layerEntitySetList: layer = layerEntitySet.layer if layer.geometryType( ) != QgsWkbTypes.PolygonGeometry and layer.geometryType( ) != QgsWkbTypes.LineGeometry: self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False if removeOriginals: layerList.append(layer) coordTransform = QgsCoordinateTransform( layer.crs(), self.poligonEntity.layer.crs(), QgsProject.instance()) for featureId in layerEntitySet.featureIds: # se la feature è quella di polygonEntity è errore if layer.id() == self.poligonEntity.layerId( ) and featureId == self.poligonEntity.featureId: self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False f = layerEntitySet.getFeature(featureId) # trasformo la geometria nel crs del layer del poligono da modificare geomToAdd = f.geometry() geomToAdd.transform(coordTransform) # se il poligono è contenuto nella geometria da aggiungere if geomToAdd.contains(geom): # Riduco la geometria in point o polyline simplifiedGeoms = qad_utils.asPointOrPolyline(geom) # deve essere un poligono senza ring if len(simplifiedGeoms) != 1 or simplifiedGeoms[0].wkbType( ) != QgsWkbTypes.LineString: self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False points = simplifiedGeoms[0].asPolyline( ) # vettore di punti # aggiungo un'isola if geomToAdd.addRing(points) != 0: # 0 in case of success self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False del geom geom = QgsGeometry.fromPolygonXY(geomToAdd.asPolygon()) else: # se il poligono non è contenuto nella geometria da aggiungere # Riduco la geometria in point o polyline simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd) for simplifiedGeom in simplifiedGeoms: # se la geometria da aggiungere è contenuta nel poligono if geom.contains(simplifiedGeom): points = simplifiedGeom.asPolyline( ) # vettore di punti # aggiungo un'isola if geom.addRing( points) != 0: # 0 in case of success self.showMsg( QadMsg.translate("QAD", "Invalid object.")) return False else: # aggiungo una parte if geom.addPartGeometry( simplifiedGeom) != QgsGeometry.Success: self.showMsg( QadMsg.translate("QAD", "Invalid object.")) return False f = self.poligonEntity.getFeature() f.setGeometry(geom) layerList = entitySet.getLayerList() layerList.append(self.poligonEntity.layer) self.plugIn.beginEditCommand("Feature edited", layerList) # plugIn, layer, feature, refresh, check_validity if qad_layer.updateFeatureToLayer(self.plugIn, self.poligonEntity.layer, f, False, False) == False: self.plugIn.destroyEditCommand() return False if removeOriginals: for layerEntitySet in entitySet.layerEntitySetList: if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False: self.plugIn.destroyEditCommand() return self.plugIn.endEditCommand() self.nOperationsToUndo = self.nOperationsToUndo + 1 return True
def processPoly(source, sink, feedback, maxseglen): layercrs = source.sourceCrs() if layercrs != epsg4326: transto4326 = QgsCoordinateTransform(layercrs, epsg4326, QgsProject.instance()) transfrom4326 = QgsCoordinateTransform(epsg4326, layercrs, QgsProject.instance()) total = 100.0 / source.featureCount() if source.featureCount() else 0 iterator = source.getFeatures() num_bad = 0 for cnt, feature in enumerate(iterator): if feedback.isCanceled(): break try: if not feature.geometry().isMultipart(): poly = feature.geometry().asPolygon() numpolygons = len(poly) if numpolygons < 1: continue ptset = [] # Iterate through all points in the polygon and if the distance # is greater than the maxseglen, then add additional points. for points in poly: numpoints = len(points) if numpoints < 2: continue # If the input is not 4326 we need to convert it to that and then back to the output CRS ptStart = QgsPointXY(points[0][0], points[0][1]) if layercrs != epsg4326: # Convert to 4326 ptStart = transto4326.transform(ptStart) pts = [ptStart] for x in range(1, numpoints): ptEnd = QgsPointXY(points[x][0], points[x][1]) if layercrs != epsg4326: # Convert to 4326 ptEnd = transto4326.transform(ptEnd) l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x()) # Check to see if the distance is greater than the maximum # segment length and if so lets add additional points. if l.s13 > maxseglen: n = int(math.ceil(l.s13 / maxseglen)) seglen = l.s13 / n for i in range(1, n): s = seglen * i g = l.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append(QgsPointXY(g['lon2'], g['lat2'])) pts.append(ptEnd) ptStart = ptEnd if layercrs != epsg4326: # Convert each point to the output CRS for x, pt in enumerate(pts): pts[x] = transfrom4326.transform(pt) ptset.append(pts) if len(ptset) > 0: featureout = QgsFeature() featureout.setGeometry(QgsGeometry.fromPolygonXY(ptset)) featureout.setAttributes(feature.attributes()) sink.addFeature(featureout) else: multipoly = feature.geometry().asMultiPolygon() multiset = [] for poly in multipoly: ptset = [] for points in poly: numpoints = len(points) if numpoints < 2: continue # If the input is not 4326 we need to convert it to that and then back to the output CRS ptStart = QgsPointXY(points[0][0], points[0][1]) if layercrs != epsg4326: # Convert to 4326 ptStart = transto4326.transform(ptStart) pts = [ptStart] for x in range(1, numpoints): ptEnd = QgsPointXY(points[x][0], points[x][1]) if layercrs != epsg4326: # Convert to 4326 ptEnd = transto4326.transform(ptEnd) l = geod.InverseLine(ptStart.y(), ptStart.x(), ptEnd.y(), ptEnd.x()) if l.s13 > maxseglen: n = int(math.ceil(l.s13 / maxseglen)) seglen = l.s13 / n for i in range(1, n): s = seglen * i g = l.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) pts.append(QgsPointXY( g['lon2'], g['lat2'])) pts.append(ptEnd) ptStart = ptEnd if layercrs != epsg4326: # Convert each point to the output CRS for x, pt in enumerate(pts): pts[x] = transfrom4326.transform(pt) ptset.append(pts) multiset.append(ptset) if len(multiset) > 0: featureout = QgsFeature() featureout.setGeometry( QgsGeometry.fromMultiPolygonXY(multiset)) featureout.setAttributes(feature.attributes()) sink.addFeature(featureout) except: num_bad += 1 '''s = traceback.format_exc() feedback.pushInfo(s)''' feedback.setProgress(int(cnt * total)) return num_bad
def _hexagonGrid(self, sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback): feat = QgsFeature() # To preserve symmetry, hspacing is fixed relative to vspacing xVertexLo = 0.288675134594813 * vSpacing xVertexHi = 0.577350269189626 * vSpacing hSpacing = xVertexLo + xVertexHi hOverlay = hSpacing - hOverlay if hOverlay < 0: raise QgsProcessingException( self.tr('To preserve symmetry, hspacing is fixed relative to vspacing\n \ hspacing is fixed at: {0} and hoverlay is fixed at: {1}\n \ hoverlay cannot be negative. Increase hoverlay.').format(hSpacing, hOverlay) ) halfVSpacing = vSpacing / 2.0 columns = int(math.ceil(float(bbox.width()) / hOverlay)) rows = int(math.ceil(float(bbox.height()) / (vSpacing - vOverlay))) cells = rows * columns count_update = cells * 0.05 id = 1 count = 0 for col in range(columns): if feedback.isCanceled(): break # (column + 1) and (row + 1) calculation is used to maintain # topology between adjacent shapes and avoid overlaps/holes # due to rounding errors x1 = bbox.xMinimum() + (col * hOverlay) # far left x2 = x1 + (xVertexHi - xVertexLo) # left x3 = bbox.xMinimum() + (col * hOverlay) + hSpacing # right x4 = x3 + (xVertexHi - xVertexLo) # far right for row in range(rows): if (col % 2) == 0: y1 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 0) * halfVSpacing) # hi y2 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 1) * halfVSpacing) # mid y3 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 2) * halfVSpacing) # lo else: y1 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 1) * halfVSpacing) # hi y2 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 2) * halfVSpacing) # mid y3 = bbox.yMaximum() + (row * vOverlay) - (((row * 2) + 3) * halfVSpacing) # lo polyline = [] polyline.append(QgsPointXY(x1, y2)) polyline.append(QgsPointXY(x2, y1)) polyline.append(QgsPointXY(x3, y1)) polyline.append(QgsPointXY(x4, y2)) polyline.append(QgsPointXY(x3, y3)) polyline.append(QgsPointXY(x2, y3)) polyline.append(QgsPointXY(x1, y2)) feat.setGeometry(QgsGeometry.fromPolygonXY([polyline])) feat.setAttributes([x1, y1, x4, y3, id]) sink.addFeature(feat, QgsFeatureSink.FastInsert) id += 1 count += 1 if int(math.fmod(count, count_update)) == 0: feedback.setProgress(int(count / cells * 100))
def unionIntersSubtractEntitySetToPolygon(self, entitySet, opType, removeOriginals=False): """ Unisce o interseca i poligoni di entitySet al poligono corrente """ geom = self.poligonEntity.getGeometry() layerList = [] layerList.append(self.poligonEntity.layer) geomList = [] geomList.append(geom) for layerEntitySet in entitySet.layerEntitySetList: del geomList[:] layer = layerEntitySet.layer coordTransform = QgsCoordinateTransform( layer.crs(), self.poligonEntity.layer.crs(), QgsProject.instance()) if layer.geometryType() == QgsWkbTypes.PolygonGeometry: for featureId in layerEntitySet.featureIds: # se la feature è quella di polygonEntity è errore if layer.id() == self.poligonEntity.layerId( ) and featureId == self.poligonEntity.featureId: self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False f = layerEntitySet.getFeature(featureId) # trasformo la geometria nel crs del layer del poligono da modificare geomToAdd = f.geometry() geomToAdd.transform(coordTransform) if opType == QadMAPMPEDITCommandOpTypeEnum.UNION: geom = geom.combine(geomToAdd) elif opType == QadMAPMPEDITCommandOpTypeEnum.INTERSECTION: geom = geom.intersection(geomToAdd) elif opType == QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE: geom = geom.difference(geomToAdd) if geom is None: self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False if removeOriginals and layer.id( ) != self.poligonEntity.layerId(): layerList.append(layer) elif layer.geometryType() == QgsWkbTypes.LineGeometry: for featureId in layerEntitySet.featureIds: f = layerEntitySet.getFeature(featureId) # trasformo la geometria nel crs del layer del poligono da modificare geomToAdd = f.geometry() geomToAdd.transform(coordTransform) # Riduco la geometria in point o polyline simplifiedGeoms = qad_utils.asPointOrPolyline(geomToAdd) for simplifiedGeom in simplifiedGeoms: if simplifiedGeom.wkbType() != QgsWkbTypes.LineString: self.showMsg( QadMsg.translate("QAD", "Invalid object.")) return False points = simplifiedGeom.asPolyline( ) # vettore di punti if len(points) < 4 or points[0] != points[ -1]: # polilinea chiusa con almeno 4 punti (primo e ultimo uguali) self.showMsg( QadMsg.translate("QAD", "Invalid object.")) return False geomToAdd = QgsGeometry.fromPolygonXY([points]) if opType == QadMAPMPEDITCommandOpTypeEnum.UNION: geom = geom.combine(geomToAdd) elif opType == QadMAPMPEDITCommandOpTypeEnum.INTERSECTION: geom = geom.intersection(geomToAdd) elif opType == QadMAPMPEDITCommandOpTypeEnum.DIFFERENCE: geom = geom.difference(geomToAdd) if geom is None or geom.type( ) != QgsWkbTypes.PolygonGeometry: self.showMsg( QadMsg.translate("QAD", "Invalid object.")) return False if removeOriginals: layerList.append(layer) else: self.showMsg(QadMsg.translate("QAD", "Invalid object.")) return False f = self.poligonEntity.getFeature() f.setGeometry(geom) self.plugIn.beginEditCommand("Feature edited", layerList) # plugIn, layer, feature, refresh, check_validity if qad_layer.updateFeatureToLayer(self.plugIn, self.poligonEntity.layer, f, False, False) == False: self.plugIn.destroyEditCommand() return False if removeOriginals: for layerEntitySet in entitySet.layerEntitySetList: if qad_layer.deleteFeaturesToLayer(self.plugIn, layerEntitySet.layer, layerEntitySet.featureIds, False) == False: self.plugIn.destroyEditCommand() return self.plugIn.endEditCommand() self.nOperationsToUndo = self.nOperationsToUndo + 1 return True
def ovals(self, sink, source, width, height, rotation, segments, feedback): features = source.getFeatures() ft = QgsFeature() total = 100.0 / source.featureCount() if source.featureCount() else 0 if rotation >= 0: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] angle = feat[rotation] # block 0/NULL width or height, but allow 0 as angle value if not w or not h: feedback.pushInfo(QCoreApplication.translate('RectanglesOvalsDiamondsVariable', 'Feature {} has empty ' 'width or height. ' 'Skipping…').format(feat.id())) continue if angle == NULL: feedback.pushInfo(QCoreApplication.translate('RectanglesOvalsDiamondsVariable', 'Feature {} has empty ' 'angle. ' 'Skipping…').format(feat.id())) continue xOffset = w / 2.0 yOffset = h / 2.0 phi = angle * math.pi / 180 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [] for t in [(2 * math.pi) / segments * i for i in range(segments)]: points.append((xOffset * math.cos(t), yOffset * math.sin(t))) polygon = [[QgsPointXY(i[0] * math.cos(phi) + i[1] * math.sin(phi) + x, -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) else: for current, feat in enumerate(features): if feedback.isCanceled(): break if not feat.hasGeometry(): continue w = feat[width] h = feat[height] if not w or not h: feedback.pushInfo(QCoreApplication.translate('RectanglesOvalsDiamondsVariable', 'Feature {} has empty ' 'width or height. ' 'Skipping…').format(feat.id())) continue xOffset = w / 2.0 yOffset = h / 2.0 point = feat.geometry().asPoint() x = point.x() y = point.y() points = [] for t in [(2 * math.pi) / segments * i for i in range(segments)]: points.append((xOffset * math.cos(t), yOffset * math.sin(t))) polygon = [[QgsPointXY(i[0] + x, i[1] + y) for i in points]] ft.setGeometry(QgsGeometry.fromPolygonXY(polygon)) ft.setAttributes(feat.attributes()) sink.addFeature(ft, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total))
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 = bd2wgs(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 = bd2wgs(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 = bd2wgs(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 = bd2wgs(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 = bd2wgs(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 = bd2wgs(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}