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(QGis.fromOldWkbType(layerA.wkbType())) writer = self.getOutputFromName( Difference.OUTPUT).getVectorWriter(layerA.pendingFields(), geomType, layerA.crs()) outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) total = 100.0 / len(selectionA) if len(selectionA) > 0 else 1 for current, inFeatA in enumerate(selectionA): add = True geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) attrs = inFeatA.attributes() intersections = index.intersects(geom.boundingBox()) for i in intersections: request = QgsFeatureRequest().setFilterFid(i) inFeatB = layerB.getFeatures(request).next() tmpGeom = QgsGeometry(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, progress): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT2)) ignoreNull = self.getParameterValue(Intersection.IGNORE_NULL) geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(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) if len(selectionA) > 0 else 1 for current, inFeatA in enumerate(selectionA): progress.setPercentage(int(current * total)) geom = inFeatA.geometry() if not geom: if ignoreNull: continue else: raise GeoAlgorithmExecutionException( self.tr('Input layer A contains NULL geometries. ' 'Please check "Ignore NULL geometries" ' 'if you want to run this algorithm anyway.')) if not geom.isGeosValid(): raise GeoAlgorithmExecutionException( self.tr('Input layer A contains invalid geometries ' '(feature {}). Unable to complete intersection ' 'algorithm.'.format(inFeatA.id()))) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for inFeatB in vlayerB.getFeatures(QgsFeatureRequest().setFilterFids(intersects)): tmpGeom = QgsGeometry(inFeatB.geometry()) if not geom: if ignoreNull: continue else: raise GeoAlgorithmExecutionException( self.tr('Input layer B contains NULL geometries. ' 'Please check "Ignore NULL geometries" ' 'if you want to run this algorithm anyway.')) if not geom.isGeosValid(): raise GeoAlgorithmExecutionException( self.tr('Input layer B contains invalid geometries ' '(feature {}). Unable to complete intersection ' 'algorithm.'.format(inFeatB.id()))) if geom.intersects(tmpGeom): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com is not None: int_sym = geom.symDifference(tmpGeom) if int_sym: diff_geom = int_com.difference(int_sym) int_geom = QgsGeometry(diff_geom) if int_geom.isGeosEmpty() 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) except: raise GeoAlgorithmExecutionException( self.tr('Feature geometry error: one or ' 'more output features ignored due ' 'to invalid geometry.')) del writer
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT2)) ignoreNull = self.getParameterValue(Intersection.IGNORE_NULL) geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType( 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() if not geom: if ignoreNull: continue else: raise GeoAlgorithmExecutionException( self.tr('Input layer A contains NULL geometries. ' 'Please check "Ignore NULL geometries" ' 'if you want to run this algorithm anyway.')) if not geom.isGeosValid(): raise GeoAlgorithmExecutionException( self.tr('Input layer A contains invalid geometries ' '(feature {}). Unable to complete intersection ' 'algorithm.'.format(inFeatA.id()))) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for inFeatB in vlayerB.getFeatures( QgsFeatureRequest().setFilterFids(intersects)): tmpGeom = QgsGeometry(inFeatB.geometry()) if not geom: if ignoreNull: continue else: raise GeoAlgorithmExecutionException( self.tr( 'Input layer B contains NULL geometries. ' 'Please check "Ignore NULL geometries" ' 'if you want to run this algorithm anyway.')) if not geom.isGeosValid(): raise GeoAlgorithmExecutionException( self.tr( 'Input layer B contains invalid geometries ' '(feature {}). Unable to complete intersection ' 'algorithm.'.format(inFeatB.id()))) if geom.intersects(tmpGeom): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if int_geom.wkbType( ) == QGis.WKBUnknown or QgsWKBTypes.flatType( int_geom.geometry().wkbType( )) == QgsWKBTypes.GeometryCollection: int_com = geom.combine(tmpGeom) int_geom = QgsGeometry() if int_com is not None: int_sym = geom.symDifference(tmpGeom) if int_sym: diff_geom = int_com.difference(int_sym) int_geom = QgsGeometry(diff_geom) if int_geom.isGeosEmpty() 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) except: raise GeoAlgorithmExecutionException( self.tr('Feature geometry error: one or ' 'more output features ignored due ' 'to invalid geometry.')) 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(QGis.fromOldWkbType(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(QgsGeometry(maskFeat.constGeometry())) # 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) if len(input_features) > 0 else 1 else: total = 0 for current, in_feat in enumerate(input_features): if not in_feat.constGeometry(): 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.constGeometry().geometry()): continue if not engine.contains(in_feat.constGeometry().geometry()): cur_geom = QgsGeometry(in_feat.constGeometry()) new_geom = combined_clip_geom.intersection(cur_geom) if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: int_com = in_feat.constGeometry().combine(new_geom) int_sym = in_feat.constGeometry().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 = QgsGeometry(in_feat.constGeometry()) 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 processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(self.OVERLAY)) geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(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 = QgsGeometry(featA.geometry()) diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexA.intersects(geom.boundingBox()) for i in intersects: layerB.getFeatures( QgsFeatureRequest().setFilterFid(i)).nextFeature(featB) tmpGeom = QgsGeometry(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 = QgsGeometry(featA.geometry()) diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexB.intersects(geom.boundingBox()) for i in intersects: layerA.getFeatures( QgsFeatureRequest().setFilterFid(i)).nextFeature(featB) tmpGeom = QgsGeometry(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, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(Difference.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(Difference.OVERLAY)) ignoreInvalid = self.getParameterValue(Difference.IGNORE_INVALID) geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(layerA.wkbType())) writer = self.getOutputFromName(Difference.OUTPUT).getVectorWriter( layerA.pendingFields(), 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 = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) attrs = inFeatA.attributes() intersections = index.intersects(geom.boundingBox()) for i in intersections: request = QgsFeatureRequest().setFilterFid(i) inFeatB = layerB.getFeatures(request).next() tmpGeom = QgsGeometry(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