def __init__(self, table, parent=None): TableDataModel.__init__(self, table, parent) self.layer = None if isinstance(table, LVectorTable): self.layer = VLayerRegistry.instance().getLayer(table.name) else: self.layer = VLayerRegistry.instance().getLayer(table) if not self.layer: return # populate self.resdata self.resdata = [] for f in self.layer.getFeatures(): a = f.attributes() # add the geometry type if f.geometry(): a.append(QgsWKBTypes.displayString(QGis.fromOldWkbType(f.geometry().wkbType()))) else: a.append('None') self.resdata.append(a) self.fetchedFrom = 0 self.fetchedCount = len(self.resdata)
def testWriteShapefileWithZ(self): """Check writing geometries with Z dimension to an ESRI shapefile.""" #start by saving a memory layer and forcing z ml = QgsVectorLayer( ('Point?crs=epsg:4326&field=id:int'), 'test', 'memory') assert ml is not None, 'Provider not initialized' assert ml.isValid(), 'Source layer not valid' provider = ml.dataProvider() assert provider is not None ft = QgsFeature() ft.setGeometry(QgsGeometry.fromWkt('PointZ (1 2 3)')) ft.setAttributes([1]) res, features = provider.addFeatures([ft]) assert res assert len(features) > 0 # check with both a standard PointZ and 25d style Point25D type for t in [QgsWKBTypes.PointZ, QgsWKBTypes.Point25D]: dest_file_name = os.path.join(str(QDir.tempPath()), 'point_{}.shp'.format(QgsWKBTypes.displayString(t))) print(dest_file_name) crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile', overrideGeometryType=t) self.assertEqual(write_result, QgsVectorFileWriter.NoError) # Open result and check created_layer = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr') f = created_layer.getFeatures(QgsFeatureRequest()).next() g = f.geometry() wkt = g.exportToWkt() expWkt = 'PointZ (1 2 3)' assert compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt) #also try saving out the shapefile version again, as an extra test #this tests that saving a layer with z WITHOUT explicitly telling the writer to keep z values, #will stay retain the z values dest_file_name = os.path.join(str(QDir.tempPath()), 'point_{}_copy.shp'.format(QgsWKBTypes.displayString(t))) print(dest_file_name) crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result = QgsVectorFileWriter.writeAsVectorFormat( created_layer, dest_file_name, 'utf-8', crs, 'ESRI Shapefile') self.assertEqual(write_result, QgsVectorFileWriter.NoError) # Open result and check created_layer_from_shp = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr') f = created_layer_from_shp.getFeatures(QgsFeatureRequest()).next() g = f.geometry() wkt = g.exportToWkt() assert compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)
def testWriteShapefileWithZ(self): """Check writing geometries with Z dimension to an ESRI shapefile.""" #start by saving a memory layer and forcing z ml = QgsVectorLayer( ('Point?crs=epsg:4326&field=id:int'), 'test', 'memory') assert ml is not None, 'Provider not initialized' assert ml.isValid(), 'Source layer not valid' provider = ml.dataProvider() assert provider is not None ft = QgsFeature() ft.setGeometry(QgsGeometry.fromWkt('PointZ (1 2 3)')) ft.setAttributes([1]) res, features = provider.addFeatures([ft]) assert res assert len(features) > 0 # check with both a standard PointZ and 25d style Point25D type for t in [QgsWKBTypes.PointZ, QgsWKBTypes.Point25D]: dest_file_name = os.path.join(str(QDir.tempPath()), 'point_{}.shp'.format(QgsWKBTypes.displayString(t))) crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile', overrideGeometryType=t) self.assertEqual(write_result, QgsVectorFileWriter.NoError) # Open result and check created_layer = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr') f = next(created_layer.getFeatures(QgsFeatureRequest())) g = f.geometry() wkt = g.exportToWkt() expWkt = 'PointZ (1 2 3)' assert compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt) #also try saving out the shapefile version again, as an extra test #this tests that saving a layer with z WITHOUT explicitly telling the writer to keep z values, #will stay retain the z values dest_file_name = os.path.join(str(QDir.tempPath()), 'point_{}_copy.shp'.format(QgsWKBTypes.displayString(t))) crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result = QgsVectorFileWriter.writeAsVectorFormat( created_layer, dest_file_name, 'utf-8', crs, 'ESRI Shapefile') self.assertEqual(write_result, QgsVectorFileWriter.NoError) # Open result and check created_layer_from_shp = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr') f = next(created_layer_from_shp.getFeatures(QgsFeatureRequest())) g = f.geometry() wkt = g.exportToWkt() assert compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)
def run(self): """Run method that performs all the real work""" self.remove_result_layers(remove_all=True, delete_source=True) layers = self.iface.legendInterface().layers() if not layers: print_log( "Tool afgebroken! Geen layers gevonden. Voeg eerst layers toe", "e", self.iface) return layer_points, layer_lines, layer_polygons = [], [], [] if b_QgsWKBTypes: for i, layer in enumerate(layers): if hasattr(layer, "wkbType"): # qgis.core.QgsWKBTypes.displayString(int(vl.wkbType())) if "point" in QgsWKBTypes.displayString( int(layer.wkbType())).lower(): ## QGis.WKBPoint: layer_points.append(layer) elif "line" in QgsWKBTypes.displayString( int(layer.wkbType())).lower( ): ##QGis.WKBLineString: layer_lines.append(layer) elif "polygon" in QgsWKBTypes.displayString( int(layer.wkbType())).lower(): ##QGis.WKBPolygon: layer_polygons.append(layer) else: pass layer_1 = layer_points[:] # more on slicing: https://www.afternerd.com/blog/python-copy-list/ layer_2 = layer_lines[:] layer_3 = layer_points[:] layer_4 = layer_points[:] layer_5 = layer_polygons[:] layer_6 = layer_polygons[:] layer_7 = layer_polygons[:] else: print_log( "ImportError for QgsWKBTypes. Kan geen geometrie herkennen voor layer inputs. \ Controleer of juiste layers zijn geselecteerd of upgrade QGIS.", "w", self.iface) layer_points = layer_lines = layer_polygons = layers layer_1 = layers[:] layer_2 = layers[:] layer_3 = layers[:] layer_4 = layers[:] layer_5 = layers[:] layer_6 = layers[:] layer_7 = layers[:] layer_1 = self.move_to_front(layer_1, keyword_1) layer_2 = self.move_to_front(layer_2, keyword_2) layer_3 = self.move_to_front(layer_3, keyword_3) layer_4 = self.move_to_front(layer_4, keyword_4) layer_5 = self.move_to_front(layer_5, keyword_5) layer_6 = self.move_to_front(layer_6, keyword_6) layer_7 = self.move_to_front(layer_7, keyword_7) self.dlg.comboBox_1.clear() self.dlg.comboBox_2.clear() self.dlg.comboBox_3.clear() self.dlg.comboBox_4.clear() self.dlg.comboBox_5.clear() self.dlg.comboBox_6.clear() self.dlg.comboBox_7.clear() self.dlg.comboBox_1.addItems([i.name() for i in layer_1]) # knooppunt self.dlg.comboBox_2.addItems([i.name() for i in layer_2]) # afvoerrelatie self.dlg.comboBox_3.addItems([i.name() for i in layer_3]) # drinkwater BAG self.dlg.comboBox_4.addItems([i.name() for i in layer_4]) # VE's self.dlg.comboBox_5.addItems([i.name() for i in layer_5]) # plancap self.dlg.comboBox_6.addItems([i.name() for i in layer_6]) # verhard opp self.dlg.comboBox_7.addItems([i.name() for i in layer_7]) # bemalingsgebieden msg_tooltip = "Kaartlagen met '{}' in naam komen bovenaan de keuzelijst te staan.\ \nVoor het instellen van een eigen zoekterm: ga naar local_settings.py in de app directory van de plugin." self.dlg.comboBox_1.setToolTip(msg_tooltip.format(keyword_1)) self.dlg.comboBox_2.setToolTip(msg_tooltip.format(keyword_2)) self.dlg.comboBox_3.setToolTip(msg_tooltip.format(keyword_3)) self.dlg.comboBox_4.setToolTip(msg_tooltip.format(keyword_4)) self.dlg.comboBox_5.setToolTip(msg_tooltip.format(keyword_5)) self.dlg.comboBox_6.setToolTip(msg_tooltip.format(keyword_6)) self.dlg.comboBox_7.setToolTip(msg_tooltip.format(keyword_7)) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: ##QgsMessageLog.logMessage("sel_index = {}".format(sel_index, level=QgsMessageLog.INFO)) ##QgsMessageLog.logMessage("layer_index 4 = {}".format(self.move_to_front(layer_points, "VE")[self.dlg.comboBox_4.currentIndex()].name()), level=QgsMessageLog.INFO) ##QgsMessageLog.logMessage("layer4 = {}".format([i.name() for i in l4]), level=QgsMessageLog.INFO) sel_layers = [ layer_1[self.dlg.comboBox_1.currentIndex()], layer_2[self.dlg.comboBox_2.currentIndex()], layer_3[self.dlg.comboBox_3.currentIndex()], layer_4[self.dlg.comboBox_4.currentIndex()], layer_5[self.dlg.comboBox_5.currentIndex()], layer_6[self.dlg.comboBox_6.currentIndex()], layer_7[self.dlg.comboBox_7.currentIndex()], ] for i, layer in enumerate(sel_layers): print_log("input {}:\t{}".format(i + 1, layer.name()), "i") gdb = self.dlg.lineEdit.text() # if not gdb or not os.path.exists(gdb): print_log( "Script afgebroken! Geen geldige output map opgegeven ({}...)" .format(gdb), "e", self.iface) return qgis_warnings_log = settings.qgis_warnings_log with open(qgis_warnings_log, 'w') as logfile: import time logfile.write('{level}: date {time}'.format( level="INFO", time=time.asctime())) blokje_log("Veld-info ophalen...", "i") INP_FIELDS_XLS = settings.INP_FIELDS_XLS INP_FIELDS_CSV = settings.INP_FIELDS_CSV try: if settings.b_raise_xlrd_import_error: print_log( "b_raise_xlrd_import_error = True (zie local_settings.py)", "w", self.iface) raise ImportError # for testing csv from xlrd import open_workbook d_velden = get_d_velden(INP_FIELDS_XLS, 0, open_workbook) except ImportError: # for compatibility with iMac print_log( "import error 'xlrd': inp_fields.csv wordt gebruikt als input in plaats van inp_fields.xls", "w", self.iface) d_velden = get_d_velden_csv(INP_FIELDS_CSV) for fld in d_velden: print_log("{}\n{}".format(fld, d_velden[fld]), "d") # check for required fields vl = sel_layers[0] # knooppunt if vl.fieldNameIndex('VAN_KNOOPN') == -1: print_log( "Script afgebroken! Verplicht veld 'VAN_KNOOPN' niet gevonden in kaartlaag '{}'" .format(vl.name()), "e", self.iface) return vl = sel_layers[1] # afvoerrelatie if vl.fieldNameIndex('VAN_KNOOPN') == -1: print_log( "Script afgebroken! Verplicht veld 'VAN_KNOOPN' niet gevonden in kaartlaag '{}'" .format(vl.name()), "e", self.iface) return # run module 1 l_K_ONTV_VAN, inp_polygon_layer = m1.main(self.iface, sel_layers, gdb, d_velden) # run module 2 m2.main(self.iface, sel_layers, gdb, d_velden, l_K_ONTV_VAN, inp_polygon_layer) if settings.b_remove_results_after_run: self.remove_result_layers(remove_all=False, delete_source=False) ##self.iface.mainWindow().statusBar().showMessage("dit is de mainWindow") warnings = [] with open(qgis_warnings_log, 'r') as log_file: for line in log_file.readlines(): if "WARNING" in line: warnings.append(line) msg = QMessageBox() if len(warnings) > 0: msg.setIcon(QMessageBox.Warning) msg.setWindowTitle("Script completed") msg.setText( "{} warnings were encountered when running script".format( len(warnings))) msg.setInformativeText( "For more information see details below or view log panel") detailedText = "The details are as follows:" detailedText += "\n" + "".join(warnings) detailedText += "\nlogfile: {}".format(settings.logFile) msg.setDetailedText(detailedText) msg.setStyleSheet("QLabel{min-width: 300px;}") else: msg.setIcon(QMessageBox.Information) msg.setWindowTitle("Script completed") msg.setText( "No problems were encountered when running script!") retval = msg.exec_() ##QMessageBox.information(msg, "Info", "Script completed!") QgsMessageLog.logMessage("Script completed!", level=QgsMessageLog.INFO)
def run(self): """Run method that performs all the real work""" self.remove_result_layers(remove_all=True, delete_source=True) layers = self.iface.legendInterface().layers() if not layers: print_log( "Tool afgebroken! Geen layers gevonden. Voeg eerst layers toe", "e", self.iface) return layer_points, layer_lines, layer_polygons = [], [], [] if b_QgsWKBTypes: for i, layer in enumerate(layers): if hasattr(layer, "wkbType"): # qgis.core.QgsWKBTypes.displayString(int(vl.wkbType())) if "point" in QgsWKBTypes.displayString( int(layer.wkbType())).lower(): ## QGis.WKBPoint: layer_points.append(layer) elif "line" in QgsWKBTypes.displayString( int(layer.wkbType())).lower( ): ##QGis.WKBLineString: layer_lines.append(layer) elif "polygon" in QgsWKBTypes.displayString( int(layer.wkbType())).lower(): ##QGis.WKBPolygon: layer_polygons.append(layer) else: pass else: print_log( "ImportError for QgsWKBTypes. Kan geen geometrie herkennen voor layer inputs. \ Controleer of juiste layers zijn geselecteerd of upgrade QGIS.", "w", self.iface) layer_points = layer_lines = layer_polygons = layers self.dlg.comboBox_1.clear() self.dlg.comboBox_2.clear() self.dlg.comboBox_3.clear() self.dlg.comboBox_4.clear() self.dlg.comboBox_5.clear() self.dlg.comboBox_6.clear() self.dlg.comboBox_7.clear() self.dlg.comboBox_1.addItems([ i.name() for i in self.move_to_front(layer_points, "punt") ]) # knooppunt self.dlg.comboBox_2.addItems([ i.name() for i in self.move_to_front(layer_lines, "lijn") ]) # afvoerrelatie self.dlg.comboBox_3.addItems([ i.name() for i in self.move_to_front(layer_points, "BAG") ]) # drinkwater BAG self.dlg.comboBox_4.addItems( [i.name() for i in self.move_to_front(layer_points, "VE")]) # VE's self.dlg.comboBox_5.addItems([ i.name() for i in self.move_to_front(layer_polygons, "RIGO") ]) # plancap self.dlg.comboBox_6.addItems([ i.name() for i in self.move_to_front(layer_polygons, "opp") ]) # verhard opp self.dlg.comboBox_7.addItems([ i.name() for i in self.move_to_front(layer_polygons, "bemaling") ]) # bemalingsgebieden # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: ##QgsMessageLog.logMessage("sel_index = {}".format(sel_index, level=QgsMessageLog.INFO)) ##QgsMessageLog.logMessage("layer_index 4 = {}".format(self.move_to_front(layer_points, "VE")[self.dlg.comboBox_4.currentIndex()].name()), level=QgsMessageLog.INFO) ##QgsMessageLog.logMessage("layer4 = {}".format([i.name() for i in l4]), level=QgsMessageLog.INFO) sel_layers = [ self.move_to_front(layer_points, "punt")[self.dlg.comboBox_1.currentIndex()], self.move_to_front(layer_lines, "lijn")[self.dlg.comboBox_2.currentIndex()], self.move_to_front(layer_points, "BAG")[self.dlg.comboBox_3.currentIndex()], self.move_to_front(layer_points, "VE")[self.dlg.comboBox_4.currentIndex()], self.move_to_front(layer_polygons, "RIGO")[self.dlg.comboBox_5.currentIndex()], self.move_to_front(layer_polygons, "opp")[self.dlg.comboBox_6.currentIndex()], self.move_to_front( layer_polygons, "bemaling")[self.dlg.comboBox_7.currentIndex()], ] # refresh input layers, werkt niet... voorlopig dan maar handmatig weggooien. ##sel_layernames = [layer.name() for layer in sel_layers] ##self.remove_result_layers(settings.l_result_layers_all) ##sel_layers = [] ##layers = self.iface.legendInterface().layers() ##for layer in layers: ## if layer.name() in sel_layernames: ## sel_layers.append(layer) gdb = self.dlg.lineEdit.text() if not gdb or not os.path.exists(gdb): print_log( "Script afgebroken! Geen geldige output map opgegeven ({}...)" .format(gdb), "e", self.iface) return qgis_warnings_log = settings.qgis_warnings_log with open(qgis_warnings_log, 'w') as logfile: import time logfile.write('{level}: date {time}'.format( level="INFO", time=time.asctime())) blokje_log("Veld-info ophalen...", "i") INP_FIELDS_XLS = settings.INP_FIELDS_XLS INP_FIELDS_CSV = settings.INP_FIELDS_CSV try: from xlrd import open_workbook d_velden = get_d_velden(INP_FIELDS_XLS, 0, open_workbook) except ImportError: # for compatibility with iMac print_log( "import error 'xlrd': inp_fields.csv wordt gebruikt als input in plaats van inp_fields.xls!", "w", self.iface) d_velden = get_d_velden_csv(INP_FIELDS_CSV) for fld in d_velden: print_log("{}\n{}".format(fld, d_velden[fld]), "d") ##self.iface.messageBar().pushMessage("titel", "Start module 1", QgsMessageBar.INFO, duration=5) m1.main(self.iface, sel_layers, gdb, d_velden) ##self.iface.messageBar().pushMessage("titel", "Start module 2", QgsMessageBar.INFO, duration=5) m2.main(self.iface, sel_layers, gdb, d_velden) self.remove_result_layers(remove_all=False, delete_source=False) ##self.iface.mainWindow().statusBar().showMessage("dit is de mainWindow") warnings = [] with open(qgis_warnings_log, 'r') as log_file: for line in log_file.readlines(): if "WARNING" in line: warnings.append(line) msg = QMessageBox() if len(warnings) > 0: msg.setIcon(QMessageBox.Warning) msg.setWindowTitle("Script completed") msg.setText( "{} warnings were encountered when running script".format( len(warnings))) msg.setInformativeText( "For more information see details below or view log panel") msg.setDetailedText("The details are as follows:") msg.setDetailedText("\n".join(warnings)) # for line in warnings: # msg.setDetailedText(line) else: msg.setIcon(QMessageBox.Information) msg.setWindowTitle("Script completed") msg.setText( "No problems were encountered when running script!") retval = msg.exec_() ##QMessageBox.information(msg, "Info", "Script completed!") QgsMessageLog.logMessage("Script completed!", level=QgsMessageLog.INFO)
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT2)) vproviderA = vlayerA.dataProvider() geomType = vproviderA.geometryType() if geomType in GEOM_25D: raise GeoAlgorithmExecutionException( self.tr('Input layer does not support 2.5D type geometry ({}).' ).format(QgsWKBTypes.displayString(geomType))) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, geomType, vproviderA.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 = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for i in intersects: request = QgsFeatureRequest().setFilterFid(i) inFeatB = vlayerB.getFeatures(request).next() tmpGeom = QgsGeometry(inFeatB.geometry()) 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_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): layerA = dataobjects.getObjectFromUri( self.getParameterValue(Clip.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(Clip.OVERLAY)) geomType = layerA.dataProvider().geometryType() if geomType in GEOM_25D: raise GeoAlgorithmExecutionException( self.tr('Input layer does not support 2.5D type geometry ({}).' ).format(QgsWKBTypes.displayString(geomType))) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layerA.pendingFields(), layerA.dataProvider().geometryType(), layerA.dataProvider().crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): geom = QgsGeometry(inFeatA.geometry()) attrs = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) first = True found = False if len(intersects) > 0: for i in intersects: layerB.getFeatures(QgsFeatureRequest().setFilterFid( i)).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(cur_geom.combine(tmpGeom)) 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.')) break outFeat.setGeometry(QgsGeometry(new_geom)) if found: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(geom.intersection(cur_geom)) if new_geom.wkbType( ) == QGis.WKBUnknown or QgsWKBTypes.flatType( new_geom.geometry().wkbType( )) == QgsWKBTypes.GeometryCollection: int_com = QgsGeometry(geom.combine(cur_geom)) int_sym = QgsGeometry(geom.symDifference(cur_geom)) new_geom = QgsGeometry(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.')) continue try: outFeat.setGeometry(new_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, 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): layerA = dataobjects.getObjectFromUri( self.getParameterValue(Clip.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(Clip.OVERLAY)) geomType = layerA.dataProvider().geometryType() if geomType in GEOM_25D: raise GeoAlgorithmExecutionException( self.tr('Input layer does not support 2.5D type geometry ({}).').format(QgsWKBTypes.displayString(geomType))) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layerA.pendingFields(), layerA.dataProvider().geometryType(), layerA.dataProvider().crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) total = 100.0 / len(selectionA) for current, inFeatA in enumerate(selectionA): geom = QgsGeometry(inFeatA.geometry()) attrs = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) first = True found = False if len(intersects) > 0: for i in intersects: layerB.getFeatures( QgsFeatureRequest().setFilterFid(i)).nextFeature( inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(cur_geom.combine(tmpGeom)) 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.')) break outFeat.setGeometry(QgsGeometry(new_geom)) if found: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(geom.intersection(cur_geom)) if new_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(new_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: int_com = QgsGeometry(geom.combine(cur_geom)) int_sym = QgsGeometry(geom.symDifference(cur_geom)) new_geom = QgsGeometry(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.')) continue try: outFeat.setGeometry(new_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, 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(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(Union.INPUT2)) vproviderA = vlayerA.dataProvider() geomType = vproviderA.geometryType() if geomType in GEOM_25D: raise GeoAlgorithmExecutionException( self.tr('Input layer does not support 2.5D type geometry ({}).' ).format(QgsWKBTypes.displayString(geomType))) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter( fields, geomType, vproviderA.crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType( ) == QGis.WKBUnknown 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) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, 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) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) # the remaining bit of inFeatA'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.isGeosEmpty() or not diff_geom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) if diff_geom.wkbType() == 0 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) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) length = len(vproviderA.fields()) atMapA = [None] * length featuresA = vector.features(vlayerB) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 100) add = False geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(inFeatA.attributes()) intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: for id in intersects: request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerA.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if diff_geom.intersects(tmpGeom): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) if diff_geom.isGeosEmpty( ) or not diff_geom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) else: try: # Ihis only happends if the bounding box # intersects, but the geometry doesn't outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, 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) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) nElement += 1 del writer