def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context) target_crs = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context) target_geom = QgsGeometry.fromRect(extent) fields = QgsFields() fields.append(QgsField('auth_id', QVariant.String, '', 20)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem()) # make intersection tests nice and fast engine = QgsGeometry.createGeometryEngine(target_geom.constGet()) engine.prepareGeometry() layer_bounds = QgsGeometry.fromRect(source.sourceExtent()) crses_to_check = QgsCoordinateReferenceSystem.validSrsIds() total = 100.0 / len(crses_to_check) found_results = 0 transform_context = QgsCoordinateTransformContext() for current, srs_id in enumerate(crses_to_check): if feedback.isCanceled(): break candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id) if not candidate_crs.isValid(): continue transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs, transform_context) transformed_bounds = QgsGeometry(layer_bounds) try: if not transformed_bounds.transform(transform_candidate) == 0: continue except: continue try: if engine.intersects(transformed_bounds.constGet()): feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid())) f = QgsFeature(fields) f.setAttributes([candidate_crs.authid()]) sink.addFeature(f, QgsFeatureSink.FastInsert) found_results += 1 except: continue feedback.setProgress(int(current * total)) if found_results == 0: feedback.reportError(self.tr('No matching projections found')) return {self.OUTPUT: dest_id}
def transformGeom(self, item): src_crs = QgsCoordinateReferenceSystem() src_crs.createFromSrid(item.srid) dest_crs = self.mapCanvas.mapRenderer().destinationCrs() geom = QgsGeometry(item.geometry) geom.transform(QgsCoordinateTransform(src_crs, dest_crs)) return geom
def set_next_analysis_extent(self, extent, crs): """Setter for the next analysis extent. This function will redraw the rubberband if needed. :param extent: The next analysis extent. :type extent: QgsGeometry :param crs: The CRS of the extent. :type crs: QgsCoordinateReferenceSystem """ extent = QgsGeometry(extent) transform = QgsCoordinateTransform(crs, self.crs) extent.transform(transform) self._next_analysis_extent = extent if self._show_rubber_bands: self.display_next_analysis()
def set_user_extent(self, extent, crs): """Setter for the user requested extent. This function will redraw the rubberband if needed. :param extent: The user extent. :type extent: QgsGeometry :param crs: The CRS of the extent. :type crs: QgsCoordinateReferenceSystem """ extent = QgsGeometry(extent) transform = QgsCoordinateTransform(crs, self.crs) extent.transform(transform) self._user_extent = extent set_setting('user_extent', extent.exportToWkt()) set_setting('user_extent_crs', crs.authid()) if self._show_rubber_bands: self.display_user_extent()
def _addHighlightGeom(self): def highlight(): rb = QgsRubberBand( self.canvas, QGis.Polygon) rb.setBorderColor( QColor( 255, 0, 0 ) ) rb.setWidth( 2 ) rb.setToGeometry( geomRB, None ) return rb crsCanvas = self.canvas.mapSettings().destinationCrs() crsLayer = self.layerSrc.crs() if not crsCanvas == crsLayer: geomRB = QgsGeometry( self.geom ) ct = QgsCoordinateTransform( crsLayer, crsCanvas ) geomRB.transform( ct ) else: geomRB = self.geom return highlight()
def dissolvePolygonsOnCanvas(writer, layer): """dissolve polygons of the layer and clip the dissolution with base extent""" settings = writer.settings baseExtent = settings.baseExtent baseExtentGeom = baseExtent.geometry() rotation = baseExtent.rotation() transform = QgsCoordinateTransform(layer.crs(), settings.crs) combi = None request = QgsFeatureRequest() request.setFilterRect(transform.transformBoundingBox(baseExtent.boundingBox(), QgsCoordinateTransform.ReverseTransform)) for f in layer.getFeatures(request): geometry = f.geometry() if geometry is None: logMessage("null geometry skipped") continue # coordinate transformation - layer crs to project crs geom = QgsGeometry(geometry) if geom.transform(transform) != 0: logMessage("Failed to transform geometry") continue # check if geometry intersects with the base extent (rotated rect) if rotation and not baseExtentGeom.intersects(geom): continue if combi: combi = combi.combine(geom) else: combi = geom # clip geom with slightly smaller extent than base extent # to make sure that the clipped polygon stays within the base extent geom = combi.intersection(baseExtent.clone().scale(0.999999).geometry()) if geom is None: return None # check if geometry is empty if geom.isGeosEmpty(): logMessage("empty geometry") return None return geom
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context) extent = self.getParameterValue(self.TARGET_AREA).split(',') if not extent: extent = QgsProcessingUtils.combineLayerExtents([layer]) target_crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.TARGET_AREA_CRS)) target_geom = QgsGeometry.fromRect(QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3]))) output_file = self.getOutputValue(self.OUTPUT_HTML_FILE) # make intersection tests nice and fast engine = QgsGeometry.createGeometryEngine(target_geom.geometry()) engine.prepareGeometry() layer_bounds = QgsGeometry.fromRect(layer.extent()) results = [] for srs_id in QgsCoordinateReferenceSystem.validSrsIds(): candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id) if not candidate_crs.isValid(): continue transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs) transformed_bounds = QgsGeometry(layer_bounds) try: if not transformed_bounds.transform(transform_candidate) == 0: continue except: continue if engine.intersects(transformed_bounds.geometry()): results.append(candidate_crs.authid()) self.createHTML(output_file, results)
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) method = self.getParameterValue(self.METHOD) geometryType = layer.geometryType() idx1 = -1 idx2 = -1 fields = layer.pendingFields() if geometryType == QGis.Polygon: (idx1, fields) = vector.findOrCreateField(layer, fields, 'area', 21, 6) (idx2, fields) = vector.findOrCreateField(layer, fields, 'perimeter', 21, 6) elif geometryType == QGis.Line: (idx1, fields) = vector.findOrCreateField(layer, fields, 'length', 21, 6) idx2 = idx1 else: (idx1, fields) = vector.findOrCreateField(layer, fields, 'xcoord', 21, 6) (idx2, fields) = vector.findOrCreateField(layer, fields, 'ycoord', 21, 6) writer = self.getOutputFromName( self.OUTPUT).getVectorWriter(fields.toList(), layer.dataProvider().geometryType(), layer.crs()) ellips = None crs = None coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if method == 2: ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid', 'NONE')[0] crs = layer.crs().srsid() elif method == 1: mapCRS = iface.mapCanvas().mapRenderer().destinationCrs() layCRS = layer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) outFeat = QgsFeature() inGeom = QgsGeometry() outFeat.initAttributes(len(fields)) outFeat.setFields(fields) current = 0 features = vector.features(layer) total = 100.0 / float(len(features)) for f in features: inGeom = f.geometry() if method == 1: inGeom.transform(coordTransform) (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs) outFeat.setGeometry(inGeom) attrs = f.attributes() attrs.insert(idx1, attr1) if attr2 is not None: attrs.insert(idx2, attr2) outFeat.setAttributes(attrs) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) method = self.getParameterValue(self.METHOD) geometryType = layer.geometryType() fields = layer.fields() export_z = False export_m = False if geometryType == QgsWkbTypes.PolygonGeometry: areaName = vector.createUniqueFieldName("area", fields) fields.append(QgsField(areaName, QVariant.Double)) perimeterName = vector.createUniqueFieldName("perimeter", fields) fields.append(QgsField(perimeterName, QVariant.Double)) elif geometryType == QgsWkbTypes.LineGeometry: lengthName = vector.createUniqueFieldName("length", fields) fields.append(QgsField(lengthName, QVariant.Double)) else: xName = vector.createUniqueFieldName("xcoord", fields) fields.append(QgsField(xName, QVariant.Double)) yName = vector.createUniqueFieldName("ycoord", fields) fields.append(QgsField(yName, QVariant.Double)) if QgsWkbTypes.hasZ(layer.wkbType()): export_z = True zName = vector.createUniqueFieldName("zcoord", fields) fields.append(QgsField(zName, QVariant.Double)) if QgsWkbTypes.hasM(layer.wkbType()): export_m = True zName = vector.createUniqueFieldName("mvalue", fields) fields.append(QgsField(zName, QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields.toList(), layer.wkbType(), layer.crs()) ellips = None crs = None coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if method == 2: ellips = QgsProject.instance().readEntry("Measure", "/Ellipsoid", "NONE")[0] crs = layer.crs().srsid() elif method == 1: mapCRS = iface.mapCanvas().mapSettings().destinationCrs() layCRS = layer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) outFeat = QgsFeature() inGeom = QgsGeometry() outFeat.initAttributes(len(fields)) outFeat.setFields(fields) features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): inGeom = f.geometry() if method == 1: inGeom.transform(coordTransform) (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs) outFeat.setGeometry(inGeom) attrs = f.attributes() attrs.append(attr1) if attr2 is not None: attrs.append(attr2) # add point z/m if export_z: attrs.append(inGeom.geometry().z()) if export_m: attrs.append(inGeom.geometry().m()) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) method = self.getParameterValue(self.METHOD) geometryType = layer.geometryType() fields = layer.fields() export_z = False export_m = False if geometryType == QgsWkbTypes.PolygonGeometry: areaName = vector.createUniqueFieldName('area', fields) fields.append(QgsField(areaName, QVariant.Double)) perimeterName = vector.createUniqueFieldName('perimeter', fields) fields.append(QgsField(perimeterName, QVariant.Double)) elif geometryType == QgsWkbTypes.LineGeometry: lengthName = vector.createUniqueFieldName('length', fields) fields.append(QgsField(lengthName, QVariant.Double)) else: xName = vector.createUniqueFieldName('xcoord', fields) fields.append(QgsField(xName, QVariant.Double)) yName = vector.createUniqueFieldName('ycoord', fields) fields.append(QgsField(yName, QVariant.Double)) if QgsWkbTypes.hasZ(layer.wkbType()): export_z = True zName = vector.createUniqueFieldName('zcoord', fields) fields.append(QgsField(zName, QVariant.Double)) if QgsWkbTypes.hasM(layer.wkbType()): export_m = True zName = vector.createUniqueFieldName('mvalue', fields) fields.append(QgsField(zName, QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), layer.wkbType(), layer.crs()) ellips = None crs = None coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if method == 2: ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid', 'NONE')[0] crs = layer.crs().srsid() elif method == 1: mapCRS = iface.mapCanvas().mapSettings().destinationCrs() layCRS = layer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) outFeat = QgsFeature() inGeom = QgsGeometry() outFeat.initAttributes(len(fields)) outFeat.setFields(fields) features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): inGeom = f.geometry() if method == 1: inGeom.transform(coordTransform) (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs) outFeat.setGeometry(inGeom) attrs = f.attributes() attrs.append(attr1) if attr2 is not None: attrs.append(attr2) # add point z/m if export_z: attrs.append(inGeom.geometry().z()) if export_m: attrs.append(inGeom.geometry().m()) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def export_geometry_info( self ): ellips = None crs = None coordTransform = None # calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if self.myCalcType == 2: settings = QSettings() ellips = settings.value( "/qgis/measure/ellipsoid", "WGS84" ) crs = self.vlayer.crs().srsid() elif self.myCalcType == 1: mapCRS = self.parent.iface.mapCanvas().mapRenderer().destinationCrs() layCRS = self.vlayer.crs() coordTransform = QgsCoordinateTransform( layCRS, mapCRS ) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() nElement = 0 vprovider = self.vlayer.dataProvider() self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0) self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, vprovider.featureCount() ) ) ( fields, index1, index2 ) = self.checkMeasurementFields( self.vlayer, not self.writeShape ) if self.writeShape: writer = QgsVectorFileWriter( self.myName, self.myEncoding, fields, vprovider.geometryType(), vprovider.crs() ) fit = vprovider.getFeatures() while fit.nextFeature(inFeat): self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement ) nElement += 1 inGeom = inFeat.geometry() if self.myCalcType == 1: inGeom.transform( coordTransform ) ( attr1, attr2 ) = self.simpleMeasure( inGeom, self.myCalcType, ellips, crs ) if self.writeShape: outFeat.setGeometry( inGeom ) atMap = inFeat.attributes() maxIndex = index1 if index1 > index2 else index2 if maxIndex >= len(atMap): atMap += [ "" ] * ( index2+1 - len(atMap) ) atMap[ index1 ] = attr1 if index1 != index2: atMap[ index2 ] = attr2 outFeat.setAttributes( atMap ) writer.addFeature( outFeat ) else: changeMap = {} changeMap[ inFeat.id() ] = {} changeMap[ inFeat.id() ][ index1 ] = attr1 if index1!=index2: changeMap[ inFeat.id() ][ index2 ] = attr2 vprovider.changeAttributeValues( changeMap ) self.vlayer.updateFields() if self.writeShape: del writer return True
def copySourceFeaturesToTargetLayer(self): success = True layers = self.dependentLayers() for layer in layers: if layer.name( ) != YleiskaavaDatabase.KAAVAOBJEKTI_ALUE and layer.name( ) != YleiskaavaDatabase.KAAVAOBJEKTI_ALUE_TAYDENTAVA and layer.name( ) != YleiskaavaDatabase.KAAVAOBJEKTI_VIIVA and layer.name( ) != YleiskaavaDatabase.KAAVAOBJEKTI_PISTE and layer.name( ) != "kaavaobjekti_kaavamaarays_yhteys" and layer.name( ) != "kaavamääräykset": self.sourceLayer = layer self.sourceFeatures = layer.selectedFeatures() self.sourceFeatureCount = layer.selectedFeatureCount() self.sourceCRS = layer.sourceCrs() self.sourceLayerFields = layer.fields().toList() elif layer.name( ) != "kaavaobjekti_kaavamaarays_yhteys" and layer.name( ) != "kaavamääräykset": self.targetLayer = layer self.targetCRS = layer.sourceCrs() # QgsMessageLog.logMessage("copySourceFeaturesToTargetLayer - targetLayer.name(): " + str(self.targetLayer.name()), 'Yleiskaava-työkalu', Qgis.Info) # QgsMessageLog.logMessage("copySourceFeaturesToTargetLayer - targetCRS: " + self.targetCRS.authid(), 'Yleiskaava-työkalu', Qgis.Info) transform = None if self.sourceCRS != self.targetCRS: transform = QgsCoordinateTransform(self.sourceCRS, self.targetCRS, self.transformContext) for index, sourceFeature in enumerate(self.sourceFeatures): targetLayerFeature = QgsFeature() targetLayerFeature.setFields(self.targetLayer.fields()) featureID = str(uuid.uuid4()) targetLayerFeature.setAttribute("id", featureID) sourceGeom = sourceFeature.geometry() if not sourceGeom.isNull() and transform is not None: transformedSourceGeom = QgsGeometry(sourceGeom) transformedSourceGeom.transform(transform) else: transformedSourceGeom = QgsGeometry(sourceGeom) targetLayerFeature.setGeometry(transformedSourceGeom) success = self.setTargetFeatureValues(sourceFeature, targetLayerFeature) if not success: return success # QgsMessageLog.logMessage("copySourceFeaturesToTargetLayer - targetLayerFeature['nro']: " + str(targetLayerFeature['nro']), 'Yleiskaava-työkalu', Qgis.Info) self.handleRegulationAndLandUseClassificationInSourceToTargetCopy( sourceFeature, self.targetSchemaTableName, targetLayerFeature, False) self.handleSpatialPlanRelationInSourceToTargetCopy( targetLayerFeature) return_data = self.yleiskaavaDatabase.createTargetFeature( self.targetSchemaTableName, sourceFeature, targetLayerFeature, self.targetCRS) # QgsMessageLog.logMessage('createTargetFeature valmis', 'Yleiskaava-työkalu', Qgis.Info) # QgsMessageLog.logMessage(json.dumps(return_data), 'Yleiskaava-työkalu', Qgis.Info) for item in return_data['messages']: CopySourceDataToDatabaseTask.yleiskaava_exceptions.append(item) QgsMessageLog.logMessage( "lisätty poikkeuksiin: " + item['message'], 'Yleiskaava-työkalu', Qgis.Info) if not return_data['success']: # exception = "yleiskaavaDatabase.createTargetFeature epäonnistui, sourceFeature-attribuutit: " # for field in self.targetLayer.fields().toList(): # if sourceFeature[field.name()]: # exception += str(sourceFeature[field.name()]) + ", " # exception = exception[:-2] # CopySourceDataToDatabaseTask.yleiskaava_exceptions.append(exception) break else: # Kaavakohteen pitää olla jo tallennettuna tietokannassa, jotta voidaan lisätä relaatio kaavamääräykseen self.handleRegulationAndLandUseClassificationInSourceToTargetCopy( sourceFeature, self.targetSchemaTableName, targetLayerFeature, True) if self.isCanceled(): break progress = (index / self.sourceFeatureCount) * 100 self.setProgress(progress) return success
def getSchnittpunkteAusPolygonen(self, overlapFeats, featureCrs, laengsProfil, feedback): schnittpunktFeatures = [] schnittLinesFeatures = [] ioFeat = 0 countPoints = 0 try: for feat in overlapFeats: #Feature bekommt neues Attribut Station if ioFeat == 0: fields = feat.fields() fields.append(QgsField("station", QVariant.Double)) schnittpunktFeaturesOfThisPolygon = [] schnittpunktListOfPolygon = [ ] #Liste [points, stations, feature.id's] #check if Multipolygon iMulti = 0 iRing = 0 tempGeom = QgsGeometry() tempGeom.fromWkb(feat.geometry().asWkb()) #transform geom to Project.crs() if crs a different if not featureCrs.authid() == QgsProject.instance().crs( ).authid(): trafo = QgsCoordinateTransform(featureCrs, QgsProject.instance().crs(), QgsProject.instance()) #transform Geom to Project.crs() tempGeom.transform(trafo, QgsCoordinateTransform.ForwardTransform, False) if tempGeom.isMultipart(): multiGeom = tempGeom.asMultiPolygon() #Schleife zum Auflösen des Multiparts for polygon in multiGeom: for ring in polygon: points = [] for pxy in ring: #feedback.pushInfo(str(iMulti)+" "+str(iRing)+" "+str(pxy) + " " + str(type(pxy))) points.append(QgsPoint(pxy.x(), pxy.y())) singlePolygon = QgsGeometry().fromPolyline(points) iRing = iRing + 1 #feedback.pushInfo(str(iMulti) + str(type(singlePolygon)) + str(polygon)) schnittpunktFeaturesOfThisPolygonItem = self.makeIntersectionFeatures( feat, singlePolygon, laengsProfil, fields, feedback) for spfotp in schnittpunktFeaturesOfThisPolygonItem: schnittpunktFeaturesOfThisPolygon.append( spfotp) #Liste [points, stations, feature.id's] schnittpunktListOfPolygonItem = self.makeIntersectionPointsStationList( feat, singlePolygon, laengsProfil, fields, feedback) for sp in schnittpunktListOfPolygonItem: schnittpunktListOfPolygon.append(sp) iMulti = iMulti + 1 else: # single Geometry schnittpunktFeaturesOfThisPolygon = self.makeIntersectionFeatures( feat, tempGeom, laengsProfil, fields, feedback) schnittpunktListOfPolygon = self.makeIntersectionPointsStationList( feat, tempGeom, laengsProfil, fields, feedback) #create LineFeatures schnittLinesFeats = self.makeLineFeaturesFromPointStationList( feat, schnittpunktListOfPolygon, laengsProfil, feedback) for f in schnittLinesFeats: schnittLinesFeatures.append(f) #add to list for schnittFeat in schnittpunktFeaturesOfThisPolygon: #Intersection Feature in project.crs() schnittpunktFeatures.append(schnittFeat) #feedback.pushInfo(str(schnittFeat.attributes())) ioFeat = ioFeat + 1 #count Intersections countPoints = countPoints + len( schnittpunktFeaturesOfThisPolygon) except: msg = self.tr( "Error: Creating Intersections Geometry {0} Feature {1}" ).format(str(type(feat.geometry())), str(feat.attributes())) feedback.reportError(msg) raise QgsProcessingException(msg) msgInfo = self.tr("Intersected Lines: {0} Intersections: {1}").format( ioFeat, countPoints) feedback.pushInfo(msgInfo) return schnittpunktFeatures, schnittLinesFeatures
def features(self, request=None, clipGeom=None): settings = self.writer.settings mapTo3d = settings.mapTo3d() baseExtent = settings.baseExtent baseExtentGeom = baseExtent.geometry() rotation = baseExtent.rotation() prop = self.prop useZ = prop.useZ() if useZ: srs_from = osr.SpatialReference() srs_from.ImportFromProj4(str(self.layer.crs().toProj4())) srs_to = osr.SpatialReference() srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4())) ogr_transform = osr.CreateCoordinateTransformation(srs_from, srs_to) clipGeomWkb = clipGeom.asWkb() if clipGeom else None ogr_clipGeom = ogr.CreateGeometryFromWkb(clipGeomWkb) if clipGeomWkb else None else: # z_func: function to get elevation at given point (x, y) on surface if prop.isHeightRelativeToDEM(): if self.geomType == QGis.Polygon and prop.type_index == 1: # Overlay z_func = lambda x, y: 0 else: # get elevation from DEM z_func = lambda x, y: self.writer.demProvider.readValue(x, y) else: z_func = lambda x, y: 0 request = request or QgsFeatureRequest() for f in self.layer.getFeatures(request): geometry = f.geometry() if geometry is None: logMessage("null geometry skipped") continue # coordinate transformation - layer crs to project crs geom = QgsGeometry(geometry) if geom.transform(self.transform) != 0: logMessage("Failed to transform geometry") continue # check if geometry intersects with the base extent (rotated rect) if rotation and not baseExtentGeom.intersects(geom): continue # create feature feat = Feature(self.writer, self, f) # transform_func: function to transform the map coordinates to 3d coordinates relativeHeight = prop.relativeHeight(f) def transform_func(x, y, z): return mapTo3d.transform(x, y, z + relativeHeight) if useZ: ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb()) # transform geometry from layer CRS to project CRS if ogr_geom.Transform(ogr_transform) != 0: logMessage("Failed to transform geometry") continue # clip geometry if ogr_clipGeom and self.geomType == QGis.Line: ogr_geom = ogr_geom.Intersection(ogr_clipGeom) if ogr_geom is None: continue # check if geometry is empty if ogr_geom.IsEmpty(): logMessage("empty geometry skipped") continue feat.geom = self.geomClass.fromOgrGeometry25D(ogr_geom, transform_func) else: # clip geometry if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]: geom = geom.intersection(clipGeom) if geom is None: continue # check if geometry is empty if geom.isGeosEmpty(): logMessage("empty geometry skipped") continue if self.geomType == QGis.Polygon: feat.geom = self.geomClass.fromQgsGeometry(geom, z_func, transform_func, self.hasLabel()) if prop.type_index == 1 and prop.isHeightRelativeToDEM(): # Overlay and relative to DEM feat.geom.splitPolygon(self.writer.triangleMesh()) else: feat.geom = self.geomClass.fromQgsGeometry(geom, z_func, transform_func) if feat.geom is None: continue yield feat
def geomTransform(self, geom, crs_orig, crs_dest): g = QgsGeometry(geom) crsTransform = QgsCoordinateTransform( crs_orig, crs_dest, QgsCoordinateTransformContext()) # which context ? g.transform(crsTransform) return g
def setSelectFeatures(canvas, selectGeometry, doContains, doDifference, singleSelect=None): """ QgsMapCanvas* canvas, QgsGeometry* selectGeometry, bool doContains, bool doDifference, bool singleSelect """ if selectGeometry.type() != QGis.Polygon: return vlayer = getCurrentVectorLayer(canvas) if vlayer == None: return #toLayerCoordinates will throw an exception for any 'invalid' points in #the rubber band. #For example, if you project a world map onto a globe using EPSG 2163 #and then click somewhere off the globe, an exception will be thrown. selectGeomTrans = QgsGeometry(selectGeometry) if canvas.mapSettings().hasCrsTransformEnabled(): try: ct = QgsCoordinateTransform(canvas.mapSettings().destinationCrs(), vlayer.crs()) selectGeomTrans.transform( ct ) except QgsCsException as cse: Q_UNUSED(cse) #catch exception for 'invalid' point and leave existing selection unchanged """ QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) ); QgisApp::instance()->messageBar()->pushMessage( QObject::tr( "CRS Exception" ), QObject::tr( "Selection extends beyond layer's coordinate system" ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() ); """ return QApplication.setOverrideCursor(Qt.WaitCursor) """ QgsDebugMsg( "Selection layer: " + vlayer->name() ); QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() ); QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) ); QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) ); """ context = QgsRenderContext().fromMapSettings(canvas.mapSettings()) r = vlayer.rendererV2() if r: r.startRender(context, vlayer.pendingFields()) request = QgsFeatureRequest() request.setFilterRect(selectGeomTrans.boundingBox()) request.setFlags(QgsFeatureRequest.ExactIntersect) if r: request.setSubsetOfAttributes(r.usedAttributes(), vlayer.pendingFields()) else: request.setSubsetOfAttributes(QgsAttributeList) fit = vlayer.getFeatures(request) newSelectedFeatures = [] #QgsFeatureIds f = QgsFeature() closestFeatureId = 0 #QgsFeatureId foundSingleFeature = False #double closestFeatureDist = std::numeric_limits<double>::max(); closestFeatureDist = sys.float_info.max while fit.nextFeature(f): # make sure to only use features that are visible if r and not r.willRenderFeature( f ): continue; g = QgsGeometry(f.geometry()) if doContains: if not selectGeomTrans.contains(g): continue else: if not selectGeomTrans.intersects(g): continue if singleSelect: foundSingleFeature = True distance = float(g.distance(selectGeomTrans)) if ( distance <= closestFeatureDist ): closestFeatureDist = distance closestFeatureId = f.id() else: newSelectedFeatures.insert(0, f.id()) if singleSelect and foundSingleFeature: newSelectedFeatures.insert(0, closestFeatureId) if r: r.stopRender(context) #QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) if doDifference: layerSelectedFeatures = vlayer.selectedFeaturesIds() selectedFeatures = [] #QgsFeatureIds deselectedFeatures = []# QgsFeatureIds # i = QgsFeatureIds.const_iterator(newSelectedFeatures.constEnd()) # while i != newSelectedFeatures.constBegin(): # i = i - 1 # if layerSelectedFeatures.contains(i): # deselectedFeatures.insert(0, i) # else: # selectedFeatures.insert(0, i) for item in newSelectedFeatures: if item in layerSelectedFeatures: deselectedFeatures.insert(0, item) else: selectedFeatures.insert(0, item) vlayer.modifySelection(selectedFeatures, deselectedFeatures) else: vlayer.setSelectedFeatures(newSelectedFeatures) QApplication.restoreOverrideCursor() """
def geomTransform(self, geom, crs_orig, crs_dest): g = QgsGeometry(geom) crsTransform = QgsCoordinateTransform(crs_orig, crs_dest, QgsProject().instance()) g.transform(crsTransform) return g
def setSelectFeaturesOrRubberband_Tas(canvas, selectGeometry, doContains=True, doDifference=False, singleSelect=False): if (selectGeometry.type() != QGis.Polygon): return vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer(canvas) if (vlayer == None): return #// toLayerCoordinates will throw an exception for any 'invalid' points in #// the rubber band. #// For example, if you project a world map onto a globe using EPSG 2163 #// and then click somewhere off the globe, an exception will be thrown. selectGeomTrans = QgsGeometry(selectGeometry) if (canvas.mapSettings().hasCrsTransformEnabled()): try: ct = QgsCoordinateTransform( canvas.mapSettings().destinationCrs(), vlayer.crs()) # print selectGeomTrans.boundingBox().xMaximum () # polygonList = [] # for polygon in selectGeomTrans1.asPolygon(): # pointList = [] # for point in polygon: # transPoint = QgisHelper.CrsTransformPoint(point.x(), point.y(), define._mapCrs, vlayer.crs()) # pointList.append(transPoint) # polygonList.extend(pointList) # selectGeomTrans = QgsGeometry.fromPolygon (pointList) selectGeomTrans.transform(ct) except QgsCsException as cse: raise UserWarning, "Coordinate Transform Error in QgsMapToolSelectUtils\n" + cse.message QApplication.setOverrideCursor(Qt.WaitCursor) fit = vlayer.getFeatures(QgsFeatureRequest().setFilterRect( selectGeomTrans.boundingBox()).setFlags( QgsFeatureRequest.ExactIntersect).setSubsetOfAttributes([])) newSelectedFeatures = [] newSelectedFeatureList = [] f = QgsFeature() closestFeatureId = 0 foundSingleFeature = False closestFeatureDist = 9.0E+10 for f in fit: g = f.geometry() if (doContains): if (not selectGeomTrans.contains(g)): continue else: if (not selectGeomTrans.intersects(g)): continue if (singleSelect): foundSingleFeature = True distance = g.distance(selectGeomTrans) if (distance <= closestFeatureDist): closestFeatureDist = distance closestFeatureId = f.id() else: newSelectedFeatures.append(f.id()) newSelectedFeatureList.append(f) if (singleSelect and foundSingleFeature): newSelectedFeatures.append(closestFeatureId) featIter = vlayer.getFeatures(QgsFeatureRequest(closestFeatureId)) for feat in featIter: newSelectedFeatureList.append(feat) if (doDifference): layerSelectedFeatures = vlayer.selectedFeaturesIds() deselectedFeatures = [] selectedFeatures = [] for i in newSelectedFeatures.reverse(): if i in layerSelectedFeatures: deselectedFeatures.append(i) else: selectedFeatures.append(i) vlayer.modifySelection(selectedFeatures, deselectedFeatures) else: vlayer.setSelectedFeatures(newSelectedFeatures) QApplication.restoreOverrideCursor() return newSelectedFeatureList
def split_line_at_points( polyline_input, point_features, point_feature_id_field="id", start_node_id=None, end_node_id=None, ): """Split line at points Args: polyline (QgsPolyline): point_features (iteratable object of QgsFeature or list of dictonaries with id and geometry ('geom'): point_feature_id_field (str): fieldname if the id field of the point_features start_node_id (str or int): node id of point at begin of polyline end_node_id (str or int): node id of point at end of polyline Returns: (list of dict): Splitted polyline into parts as dictonary with: geom: Polyline geometry start_node_id: id of node at starting point of line end_node_id: id of node at end point of line distance at line: is distance of original line at the begin of this line part """ snap_points = [] source_crs = QgsCoordinateReferenceSystem(4326) dest_crs = QgsCoordinateReferenceSystem(3857) transform = QgsCoordinateTransform(source_crs, dest_crs, QgsProject.instance()) transform_back = QgsCoordinateTransform(dest_crs, source_crs, QgsProject.instance()) polyline = QgsGeometry(polyline_input) polyline.transform(transform) for point in point_features: if type(point) == QgsFeature: point = { point_feature_id_field: point[point_feature_id_field], "geom": point.geometry(), } if hasattr(point["geom"], "asPoint"): geom = point["geom"].asPoint() else: geom = point["geom"] geom = QgsGeometry.fromPointXY(geom) geom.transform(transform) geom = geom.asPoint() closest_seg = polyline.closestSegmentWithContext(geom) # get nearest point (related to the point) on the line point_on_line = closest_seg[1] point_geom_on_line = QgsPoint(point_on_line[0], point_on_line[1]) # get nr of vertex (at the end of the line where the closest point is # found end_vertex_nr = closest_seg[2] start_vertex_nr = end_vertex_nr - 1 p1 = polyline.asPolyline()[start_vertex_nr] # first vertex p2 = point_geom_on_line distance_on_subline = math.hypot(p2.x() - p1.x(), p2.y() - p1.y()) snap_points.append(( start_vertex_nr, distance_on_subline, point_geom_on_line, point[point_feature_id_field], )) # order on vertex nr and if same vertex nr on distance snap_points.sort(key=lambda x: x[1]) snap_points.sort(key=lambda x: x[0]) # create line parts line_parts = [] line_points = [] start_point_id = start_node_id total_line_distance = 0 for i, vertex in enumerate(polyline.asPolyline()): line_points.append(QgsPoint(vertex[0], vertex[1])) # get points after this vertex split_points_on_segment = [p for p in snap_points if p[0] == i] for point in split_points_on_segment: # only add another point if point is not equal to last vertex # todo: throw error when at begin or end vertex of original line? # todo: what to do of multiple points on same location? line_points.append(point[2]) geom = QgsGeometry.fromPolyline(line_points) # length, unit_type = d.convertMeasurement( # d.computeDistance(line_points), # Qgis.Meters, Qgis.Meters, False) # Qgis.Degrees length = geom.length() # add line parts line_parts.append({ "geom": geom.transform(transform_back), "start_point_id": start_point_id, "end_point_id": point[3], "distance_at_line": total_line_distance, "length": length, }) # create starting point of new line line_points = [point[2]] start_point_id = point[3] total_line_distance += length # last part of the line geom = QgsGeometry.fromPolyline(line_points) length = geom.length() # length, something = d.convertMeasurement( # d.computeDistance(line_points), # Qgis.Meters, Qgis.Meters, False) line_parts.append({ "geom": geom, "start_point_id": start_point_id, "end_point_id": end_node_id, "distance_at_line": total_line_distance, "length": length, }) return line_parts
def do_indexjoin(self, feat): '''Find the nearest neigbour using an index, if possible Parameter: feat -- The feature for which a neighbour is sought ''' infeature = feat infeatureid = infeature.id() inputgeom = QgsGeometry(infeature.geometry()) # Shall approximate input geometries be used? if self.approximateinputgeom: # Use the centroid as the input geometry inputgeom = QgsGeometry(infeature.geometry()).centroid() # Check if the coordinate systems are equal, if not, # transform the input feature! if (self.inpvl.crs() != self.joinvl.crs()): try: inputgeom.transform(QgsCoordinateTransform( self.inpvl.crs(), self.joinvl.crs())) except: import traceback self.error.emit(self.tr('CRS Transformation error!') + ' - ' + traceback.format_exc()) self.abort = True return nnfeature = None mindist = float("inf") ## Find the closest feature! if (self.approximateinputgeom or self.inpvl.wkbType() == QGis.WKBPoint or self.inpvl.wkbType() == QGis.WKBPoint25D): # The input layer's geometry type is point, or shall be # approximated to point (centroid). # Then a join index will always be used. if (self.usejoinlayerapprox or self.joinvl.wkbType() == QGis.WKBPoint or self.joinvl.wkbType() == QGis.WKBPoint25D): # The join layer's geometry type is point, or the # user wants approximate join geometries to be used. # Then the join index nearest neighbour function can # be used without refinement. if self.selfjoin: # Self join! # Have to get the two nearest neighbours nearestids = self.joinlind.nearestNeighbor( inputgeom.asPoint(), 2) if nearestids[0] == infeatureid and len(nearestids) > 1: # The first feature is the same as the input # feature, so choose the second one nnfeature = self.joinvl.getFeatures( QgsFeatureRequest(nearestids[1])).next() else: # The first feature is not the same as the # input feature, so choose it nnfeature = self.joinvl.getFeatures( QgsFeatureRequest(nearestids[0])).next() ## Pick the second closest neighbour! ## (the first is supposed to be the point itself) ## Should we check for coinciding points? #nearestid = self.joinlind.nearestNeighbor( # inputgeom.asPoint(), 2)[1] #nnfeature = self.joinvl.getFeatures( # QgsFeatureRequest(nearestid)).next() else: # Not a self join, so we can search for only the # nearest neighbour (1) nearestid = self.joinlind.nearestNeighbor( inputgeom.asPoint(), 1)[0] nnfeature = self.joinvl.getFeatures( QgsFeatureRequest(nearestid)).next() mindist = inputgeom.distance(nnfeature.geometry()) elif (self.joinvl.wkbType() == QGis.WKBPolygon or self.joinvl.wkbType() == QGis.WKBPolygon25D or self.joinvl.wkbType() == QGis.WKBLineString or self.joinvl.wkbType() == QGis.WKBLineString25D): # Use the join layer index to speed up the join when # the join layer geometry type is polygon or line # and the input layer geometry type is point or an # approximation (point) nearestindexid = self.joinlind.nearestNeighbor( inputgeom.asPoint(), 1)[0] # Check for self join if self.selfjoin and nearestindexid == infeatureid: # Self join and same feature, so get the two # first two neighbours nearestindexes = self.joinlind.nearestNeighbor( inputgeom.asPoint(), 2) nearestindexid = nearestindexes[0] if (nearestindexid == infeatureid and len(nearestindexes) > 1): nearestindexid = nearestindexes[1] nnfeature = self.joinvl.getFeatures( QgsFeatureRequest(nearestindexid)).next() mindist = inputgeom.distance(nnfeature.geometry()) px = inputgeom.asPoint().x() py = inputgeom.asPoint().y() closefids = self.joinlind.intersects(QgsRectangle( px - mindist, py - mindist, px + mindist, py + mindist)) for closefid in closefids: if self.abort is True: break # Check for self join and same feature if self.selfjoin and closefid == infeatureid: continue closef = self.joinvl.getFeatures( QgsFeatureRequest(closefid)).next() thisdistance = inputgeom.distance(closef.geometry()) if thisdistance < mindist: mindist = thisdistance nnfeature = closef if mindist == 0: break else: # Join with no index use # Go through all the features from the join layer! for inFeatJoin in self.joinf: if self.abort is True: break joingeom = QgsGeometry(inFeatJoin.geometry()) thisdistance = inputgeom.distance(joingeom) # If the distance is 0, check for equality of the # features (in case it is a self join) if (thisdistance == 0 and self.selfjoin and infeatureid == inFeatJoin.id()): continue if thisdistance < mindist: mindist = thisdistance nnfeature = inFeatJoin # For 0 distance, settle with the first feature if mindist == 0: break else: # non-simple point input geometries (could be multipoint) if (self.nonpointexactindex): # Use the spatial index on the join layer (default). # First we do an approximate search # Get the input geometry centroid centroid = QgsGeometry(infeature.geometry()).centroid() centroidgeom = centroid.asPoint() # Find the nearest neighbour (index geometries only) nearestid = self.joinlind.nearestNeighbor(centroidgeom, 1)[0] # Check for self join if self.selfjoin and nearestid == infeatureid: # Self join and same feature, so get the two # first two neighbours nearestindexes = self.joinlind.nearestNeighbor( centroidgeom, 2) nearestid = nearestindexes[0] if nearestid == infeatureid and len(nearestindexes) > 1: nearestid = nearestindexes[1] nnfeature = self.joinvl.getFeatures( QgsFeatureRequest(nearestid)).next() mindist = inputgeom.distance(nnfeature.geometry()) # Calculate the search rectangle (inputgeom BBOX inpbbox = infeature.geometry().boundingBox() minx = inpbbox.xMinimum() - mindist maxx = inpbbox.xMaximum() + mindist miny = inpbbox.yMinimum() - mindist maxy = inpbbox.yMaximum() + mindist #minx = min(inpbbox.xMinimum(), centroidgeom.x() - mindist) #maxx = max(inpbbox.xMaximum(), centroidgeom.x() + mindist) #miny = min(inpbbox.yMinimum(), centroidgeom.y() - mindist) #maxy = max(inpbbox.yMaximum(), centroidgeom.y() + mindist) searchrectangle = QgsRectangle(minx, miny, maxx, maxy) # Fetch the candidate join geometries closefids = self.joinlind.intersects(searchrectangle) # Loop through the geometries and choose the closest # one for closefid in closefids: if self.abort is True: break # Check for self join and identical feature if self.selfjoin and closefid == infeatureid: continue closef = self.joinvl.getFeatures( QgsFeatureRequest(closefid)).next() thisdistance = inputgeom.distance(closef.geometry()) if thisdistance < mindist: mindist = thisdistance nnfeature = closef if mindist == 0: break else: # Join with no index use # Check all the features of the join layer! mindist = float("inf") # should not be necessary for inFeatJoin in self.joinf: if self.abort is True: break joingeom = QgsGeometry(inFeatJoin.geometry()) thisdistance = inputgeom.distance(joingeom) # If the distance is 0, check for equality of the # features (in case it is a self join) if (thisdistance == 0 and self.selfjoin and infeatureid == inFeatJoin.id()): continue if thisdistance < mindist: mindist = thisdistance nnfeature = inFeatJoin # For 0 distance, settle with the first feature if mindist == 0: break if not self.abort: atMapA = infeature.attributes() atMapB = nnfeature.attributes() attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) attrs.append(mindist) outFeat = QgsFeature() # Use the original input layer geometry!: outFeat.setGeometry(QgsGeometry(infeature.geometry())) # Use the modified input layer geometry (could be # centroid) #outFeat.setGeometry(QgsGeometry(inputgeom)) outFeat.setAttributes(attrs) self.calculate_progress() self.features.append(outFeat)
def processAlgorithm(self, parameters, context, feedback): if DEBUG_MODE: logMessage("processAlgorithm(): {}".format( self.__class__.__name__)) source = self.parameterAsSource(parameters, self.INPUT, context) source_layer = self.parameterAsLayer(parameters, self.INPUT, context) title_field = self.parameterAsString(parameters, self.TITLE_FIELD, context) cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context) fixed_scale = self.parameterAsEnum(parameters, self.SCALE, context) # == 1 buf = self.parameterAsDouble(parameters, self.BUFFER, context) tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context) orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT, context) out_dir = self.parameterAsString(parameters, self.OUTPUT, context) mapSettings = self.controller.settings.mapSettings baseExtent = self.controller.settings.baseExtent rotation = mapSettings.rotation() orig_size = mapSettings.outputSize() if cf_filter: #TODO: FIX ME #cf_layer = QgsMemoryProviderUtils.createMemoryLayer("current feature", # source_layer.fields(), # source_layer.wkbType(), # source_layer.crs()) doc = QDomDocument("qgis") source_layer.exportNamedStyle(doc) orig_layers = mapSettings.layers() total = source.featureCount() for current, feature in enumerate(source.getFeatures()): if feedback.isCanceled(): break if cf_filter: cf_layer = QgsMemoryProviderUtils.createMemoryLayer( "current feature", source_layer.fields(), source_layer.wkbType(), source_layer.crs()) cf_layer.startEditing() cf_layer.addFeature(feature) cf_layer.commitChanges() cf_layer.importNamedStyle(doc) layers = [ cf_layer if lyr == source_layer else lyr for lyr in orig_layers ] mapSettings.setLayers(layers) title = feature.attribute(title_field) feedback.setProgressText("({}/{}) Exporting {}...".format( current + 1, total, title)) # extent geometry = QgsGeometry(feature.geometry()) geometry.transform(self.transform) center = geometry.centroid().asPoint() if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry: tex_height = orig_tex_height or int( tex_width * orig_size.height() / orig_size.width()) rect = RotatedRect(center, baseExtent.width(), baseExtent.width() * tex_height / tex_width, rotation).scale(1 + buf / 100) else: geometry.rotate(rotation, center) rect = geometry.boundingBox().scaled(1 + buf / 100) center = RotatedRect.rotatePoint(rect.center(), rotation, center) if orig_tex_height: tex_height = orig_tex_height tex_ratio = tex_width / tex_height rect_ratio = rect.width() / rect.height() if tex_ratio > rect_ratio: rect = RotatedRect(center, rect.height() * tex_ratio, rect.height(), rotation) else: rect = RotatedRect(center, rect.width(), rect.width() / tex_ratio, rotation) else: # fit to buffered geometry bounding box rect = RotatedRect(center, rect.width(), rect.height(), rotation) tex_height = tex_width * rect.height() / rect.width() rect.toMapSettings(mapSettings) mapSettings.setOutputSize(QSize(tex_width, tex_height)) self.controller.settings.setMapSettings(mapSettings) self.export(title, out_dir, feedback) feedback.setProgress(int(current / total * 100)) return {}
def in_mask(self, feature, srid=None): if feature is None: # expression overview return False if self.layer is None: return False try: # layer is not None but destroyed ? self.layer.id() except: self.reset_mask_layer() return False # mask layer empty due to unloaded memlayersaver plugin > no filtering if self.layer.featureCount() == 0: return True mask_geom, bbox = self.mask_geometry() geom = QgsGeometry(feature.geometry()) if not geom.isGeosValid(): geom = geom.buffer(0.0, 1) if geom is None: return False if srid is not None and self.layer.crs().postgisSrid() != srid: src_crs = QgsCoordinateReferenceSystem(srid) dest_crs = self.layer.crs() xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance()) try: geom.transform(xform) except: # transformation error. Check layer projection. pass if geom.type() == QgsWkbTypes.PolygonGeometry: if self.parameters.polygon_mask_method == 2 and not self.has_point_on_surface: self.parameters.polygon_mask_method = 1 if self.parameters.polygon_mask_method == 0: # this method can only work when no geometry simplification is involved return (mask_geom.overlaps(geom) or mask_geom.contains(geom)) elif self.parameters.polygon_mask_method == 1: # the fastest method, but with possible inaccuracies pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.centroid()) elif self.parameters.polygon_mask_method == 2: # will always work pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.pointOnSurface()) else: return False elif geom.type() == QgsWkbTypes.LineGeometry: if self.parameters.line_mask_method == 0: return mask_geom.intersects(geom) elif self.parameters.line_mask_method == 1: return mask_geom.contains(geom) else: return False elif geom.type() == QgsWkbTypes.PointGeometry: return mask_geom.intersects(geom) else: return False
def export_geometry_info(self): ellips = None crs = None coordTransform = None # calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if self.myCalcType == 2: settings = QSettings() ellips = settings.value("/qgis/measure/ellipsoid", "WGS84") crs = self.vlayer.crs().srsid() elif self.myCalcType == 1: mapCRS = self.parent.iface.mapCanvas().mapRenderer().destinationCrs() layCRS = self.vlayer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() nElement = 0 vprovider = self.vlayer.dataProvider() self.emit(SIGNAL("runStatus( PyQt_PyObject )"), 0) self.emit(SIGNAL("runRange( PyQt_PyObject )"), (0, vprovider.featureCount())) (fields, index1, index2) = self.checkMeasurementFields(self.vlayer, not self.writeShape) if self.writeShape: writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields, vprovider.geometryType(), vprovider.crs()) fit = vprovider.getFeatures() while fit.nextFeature(inFeat): self.emit(SIGNAL("runStatus( PyQt_PyObject )"), nElement) nElement += 1 inGeom = inFeat.geometry() if self.myCalcType == 1: inGeom.transform(coordTransform) (attr1, attr2) = self.simpleMeasure(inGeom, self.myCalcType, ellips, crs) if self.writeShape: outFeat.setGeometry(inGeom) atMap = inFeat.attributes() maxIndex = index1 if index1 > index2 else index2 if maxIndex >= len(atMap): atMap += [""] * (index2 + 1 - len(atMap)) atMap[index1] = attr1 if index1 != index2: atMap[index2] = attr2 outFeat.setAttributes(atMap) writer.addFeature(outFeat) else: changeMap = {} changeMap[inFeat.id()] = {} changeMap[inFeat.id()][index1] = attr1 if index1 != index2: changeMap[inFeat.id()][index2] = attr2 vprovider.changeAttributeValues(changeMap) self.vlayer.updateFields() if self.writeShape: del writer return True
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.PrmInputLayer, context) preserve_final_pt = self.parameterAsBool(parameters, self.PrmPreserveFinalPoint, context) min_distance = self.parameterAsDouble(parameters, self.PrmMinDistance, context) units = self.parameterAsInt(parameters, self.PrmUnitsOfMeasure, context) # Get the minimum distance in meters min_distance = min_distance * conversionToMeters(units) wkbtype = source.wkbType() num_bad = 0 if QgsWkbTypes.geometryType(wkbtype) != QgsWkbTypes.LineGeometry: feedback.reportError(tr("Please select a valid line layer.")) return({}) layercrs = source.sourceCrs() (sink, dest_id) = self.parameterAsSink( parameters, self.PrmOutputLayer, context, source.fields(), wkbtype, layercrs) 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 geom = feature.geometry() # Force the geometry to be in degrees so that we can use the geodesic algorithms if layercrs != epsg4326: results = geom.transform(transto4326) num_parts = geom.constGet().partCount() # feedback.pushInfo('num_parts {}'.format(num_parts)) try: fline = QgsFeature() fgeom = QgsGeometry() is_valid = False for part in geom.constGet().parts(): vertex_cnt = part.vertexCount() # feedback.pushInfo('vertex_cnt {}'.format(vertex_cnt)) if vertex_cnt <= 1: # line of 1 or less points is invalid continue pts = [] for vcnt, vertex in enumerate(part.vertices()): if vcnt == 0: # This is the first point so we will save it pts.append(vertex) ptLast = vertex else: ptNext = vertex gline = geod.InverseLine(ptLast.y(), ptLast.x(), ptNext.y(), ptNext.x()) if gline.s13 >= min_distance: pts.append(ptNext) ptLast = ptNext elif (vcnt == vertex_cnt - 1) and preserve_final_pt: if len(pts) >= 2: # We have two or more points already on our pts list. Check to see if # the next to last entry distance and the end point are greater than the # the minimum distance. If so replace the last entry with this one else # because the user has selected to preserve the last end point we will # accept the end point. gline = geod.InverseLine(pts[-2].y(), pts[-2].x(), ptNext.y(), ptNext.x()) if gline.s13 >= min_distance: pts[-1] = ptNext else: pts.append(ptNext) elif len(pts) == 1: # We have only the beginning point of the line and because the user has # selected that the last point to be preserved we will allow a distance less # than the minimum so that the line can be preserved. pts.append(ptNext) if len(pts) > 1: # There must be more than one point to make a valid line fgeom.addPoints(pts, QgsWkbTypes.LineGeometry) is_valid = True if is_valid: # Only save the feature if it is valid fline.setAttributes(feature.attributes()) if layercrs != epsg4326: fgeom.transform(transfrom4326) fline.setGeometry(fgeom) sink.addFeature(fline) else: num_bad += 1 except Exception: '''s = traceback.format_exc() feedback.pushInfo(s)''' num_bad += 1 feedback.setProgress(int(cnt * total)) if num_bad > 0: feedback.pushInfo(tr("{} out of {} features from input layer were invalid and were skipped.".format(num_bad, source.featureCount()))) return {self.PrmOutputLayer: dest_id}
def features(self, request=None, clipGeom=None): settings = self.writer.settings mapTo3d = settings.mapTo3d() baseExtent = settings.baseExtent baseExtentGeom = baseExtent.geometry() rotation = baseExtent.rotation() prop = self.prop useZ = prop.useZ() if useZ: srs_from = osr.SpatialReference() srs_from.ImportFromProj4(str(self.layer.crs().toProj4())) srs_to = osr.SpatialReference() srs_to.ImportFromProj4(str(self.writer.settings.crs.toProj4())) ogr_transform = osr.CreateCoordinateTransformation( srs_from, srs_to) clipGeomWkb = clipGeom.asWkb() if clipGeom else None ogr_clipGeom = ogr.CreateGeometryFromWkb( clipGeomWkb) if clipGeomWkb else None else: # z_func: function to get elevation at given point (x, y) on surface if prop.isHeightRelativeToDEM(): if self.geomType == QGis.Polygon and prop.type_index == 1: # Overlay z_func = lambda x, y: 0 else: # get elevation from DEM z_func = lambda x, y: self.writer.demProvider.readValue( x, y) else: z_func = lambda x, y: 0 request = request or QgsFeatureRequest() for f in self.layer.getFeatures(request): geometry = f.geometry() if geometry is None: logMessage("null geometry skipped") continue # coordinate transformation - layer crs to project crs geom = QgsGeometry(geometry) if geom.transform(self.transform) != 0: logMessage("Failed to transform geometry") continue # check if geometry intersects with the base extent (rotated rect) if rotation and not baseExtentGeom.intersects(geom): continue # create feature feat = Feature(self.writer, self, f) # transform_func: function to transform the map coordinates to 3d coordinates relativeHeight = prop.relativeHeight(f) def transform_func(x, y, z): return mapTo3d.transform(x, y, z + relativeHeight) if useZ: ogr_geom = ogr.CreateGeometryFromWkb(geometry.asWkb()) # transform geometry from layer CRS to project CRS if ogr_geom.Transform(ogr_transform) != 0: logMessage("Failed to transform geometry") continue # clip geometry if ogr_clipGeom and self.geomType == QGis.Line: ogr_geom = ogr_geom.Intersection(ogr_clipGeom) if ogr_geom is None: continue # check if geometry is empty if ogr_geom.IsEmpty(): logMessage("empty geometry skipped") continue feat.geom = self.geomClass.fromOgrGeometry25D( ogr_geom, transform_func) else: # clip geometry if clipGeom and self.geomType in [QGis.Line, QGis.Polygon]: geom = geom.intersection(clipGeom) if geom is None: continue # check if geometry is empty if geom.isGeosEmpty(): logMessage("empty geometry skipped") continue if self.geomType == QGis.Polygon: feat.geom = self.geomClass.fromQgsGeometry( geom, z_func, transform_func, self.hasLabel()) if prop.type_index == 1 and prop.isHeightRelativeToDEM( ): # Overlay and relative to DEM feat.geom.splitPolygon(self.writer.triangleMesh()) else: feat.geom = self.geomClass.fromQgsGeometry( geom, z_func, transform_func) if feat.geom is None: continue yield feat
def multi_buffering(layer, radii, callback=None): """Buffer a vector layer using many buffers (for volcanoes or rivers). This processing algorithm will keep the original attribute table and will add a new one for the hazard class name according to safe.definitions.fields.hazard_value_field. radii = OrderedDict() radii[500] = 'high' radii[1000] = 'medium' radii[2000] = 'low' Issue https://github.com/inasafe/inasafe/issues/3185 :param layer: The layer to polygonize. :type layer: QgsVectorLayer :param radii: A dictionary of radius. :type radii: OrderedDict :param callback: A function to all to indicate progress. The function should accept params 'current' (int), 'maximum' (int) and 'step' (str). Defaults to None. :type callback: function :return: The buffered vector layer. :rtype: QgsVectorLayer """ # Layer output output_layer_name = buffer_steps['output_layer_name'] processing_step = buffer_steps['step_name'] input_crs = layer.crs() feature_count = layer.featureCount() fields = layer.fields() # Set the new hazard class field. new_field = create_field_from_definition(hazard_class_field) fields.append(new_field) # Set the new buffer distances field. new_field = create_field_from_definition(buffer_distance_field) fields.append(new_field) buffered = create_memory_layer(output_layer_name, QGis.Polygon, input_crs, fields) data_provider = buffered.dataProvider() # Reproject features if needed into UTM if the layer is in 4326. if layer.crs().authid() == 'EPSG:4326': center = layer.extent().center() utm = QgsCoordinateReferenceSystem( get_utm_epsg(center.x(), center.y(), input_crs)) transform = QgsCoordinateTransform(layer.crs(), utm) reverse_transform = QgsCoordinateTransform(utm, layer.crs()) else: transform = None reverse_transform = None for i, feature in enumerate(layer.getFeatures()): geom = QgsGeometry(feature.geometry()) if transform: geom.transform(transform) inner_ring = None for radius in radii: attributes = feature.attributes() # We add the hazard value name to the attribute table. attributes.append(radii[radius]) # We add the value of buffer distance to the attribute table. attributes.append(radius) circle = geom.buffer(radius, 30) if inner_ring: circle.addRing(inner_ring) inner_ring = circle.asPolygon()[0] new_feature = QgsFeature() if reverse_transform: circle.transform(reverse_transform) new_feature.setGeometry(circle) new_feature.setAttributes(attributes) data_provider.addFeatures([new_feature]) if callback: callback(current=i, maximum=feature_count, step=processing_step) # We transfer keywords to the output. buffered.keywords = layer.keywords buffered.keywords['layer_geometry'] = 'polygon' buffered.keywords['layer_purpose'] = layer_purpose_hazard['key'] buffered.keywords['inasafe_fields'][hazard_class_field['key']] = ( hazard_class_field['field_name']) check_layer(buffered) return buffered
def run(self): # Converter escala textual para numérica (denominador) escala = self.escalaAvaliacao.currentText() # '1:100.000' escalaAval = escala.split(':')[1].replace('.','') escalaAval = int(escalaAval) self.canvas.zoomScale(escalaAval) listaHomologosXY = {} # dicionario yx. listaHomologosZ = {} # dicionario z. # Raio definido raio = self.spinBox.value() # Layers selecionados layer1 = self.referenciaComboBox.currentLayer() layer2 = self.avaliacaoComboBox.currentLayer() # Teste para identificar se esta setado. XY = False Z = False if self.xy.isChecked(): XY = True if self.z.isChecked(): Z = True # Troca de referência CRS para uma que utiliza medição em metros (3857). source1 = layer1.crs() source2 = layer2.crs() dest = QgsCoordinateReferenceSystem(3857) tr1 = QgsCoordinateTransform(source1, dest) tr2 = QgsCoordinateTransform(source2, dest) lista1 = [feat1 for feat1 in layer1.getFeatures()] lista2 = [feat2 for feat2 in layer2.getFeatures()] lista3 = [] spIndex1 = QgsSpatialIndex() neighbour = QgsFeature() for feat1 in lista1: spIndex1.insertFeature(feat1) # transforma features em indices espaciais geom1 = QgsGeometry(feat1.geometry()) geom1.transform(tr1) raioTeste = raio neighbour = None encontrado = False for feat2 in lista2: pt = feat2.geometry().asPoint() nearestid = spIndex1.nearestNeighbor(pt, 2)[0] # realiza a analise do vizinho mais próximo, numero de vizinhos é definido no segundo argumento. #print nearestid request = QgsFeatureRequest().setFilterFid(nearestid) geom2 = QgsGeometry(feat2.geometry()) geom2.transform(tr2) if geom1.buffer (raioTeste, 20 ) .contains (geom2): raioTeste = sqrt (geom1.asPoint (). sqrDist (geom2.asPoint ())) neighbour = feat2 encontrado = True # apenas pra descobrir se não foi encontrado. if encontrado == False: #print u'\nHouve pontos nao encontrados dentro do raio definido.' frase = ("<span style='color:purple'>HOUVE PONTOS NAO ENCONTRADOS.</span>") lista3.append(frase) else: if XY: listaHomologosXY[int(feat1.id()), int(neighbour.id())] = (raioTeste) if Z: listaHomologosZ[int(feat1.id()), int(neighbour.id())] = feat1.geometry().geometry().z() - neighbour.geometry().geometry().z() lista2.remove(neighbour) if XY or Z: #print '\nHomologos: \n', listaHomologosXY.keys() distAcum = 0 resultado2 = "<span style='color:orange'>DISTANCIA ENTRE PONTOS: </span>",[ round(v, 2) for v in listaHomologosXY.values()] resultado1 = "<span style='color:orange'>PONTOS HOMOLOGOS: </span>",listaHomologosXY.keys() #print '\nDistancia entre pontos Homologados:\n',resultado2 lista3.append(resultado1) lista3.append(resultado2) if XY: distAcum = 0 for valorXY in listaHomologosXY.values(): distAcum += valorXY resultado = int(distAcum / len(listaHomologosXY)) #print '\nDistancia media:\n', round(resultado,2) b = "<span style='color:orange'>DISTANCIA MEDIA: </span>", round(resultado,2) lista3.append(b) if Z: zAcum = 0 for valorZ in listaHomologosZ.values(): zAcum += valorZ resultado = int(zAcum / len(listaHomologosZ)) #print '\nDiferenca media de elevacao: \n', round(resultado,3) a = "<span style='color:orange'>DISTANCIA MEDIA DE ELEVACAO: </span>", round(resultado,3) lista3.append(a) # Formatação para apresentar QmessageBox de forma bem distribuida. message = u"" one_data = u"<p>{0}</p>" two_data = u"<p>{0} {1}</p>" for data in lista3: message += one_data.format(data) if type(data) == str else two_data.format(data[0], data[1]) QMessageBox.about(self, "RESULTADO: ", message )
def updateNavigationInfo(self): if self.gpsConnection is None: self.setMessage(self.tr("Cannot connect to GPS")) return try: gpsinfo = self.gpsConnection.currentGPSInformation() except RuntimeError: # if the GPS is closed in KADAS main interface, stop the navigation self.stopNavigation() return if gpsinfo is None: self.setMessage(self.tr("Cannot connect to GPS")) return layer = self.iface.activeLayer() LOG.debug("Debug: type(layer) = {}".format(type(layer))) point = QgsPointXY(gpsinfo.longitude, gpsinfo.latitude) if gpsinfo.speed > GPS_MIN_SPEED: # if we are moving, it is better for the user experience to # project the current point using the speed vector instead # of using 'point' directly, otherwise we get to feel of being # "behind the current position" qgsdistance = QgsDistanceArea() qgsdistance.setSourceCrs( QgsCoordinateReferenceSystem(4326), QgsProject.instance().transformContext(), ) qgsdistance.setEllipsoid(qgsdistance.sourceCrs().ellipsoidAcronym()) point = qgsdistance.computeSpheroidProject( point, (gpsinfo.speed / SPEED_DIVIDE_BY) * REFRESH_RATE_S, math.radians(gpsinfo.direction), ) origCrs = QgsCoordinateReferenceSystem(4326) canvasCrs = self.iface.mapCanvas().mapSettings().destinationCrs() self.transform = QgsCoordinateTransform( origCrs, canvasCrs, QgsProject.instance() ) if ( isinstance(layer, QgsVectorLayer) and layer.geometryType() == QgsWkbTypes.LineGeometry ): feature = next(layer.getFeatures(), None) if feature: geom = feature.geometry() layer = self.getOptimalRouteLayerForGeometry(geom) if layer is not None: rubbergeom = QgsGeometry(layer.geom) rubbergeom.transform(self.transform) self.rubberband.setToGeometry(rubbergeom) if hasattr(layer, "valhalla") and layer.hasRoute(): try: maneuver = layer.maneuverForPoint(point, gpsinfo.speed) self.refreshCanvas(maneuver["closest_point"], gpsinfo) LOG.debug(maneuver) except NotInRouteException: self.refreshCanvas(point, gpsinfo) self.setMessage(self.tr("You are not on the route")) return self.setWidgetsVisibility(False) html = route_html_template.format(**maneuver) self.textBrowser.setHtml(html) self.textBrowser.setFixedHeight(self.textBrowser.document().size().height()) self.setWarnings(maneuver["raw_distleft"]) # FIXME: we could have some better way of differentiating this... elif not isinstance(layer, type(None)): if layer.name() != "Routes": self.setMessage( self.tr("Select a route or waypoint layer for navigation") ) self.stopNavigation() return waypoints = self.waypointsFromLayer(self.navLayer) if waypoints: if self.waypointLayer is None: self.waypointLayer = self.navLayer self.populateWaypoints(waypoints) else: self.updateWaypoints() waypointItem = ( self.listWaypoints.currentItem() or self.listWaypoints.item(0) ) waypoint = waypointItem.point instructions = getInstructionsToWaypoint(waypoint, gpsinfo) self.setCompass(instructions["heading"], instructions["wpangle"]) html = waypoint_html_template.format(**instructions) self.textBrowser.setHtml(html) self.textBrowser.setFixedHeight( self.textBrowser.document().size().height() ) self.labelWaypointName.setText( waypoint_name_html_template.format(name=waypointItem.name) ) self.setWidgetsVisibility(True) self.setWarnings(instructions["raw_distleft"]) else: self.setMessage(self.tr("The 'Routes' layer has no waypoints.")) self.stopNavigation() return else: self.setMessage(self.tr("Select a route or waypoint layer for navigation")) self.stopNavigation() return
def reprojectGeometry(self, geom: QgsGeometry) -> QgsGeometry: if geom is not None: geom.transform(self.transformation, QgsCoordinateTransform.ForwardTransform, self.hasZ) return geom
def generateFootprintsForFilmVertical(self): self.reloadFpLayer() self.reloadCpLayer() # Error wenn nur ein punkt vorhanden if self.cpLayer.featureCount() > 1: caps = self.fpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: #Get FORM1 from FilmInfoDict f1 = self.currentFilmInfoDict["form1"] # Image height f2 = self.currentFilmInfoDict["form2"] # Image width iterFeatures = self.cpLayer.getFeatures() iterNext = self.cpLayer.getFeatures() existingFootpints = QgsVectorLayerUtils.getValues( self.fpLayer, "bildnummer")[0] ft = QgsFeature() ftNext = QgsFeature() iterNext.nextFeature(ftNext) fpFeats = [] kappasToUpdate = {} # iterate over points from CP Layer > LON, LAT i = 0 while iterFeatures.nextFeature(ft): i += 1 iterNext.nextFeature(ftNext) p = QgsPointXY(ft.geometry().asPoint()) if ft['bildnummer'] in existingFootpints: pPrevGeom = QgsGeometry(ft.geometry()) #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD'])) continue if i == 1: pPrevGeom = QgsGeometry(ftNext.geometry()) #if iterNext.isClosed(): # #use pPrev as pNext # pNext = QgsPoint(pPrev) #else: # pNext = QgsPoint(ftNext.geometry().asPoint()) #kappa = p.azimuth(pPrev) #kappa = p.azimuth(pNext) # d = math.sqrt(2*((f1/2 * ft['MASS']/1000)**2)) d1 = f1 / 2 * ft['massstab'] / 1000 d2 = f2 / 2 * ft['massstab'] / 1000 #QMessageBox.warning(None, u"Bild Nummern", "{0}".format(d)) calcCrs = QgsCoordinateReferenceSystem() calcCrs.createFromProj4(self.Proj4Utm(p)) ctF = QgsCoordinateTransform(self.cpLayer.crs(), calcCrs, QgsProject.instance()) cpMetric = QgsGeometry(ft.geometry()) cpMetric.transform(ctF) pPrevGeom.transform(ctF) pMetric = QgsPointXY(cpMetric.asPoint()) pPrevMetric = QgsPointXY(pPrevGeom.asPoint()) kappaMetric = pMetric.azimuth(pPrevMetric) pPrevGeom = QgsGeometry(ft.geometry()) left = pMetric.x() - d2 bottom = pMetric.y() - d1 right = pMetric.x() + d2 top = pMetric.y() + d1 #R = 6371 #D = (d/1000) #cpLat = math.radians(p.y()) #cpLon = math.radians(p.x()) #urLat = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*math.cos(urBrng) ) #urLon = cpLon + math.atan2(math.sin(urBrng)*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(urLat)) #top = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R) ) #bottom = math.asin( math.sin(cpLat)*math.cos(D/R) + math.cos(cpLat)*math.sin(D/R)*-1 ) #lat = math.asin( math.sin(cpLat)*math.cos(D/R) ) #right = cpLon + math.atan2(math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat)) #left = cpLon + math.atan2(-1*math.sin(D/R)*math.cos(cpLat), math.cos(D/R)-math.sin(cpLat)*math.sin(lat)) #QMessageBox.warning(None, u"Bild Nummern", "{0}, {1}, {2}, {3}".format(math.degrees(top), math.degrees(bottom), math.degrees(left), math.degrees(right))) #rect = QgsRectangle(math.degrees(left), math.degrees(bottom), math.degrees(right), math.degrees(top)) #l = math.degrees(left) #b = math.degrees(bottom) #r = math.degrees(right) #t = math.degrees(top) p1 = QgsGeometry.fromPointXY(QgsPointXY(left, bottom)) p2 = QgsGeometry.fromPointXY(QgsPointXY(right, bottom)) p3 = QgsGeometry.fromPointXY(QgsPointXY(right, top)) p4 = QgsGeometry.fromPointXY(QgsPointXY(left, top)) #p1.rotate(kappa+90, p) #p2.rotate(kappa+90, p) #p3.rotate(kappa+90, p) #p4.rotate(kappa+90, p) pol = [[ p1.asPoint(), p2.asPoint(), p3.asPoint(), p4.asPoint() ]] geom = QgsGeometry.fromPolygonXY(pol) geom.rotate(kappaMetric, pMetric) #Transform to DestinationCRS ctB = QgsCoordinateTransform(calcCrs, self.fpLayer.crs(), QgsProject.instance()) geom.transform(ctB) feat = QgsFeature(self.fpLayer.fields()) feat.setGeometry(geom) feat.setAttribute('filmnummer', self.currentFilmNumber) feat.setAttribute('bildnummer', ft['bildnummer']) da = QgsDistanceArea() da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym()) feat.setAttribute('shape_length', da.measurePerimeter(geom)) feat.setAttribute('shape_area', da.measureArea(geom)) fpFeats.append(feat) # update Kappa in cpLayer kappasToUpdate[ft.id()] = { ft.fieldNameIndex('kappa'): kappaMetric } iterFeatures.close() iterNext.close() resCAVs = self.cpLayer.dataProvider().changeAttributeValues( kappasToUpdate) QgsMessageLog.logMessage( f"Kappa Update for {kappasToUpdate}, Success: {resCAVs}", tag="APIS", level=Qgis.Success if resCAVs else Qgis.Critical) (res, outFeats) = self.fpLayer.dataProvider().addFeatures(fpFeats) self.fpLayer.updateExtents() if self.canvas.isCachingEnabled(): self.fpLayer.triggerRepaint() else: self.canvas.refresh() else: #Caps QMessageBox.warning(None, "Layer Capabilities!", "Layer Capabilities!") else: #small feature count QMessageBox.warning( None, "Footprints", "Zum Berechnen der senkrecht Footprint müssen mindestens zwei Bilder kartiert werden!" )
def processAlgorithm(self, parameters, context, feedback): if DEBUG_MODE: logMessage( "processAlgorithm(): {}".format(self.__class__.__name__), False) clayer = self.parameterAsLayer(parameters, self.INPUT, context) title_field = self.parameterAsString(parameters, self.TITLE_FIELD, context) cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context) fixed_scale = self.parameterAsEnum(parameters, self.SCALE, context) # == 1 buf = self.parameterAsDouble(parameters, self.BUFFER, context) tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context) orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT, context) header_exp = QgsExpression( self.parameterAsExpression(parameters, self.HEADER, context)) footer_exp = QgsExpression( self.parameterAsExpression(parameters, self.FOOTER, context)) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.layerScope(clayer)) out_dir = self.parameterAsString(parameters, self.OUTPUT, context) if not QDir(out_dir).exists(): QDir().mkpath(out_dir) if DEBUG_MODE: openDirectory(out_dir) mapSettings = self.controller.settings.mapSettings baseExtent = self.controller.settings.baseExtent rotation = mapSettings.rotation() orig_size = mapSettings.outputSize() if cf_filter: cf_layer = QgsMemoryProviderUtils.createMemoryLayer( "current feature", clayer.fields(), clayer.wkbType(), clayer.crs()) layers = [ cf_layer if lyr == clayer else lyr for lyr in mapSettings.layers() ] mapSettings.setLayers(layers) doc = QDomDocument("qgis") clayer.exportNamedStyle(doc) cf_layer.importNamedStyle(doc) total = clayer.featureCount() for current, feature in enumerate(clayer.getFeatures()): if feedback.isCanceled(): break if cf_filter: cf_layer.startEditing() cf_layer.deleteFeatures( [f.id() for f in cf_layer.getFeatures()]) cf_layer.addFeature(feature) cf_layer.commitChanges() title = feature.attribute(title_field) feedback.setProgressText("({}/{}) Exporting {}...".format( current + 1, total, title)) logMessage("Exporting {}...".format(title), False) # extent geometry = QgsGeometry(feature.geometry()) geometry.transform(self.transform) center = geometry.centroid().asPoint() if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry: tex_height = orig_tex_height or int( tex_width * orig_size.height() / orig_size.width()) rect = RotatedRect(center, baseExtent.width(), baseExtent.width() * tex_height / tex_width, rotation).scale(1 + buf / 100) else: geometry.rotate(rotation, center) rect = geometry.boundingBox().scaled(1 + buf / 100) center = RotatedRect.rotatePoint(rect.center(), rotation, center) if orig_tex_height: tex_height = orig_tex_height tex_ratio = tex_width / tex_height rect_ratio = rect.width() / rect.height() if tex_ratio > rect_ratio: rect = RotatedRect(center, rect.height() * tex_ratio, rect.height(), rotation) else: rect = RotatedRect(center, rect.width(), rect.width() / tex_ratio, rotation) else: # fit to buffered geometry bounding box rect = RotatedRect(center, rect.width(), rect.height(), rotation) tex_height = tex_width * rect.height() / rect.width() rect.toMapSettings(mapSettings) mapSettings.setOutputSize(QSize(tex_width, tex_height)) self.controller.settings.setMapSettings(mapSettings) # labels exp_context.setFeature(feature) self.controller.settings.setHeaderLabel( header_exp.evaluate(exp_context)) self.controller.settings.setFooterLabel( footer_exp.evaluate(exp_context)) self.export(title, out_dir, feedback) feedback.setProgress(int(current / total * 100)) if P_OPEN_DIRECTORY and not DEBUG_MODE: openDirectory(out_dir) return {}
def in_mask(self, feature, srid=None): if feature is None: # expression overview return False if self.layer is None: return False try: # layer is not None but destroyed ? self.layer.id() except: self.reset_mask_layer() return False # mask layer empty due to unloaded memlayersaver plugin > no filtering if self.layer.featureCount() == 0: return True mask_geom, bbox = self.mask_geometry() geom = QgsGeometry(feature.geometry()) if not geom.isGeosValid(): geom = geom.buffer(0.0, 1) if geom is None: return False if srid is not None and self.layer.crs().postgisSrid() != srid: src_crs = QgsCoordinateReferenceSystem(srid) dest_crs = self.layer.crs() xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance()) try: geom.transform(xform) except Exception as e: for m in e.args: QgsMessageLog.logMessage("in_mask - {}".format(m), "Extensions") # transformation error. Check layer projection. pass if geom.type() == QgsWkbTypes.PolygonGeometry: if (self.parameters.polygon_mask_method == 2 and not self.has_point_on_surface): self.parameters.polygon_mask_method = 1 if self.parameters.polygon_mask_method == 0: # this method can only work when no geometry simplification is involved return mask_geom.overlaps(geom) or mask_geom.contains(geom) elif self.parameters.polygon_mask_method == 1: # the fastest method, but with possible inaccuracies pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains( geom.centroid()) elif self.parameters.polygon_mask_method == 2: # will always work pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains( geom.pointOnSurface()) else: return False elif geom.type() == QgsWkbTypes.LineGeometry: if self.parameters.line_mask_method == 0: return mask_geom.intersects(geom) elif self.parameters.line_mask_method == 1: return mask_geom.contains(geom) else: return False elif geom.type() == QgsWkbTypes.PointGeometry: return mask_geom.intersects(geom) else: return False
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context) target_crs = self.parameterAsExtentCrs(parameters, self.TARGET_AREA, context) if self.TARGET_AREA_CRS in parameters: c = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context) if c.isValid(): target_crs = c target_geom = QgsGeometry.fromRect(extent) fields = QgsFields() fields.append(QgsField('auth_id', QVariant.String, '', 20)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) # make intersection tests nice and fast engine = QgsGeometry.createGeometryEngine(target_geom.constGet()) engine.prepareGeometry() layer_bounds = QgsGeometry.fromRect(source.sourceExtent()) crses_to_check = QgsCoordinateReferenceSystem.validSrsIds() total = 100.0 / len(crses_to_check) found_results = 0 transform_context = QgsCoordinateTransformContext() for current, srs_id in enumerate(crses_to_check): if feedback.isCanceled(): break candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id) if not candidate_crs.isValid(): continue transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs, transform_context) transformed_bounds = QgsGeometry(layer_bounds) try: if not transformed_bounds.transform(transform_candidate) == 0: continue except: continue try: if engine.intersects(transformed_bounds.constGet()): feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid())) f = QgsFeature(fields) f.setAttributes([candidate_crs.authid()]) sink.addFeature(f, QgsFeatureSink.FastInsert) found_results += 1 except: continue feedback.setProgress(int(current * total)) if found_results == 0: feedback.reportError(self.tr('No matching projections found')) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) method = self.getParameterValue(self.METHOD) geometryType = layer.geometryType() fields = layer.pendingFields() if geometryType == QGis.Polygon: areaName = vector.createUniqueFieldName('area', fields) fields.append(QgsField(areaName, QVariant.Double)) perimeterName = vector.createUniqueFieldName('perimeter', fields) fields.append(QgsField(perimeterName, QVariant.Double)) elif geometryType == QGis.Line: lengthName = vector.createUniqueFieldName('length', fields) fields.append(QgsField(lengthName, QVariant.Double)) else: xName = vector.createUniqueFieldName('xcoord', fields) fields.append(QgsField(xName, QVariant.Double)) yName = vector.createUniqueFieldName('ycoord', fields) fields.append(QgsField(yName, QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), layer.dataProvider().geometryType(), layer.crs()) ellips = None crs = None coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if method == 2: ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid', 'NONE')[0] crs = layer.crs().srsid() elif method == 1: mapCRS = iface.mapCanvas().mapRenderer().destinationCrs() layCRS = layer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) outFeat = QgsFeature() inGeom = QgsGeometry() outFeat.initAttributes(len(fields)) outFeat.setFields(fields) current = 0 features = vector.features(layer) total = 100.0 / float(len(features)) for f in features: inGeom = f.geometry() if method == 1: inGeom.transform(coordTransform) (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs) outFeat.setGeometry(inGeom) attrs = f.attributes() attrs.append(attr1) if attr2 is not None: attrs.append(attr2) outFeat.setAttributes(attrs) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def multi_buffering(layer, radii, callback=None): """Buffer a vector layer using many buffers (for volcanoes or rivers). This processing algorithm will keep the original attribute table and will add a new one for the hazard class name according to safe.definitions.fields.hazard_value_field. radii = OrderedDict() radii[500] = 'high' radii[1000] = 'medium' radii[2000] = 'low' Issue https://github.com/inasafe/inasafe/issues/3185 :param layer: The layer to polygonize. :type layer: QgsVectorLayer :param radii: A dictionary of radius. :type radii: OrderedDict :param callback: A function to all to indicate progress. The function should accept params 'current' (int), 'maximum' (int) and 'step' (str). Defaults to None. :type callback: function :return: The buffered vector layer. :rtype: QgsVectorLayer """ # Layer output output_layer_name = buffer_steps['output_layer_name'] processing_step = buffer_steps['step_name'] input_crs = layer.crs() feature_count = layer.featureCount() fields = layer.fields() # Set the new hazard class field. new_field = create_field_from_definition(hazard_class_field) fields.append(new_field) # Set the new buffer distances field. new_field = create_field_from_definition(buffer_distance_field) fields.append(new_field) buffered = create_memory_layer( output_layer_name, QGis.Polygon, input_crs, fields) data_provider = buffered.dataProvider() # Reproject features if needed into UTM if the layer is in 4326. if layer.crs().authid() == 'EPSG:4326': center = layer.extent().center() utm = QgsCoordinateReferenceSystem( get_utm_epsg(center.x(), center.y(), input_crs)) transform = QgsCoordinateTransform(layer.crs(), utm) reverse_transform = QgsCoordinateTransform(utm, layer.crs()) else: transform = None reverse_transform = None for i, feature in enumerate(layer.getFeatures()): geom = QgsGeometry(feature.geometry()) if transform: geom.transform(transform) inner_ring = None for radius in radii: attributes = feature.attributes() # We add the hazard value name to the attribute table. attributes.append(radii[radius]) # We add the value of buffer distance to the attribute table. attributes.append(radius) circle = geom.buffer(radius, 30) if inner_ring: circle.addRing(inner_ring) inner_ring = circle.asPolygon()[0] new_feature = QgsFeature() if reverse_transform: circle.transform(reverse_transform) new_feature.setGeometry(circle) new_feature.setAttributes(attributes) data_provider.addFeatures([new_feature]) if callback: callback(current=i, maximum=feature_count, step=processing_step) # We transfer keywords to the output. buffered.keywords = layer.keywords buffered.keywords['layer_geometry'] = 'polygon' buffered.keywords['layer_purpose'] = layer_purpose_hazard['key'] buffered.keywords['inasafe_fields'][hazard_class_field['key']] = ( hazard_class_field['field_name']) check_layer(buffered) return buffered
class GeometryHighlight(QgsMapCanvasItem): _mapCanvas = None # QgsMapCanvas _geometry = None # QgsGeometry() _brush = QBrush() _pen = QPen() def __init__(self, mapCanvas, geometry, layer): super(GeometryHighlight, self).__init__(mapCanvas) self._mapCanvas = mapCanvas if not geometry or not isinstance(geometry, QgsGeometry) or geometry.isEmpty() or not geometry.isGeosValid(): return self._geometry = QgsGeometry(geometry) # Force deep copy self.setLineColor(Project.highlightLineColor()) self.setFillColor(Project.highlightFillColor()) if (layer and self._mapCanvas.mapSettings().hasCrsTransformEnabled()): ct = self._mapCanvas.mapSettings().layerTransform(layer) if ct: self._geometry.transform(ct) self.updateRect() self.update() def remove(self): self._mapCanvas.scene().removeItem(self) def setLineWidth(self, width): self._pen.setWidth(width) def setLineColor(self, color): lineColor = QColor(color) lineColor.setAlpha(255) self._pen.setColor(lineColor) def setFillColor(self, fillColor): self._brush.setColor(fillColor) self._brush.setStyle(Qt.SolidPattern) def updatePosition(self): pass # protected: def paint(self, painter, option=None, widget=None): # Override if not self._geometry: return painter.setPen(self._pen) painter.setBrush(self._brush) wkbType = self._geometry.wkbType() if wkbType == QGis.WKBPoint or wkbType == QGis.WKBPoint25D: self._paintPoint(painter, self._geometry.asPoint()) elif wkbType == QGis.WKBMultiPoint or wkbType == QGis.WKBMultiPoint25D: for point in self._geometry.asMultiPoint(): self._paintPoint(painter, point) elif wkbType == QGis.WKBLineString or wkbType == QGis.WKBLineString25D: self._paintLine(painter, self._geometry.asPolyline()) elif wkbType == QGis.WKBMultiLineString or wkbType == QGis.WKBMultiLineString25D: for line in self._geometry.asMultiPolyline(): self._paintLine(painter, line) elif wkbType == QGis.WKBPolygon or wkbType == QGis.WKBPolygon25D: self._paintPolygon(painter, self._geometry.asPolygon()) elif wkbType == QGis.WKBMultiPolygon or wkbType == QGis.WKBMultiPolygon25D: for polygon in self._geometry.asMultiPolygon(): self._paintPolygon(painter, polygon) def updateRect(self): if self._geometry: r = self._geometry.boundingBox() if r.isEmpty(): d = self._mapCanvas.extent().width() * 0.005 r.setXMinimum(r.xMinimum() - d) r.setYMinimum(r.yMinimum() - d) r.setXMaximum(r.xMaximum() + d) r.setYMaximum(r.yMaximum() + d) self.setRect(r) self.setVisible(True) else: self.setRect(QgsRectangle()) # private: def _paintPoint(self, painter, point): painter.drawEllipse(self.toCanvasCoordinates(point) - self.pos(), 2, 2) def _paintLine(self, painter, line): polyline = QPolygonF() for point in line: polyline.append(self.toCanvasCoordinates(point) - self.pos()) painter.drawPolyline(polyline) def _paintPolygon(self, painter, polygon): path = QPainterPath() for line in polygon: ring = QPolygonF() for point in line: cur = self.toCanvasCoordinates(point) - self.pos() ring.append(cur) ring.append(ring[0]) path.addPolygon(ring) painter.drawPath(path)
def run(self): """Experimental impact function.""" self.validate() self.prepare() self.provenance.append_step( 'Calculating Step', 'Impact function is calculating the impact.') # Get parameters from layer's keywords self.hazard_class_attribute = self.hazard.keyword('field') self.hazard_class_mapping = self.hazard.keyword('value_map') self.exposure_class_attribute = self.exposure.keyword( 'structure_class_field') # Prepare Hazard Layer hazard_provider = self.hazard.layer.dataProvider() # Check affected field exists in the hazard layer affected_field_index = hazard_provider.fieldNameIndex( self.hazard_class_attribute) if affected_field_index == -1: message = tr( 'Field "%s" is not present in the attribute table of the ' 'hazard layer. Please change the Affected Field parameter in ' 'the IF Option.') % self.hazard_class_attribute raise GetDataError(message) srs = self.exposure.layer.crs().toWkt() exposure_provider = self.exposure.layer.dataProvider() exposure_fields = exposure_provider.fields() # Check self.exposure_class_attribute exists in exposure layer building_type_field_index = exposure_provider.fieldNameIndex( self.exposure_class_attribute) if building_type_field_index == -1: message = tr( 'Field "%s" is not present in the attribute table of ' 'the exposure layer. Please change the Building Type ' 'Field parameter in the IF Option.' ) % self.exposure_class_attribute raise GetDataError(message) # If target_field does not exist, add it: if exposure_fields.indexFromName(self.target_field) == -1: exposure_provider.addAttributes( [QgsField(self.target_field, QVariant.Int)]) target_field_index = exposure_provider.fieldNameIndex( self.target_field) exposure_fields = exposure_provider.fields() # Create layer to store the buildings from E and extent buildings_are_points = is_point_layer(self.exposure.layer) if buildings_are_points: building_layer = QgsVectorLayer( 'Point?crs=' + srs, 'impact_buildings', 'memory') else: building_layer = QgsVectorLayer( 'Polygon?crs=' + srs, 'impact_buildings', 'memory') building_provider = building_layer.dataProvider() # Set attributes building_provider.addAttributes(exposure_fields.toList()) building_layer.startEditing() building_layer.commitChanges() # Filter geometry and data using the requested extent requested_extent = QgsRectangle(*self.requested_extent) # This is a hack - we should be setting the extent CRS # in the IF base class via safe/engine/core.py:calculate_impact # for now we assume the extent is in 4326 because it # is set to that from geo_extent # See issue #1857 transform = QgsCoordinateTransform( self.requested_extent_crs, self.hazard.crs()) projected_extent = transform.transformBoundingBox(requested_extent) request = QgsFeatureRequest() request.setFilterRect(projected_extent) # Split building_layer by H and save as result: # 1) Filter from H inundated features # 2) Mark buildings as inundated (1) or not inundated (0) # make spatial index of affected polygons hazard_index = QgsSpatialIndex() hazard_geometries = {} # key = feature id, value = geometry has_hazard_objects = False for feature in self.hazard.layer.getFeatures(request): value = feature[affected_field_index] if value not in self.hazard_class_mapping[self.wet]: continue hazard_index.insertFeature(feature) hazard_geometries[feature.id()] = QgsGeometry(feature.geometry()) has_hazard_objects = True if not has_hazard_objects: message = tr( 'There are no objects in the hazard layer with %s ' 'value in %s. Please check your data or use another ' 'attribute.') % ( self.hazard_class_attribute, ', '.join(self.hazard_class_mapping[self.wet])) raise GetDataError(message) # Filter out just those EXPOSURE features in the analysis extents transform = QgsCoordinateTransform( self.requested_extent_crs, self.exposure.layer.crs()) projected_extent = transform.transformBoundingBox(requested_extent) request = QgsFeatureRequest() request.setFilterRect(projected_extent) # We will use this transform to project each exposure feature into # the CRS of the Hazard. transform = QgsCoordinateTransform( self.exposure.crs(), self.hazard.crs()) features = [] for feature in self.exposure.layer.getFeatures(request): # Make a deep copy as the geometry is passed by reference # If we don't do this, subsequent operations will affect the # original feature geometry as well as the copy TS building_geom = QgsGeometry(feature.geometry()) # Project the building geometry to hazard CRS building_bounds = transform.transform(building_geom.boundingBox()) affected = False # get tentative list of intersecting hazard features # only based on intersection of bounding boxes ids = hazard_index.intersects(building_bounds) for fid in ids: # run (slow) exact intersection test building_geom.transform(transform) if hazard_geometries[fid].intersects(building_geom): affected = True break new_feature = QgsFeature() # We write out the original feature geom, not the projected one new_feature.setGeometry(feature.geometry()) new_feature.setAttributes(feature.attributes()) new_feature[target_field_index] = 1 if affected else 0 features.append(new_feature) # every once in a while commit the created features # to the output layer if len(features) == 1000: (_, __) = building_provider.addFeatures(features) features = [] (_, __) = building_provider.addFeatures(features) building_layer.updateExtents() # Generate simple impact report self.buildings = {} self.affected_buildings = OrderedDict([ (tr('Flooded'), {}) ]) buildings_data = building_layer.getFeatures() building_type_field_index = building_layer.fieldNameIndex( self.exposure_class_attribute) for building in buildings_data: record = building.attributes() building_type = record[building_type_field_index] if building_type in [None, 'NULL', 'null', 'Null']: building_type = 'Unknown type' if building_type not in self.buildings: self.buildings[building_type] = 0 for category in self.affected_buildings.keys(): self.affected_buildings[category][ building_type] = OrderedDict([ (tr('Buildings Affected'), 0)]) self.buildings[building_type] += 1 if record[target_field_index] == 1: self.affected_buildings[tr('Flooded')][building_type][ tr('Buildings Affected')] += 1 # Lump small entries and 'unknown' into 'other' category # Building threshold #2468 postprocessors = self.parameters['postprocessors'] building_postprocessors = postprocessors['BuildingType'][0] self.building_report_threshold = building_postprocessors.value[0].value self._consolidate_to_other() impact_summary = self.html_report() # For printing map purpose map_title = tr('Buildings inundated') legend_title = tr('Structure inundated status') style_classes = [ dict(label=tr('Not Inundated'), value=0, colour='#1EFC7C', transparency=0, size=0.5), dict(label=tr('Inundated'), value=1, colour='#F31A1C', transparency=0, size=0.5)] style_info = dict( target_field=self.target_field, style_classes=style_classes, style_type='categorizedSymbol') # Convert QgsVectorLayer to inasafe layer and return it. if building_layer.featureCount() < 1: raise ZeroImpactException(tr( 'No buildings were impacted by this flood.')) extra_keywords = { 'impact_summary': impact_summary, 'map_title': map_title, 'legend_title': legend_title, 'target_field': self.target_field, 'buildings_total': self.total_buildings, 'buildings_affected': self.total_affected_buildings } self.set_if_provenance() impact_layer_keywords = self.generate_impact_keywords(extra_keywords) building_layer = Vector( data=building_layer, name=tr('Flooded buildings'), keywords=impact_layer_keywords, style_info=style_info) self._impact = building_layer return building_layer
def generateFootprintsForFilmOblique(self): self.reloadFpLayer() self.reloadCpLayer() caps = self.fpLayer.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddFeatures: if self.cpLayer.dataProvider().featureCount() > 0: iter = self.cpLayer.getFeatures() existingFootpints = QgsVectorLayerUtils.getValues( self.fpLayer, "bildnummer")[0] cpFt = QgsFeature() fpFts = [] #iterate over points from CP Layer > LON, LAT while iter.nextFeature(cpFt): if cpFt['bildnummer'] in existingFootpints: #QMessageBox.warning(None, u"Bild Nummern", u"Footprint für das Bild mit der Nummer {0} wurde bereits erstellt.".format(ft['BILD'])) continue cp = cpFt.geometry() cpMetric = QgsGeometry(cp) destCrs = QgsCoordinateReferenceSystem() destCrs.createFromProj4(self.Proj4Utm(cp.asPoint())) coordTransformF = QgsCoordinateTransform( self.cpLayer.crs(), destCrs, QgsProject.instance()) coordTransformB = QgsCoordinateTransform( destCrs, self.cpLayer.crs(), QgsProject.instance()) cpMetric.transform(coordTransformF) if cpFt['radius'] == '': r = 175 else: r = float(cpFt['radius']) fpMetric = QgsGeometry(cpMetric.buffer(r, 18)) fp = QgsGeometry(fpMetric) fp.transform(coordTransformB) fpFt = QgsFeature(self.fpLayer.fields()) fpFt.setGeometry(fp) fpFt.setAttribute("bildnummer", cpFt["bildnummer"]) fpFt.setAttribute("filmnummer", cpFt["filmnummer"]) da = QgsDistanceArea() da.setEllipsoid(self.fpLayer.crs().ellipsoidAcronym()) fpFt.setAttribute('shape_length', da.measurePerimeter(fp)) fpFt.setAttribute('shape_area', da.measureArea(fp)) fpFts.append(fpFt) (res, outFeats) = self.fpLayer.dataProvider().addFeatures(fpFts) self.fpLayer.updateExtents() if self.canvas.isCachingEnabled(): self.fpLayer.triggerRepaint() else: self.canvas.refresh() else: QMessageBox.warning( None, "Keine Bildmittelpunkte", "Keine Bildmittelpunkte für den Film {0} vorhanden.". format(self.currentFilmNumber)) else: QMessageBox.warning( None, "Layer Capabilities", "AddFeature is not enabled ({0})".format( self.fpLayer.dataProvider().capabilitiesString()))
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) method = self.getParameterValue(self.METHOD) geometryType = layer.geometryType() fields = layer.pendingFields() if geometryType == QGis.Polygon: areaName = vector.createUniqueFieldName('area', fields) fields.append(QgsField(areaName, QVariant.Double)) perimeterName = vector.createUniqueFieldName('perimeter', fields) fields.append(QgsField(perimeterName, QVariant.Double)) elif geometryType == QGis.Line: lengthName = vector.createUniqueFieldName('length', fields) fields.append(QgsField(lengthName, QVariant.Double)) else: xName = vector.createUniqueFieldName('xcoord', fields) fields.append(QgsField(xName, QVariant.Double)) yName = vector.createUniqueFieldName('ycoord', fields) fields.append(QgsField(yName, QVariant.Double)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), layer.dataProvider().geometryType(), layer.crs()) ellips = None crs = None coordTransform = None # Calculate with: # 0 - layer CRS # 1 - project CRS # 2 - ellipsoidal if method == 2: ellips = QgsProject.instance().readEntry('Measure', '/Ellipsoid', 'NONE')[0] crs = layer.crs().srsid() elif method == 1: mapCRS = iface.mapCanvas().mapSettings().destinationCrs() layCRS = layer.crs() coordTransform = QgsCoordinateTransform(layCRS, mapCRS) outFeat = QgsFeature() inGeom = QgsGeometry() outFeat.initAttributes(len(fields)) outFeat.setFields(fields) features = vector.features(layer) total = 100.0 / len(features) for current, f in enumerate(features): inGeom = f.geometry() if method == 1: inGeom.transform(coordTransform) (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs) outFeat.setGeometry(inGeom) attrs = f.attributes() attrs.append(attr1) if attr2 is not None: attrs.append(attr2) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def setSelectFeatures(canvas, selectGeometry, doContains, doDifference, singleSelect=None): """ QgsMapCanvas* canvas, QgsGeometry* selectGeometry, bool doContains, bool doDifference, bool singleSelect """ if selectGeometry.type() != QGis.Polygon: return vlayer = getCurrentVectorLayer(canvas) if vlayer == None: return #toLayerCoordinates will throw an exception for any 'invalid' points in #the rubber band. #For example, if you project a world map onto a globe using EPSG 2163 #and then click somewhere off the globe, an exception will be thrown. selectGeomTrans = QgsGeometry(selectGeometry) if canvas.mapSettings().hasCrsTransformEnabled(): try: ct = QgsCoordinateTransform(canvas.mapSettings().destinationCrs(), vlayer.crs()) selectGeomTrans.transform(ct) except QgsCsException as cse: Q_UNUSED(cse) #catch exception for 'invalid' point and leave existing selection unchanged """ QgsLogger::warning( "Caught CRS exception " + QString( __FILE__ ) + ": " + QString::number( __LINE__ ) ); QgisApp::instance()->messageBar()->pushMessage( QObject::tr( "CRS Exception" ), QObject::tr( "Selection extends beyond layer's coordinate system" ), QgsMessageBar::WARNING, QgisApp::instance()->messageTimeout() ); """ return QApplication.setOverrideCursor(Qt.WaitCursor) """ QgsDebugMsg( "Selection layer: " + vlayer->name() ); QgsDebugMsg( "Selection polygon: " + selectGeomTrans.exportToWkt() ); QgsDebugMsg( "doContains: " + QString( doContains ? "T" : "F" ) ); QgsDebugMsg( "doDifference: " + QString( doDifference ? "T" : "F" ) ); """ context = QgsRenderContext().fromMapSettings(canvas.mapSettings()) r = vlayer.rendererV2() if r: r.startRender(context, vlayer.pendingFields()) request = QgsFeatureRequest() request.setFilterRect(selectGeomTrans.boundingBox()) request.setFlags(QgsFeatureRequest.ExactIntersect) if r: request.setSubsetOfAttributes(r.usedAttributes(), vlayer.pendingFields()) else: request.setSubsetOfAttributes(QgsAttributeList) fit = vlayer.getFeatures(request) newSelectedFeatures = [] #QgsFeatureIds f = QgsFeature() closestFeatureId = 0 #QgsFeatureId foundSingleFeature = False #double closestFeatureDist = std::numeric_limits<double>::max(); closestFeatureDist = sys.float_info.max while fit.nextFeature(f): # make sure to only use features that are visible if r and not r.willRenderFeature(f): continue g = QgsGeometry(f.geometry()) if doContains: if not selectGeomTrans.contains(g): continue else: if not selectGeomTrans.intersects(g): continue if singleSelect: foundSingleFeature = True distance = float(g.distance(selectGeomTrans)) if (distance <= closestFeatureDist): closestFeatureDist = distance closestFeatureId = f.id() else: newSelectedFeatures.insert(0, f.id()) if singleSelect and foundSingleFeature: newSelectedFeatures.insert(0, closestFeatureId) if r: r.stopRender(context) #QgsDebugMsg( "Number of new selected features: " + QString::number( newSelectedFeatures.size() ) if doDifference: layerSelectedFeatures = vlayer.selectedFeaturesIds() selectedFeatures = [] #QgsFeatureIds deselectedFeatures = [] # QgsFeatureIds # i = QgsFeatureIds.const_iterator(newSelectedFeatures.constEnd()) # while i != newSelectedFeatures.constBegin(): # i = i - 1 # if layerSelectedFeatures.contains(i): # deselectedFeatures.insert(0, i) # else: # selectedFeatures.insert(0, i) for item in newSelectedFeatures: if item in layerSelectedFeatures: deselectedFeatures.insert(0, item) else: selectedFeatures.insert(0, item) vlayer.modifySelection(selectedFeatures, deselectedFeatures) else: vlayer.setSelectedFeatures(newSelectedFeatures) QApplication.restoreOverrideCursor() """