def processAlgorithm(self, parameters, context, feedback): layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Difference.INPUT), context) layerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Difference.OVERLAY), context) geomType = QgsWkbTypes.multiType(layerA.wkbType()) writer = self.getOutputFromName( Difference.OUTPUT).getVectorWriter(layerA.fields(), geomType, layerA.crs(), context) outFeat = QgsFeature() index = QgsProcessingUtils.createSpatialIndex(layerB, context) selectionA = QgsProcessingUtils.getFeatures(layerA, context) total = 100.0 / layerA.featureCount() if layerA.featureCount() else 0 for current, inFeatA in enumerate(selectionA): geom = inFeatA.geometry() diff_geom = QgsGeometry(geom) attrs = inFeatA.attributes() intersections = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([]) for inFeatB in layerB.getFeatures(request): tmpGeom = inFeatB.geometry() if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat, QgsFeatureSink.FastInsert) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT2)) geomType = QgsWkbTypes.multiType(vlayerA.wkbType()) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs()) outFeat = QgsFeature() index = vector.spatialindex(vlayerB) selectionA = vector.features(vlayerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): progress.setPercentage(int(current * total)) geom = inFeatA.geometry() atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects) engine = None if len(intersects) > 0: # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for inFeatB in vlayerB.getFeatures(request): tmpGeom = inFeatB.geometry() if engine.intersects(tmpGeom.geometry()): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isGeosEmpty() or not int_geom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) try: if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) continue del writer
def processAlgorithm(self, parameters, context, feedback): vlayerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT2), context) geomType = QgsWkbTypes.multiType(vlayerA.wkbType()) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context) outFeat = QgsFeature() index = QgsProcessingUtils.createSpatialIndex(vlayerB, context) selectionA = QgsProcessingUtils.getFeatures(vlayerA, context) total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0 for current, inFeatA in enumerate(selectionA): feedback.setProgress(int(current * total)) geom = inFeatA.geometry() atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects) engine = None if len(intersects) > 0: # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for inFeatB in vlayerB.getFeatures(request): tmpGeom = inFeatB.geometry() if engine.intersects(tmpGeom.geometry()): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isEmpty() or not int_geom.isGeosValid(): raise GeoAlgorithmExecutionException( self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) try: if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat, QgsFeatureSink.FastInsert) except: raise GeoAlgorithmExecutionException( self.tr('Feature geometry error: One or more ' 'output features ignored due to invalid ' 'geometry.')) del writer
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(Difference.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(Difference.OVERLAY)) ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID) geomType = QgsWkbTypes.multiType(layerA.wkbType()) writer = self.getOutputFromName( Difference.OUTPUT).getVectorWriter(layerA.fields(), geomType, layerA.crs()) outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): add = True geom = inFeatA.geometry() diff_geom = QgsGeometry(geom) attrs = inFeatA.attributes() intersections = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([]) for inFeatB in layerB.getFeatures(request): tmpGeom = inFeatB.geometry() if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) if diff_geom.isGeosEmpty(): ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature with NULL geometry found.')) if not diff_geom.isGeosValid(): if ignoreInvalid: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) add = False else: raise GeoAlgorithmExecutionException(self.tr('Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag')) break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) continue progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) field_name = self.parameterAsString(parameters, self.FIELD, context) geom_type = QgsWkbTypes.multiType(source.wkbType()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), geom_type, source.sourceCrs()) index = source.fields().lookupField(field_name) collection_geom = {} collection_attrs = {} features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, feature in enumerate(features): if feedback.isCanceled(): break atMap = feature.attributes() idVar = atMap[index] if idVar in [None, NULL] or not feature.hasGeometry(): sink.addFeature(feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) continue key = str(idVar).strip() if key not in collection_geom: collection_geom[key] = [] collection_attrs[key] = atMap inGeom = feature.geometry() collection_geom[key].append(inGeom) feedback.setProgress(int(current * total)) for key, geoms in collection_geom.items(): if feedback.isCanceled(): break feature = QgsFeature() feature.setAttributes(collection_attrs[key]) feature.setGeometry(QgsGeometry.collectGeometry(geoms)) sink.addFeature(feature, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) fieldName = self.getParameterValue(self.FIELD) geomType = QgsWkbTypes.multiType(layer.wkbType()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), geomType, layer.crs(), context) outFeat = QgsFeature() inGeom = QgsGeometry() index = layer.fields().lookupField(fieldName) collection_geom = {} collection_attrs = {} features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / layer.featureCount() if layer.featureCount() else 0 for current, feature in enumerate(features): atMap = feature.attributes() idVar = atMap[index] if idVar in [None, NULL]: outFeat.setAttributes(atMap) outFeat.setGeometry(feature.geometry()) writer.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) continue key = str(idVar).strip() if key not in collection_geom: collection_geom[key] = [] collection_attrs[key] = atMap inGeom = feature.geometry() collection_geom[key].append(inGeom) feedback.setProgress(int(current * total)) for key, geoms in collection_geom.items(): outFeat.setAttributes(collection_attrs[key]) outFeat.setGeometry(QgsGeometry.collectGeometry(geoms)) writer.addFeature(outFeat, QgsFeatureSink.FastInsert) del writer
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, sourceA.fields(), geomType, sourceA.sourceCrs()) featB = QgsFeature() outFeat = QgsFeature() indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback) total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(): if feedback.isCanceled(): break if featA.hasGeometry(): geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext()) for featB in sourceB.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) else: sink.addFeature(featA, QgsFeatureSink.FastInsert) count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT)) writer = self.getOutputFromName( self.OUTPUT).getVectorWriter( layer.fields(), QgsWkbTypes.multiType(layer.wkbType()), layer.crs()) features = vector.features(layer) if len(features) == 0: raise GeoAlgorithmExecutionException(self.tr('There are no features in the input layer')) total = 100.0 / len(features) for current, inputFeature in enumerate(features): outputFeature = inputFeature if inputFeature.geometry(): outputGeometry = inputFeature.geometry().makeValid() if not outputGeometry: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, 'makeValid failed for feature {}'.format(inputFeature.id())) if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: tmpGeometries = outputGeometry.asGeometryCollection() for g in tmpGeometries: if g.type() == inputFeature.geometry().type(): try: g.convertToMultiType() outputFeature.setGeometry(QgsGeometry(g)) writer.addFeature(outputFeature) except: pass feedback.setProgress(int(current * total)) continue outputGeometry.convertToMultiType() outputFeature.setGeometry(outputGeometry) writer.addFeature(outputFeature) feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, feedback): layerA = dataobjects.getLayerFromString( self.getParameterValue(Difference.INPUT)) layerB = dataobjects.getLayerFromString( self.getParameterValue(Difference.OVERLAY)) geomType = QgsWkbTypes.multiType(layerA.wkbType()) writer = self.getOutputFromName( Difference.OUTPUT).getVectorWriter(layerA.fields(), geomType, layerA.crs()) outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): geom = inFeatA.geometry() diff_geom = QgsGeometry(geom) attrs = inFeatA.attributes() intersections = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([]) for inFeatB in layerB.getFeatures(request): tmpGeom = inFeatB.geometry() if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) continue feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs()) features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inputFeature in enumerate(features): if feedback.isCanceled(): break outputFeature = inputFeature if inputFeature.geometry(): outputGeometry = inputFeature.geometry().makeValid() if not outputGeometry: feedback.pushInfo('makeValid failed for feature {}'.format(inputFeature.id())) if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: tmpGeometries = outputGeometry.asGeometryCollection() for g in tmpGeometries: if g.type() == inputFeature.geometry().type(): try: g.convertToMultiType() outputFeature.setGeometry(QgsGeometry(g)) sink.addFeature(outputFeature, QgsFeatureSink.FastInsert) except: pass feedback.setProgress(int(current * total)) continue outputGeometry.convertToMultiType() outputFeature.setGeometry(outputGeometry) sink.addFeature(outputFeature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) fieldName = self.getParameterValue(self.FIELD) geomType = QgsWkbTypes.multiType(layer.wkbType()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), geomType, layer.crs()) outFeat = QgsFeature() inGeom = QgsGeometry() index = layer.fields().lookupField(fieldName) collection_geom = {} collection_attrs = {} features = vector.features(layer) total = 100.0 / len(features) for current, feature in enumerate(features): atMap = feature.attributes() idVar = atMap[index] key = str(idVar).strip() if not key in collection_geom: collection_geom[key] = [] collection_attrs[key] = atMap inGeom = feature.geometry() collection_geom[key].append(inGeom) progress.setPercentage(int(current * total)) for key, geoms in collection_geom.items(): outFeat.setAttributes(collection_attrs[key]) outFeat.setGeometry(QgsGeometry.collectGeometry(geoms)) writer.addFeature(outFeat) del writer
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) writer = self.getOutputFromName( self.OUTPUT).getVectorWriter(layer.fields(), QgsWkbTypes.multiType(layer.wkbType()), layer.crs(), context) features = QgsProcessingUtils.getFeatures(layer, context) if QgsProcessingUtils.featureCount(layer, context) == 0: raise GeoAlgorithmExecutionException(self.tr('There are no features in the input layer')) total = 100.0 / QgsProcessingUtils.featureCount(layer, context) for current, inputFeature in enumerate(features): outputFeature = inputFeature if inputFeature.geometry(): outputGeometry = inputFeature.geometry().makeValid() if not outputGeometry: QgsMessageLog.logMessage('makeValid failed for feature {}'.format(inputFeature.id()), self.tr('Processing'), QgsMessageLog.WARNING) if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: tmpGeometries = outputGeometry.asGeometryCollection() for g in tmpGeometries: if g.type() == inputFeature.geometry().type(): try: g.convertToMultiType() outputFeature.setGeometry(QgsGeometry(g)) writer.addFeature(outputFeature) except: pass feedback.setProgress(int(current * total)) continue outputGeometry.convertToMultiType() outputFeature.setGeometry(outputGeometry) writer.addFeature(outputFeature) feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context) fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS, context) fieldListA = QgsFields() field_indices_a = [] if len(fieldsA) > 0: for f in fieldsA: idxA = sourceA.fields().lookupField(f) if idxA >= 0: field_indices_a.append(idxA) fieldListA.append(sourceA.fields()[idxA]) else: fieldListA = sourceA.fields() field_indices_a = [i for i in range(0, fieldListA.count())] fieldListB = QgsFields() field_indices_b = [] if len(fieldsB) > 0: for f in fieldsB: idxB = sourceB.fields().lookupField(f) if idxB >= 0: field_indices_b.append(idxB) fieldListB.append(sourceB.fields()[idxB]) else: fieldListB = sourceB.fields() field_indices_b = [i for i in range(0, fieldListB.count())] fieldListB = vector.testForUniqueness(fieldListA, fieldListB) for b in fieldListB: fieldListA.append(b) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fieldListA, geomType, sourceA.sourceCrs()) outFeat = QgsFeature() indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback) total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)): if feedback.isCanceled(): break if not featA.hasGeometry(): continue geom = featA.geometry() atMapA = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects) request.setDestinationCrs(sourceA.sourceCrs()) request.setSubsetOfAttributes(field_indices_b) engine = None if len(intersects) > 0: # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for featB in sourceB.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): out_attributes = [featA.attributes()[i] for i in field_indices_a] out_attributes.extend([featB.attributes()[i] for i in field_indices_b]) int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isEmpty() or not int_geom.isGeosValid(): raise QgsProcessingException( self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) try: if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: outFeat.setGeometry(int_geom) outFeat.setAttributes(out_attributes) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: raise QgsProcessingException( self.tr('Feature geometry error: One or more ' 'output features ignored due to invalid ' 'geometry.')) count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) layerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.OVERLAY), context) geomType = QgsWkbTypes.multiType(layerA.wkbType()) fields = vector.combineVectorFields(layerA, layerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, layerA.crs(), context) featB = QgsFeature() outFeat = QgsFeature() indexA = QgsProcessingUtils.createSpatialIndex(layerB, context) indexB = QgsProcessingUtils.createSpatialIndex(layerA, context) featuresA = QgsProcessingUtils.getFeatures(layerA, context) featuresB = QgsProcessingUtils.getFeatures(layerB, context) total = 100.0 / (QgsProcessingUtils.featureCount(layerA, context) * QgsProcessingUtils.featureCount(layerB, context)) count = 0 for featA in featuresA: geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexA.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in layerB.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) length = len(layerA.fields()) for featA in featuresB: geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in layerA.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) del writer
def processAlgorithm(self, parameters, context, feedback): feature_source = self.parameterAsSource(parameters, self.INPUT, context) mask_source = self.parameterAsSource(parameters, self.OVERLAY, context) (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, feature_source.fields(), QgsWkbTypes.multiType(feature_source.wkbType()), feature_source.sourceCrs()) # first build up a list of clip geometries clip_geoms = [] for mask_feature in mask_source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(feature_source.sourceCrs())): clip_geoms.append(mask_feature.geometry()) # are we clipping against a single feature? if so, we can show finer progress reports if len(clip_geoms) > 1: combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms) single_clip_feature = False else: combined_clip_geom = clip_geoms[0] single_clip_feature = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine( combined_clip_geom.geometry()) engine.prepareGeometry() tested_feature_ids = set() for i, clip_geom in enumerate(clip_geoms): if feedback.isCanceled(): break input_features = [ f for f in feature_source.getFeatures( QgsFeatureRequest().setFilterRect(clip_geom.boundingBox())) ] if not input_features: continue if single_clip_feature: total = 100.0 / len(input_features) else: total = 0 for current, in_feat in enumerate(input_features): if feedback.isCanceled(): break if not in_feat.geometry(): continue if in_feat.id() in tested_feature_ids: # don't retest a feature we have already checked continue tested_feature_ids.add(in_feat.id()) if not engine.intersects(in_feat.geometry().geometry()): continue if not engine.contains(in_feat.geometry().geometry()): cur_geom = in_feat.geometry() new_geom = combined_clip_geom.intersection(cur_geom) if new_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( new_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: int_com = in_feat.geometry().combine(new_geom) int_sym = in_feat.geometry().symDifference(new_geom) new_geom = int_com.difference(int_sym) else: # clip geometry totally contains feature geometry, so no need to perform intersection new_geom = in_feat.geometry() try: out_feat = QgsFeature() out_feat.setGeometry(new_geom) out_feat.setAttributes(in_feat.attributes()) sink.addFeature(out_feat) except: QgsMessageLog.logMessage( self.tr('Feature geometry error: One or more ' 'output features ignored due to ' 'invalid geometry.'), self.tr('Processing'), QgsMessageLog.CRITICAL) continue if single_clip_feature: feedback.setProgress(int(current * total)) if not single_clip_feature: # coarse progress report for multiple clip geometries feedback.setProgress(100.0 * i / len(clip_geoms)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, geomType, sourceA.sourceCrs()) featB = QgsFeature() outFeat = QgsFeature() indexA = QgsSpatialIndex(sourceA, feedback) indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback) total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(): if feedback.isCanceled(): break geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) for featB in sourceB.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) length = len(sourceA.fields()) for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())): if feedback.isCanceled(): break geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexA.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in sourceA.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) line_source = self.parameterAsSource(parameters, self.LINES, context) sameLayer = parameters[self.INPUT] == parameters[self.LINES] (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs()) spatialIndex = QgsSpatialIndex() splitGeoms = {} request = QgsFeatureRequest() request.setSubsetOfAttributes([]) request.setDestinationCrs(source.sourceCrs()) for aSplitFeature in line_source.getFeatures(request): if feedback.isCanceled(): break splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry() spatialIndex.insertFeature(aSplitFeature) # honor the case that user has selection on split layer and has setting "use selection" outFeat = QgsFeature() features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 100 for current, inFeatA in enumerate(features): if feedback.isCanceled(): break inGeom = inFeatA.geometry() attrsA = inFeatA.attributes() outFeat.setAttributes(attrsA) if inGeom.isMultipart(): inGeoms = [] for g in inGeom.asGeometryCollection(): inGeoms.append(g) else: inGeoms = [inGeom] lines = spatialIndex.intersects(inGeom.boundingBox()) if len(lines) > 0: # has intersection of bounding boxes splittingLines = [] engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() for i in lines: try: splitGeom = splitGeoms[i] except: continue # check if trying to self-intersect if sameLayer: if inFeatA.id() == i: continue if engine.intersects(splitGeom.geometry()): splittingLines.append(splitGeom) if len(splittingLines) > 0: for splitGeom in splittingLines: splitterPList = None outGeoms = [] split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry()) split_geom_engine.prepareGeometry() while len(inGeoms) > 0: if feedback.isCanceled(): break inGeom = inGeoms.pop() if inGeom.isNull(): # this has been encountered and created a run-time error continue if split_geom_engine.intersects(inGeom.geometry()): inPoints = vector.extractPoints(inGeom) if splitterPList is None: splitterPList = vector.extractPoints(splitGeom) try: result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False) except: feedback.reportError(self.tr('Geometry exception while splitting')) result = 1 # splitGeometry: If there are several intersections # between geometry and splitLine, only the first one is considered. if result == 0: # split occurred if inPoints == vector.extractPoints(inGeom): # bug in splitGeometry: sometimes it returns 0 but # the geometry is unchanged outGeoms.append(inGeom) else: inGeoms.append(inGeom) for aNewGeom in newGeometries: inGeoms.append(aNewGeom) else: outGeoms.append(inGeom) else: outGeoms.append(inGeom) inGeoms = outGeoms parts = [] for aGeom in inGeoms: if feedback.isCanceled(): break passed = True if QgsWkbTypes.geometryType(aGeom.wkbType()) == QgsWkbTypes.LineGeometry: numPoints = aGeom.geometry().numPoints() if numPoints <= 2: if numPoints == 2: passed = not aGeom.geometry().isClosed() # tests if vertex 0 = vertex 1 else: passed = False # sometimes splitting results in lines of zero length if passed: parts.append(aGeom) if len(parts) > 0: outFeat.setGeometry(QgsGeometry.collectGeometry(parts)) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(self.OVERLAY)) geomType = QgsWkbTypes.multiType(layerA.wkbType()) fields = vector.combineVectorFields(layerA, layerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, geomType, layerA.crs()) featB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(layerB) indexB = vector.spatialindex(layerA) featuresA = vector.features(layerA) featuresB = vector.features(layerB) total = 100.0 / (len(featuresA) * len(featuresB)) count = 0 for featA in featuresA: add = True geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexA.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in layerB.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) if not diffGeom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) add = False break if add: try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) continue count += 1 progress.setPercentage(int(count * total)) length = len(layerA.fields()) for featA in featuresB: add = True geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in layerA.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) if not diffGeom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) add = False break if add: try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) continue count += 1 progress.setPercentage(int(count * total)) del writer
def load_complex_gml( self, xml_uri, is_remote, attributes={}, geometry_mapping=None, logger=None, swap_xy=False, ): """ :param xml_uri: the XML URI :param is_remote: True if it has to be fetched by http :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) } :param geometry_mapping: XPath expression to a gml geometry node :param swap_xy: True if X/Y coordinates must be swapped :returns: the created layer """ try: if is_remote: xml_src = remote_open_from_qgis(xml_uri) else: # Open the file in binary mode, this means returning bytes # instead of a string whose encoding would have to be interpreted # it is up to the XML parser to determine which encoding it is xml_src = open(xml_uri, "rb") src = ComplexFeatureSource(xml_src, attributes, geometry_mapping, logger) attr_list = [(k, v[1]) for k, v in attributes.items()] layers = {} features = {} for id, fid, qgsgeoms, xml, attrs in src.getFeatures(swap_xy): # layer creation if qgsgeoms == []: if "" not in layers: layer = self._create_layer("none", None, attr_list, src.title, "nogeom") self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers["nogeom"] = layer else: for (qgsgeom, srid), tag in qgsgeoms: if tag in layers: continue type2d = QgsWkbTypes.flatType(qgsgeom.wkbType()) typemap = { QgsWkbTypes.Point: "point", QgsWkbTypes.MultiPoint: "multipoint", QgsWkbTypes.LineString: "linestring", QgsWkbTypes.MultiLineString: "multilinestring", QgsWkbTypes.Polygon: "polygon", QgsWkbTypes.MultiPolygon: "multipolygon", QgsWkbTypes.CompoundCurve: "compoundcurve", QgsWkbTypes.CircularString: "compoundcurve", QgsWkbTypes.MultiCurve: "multicurve", QgsWkbTypes.CurvePolygon: "curvepolygon", QgsWkbTypes.MultiSurface: "multisurface", } if qgsgeom and type2d in typemap: title = "{} ({})".format(src.title, no_prefix(tag)) layer = self._create_layer( typemap[QgsWkbTypes.multiType(type2d)], srid, attr_list, title, no_prefix(tag), ) else: raise RuntimeError( "Unsupported geometry type {}".format( qgsgeom.wkbType())) self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers[tag] = layer # collect features f = QgsFeature(layer.dataProvider().fields(), id) f.setAttribute("id", str(id)) f.setAttribute("fid", fid) for k, v in attrs.items(): f.setAttribute(k, v) for g, tag in qgsgeoms: if tag not in features: features[tag] = [] fcopy = QgsFeature(f) fcopy.setAttribute("_xml_", ET.tostring(xml).decode("utf8")) if g: qgsgeom, _ = g if QgsWkbTypes.isMultiType(layers[tag].wkbType( )) and QgsWkbTypes.isSingleType(qgsgeom.wkbType()): # force multi qgsgeom.convertToMultiType() fcopy.setGeometry(qgsgeom) features[tag].append(fcopy) # write features for tag, f in features.items(): if len(f) > 0: layer = layers[tag] layer.startEditing() layer.addFeatures(f) layer.commitChanges() finally: xml_src.close() # Set the styl for polygons coming from boundedBy for tag_name, layer in layers.items(): if tag_name.endswith("boundedBy"): layer.loadNamedStyle( os.path.join(os.path.dirname(__file__), "..", "gui", "bounded_by_style.qml")) return layers
def processAlgorithm(self, feedback): layerA = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_A)) splitLayer = dataobjects.getLayerFromString( self.getParameterValue(self.INPUT_B)) sameLayer = self.getParameterValue( self.INPUT_A) == self.getParameterValue(self.INPUT_B) fieldList = layerA.fields() writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fieldList, QgsWkbTypes.multiType(layerA.wkbType()), layerA.crs()) spatialIndex = QgsSpatialIndex() splitGeoms = {} request = QgsFeatureRequest() request.setSubsetOfAttributes([]) for aSplitFeature in vector.features(splitLayer, request): splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry() spatialIndex.insertFeature(aSplitFeature) # honor the case that user has selection on split layer and has setting "use selection" outFeat = QgsFeature() features = vector.features(layerA) if len(features) == 0: total = 100 else: total = 100.0 / float(len(features)) for current, inFeatA in enumerate(features): inGeom = inFeatA.geometry() attrsA = inFeatA.attributes() outFeat.setAttributes(attrsA) if inGeom.isMultipart(): inGeoms = [] for g in inGeom.asGeometryCollection(): inGeoms.append(g) else: inGeoms = [inGeom] lines = spatialIndex.intersects(inGeom.boundingBox()) if len(lines) > 0: # has intersection of bounding boxes splittingLines = [] engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() for i in lines: try: splitGeom = splitGeoms[i] except: continue # check if trying to self-intersect if sameLayer: if inFeatA.id() == i: continue if engine.intersects(splitGeom.geometry()): splittingLines.append(splitGeom) if len(splittingLines) > 0: for splitGeom in splittingLines: splitterPList = None outGeoms = [] split_geom_engine = QgsGeometry.createGeometryEngine( splitGeom.geometry()) split_geom_engine.prepareGeometry() while len(inGeoms) > 0: inGeom = inGeoms.pop() if inGeom.isNull( ): # this has been encountered and created a run-time error continue if split_geom_engine.intersects(inGeom.geometry()): inPoints = vector.extractPoints(inGeom) if splitterPList is None: splitterPList = vector.extractPoints( splitGeom) try: result, newGeometries, topoTestPoints = inGeom.splitGeometry( splitterPList, False) except: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self. tr('Geometry exception while splitting' )) result = 1 # splitGeometry: If there are several intersections # between geometry and splitLine, only the first one is considered. if result == 0: # split occurred if inPoints == vector.extractPoints( inGeom): # bug in splitGeometry: sometimes it returns 0 but # the geometry is unchanged outGeoms.append(inGeom) else: inGeoms.append(inGeom) for aNewGeom in newGeometries: inGeoms.append(aNewGeom) else: outGeoms.append(inGeom) else: outGeoms.append(inGeom) inGeoms = outGeoms parts = [] for aGeom in inGeoms: passed = True if QgsWkbTypes.geometryType( aGeom.wkbType()) == QgsWkbTypes.LineGeometry: numPoints = aGeom.geometry().numPoints() if numPoints <= 2: if numPoints == 2: passed = not aGeom.geometry().isClosed( ) # tests if vertex 0 = vertex 1 else: passed = False # sometimes splitting results in lines of zero length if passed: parts.append(aGeom) if len(parts) > 0: outFeat.setGeometry(QgsGeometry.collectGeometry(parts)) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) del writer
def linearMatrix(self, parameters, context, source, inField, target_source, targetField, same_source_and_target, matType, nPoints, feedback): if same_source_and_target: # need to fetch an extra point from the index, since the closest match will always be the same # as the input feature nPoints += 1 inIdx = source.fields().lookupField(inField) outIdx = target_source.fields().lookupField(targetField) fields = QgsFields() input_id_field = source.fields()[inIdx] input_id_field.setName('InputID') fields.append(input_id_field) if matType == 0: target_id_field = target_source.fields()[outIdx] target_id_field.setName('TargetID') fields.append(target_id_field) fields.append(QgsField('Distance', QVariant.Double)) else: fields.append(QgsField('MEAN', QVariant.Double)) fields.append(QgsField('STDDEV', QVariant.Double)) fields.append(QgsField('MIN', QVariant.Double)) fields.append(QgsField('MAX', QVariant.Double)) out_wkb = QgsWkbTypes.multiType(source.wkbType()) if matType == 0 else source.wkbType() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, out_wkb, source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback) distArea = QgsDistanceArea() distArea.setSourceCrs(source.sourceCrs(), context.transformContext()) distArea.setEllipsoid(context.project().ellipsoid()) features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([inIdx])) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break inGeom = inFeat.geometry() inID = str(inFeat.attributes()[inIdx]) featList = index.nearestNeighbor(inGeom.asPoint(), nPoints) distList = [] vari = 0.0 request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext()) for outFeat in target_source.getFeatures(request): if feedback.isCanceled(): break if same_source_and_target and inFeat.id() == outFeat.id(): continue outID = outFeat.attributes()[outIdx] outGeom = outFeat.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) if matType == 0: out_feature = QgsFeature() out_geom = QgsGeometry.unaryUnion([inFeat.geometry(), outFeat.geometry()]) out_feature.setGeometry(out_geom) out_feature.setAttributes([inID, outID, dist]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) else: distList.append(float(dist)) if matType != 0: mean = sum(distList) / len(distList) for i in distList: vari += (i - mean) * (i - mean) vari = math.sqrt(vari / len(distList)) out_feature = QgsFeature() out_feature.setGeometry(inFeat.geometry()) out_feature.setAttributes([inID, mean, vari, min(distList), max(distList)]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(self.OVERLAY)) geomType = QgsWkbTypes.multiType(layerA.wkbType()) fields = vector.combineVectorFields(layerA, layerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, geomType, layerA.crs()) featB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(layerB) indexB = vector.spatialindex(layerA) featuresA = vector.features(layerA) featuresB = vector.features(layerB) total = 100.0 / (len(featuresA) * len(featuresB)) count = 0 for featA in featuresA: add = True geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexA.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) for featB in layerB.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) if not diffGeom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) add = False break if add: try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) continue count += 1 progress.setPercentage(int(count * total)) length = len(layerA.fields()) for featA in featuresB: add = True geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) for featB in layerA.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) if not diffGeom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) add = False break if add: try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) continue count += 1 progress.setPercentage(int(count * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) line_source = self.parameterAsSource(parameters, self.LINES, context) sameLayer = parameters[self.INPUT] == parameters[self.LINES] (sink, dest_id) = self.parameterAsSink( parameters, self.OUTPUT, context, source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs()) spatialIndex = QgsSpatialIndex() splitGeoms = {} request = QgsFeatureRequest() request.setSubsetOfAttributes([]) request.setDestinationCrs(source.sourceCrs()) for aSplitFeature in line_source.getFeatures(request): if feedback.isCanceled(): break splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry() spatialIndex.insertFeature(aSplitFeature) # honor the case that user has selection on split layer and has setting "use selection" outFeat = QgsFeature() features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 100 for current, inFeatA in enumerate(features): if feedback.isCanceled(): break inGeom = inFeatA.geometry() attrsA = inFeatA.attributes() outFeat.setAttributes(attrsA) if inGeom.isMultipart(): inGeoms = [] for g in inGeom.asGeometryCollection(): inGeoms.append(g) else: inGeoms = [inGeom] lines = spatialIndex.intersects(inGeom.boundingBox()) if len(lines) > 0: # has intersection of bounding boxes splittingLines = [] engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() for i in lines: try: splitGeom = splitGeoms[i] except: continue # check if trying to self-intersect if sameLayer: if inFeatA.id() == i: continue if engine.intersects(splitGeom.geometry()): splittingLines.append(splitGeom) if len(splittingLines) > 0: for splitGeom in splittingLines: splitterPList = None outGeoms = [] split_geom_engine = QgsGeometry.createGeometryEngine( splitGeom.geometry()) split_geom_engine.prepareGeometry() while len(inGeoms) > 0: if feedback.isCanceled(): break inGeom = inGeoms.pop() if inGeom.isNull( ): # this has been encountered and created a run-time error continue if split_geom_engine.intersects(inGeom.geometry()): inPoints = vector.extractPoints(inGeom) if splitterPList is None: splitterPList = vector.extractPoints( splitGeom) try: result, newGeometries, topoTestPoints = inGeom.splitGeometry( splitterPList, False) except: feedback.reportError( self. tr('Geometry exception while splitting' )) result = 1 # splitGeometry: If there are several intersections # between geometry and splitLine, only the first one is considered. if result == 0: # split occurred if inPoints == vector.extractPoints( inGeom): # bug in splitGeometry: sometimes it returns 0 but # the geometry is unchanged outGeoms.append(inGeom) else: inGeoms.append(inGeom) for aNewGeom in newGeometries: inGeoms.append(aNewGeom) else: outGeoms.append(inGeom) else: outGeoms.append(inGeom) inGeoms = outGeoms parts = [] for aGeom in inGeoms: if feedback.isCanceled(): break passed = True if QgsWkbTypes.geometryType( aGeom.wkbType()) == QgsWkbTypes.LineGeometry: numPoints = aGeom.geometry().numPoints() if numPoints <= 2: if numPoints == 2: passed = not aGeom.geometry().isClosed( ) # tests if vertex 0 = vertex 1 else: passed = False # sometimes splitting results in lines of zero length if passed: parts.append(aGeom) if len(parts) > 0: outFeat.setGeometry(QgsGeometry.collectGeometry(parts)) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context) fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS, context) fieldListA = QgsFields() field_indices_a = [] if len(fieldsA) > 0: for f in fieldsA: idxA = sourceA.fields().lookupField(f) if idxA >= 0: field_indices_a.append(idxA) fieldListA.append(sourceA.fields()[idxA]) else: fieldListA = sourceA.fields() field_indices_a = [i for i in range(0, fieldListA.count())] fieldListB = QgsFields() field_indices_b = [] if len(fieldsB) > 0: for f in fieldsB: idxB = sourceB.fields().lookupField(f) if idxB >= 0: field_indices_b.append(idxB) fieldListB.append(sourceB.fields()[idxB]) else: fieldListB = sourceB.fields() field_indices_b = [i for i in range(0, fieldListB.count())] output_fields = QgsProcessingUtils.combineFields( fieldListA, fieldListB) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, output_fields, geomType, sourceA.sourceCrs()) outFeat = QgsFeature() indexB = QgsSpatialIndex( sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(sourceA.sourceCrs())), feedback) total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1 count = 0 for featA in sourceA.getFeatures( QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)): if feedback.isCanceled(): break if not featA.hasGeometry(): continue geom = featA.geometry() atMapA = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects) request.setDestinationCrs(sourceA.sourceCrs()) request.setSubsetOfAttributes(field_indices_b) engine = None if len(intersects) > 0: # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for featB in sourceB.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): out_attributes = [ featA.attributes()[i] for i in field_indices_a ] out_attributes.extend( [featB.attributes()[i] for i in field_indices_b]) int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( int_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isEmpty() or not int_geom.isGeosValid(): raise QgsProcessingException( self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) try: if QgsWkbTypes.geometryType(int_geom.wkbType( )) == QgsWkbTypes.geometryType(geomType): int_geom.convertToMultiType() outFeat.setGeometry(int_geom) outFeat.setAttributes(out_attributes) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: raise QgsProcessingException( self.tr('Feature geometry error: One or more ' 'output features ignored due to invalid ' 'geometry.')) count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, context, feedback): layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context) layerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.OVERLAY), context) geomType = QgsWkbTypes.multiType(layerA.wkbType()) fields = vector.combineVectorFields(layerA, layerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, layerA.crs(), context) featB = QgsFeature() outFeat = QgsFeature() indexA = QgsProcessingUtils.createSpatialIndex(layerB, context) indexB = QgsProcessingUtils.createSpatialIndex(layerA, context) featuresA = QgsProcessingUtils.getFeatures(layerA, context) featuresB = QgsProcessingUtils.getFeatures(layerB, context) total = 100.0 / (QgsProcessingUtils.featureCount(layerA, context) * QgsProcessingUtils.featureCount(layerB, context)) count = 0 for featA in featuresA: geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexA.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in layerB.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) length = len(layerA.fields()) for featA in featuresB: geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) for featB in layerA.getFeatures(request): tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) del writer
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(Difference.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(Difference.OVERLAY)) ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID) geomType = QgsWkbTypes.multiType(layerA.wkbType()) writer = self.getOutputFromName(Difference.OUTPUT).getVectorWriter( layerA.fields(), geomType, layerA.crs()) outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): add = True geom = inFeatA.geometry() diff_geom = QgsGeometry(geom) attrs = inFeatA.attributes() intersections = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids( intersections).setSubsetOfAttributes([]) for inFeatB in layerB.getFeatures(request): tmpGeom = inFeatB.geometry() if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) if diff_geom.isGeosEmpty(): ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self.tr('Feature with NULL geometry found.')) if not diff_geom.isGeosValid(): if ignoreInvalid: ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) add = False else: raise GeoAlgorithmExecutionException( self. tr('Features with invalid geometries found. Please fix these errors or specify the "Ignore invalid input features" flag' )) break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) continue progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, geomType, sourceA.sourceCrs()) featA = QgsFeature() featB = QgsFeature() outFeat = QgsFeature() indexA = QgsSpatialIndex(sourceA, feedback) indexB = QgsSpatialIndex( sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(sourceA.sourceCrs())), feedback) total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount( ) and sourceB.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(): if feedback.isCanceled(): break lstIntersectingB = [] geom = featA.geometry() atMapA = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: geom.convertToMultiType() outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: # This really shouldn't happen, as we haven't # edited the input geom at all feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for featB in sourceB.getFeatures(request): atMapB = featB.attributes() tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if not int_geom: # There was a problem creating the intersection feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( int_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: int_geom.convertToMultiType() outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) sink.addFeature( outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 if QgsWkbTypes.geometryType(int_geom.wkbType( )) == QgsWkbTypes.geometryType(geomType): try: int_geom.convertToMultiType() outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) # the remaining bit of featA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( diff_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) try: diff_geom.convertToMultiType() outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) count += 1 feedback.setProgress(int(count * total)) length = len(sourceA.fields()) atMapA = [None] * length for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs( sourceA.sourceCrs())): if feedback.isCanceled(): break add = False geom = featA.geometry() diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(featA.attributes()) intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: geom.convertToMultiType() outFeat.setGeometry(geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(diff_geom.geometry()) engine.prepareGeometry() for featB in sourceA.getFeatures(request): atMapB = featB.attributes() tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) else: try: # Ihis only happens if the bounding box # intersects, but the geometry doesn't diff_geom.convertToMultiType() outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) if add: try: diff_geom.convertToMultiType() outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): expr_context = self.createExpressionContext(parameters, context, self.source) self.group_by_expr.prepare(expr_context) # Group features in memory layers source = self.source count = self.source.featureCount() if count: progress_step = 50.0 / count current = 0 groups = {} keys = [] # We need deterministic order for the tests feature = QgsFeature() for feature in self.source.getFeatures(): expr_context.setFeature(feature) group_by_value = self.evaluateExpression(self.group_by_expr, expr_context) # Get an hashable key for the dict key = group_by_value if isinstance(key, list): key = tuple(key) group = groups.get(key, None) if group is None: sink, id = QgsProcessingUtils.createFeatureSink( 'memory:', context, source.fields(), source.wkbType(), source.sourceCrs()) layer = QgsProcessingUtils.mapLayerFromString(id, context) group = { 'sink': sink, 'layer': layer, 'feature': feature } groups[key] = group keys.append(key) group['sink'].addFeature(feature, QgsFeatureSink.FastInsert) current += 1 feedback.setProgress(int(current * progress_step)) if feedback.isCanceled(): return (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, self.fields, QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs()) if sink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) # Calculate aggregates on memory layers if len(keys): progress_step = 50.0 / len(keys) for current, key in enumerate(keys): group = groups[key] expr_context = self.createExpressionContext(parameters, context) expr_context.appendScope(QgsExpressionContextUtils.layerScope(group['layer'])) expr_context.setFeature(group['feature']) geometry = self.evaluateExpression(self.geometry_expr, expr_context) if geometry is not None and not geometry.isEmpty(): geometry = QgsGeometry.unaryUnion(geometry.asGeometryCollection()) if geometry.isEmpty(): raise QgsProcessingException( 'Impossible to combine geometries for {} = {}' .format(self.group_by, group_by_value)) attrs = [] for fields_expr in self.fields_expr: attrs.append(self.evaluateExpression(fields_expr, expr_context)) # Write output feature outFeat = QgsFeature() if geometry is not None: outFeat.setGeometry(geometry) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(50 + int(current * progress_step)) if feedback.isCanceled(): return return {self.OUTPUT: dest_id}
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_A)) splitLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_B)) sameLayer = self.getParameterValue(self.INPUT_A) == self.getParameterValue(self.INPUT_B) fieldList = layerA.fields() writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList, QgsWkbTypes.multiType(layerA.wkbType()), layerA.crs()) spatialIndex = QgsSpatialIndex() splitGeoms = {} request = QgsFeatureRequest() request.setSubsetOfAttributes([]) for aSplitFeature in vector.features(splitLayer, request): splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry() spatialIndex.insertFeature(aSplitFeature) # honor the case that user has selection on split layer and has setting "use selection" outFeat = QgsFeature() features = vector.features(layerA) if len(features) == 0: total = 100 else: total = 100.0 / float(len(features)) for current, inFeatA in enumerate(features): inGeom = inFeatA.geometry() attrsA = inFeatA.attributes() outFeat.setAttributes(attrsA) if inGeom.isMultipart(): inGeoms = [] for g in inGeom.asGeometryCollection(): inGeoms.append(g) else: inGeoms = [inGeom] lines = spatialIndex.intersects(inGeom.boundingBox()) if len(lines) > 0: # has intersection of bounding boxes splittingLines = [] engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() for i in lines: try: splitGeom = splitGeoms[i] except: continue # check if trying to self-intersect if sameLayer: if inFeatA.id() == i: continue if engine.intersects(splitGeom.geometry()): splittingLines.append(splitGeom) if len(splittingLines) > 0: for splitGeom in splittingLines: splitterPList = None outGeoms = [] split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry()) split_geom_engine.prepareGeometry() while len(inGeoms) > 0: inGeom = inGeoms.pop() if inGeom.isEmpty(): # this has been encountered and created a run-time error continue if split_geom_engine.intersects(inGeom.geometry()): inPoints = vector.extractPoints(inGeom) if splitterPList == None: splitterPList = vector.extractPoints(splitGeom) try: result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False) except: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Geometry exception while splitting')) result = 1 # splitGeometry: If there are several intersections # between geometry and splitLine, only the first one is considered. if result == 0: # split occurred if inPoints == vector.extractPoints(inGeom): # bug in splitGeometry: sometimes it returns 0 but # the geometry is unchanged outGeoms.append(inGeom) else: inGeoms.append(inGeom) for aNewGeom in newGeometries: inGeoms.append(aNewGeom) else: outGeoms.append(inGeom) else: outGeoms.append(inGeom) inGeoms = outGeoms parts = [] for aGeom in inGeoms: passed = True if QgsWkbTypes.geometryType( aGeom.wkbType() ) == QgsWkbTypes.LineGeometry: numPoints = aGeom.geometry().numPoints() if numPoints <= 2: if numPoints == 2: passed = not aGeom.geometry().isClosed() # tests if vertex 0 = vertex 1 else: passed = False # sometimes splitting results in lines of zero length if passed: parts.append(aGeom) if len(parts) > 0: outFeat.setGeometry(QgsGeometry.collectGeometry(parts)) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, feedback): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT2)) geomType = QgsWkbTypes.multiType(vlayerA.wkbType()) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, geomType, vlayerA.crs()) outFeat = QgsFeature() index = vector.spatialindex(vlayerB) selectionA = vector.features(vlayerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): feedback.setProgress(int(current * total)) geom = inFeatA.geometry() atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects) engine = None if len(intersects) > 0: # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for inFeatB in vlayerB.getFeatures(request): tmpGeom = inFeatB.geometry() if engine.intersects(tmpGeom.geometry()): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( int_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isGeosEmpty() or not int_geom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) try: if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[ int_geom.wkbType()]]: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) continue del writer
def processAlgorithm(self, progress): source_layer = dataobjects.getObjectFromUri( self.getParameterValue(Clip.INPUT)) mask_layer = dataobjects.getObjectFromUri( self.getParameterValue(Clip.OVERLAY)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( source_layer.fields(), QgsWkbTypes.multiType(source_layer.wkbType()), source_layer.crs()) # first build up a list of clip geometries clip_geoms = [] for maskFeat in vector.features(mask_layer, QgsFeatureRequest().setSubsetOfAttributes([])): clip_geoms.append(maskFeat.geometry()) # are we clipping against a single feature? if so, we can show finer progress reports if len(clip_geoms) > 1: combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms) single_clip_feature = False else: combined_clip_geom = clip_geoms[0] single_clip_feature = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(combined_clip_geom.geometry()) engine.prepareGeometry() tested_feature_ids = set() for i, clip_geom in enumerate(clip_geoms): input_features = [f for f in vector.features(source_layer, QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))] if not input_features: continue if single_clip_feature: total = 100.0 / len(input_features) else: total = 0 for current, in_feat in enumerate(input_features): if not in_feat.geometry(): continue if in_feat.id() in tested_feature_ids: # don't retest a feature we have already checked continue tested_feature_ids.add(in_feat.id()) if not engine.intersects(in_feat.geometry().geometry()): continue if not engine.contains(in_feat.geometry().geometry()): cur_geom = in_feat.geometry() new_geom = combined_clip_geom.intersection(cur_geom) if new_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(new_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: int_com = in_feat.geometry().combine(new_geom) int_sym = in_feat.geometry().symDifference(new_geom) if not int_com or not int_sym: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more ' 'input features have invalid geometry.')) else: new_geom = int_com.difference(int_sym) if new_geom.isGeosEmpty() or not new_geom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more ' 'input features have invalid geometry.')) else: # clip geometry totally contains feature geometry, so no need to perform intersection new_geom = in_feat.geometry() try: out_feat = QgsFeature() out_feat.setGeometry(new_geom) out_feat.setAttributes(in_feat.attributes()) writer.addFeature(out_feat) except: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('Feature geometry error: One or more ' 'output features ignored due to ' 'invalid geometry.')) continue if single_clip_feature: progress.setPercentage(int(current * total)) if not single_clip_feature: # coarse progress report for multiple clip geometries progress.setPercentage(100.0 * i / len(clip_geoms)) del writer
def load_complex_gml(self, xml_uri, is_remote, attributes = {}, geometry_mapping = None, logger = None, swap_xy = False): """ :param xml_uri: the XML URI :param is_remote: True if it has to be fetched by http :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) } :param geometry_mapping: XPath expression to a gml geometry node :param swap_xy: True if X/Y coordinates must be swapped :returns: the created layer """ try: if is_remote: xml_src = remote_open_from_qgis(xml_uri) else: # Open the file in binary mode, this means returning bytes # instead of a string whose encoding would have to be interpreted # it is up to the XML parser to determine which encoding it is xml_src = open(xml_uri, 'rb') src = ComplexFeatureSource(xml_src, attributes, geometry_mapping, logger) attr_list = [ (k, v[1]) for k, v in attributes.items() ] layers = {} features = {} layer_geom_type = {} for id, fid, qgsgeoms, xml, attrs in src.getFeatures(swap_xy): # layer creation if qgsgeoms == []: if "" not in layers: layer = self._create_layer('none', None, attr_list, src.title, "nogeom") self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers["nogeom"] = layer else: for (qgsgeom, srid), tag in qgsgeoms: if tag in layers: continue type2d = QgsWkbTypes.flatType(qgsgeom.wkbType()) typemap = {QgsWkbTypes.Point: 'point', QgsWkbTypes.MultiPoint: 'multipoint', QgsWkbTypes.LineString: 'linestring', QgsWkbTypes.MultiLineString: 'multilinestring', QgsWkbTypes.Polygon: 'polygon', QgsWkbTypes.MultiPolygon: 'multipolygon', QgsWkbTypes.CompoundCurve: 'compoundcurve', QgsWkbTypes.CircularString: 'compoundcurve', QgsWkbTypes.MultiCurve: 'multicurve', QgsWkbTypes.CurvePolygon: 'curvepolygon', QgsWkbTypes.MultiSurface: 'multisurface'} if qgsgeom and type2d in typemap: title = "{} ({})".format(src.title, no_prefix(tag)) layer = self._create_layer(typemap[QgsWkbTypes.multiType(type2d)], srid, attr_list, title, no_prefix(tag)) else: raise RuntimeError("Unsupported geometry type {}".format(qgsgeom.wkbType())) self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) layers[tag] = layer # collect features f = QgsFeature(layer.dataProvider().fields(), id) f.setAttribute("id", str(id)) f.setAttribute("fid", fid) for k, v in attrs.items(): r = f.setAttribute(k, v) for g, tag in qgsgeoms: if tag not in features: features[tag] = [] fcopy = QgsFeature(f) fcopy.setAttribute("_xml_", ET.tostring(xml).decode('utf8')) if g: qgsgeom, _ = g if QgsWkbTypes.isMultiType(layers[tag].wkbType()) and QgsWkbTypes.isSingleType(qgsgeom.wkbType()): # force multi qgsgeom.convertToMultiType() fcopy.setGeometry(qgsgeom) features[tag].append(fcopy) # write features for tag, f in features.items(): if len(f) > 0: layer = layers[tag] layer.startEditing() layer.addFeatures(f) layer.commitChanges() finally: xml_src.close() # Set the styl for polygons coming from boundedBy for tag_name, layer in layers.items(): if tag_name.endswith("boundedBy"): layer.loadNamedStyle(os.path.join(os.path.dirname(__file__), "..", "gui", "bounded_by_style.qml")) return layers
def processAlgorithm(self, feedback): source_layer = dataobjects.getObjectFromUri( self.getParameterValue(Clip.INPUT)) mask_layer = dataobjects.getObjectFromUri( self.getParameterValue(Clip.OVERLAY)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( source_layer.fields(), QgsWkbTypes.multiType(source_layer.wkbType()), source_layer.crs()) # first build up a list of clip geometries clip_geoms = [] for maskFeat in vector.features( mask_layer, QgsFeatureRequest().setSubsetOfAttributes([])): clip_geoms.append(maskFeat.geometry()) # are we clipping against a single feature? if so, we can show finer progress reports if len(clip_geoms) > 1: combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms) single_clip_feature = False else: combined_clip_geom = clip_geoms[0] single_clip_feature = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine( combined_clip_geom.geometry()) engine.prepareGeometry() tested_feature_ids = set() for i, clip_geom in enumerate(clip_geoms): input_features = [ f for f in vector.features( source_layer, QgsFeatureRequest().setFilterRect(clip_geom.boundingBox())) ] if not input_features: continue if single_clip_feature: total = 100.0 / len(input_features) else: total = 0 for current, in_feat in enumerate(input_features): if not in_feat.geometry(): continue if in_feat.id() in tested_feature_ids: # don't retest a feature we have already checked continue tested_feature_ids.add(in_feat.id()) if not engine.intersects(in_feat.geometry().geometry()): continue if not engine.contains(in_feat.geometry().geometry()): cur_geom = in_feat.geometry() new_geom = combined_clip_geom.intersection(cur_geom) if new_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( new_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: int_com = in_feat.geometry().combine(new_geom) int_sym = in_feat.geometry().symDifference(new_geom) new_geom = int_com.difference(int_sym) else: # clip geometry totally contains feature geometry, so no need to perform intersection new_geom = in_feat.geometry() try: out_feat = QgsFeature() out_feat.setGeometry(new_geom) out_feat.setAttributes(in_feat.attributes()) writer.addFeature(out_feat) except: ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self.tr('Feature geometry error: One or more ' 'output features ignored due to ' 'invalid geometry.')) continue if single_clip_feature: feedback.setProgress(int(current * total)) if not single_clip_feature: # coarse progress report for multiple clip geometries feedback.setProgress(100.0 * i / len(clip_geoms)) del writer
def linearMatrix(self, parameters, context, source, inField, target_source, targetField, same_source_and_target, matType, nPoints, feedback): if same_source_and_target: # need to fetch an extra point from the index, since the closest match will always be the same # as the input feature nPoints += 1 inIdx = source.fields().lookupField(inField) outIdx = target_source.fields().lookupField(targetField) fields = QgsFields() input_id_field = source.fields()[inIdx] input_id_field.setName('InputID') fields.append(input_id_field) if matType == 0: target_id_field = target_source.fields()[outIdx] target_id_field.setName('TargetID') fields.append(target_id_field) fields.append(QgsField('Distance', QVariant.Double)) else: fields.append(QgsField('MEAN', QVariant.Double)) fields.append(QgsField('STDDEV', QVariant.Double)) fields.append(QgsField('MIN', QVariant.Double)) fields.append(QgsField('MAX', QVariant.Double)) out_wkb = QgsWkbTypes.multiType( source.wkbType()) if matType == 0 else source.wkbType() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, out_wkb, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) index = QgsSpatialIndex( target_source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback) distArea = QgsDistanceArea() distArea.setSourceCrs(source.sourceCrs(), context.transformContext()) distArea.setEllipsoid(context.project().ellipsoid()) features = source.getFeatures( QgsFeatureRequest().setSubsetOfAttributes([inIdx])) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break inGeom = inFeat.geometry() inID = str(inFeat[inIdx]) featList = index.nearestNeighbor(inGeom.asPoint(), nPoints) distList = [] vari = 0.0 request = QgsFeatureRequest().setFilterFids( featList).setSubsetOfAttributes([outIdx]).setDestinationCrs( source.sourceCrs(), context.transformContext()) for outFeat in target_source.getFeatures(request): if feedback.isCanceled(): break if same_source_and_target and inFeat.id() == outFeat.id(): continue outID = outFeat[outIdx] outGeom = outFeat.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) if matType == 0: out_feature = QgsFeature() out_geom = QgsGeometry.unaryUnion( [inFeat.geometry(), outFeat.geometry()]) out_feature.setGeometry(out_geom) out_feature.setAttributes([inID, outID, dist]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) else: distList.append(float(dist)) if matType != 0: mean = sum(distList) / len(distList) for i in distList: vari += (i - mean) * (i - mean) vari = math.sqrt(vari / len(distList)) out_feature = QgsFeature() out_feature.setGeometry(inFeat.geometry()) out_feature.setAttributes( [inID, mean, vari, min(distList), max(distList)]) sink.addFeature(out_feature, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fields = vector.combineFields(sourceA.fields(), sourceB.fields()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, geomType, sourceA.sourceCrs()) featA = QgsFeature() featB = QgsFeature() outFeat = QgsFeature() indexA = QgsSpatialIndex(sourceA, feedback) indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback) total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(): if feedback.isCanceled(): break lstIntersectingB = [] geom = featA.geometry() atMapA = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: # This really shouldn't happen, as we haven't # edited the input geom at all feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for featB in sourceB.getFeatures(request): atMapB = featB.attributes() tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if not int_geom: # There was a problem creating the intersection feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) # the remaining bit of featA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(diff_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) count += 1 feedback.setProgress(int(count * total)) length = len(sourceA.fields()) atMapA = [None] * length for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())): if feedback.isCanceled(): break add = False geom = featA.geometry() diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(featA.attributes()) intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(diff_geom.geometry()) engine.prepareGeometry() for featB in sourceA.getFeatures(request): atMapB = featB.attributes() tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) else: try: # Ihis only happens if the bounding box # intersects, but the geometry doesn't outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): vlayerA = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT), context) vlayerB = QgsProcessingUtils.mapLayerFromString( self.getParameterValue(self.INPUT2), context) geomType = QgsWkbTypes.multiType(vlayerA.wkbType()) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, geomType, vlayerA.crs(), context) outFeat = QgsFeature() index = QgsProcessingUtils.createSpatialIndex(vlayerB, context) selectionA = QgsProcessingUtils.getFeatures(vlayerA, context) total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0 for current, inFeatA in enumerate(selectionA): feedback.setProgress(int(current * total)) geom = inFeatA.geometry() atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids(intersects) engine = None if len(intersects) > 0: # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for inFeatB in vlayerB.getFeatures(request): tmpGeom = inFeatB.geometry() if engine.intersects(tmpGeom.geometry()): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType( ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType( int_geom.geometry().wkbType( )) == QgsWkbTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isEmpty() or not int_geom.isGeosValid(): raise GeoAlgorithmExecutionException( self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) try: if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[ int_geom.wkbType()]]: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat, QgsFeatureSink.FastInsert) except: raise GeoAlgorithmExecutionException( self.tr('Feature geometry error: One or more ' 'output features ignored due to invalid ' 'geometry.')) del writer