# -*- coding: utf-8 -*- #----------------------------------------------------------- # # fTools # Copyright (C) 2008-2011 Carson Farmer # EMAIL: carson.farmer (at) gmail.com # WEB : http://www.ftools.ca/fTools.html # # A collection of data management and analysis tools for vector data # # Geoprocessing functions adapted from 'Geoprocessing Plugin', # (C) 2008 by Dr. Horst Duester, Stefan Ziegler #----------------------------------------------------------- # # licensed under the terms of GNU GPL 2 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # #--------------------------------------------------------------------- from PyQt4.QtCore import SIGNAL, QObject, Qt, QFile, QThread, QVariant from PyQt4.QtGui import QDialog, QDoubleValidator, QDialogButtonBox, QMessageBox from qgis.core import QGis, QgsVectorFileWriter, QgsFeature, QgsGeometry, QgsFields, QgsField, QgsFeatureRequest, QgsPoint, QgsDistanceArea, QgsWKBTypes from ui_frmGeoprocessing import Ui_Dialog import ftools_utils class GeoprocessingDialog(QDialog, Ui_Dialog): def __init__(self, iface, function): QDialog.__init__(self, iface.mainWindow()) self.iface = iface self.setupUi(self) self.param.setValidator(QDoubleValidator(self.param)) self.myFunction = function QObject.connect(self.btnBrowse, SIGNAL("clicked()"), self.outFile) QObject.connect(self.inShapeA, SIGNAL("currentIndexChanged(QString)"), self.checkA) QObject.connect(self.inShapeB, SIGNAL("currentIndexChanged(QString)"), self.checkB) if function == 4 or function == 1 or function == 2: QObject.connect(self.inShapeA, SIGNAL("currentIndexChanged(QString)"), self.update) self.manageGui() self.success = False self.cancel_close = self.buttonBox_2.button(QDialogButtonBox.Close) self.buttonOk = self.buttonBox_2.button(QDialogButtonBox.Ok) self.progressBar.setValue(0) def checkA(self): inputLayer = unicode(self.inShapeA.currentText()) if inputLayer != "": changedLayer = ftools_utils.getVectorLayerByName(inputLayer) if changedLayer.selectedFeatureCount() != 0: self.useSelectedA.setCheckState(Qt.Checked) else: self.useSelectedA.setCheckState(Qt.Unchecked) def checkB(self): inputLayer = unicode(self.inShapeB.currentText()) if inputLayer != "": changedLayer = ftools_utils.getVectorLayerByName(inputLayer) if changedLayer.selectedFeatureCount() != 0: self.useSelectedB.setCheckState(Qt.Checked) else: self.useSelectedB.setCheckState(Qt.Unchecked) def update(self): self.attrib.clear() inputLayer = unicode(self.inShapeA.currentText()) if inputLayer != "": changedLayer = ftools_utils.getVectorLayerByName(inputLayer) changedField = changedLayer.dataProvider().fields() for f in changedField: self.attrib.addItem(unicode(f.name())) if self.myFunction == 4: self.attrib.addItem("--- " + self.tr("Dissolve all") + " ---") def accept(self): if self.inShapeA.currentText() == "": QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Please specify an input layer")) elif self.inShapeB.isVisible() and self.inShapeB.currentText() == "": QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Please specify a difference/intersect/union layer")) elif self.param.isEnabled() and self.param.isVisible() and self.param.text() == "": QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Please specify valid buffer value")) elif self.attrib.isEnabled() and self.attrib.isVisible() and self.attrib.currentText() == "": QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Please specify dissolve field")) elif self.outShape.text() == "": QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Please specify output shapefile")) else: changedLayerA = ftools_utils.getVectorLayerByName(self.inShapeA.currentText()) changedLayerB = ftools_utils.getVectorLayerByName(self.inShapeB.currentText()) # check for selection in layer A if self.useSelectedA.isChecked() and changedLayerA.selectedFeatureCount() == 0: QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("No features selected, please uncheck 'Use selected' or make a selection")) # check for selection in layer B elif self.inShapeB.isVisible() and self.useSelectedB.isChecked() and changedLayerB.selectedFeatureCount() == 0: QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("No features selected, please uncheck 'Use selected' or make a selection")) else: self.outShape.clear() if self.attrib.isEnabled(): self.geoprocessing(self.inShapeA.currentText(), self.inShapeB.currentText(), unicode(self.attrib.currentText()), self.mergeOutput.checkState(), self.useSelectedA.checkState(), self.useSelectedB.checkState(), self.spnSegments.value()) else: if self.param.isEnabled() and self.param.isVisible(): parameter = float(self.param.text()) else: parameter = None self.geoprocessing(self.inShapeA.currentText(), self.inShapeB.currentText(), parameter, self.mergeOutput.checkState(), self.useSelectedA.checkState(), self.useSelectedB.checkState(), self.spnSegments.value()) def outFile(self): self.outShape.clear() (self.shapefileName, self.encoding) = ftools_utils.saveDialog(self) if self.shapefileName is None or self.encoding is None: return self.outShape.setText(self.shapefileName) def manageGui(self): if self.myFunction == 1: # Buffer self.label_2.hide() self.inShapeB.hide() self.useSelectedB.hide() self.label_4.hide() self.setWindowTitle(self.tr("Buffer(s)")) elif self.myFunction == 2: # Convex hull self.label_2.hide() self.inShapeB.hide() self.useSelectedB.hide() self.rdoBuffer.setText(self.tr("Create single minimum convex hull")) self.rdoField.setText(self.tr("Create convex hulls based on input field")) self.label_4.hide() self.param.hide() self.lblSegments.hide() self.spnSegments.hide() self.setWindowTitle(self.tr("Convex hull(s)")) self.mergeOutput.hide() elif self.myFunction == 4: # Dissolve self.label_2.hide() self.inShapeB.hide() self.useSelectedB.hide() self.rdoBuffer.hide() self.attrib.setEnabled(True) self.param.hide() self.rdoField.hide() self.mergeOutput.hide() self.lblSegments.hide() self.spnSegments.hide() self.setWindowTitle(self.tr("Dissolve")) else: self.rdoBuffer.hide() self.param.hide() self.label_4.hide() self.rdoField.hide() self.attrib.hide() self.mergeOutput.hide() self.lblSegments.hide() self.spnSegments.hide() if self.myFunction == 3: # Difference self.label_2.setText(self.tr("Difference layer")) self.setWindowTitle(self.tr("Difference")) elif self.myFunction == 5: # Intersect self.label_2.setText(self.tr("Intersect layer")) self.setWindowTitle(self.tr("Intersect")) elif self.myFunction == 7: # Symmetrical difference self.label_2.setText(self.tr("Difference layer")) self.setWindowTitle(self.tr("Symmetrical difference")) self.useSelectedA.hide() self.useSelectedB.hide() elif self.myFunction == 8: # Clip self.label_2.setText(self.tr("Clip layer")) self.setWindowTitle(self.tr("Clip")) else: # Union self.label_2.setText(self.tr("Union layer")) self.setWindowTitle(self.tr("Union")) self.useSelectedA.hide() self.useSelectedB.hide() self.resize(381, 100) self.populateLayers() def populateLayers(self): myListA = [] myListB = [] self.inShapeA.clear() self.inShapeB.clear() if self.myFunction == 4: myListA = ftools_utils.getLayerNames([QGis.Line, QGis.Polygon]) myListB = [] else: myListA = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon]) myListB = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon]) self.inShapeA.addItems(myListA) self.inShapeB.addItems(myListB) # 1: Buffer # 2: Convex Hull # 3: Difference # 4: Dissolve # 5: Intersection # 6: Union # 7: Symmetrical Difference # 8: Clip def geoprocessing(self, myLayerA, myLayerB, myParam, myMerge, mySelectionA, mySelectionB, mySegments): check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Unable to delete existing shapefile.")) return self.buttonOk.setEnabled(False) self.testThread = geoprocessingThread( self.iface.mainWindow(), self, self.myFunction, myLayerA, myLayerB, myParam, myMerge, mySelectionA, mySelectionB, mySegments, self.shapefileName, self.encoding ) QObject.connect(self.testThread, SIGNAL("runFinished(PyQt_PyObject)"), self.runFinishedFromThread) QObject.connect(self.testThread, SIGNAL("runStatus(PyQt_PyObject)"), self.runStatusFromThread) QObject.connect(self.testThread, SIGNAL("runRange(PyQt_PyObject)"), self.runRangeFromThread) self.cancel_close.setText(self.tr("Cancel")) QObject.connect(self.cancel_close, SIGNAL("clicked()"), self.cancelThread) self.testThread.start() return True def cancelThread(self): self.testThread.stop() self.buttonOk.setEnabled(True) def runFinishedFromThread(self, results): self.testThread.stop() self.buttonOk.setEnabled(True) self.cancel_close.setText(self.tr("Close")) QObject.disconnect(self.cancel_close, SIGNAL("clicked()"), self.cancelThread) out_text = "" if results[3] is not None: QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("No output created. File creation error:\n%s") % (results[3])) return if (not results[2] is None and not results[2]) or not results[1] or not results[0]: out_text = self.tr("\nWarnings:") end_text = self.tr("\nSome output geometries may be missing or invalid.\n\nWould you like to add the new layer anyway?") else: out_text = "" end_text = "" if not results[2] is None: if not results[2]: out_text = out_text + self.tr("\nInput CRS error: Different input coordinate reference systems detected, results may not be as expected.") else: out_text = out_text + self.tr("\nInput CRS error: One or more input layers missing coordinate reference information, results may not be as expected.") if not results[1]: out_text = out_text + self.tr("\nFeature geometry error: One or more output features ignored due to invalid geometry.") if not results[0]: out_text = out_text + self.tr("\nGEOS geoprocessing error: One or more input features have invalid geometry.") if self.addToCanvasCheck.isChecked(): addCanvasCheck = ftools_utils.addShapeToCanvas(unicode(self.shapefileName)) if not addCanvasCheck: QMessageBox.warning(self, self.tr("Geoprocessing"), self.tr("Error loading output shapefile:\n%s") % (unicode(self.shapefileName))) self.populateLayers() else: QMessageBox.information(self, self.tr("Geoprocessing"), self.tr("Created output shapefile:\n%s\n%s%s") % (unicode(self.shapefileName), out_text, end_text)) def runStatusFromThread(self, status): self.progressBar.setValue(status) def runRangeFromThread(self, range_vals): self.progressBar.setRange(range_vals[0], range_vals[1]) class geoprocessingThread(QThread): def __init__(self, parentThread, parentObject, function, myLayerA, myLayerB, myParam, myMerge, mySelectionA, mySelectionB, mySegments, myName, myEncoding): QThread.__init__(self, parentThread) self.parent = parentObject self.running = False self.myFunction = function self.myLayerA = myLayerA self.myLayerB = myLayerB self.myParam = myParam self.myMerge = myMerge self.mySelectionA = mySelectionA self.mySelectionB = mySelectionB self.mySegments = int(mySegments) self.myName = myName self.myEncoding = myEncoding def run(self): self.running = True self.vlayerA = ftools_utils.getVectorLayerByName(self.myLayerA) error = None if self.myFunction == 1 or self.myFunction == 2 or self.myFunction == 4: (self.myParam, useField) = self.checkParameter(self.vlayerA, self.myParam) if self.myParam is not None: if self.myFunction == 1: geos, feature, match, error = self.buffering(useField) elif self.myFunction == 2: geos, feature, match, error = self.convex_hull(useField) elif self.myFunction == 4: geos, feature, match, error = self.dissolve(useField) else: self.vlayerB = ftools_utils.getVectorLayerByName(self.myLayerB) if self.myFunction == 3: geos, feature, match, error = self.difference() elif self.myFunction == 5: geos, feature, match, error = self.intersect() elif self.myFunction == 6: geos, feature, match, error = self.union() elif self.myFunction == 7: geos, feature, match, error = self.symmetrical_difference() elif self.myFunction == 8: geos, feature, match, error = self.clip() self.emit(SIGNAL("runFinished(PyQt_PyObject)"), (geos, feature, match, error)) self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) def stop(self): self.running = False def buffering(self, useField): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() writer = QgsVectorFileWriter(self.myName, self.myEncoding, vproviderA.fields(), QGis.WKBPolygon, vproviderA.crs()) # check if writer was created properly, if not, return with error if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, True, writer.errorMessage() outFeat = QgsFeature() inFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() nElement = 0 # there is selection in input layer if self.mySelectionA: nFeat = self.vlayerA.selectedFeatureCount() selectionA = self.vlayerA.selectedFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # with dissolve if self.myMerge: first = True for inFeat in selectionA: atMap = inFeat.attributes() if useField: value = atMap[self.myParam].doDouble()[0] else: value = self.myParam inGeom = QgsGeometry(inFeat.geometry()) try: outGeom = inGeom.buffer(float(value), self.mySegments) if first: tempGeom = QgsGeometry(outGeom) first = False else: try: tempGeom = tempGeom.combine(outGeom) except: GEOS_EXCEPT = False continue except: GEOS_EXCEPT = False continue nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) try: outFeat.setGeometry(tempGeom) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False # without dissolve else: for inFeat in selectionA: atMap = inFeat.attributes() if useField: value = atMap[self.myParam] else: value = self.myParam inGeom = QgsGeometry(inFeat.geometry()) try: outGeom = inGeom.buffer(float(value), self.mySegments) if not outGeom.isGeosEmpty(): try: outFeat.setGeometry(outGeom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False continue nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) # there is no selection in input layer else: nFeat = vproviderA.featureCount() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # with dissolve if self.myMerge: first = True fit = vproviderA.getFeatures() while fit.nextFeature(inFeat): atMap = inFeat.attributes() if useField: value = atMap[self.myParam] else: value = self.myParam inGeom = QgsGeometry(inFeat.geometry()) try: outGeom = inGeom.buffer(float(value), self.mySegments) if first: tempGeom = QgsGeometry(outGeom) first = False else: try: tempGeom = tempGeom.combine(outGeom) except: GEOS_EXCEPT = False continue except: GEOS_EXCEPT = False continue nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) try: outFeat.setGeometry(tempGeom) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False # without dissolve else: fit = vproviderA.getFeatures() while fit.nextFeature(inFeat): atMap = inFeat.attributes() if useField: value = atMap[self.myParam] else: value = self.myParam inGeom = QgsGeometry(inFeat.geometry()) try: outGeom = inGeom.buffer(float(value), self.mySegments) if not outGeom.isGeosEmpty(): try: outFeat.setGeometry(outGeom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False continue nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) del writer return GEOS_EXCEPT, FEATURE_EXCEPT, True, None def convex_hull(self, useField): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() # outFeatFields = QgsFields() if useField: importedField = vproviderA.fields().at(self.myParam) importedFieldName = importedField.name() # outFeatFields.extend(vproviderA.fields()) # creating area and perimeter fields areaField = QgsField("area", QVariant.Double) perimField = QgsField("perim", QVariant.Double) # appending fields outFeatFields.append(areaField) outFeatFields.append(perimField) # writer = QgsVectorFileWriter(self.myName, self.myEncoding, outFeatFields, QGis.WKBPolygon, vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, True, writer.errorMessage() inFeat = QgsFeature() outFeat = QgsFeature() # set feature fields outFeat.setFields(outFeatFields) # inGeom = QgsGeometry() outGeom = QgsGeometry() nElement = 0 # there is selection in input layer if self.mySelectionA: nFeat = self.vlayerA.selectedFeatureCount() selectionA = self.vlayerA.selectedFeatures() if useField: unique = ftools_utils.getUniqueValues(vproviderA, self.myParam) nFeat = nFeat * len(unique) self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) for i in unique: first = True hull = [] for inFeat in selectionA: atMap = inFeat.attributes() idVar = atMap[self.myParam] if idVar == i: if first: firstFeature = QgsFeature(inFeat) first = False inGeom = QgsGeometry(inFeat.geometry()) points = ftools_utils.extractPoints(inGeom) hull.extend(points) nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) if len(hull) >= 3: tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull)) try: outGeom = tmpGeom.convexHull() outFeat.setGeometry(outGeom) (area, perim) = self.simpleMeasure(outGeom) for f in firstFeature.fields(): outFeat.setAttribute(f.name(), firstFeature.attribute(f.name())) outFeat.setAttribute("area", area) outFeat.setAttribute("perim", perim) writer.addFeature(outFeat) except: GEOS_EXCEPT = False continue else: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) hull = [] for inFeat in selectionA: inGeom = QgsGeometry(inFeat.geometry()) points = ftools_utils.extractPoints(inGeom) hull.extend(points) nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull)) try: outGeom = tmpGeom.convexHull() outFeat.setGeometry(outGeom) (area, perim) = self.simpleMeasure(outGeom) for f in inFeat.fields(): outFeat.setAttribute(f.name(), inFeat.attribute(f.name())) outFeat.setAttribute("area", area) outFeat.setAttribute("perim", perim) writer.addFeature(outFeat) except: GEOS_EXCEPT = False # there is no selection in input layer else: nFeat = vproviderA.featureCount() if useField: unique = ftools_utils.getUniqueValues(vproviderA, self.myParam) nFeat = nFeat * len(unique) self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) for i in unique: first = True hull = [] fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeat): idVar = inFeat.attribute(importedFieldName) if idVar == i: if first: firstFeature = QgsFeature(inFeat) first = False inGeom = QgsGeometry(inFeat.geometry()) points = ftools_utils.extractPoints(inGeom) hull.extend(points) nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) if len(hull) >= 3: tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull)) try: outGeom = tmpGeom.convexHull() outFeat.setGeometry(outGeom) (area, perim) = self.simpleMeasure(outGeom) for f in firstFeature.fields(): outFeat.setAttribute(f.name(), firstFeature.attribute(f.name())) outFeat.setAttribute("area", area) outFeat.setAttribute("perim", perim) writer.addFeature(outFeat) except: GEOS_EXCEPT = False continue else: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) hull = [] fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeat): inGeom = QgsGeometry(inFeat.geometry()) points = ftools_utils.extractPoints(inGeom) hull.extend(points) nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull)) try: outGeom = tmpGeom.convexHull() outFeat.setGeometry(outGeom) (area, perim) = self.simpleMeasure(outGeom) for f in inFeat.fields(): outFeat.setAttribute(f.name(), inFeat.attribute(f.name())) outFeat.setAttribute("area", area) outFeat.setAttribute("perim", perim) writer.addFeature(outFeat) except: GEOS_EXCEPT = False del writer return GEOS_EXCEPT, FEATURE_EXCEPT, True, None def dissolve(self, useField): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() writer = QgsVectorFileWriter(self.myName, self.myEncoding, vproviderA.fields(), vproviderA.geometryType(), vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, True, writer.errorMessage() inFeat = QgsFeature() outFeat = QgsFeature() nElement = 0 attrs = None # there is selection in input layer if self.mySelectionA: nFeat = self.vlayerA.selectedFeatureCount() selectionA = self.vlayerA.selectedFeatures() if not useField: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) first = True for inFeat in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) if first: attrs = inFeat.attributes() tmpInGeom = QgsGeometry(inFeat.geometry()) outFeat.setGeometry(tmpInGeom) first = False else: tmpInGeom = QgsGeometry(inFeat.geometry()) tmpOutGeom = QgsGeometry(outFeat.geometry()) try: tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom)) outFeat.setGeometry(tmpOutGeom) except: GEOS_EXCEPT = False continue outFeat.setAttributes(attrs) writer.addFeature(outFeat) else: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) outFeats = {} attrs = {} for inFeat in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) atMap = inFeat.attributes() tempItem = unicode(atMap[self.myParam]).strip() if not (tempItem in outFeats): outFeats[tempItem] = QgsGeometry(inFeat.geometry()) attrs[tempItem] = atMap else: try: outFeats[tempItem] = outFeats[tempItem].combine(inFeat.geometry()) except: GEOS_EXCEPT = False continue for k in outFeats.keys(): feature = QgsFeature() feature.setAttributes(attrs[k]) feature.setGeometry(outFeats[k]) writer.addFeature(feature) # there is no selection in input layer else: nFeat = vproviderA.featureCount() if not useField: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) first = True fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeat): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) if first: attrs = inFeat.attributes() tmpInGeom = QgsGeometry(inFeat.geometry()) outFeat.setGeometry(tmpInGeom) first = False else: tmpInGeom = QgsGeometry(inFeat.geometry()) tmpOutGeom = QgsGeometry(outFeat.geometry()) try: tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom)) outFeat.setGeometry(tmpOutGeom) except: GEOS_EXCEPT = False continue outFeat.setAttributes(attrs) writer.addFeature(outFeat) else: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) outFeats = {} attrs = {} fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeat): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) atMap = inFeat.attributes() tempItem = unicode(atMap[self.myParam]).strip() if not (tempItem in outFeats): outFeats[tempItem] = QgsGeometry(inFeat.geometry()) attrs[tempItem] = atMap else: try: outFeats[tempItem] = outFeats[tempItem].combine(inFeat.geometry()) except: GEOS_EXCEPT = False continue for k in outFeats.keys(): feature = QgsFeature() feature.setAttributes(attrs[k]) feature.setGeometry(outFeats[k]) writer.addFeature(feature) del writer return GEOS_EXCEPT, FEATURE_EXCEPT, True, None def difference(self): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() vproviderB = self.vlayerB.dataProvider() # check for crs compatibility crsA = vproviderA.crs() crsB = vproviderB.crs() if not crsA.isValid() or not crsB.isValid(): crs_match = None else: crs_match = crsA == crsB writer = QgsVectorFileWriter(self.myName, self.myEncoding, vproviderA.fields(), vproviderA.geometryType(), vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, writer.errorMessage() inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() nElement = 0 index = ftools_utils.createIndex(vproviderB) # there is selection in input layer if self.mySelectionA: nFeat = self.vlayerA.selectedFeatureCount() selectionA = self.vlayerA.selectedFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # we have selection in overlay layer if self.mySelectionB: selectionB = self.vlayerB.selectedFeaturesIds() for inFeatA in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) add = True geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: # is intersect feature in selection if id in selectionB: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) except: GEOS_EXCEPT = False add = False break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue # we have no selection in overlay layer else: for inFeatA in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) add = True geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) except: GEOS_EXCEPT = False add = False break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue # there is no selection in input layer else: nFeat = vproviderA.featureCount() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # we have selection in overlay layer if self.mySelectionB: selectionB = self.vlayerB.selectedFeaturesIds() fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 add = True self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: # now check if id in selection if id in selectionB: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) except: GEOS_EXCEPT = False add = False break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue # we have no selection in overlay layer else: fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 add = True self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) if diff_geom.isGeosEmpty(): GEOS_EXCEPT = False add = False break except: GEOS_EXCEPT = False add = False break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue del writer return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, None def intersect(self): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() vproviderB = self.vlayerB.dataProvider() # check for crs compatibility crsA = vproviderA.crs() crsB = vproviderB.crs() if not crsA.isValid() or not crsB.isValid(): crs_match = None else: crs_match = crsA == crsB fields = ftools_utils.combineVectorFields(self.vlayerA, self.vlayerB) writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields, vproviderA.geometryType(), vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, writer.errorMessage() inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() nElement = 0 index = ftools_utils.createIndex(vproviderB) # there is selection in input layer if self.mySelectionA: nFeat = self.vlayerA.selectedFeatureCount() selectionA = self.vlayerA.selectedFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # we have selection in overlay layer if self.mySelectionB: selectionB = self.vlayerB.selectedFeaturesIds() for inFeatA in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: if id in selectionB: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: 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)) try: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 gList = ftools_utils.getGeomType(geom.wkbType()) if int_geom.wkbType() in gList: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False break # we don't have selection in overlay layer else: for inFeatA in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: 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)) try: gList = ftools_utils.getGeomType(geom.wkbType()) if int_geom.wkbType() in gList: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False break # there is no selection in input layer else: nFeat = vproviderA.featureCount() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # we have selection in overlay layer if self.mySelectionB: selectionB = self.vlayerB.selectedFeaturesIds() fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: if id in selectionB: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: 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)) try: gList = ftools_utils.getGeomType(geom.wkbType()) if int_geom.wkbType() in gList: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False break # we have no selection in overlay layer else: fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: 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)) try: gList = ftools_utils.getGeomType(geom.wkbType()) if int_geom.wkbType() in gList: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False break del writer return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, None def union(self): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() vproviderB = self.vlayerB.dataProvider() # check for crs compatibility crsA = vproviderA.crs() crsB = vproviderB.crs() if not crsA.isValid() or not crsB.isValid(): crs_match = None else: crs_match = crsA == crsB fields = ftools_utils.combineVectorFields(self.vlayerA, self.vlayerB) writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields, vproviderA.geometryType(), vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, writer.errorMessage() inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = ftools_utils.createIndex(vproviderB) indexB = ftools_utils.createIndex(vproviderA) nFeat = vproviderA.featureCount() + vproviderB.featureCount() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) count = 0 nElement = 0 fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) 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 FEATURE_EXCEPT = False else: for id in intersects: count += 1 vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) try: if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection GEOS_EXCEPT = False 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 geometry 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 Exception as err: FEATURE_EXCEPT = False else: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 gList = ftools_utils.getGeomType(geom.wkbType()) if int_geom.wkbType() in gList: try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except Exception as err: FEATURE_EXCEPT = False except Exception as err: GEOS_EXCEPT = False try: # 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.wkbType() == QGis.WKBUnknown 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) outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except Exception as err: FEATURE_EXCEPT = False length = len(vproviderA.fields()) atMapA = [None] * length fitB = vproviderB.getFeatures() while fitB.nextFeature(inFeatB): add = False geom = QgsGeometry(inFeatB.geometry()) diff_geom = QgsGeometry(geom) atMap = atMapA + inFeatB.attributes() intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except Exception as err: FEATURE_EXCEPT = False else: for id in intersects: vproviderA.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatA) tmpGeom = QgsGeometry(inFeatA.geometry()) try: if diff_geom.intersects(tmpGeom): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) else: # this only happends if the bounding box # intersects, but the geometry doesn't outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except Exception as err: add = False GEOS_EXCEPT = False if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except Exception as err: FEATURE_EXCEPT = False self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) nElement += 1 del writer return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, None def symmetrical_difference(self): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() vproviderB = self.vlayerB.dataProvider() # check for crs compatibility crsA = vproviderA.crs() crsB = vproviderB.crs() if not crsA.isValid() or not crsB.isValid(): crs_match = None else: crs_match = crsA == crsB fields = ftools_utils.combineVectorFields(self.vlayerA, self.vlayerB) writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields, vproviderA.geometryType(), vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, writer.errorMessage() inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = ftools_utils.createIndex(vproviderB) indexB = ftools_utils.createIndex(vproviderA) nFeat = vproviderA.featureCount() * vproviderB.featureCount() nElement = 0 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) add = True geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) except: add = False GEOS_EXCEPT = False break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue length = len(vproviderA.fields()) fitB = vproviderB.getFeatures() while fitB.nextFeature(inFeatA): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) add = True geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = inFeatA.attributes() atMap = [None] * length + atMap intersects = indexB.intersects(geom.boundingBox()) for id in intersects: vproviderA.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) except: add = False GEOS_EXCEPT = False break if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue del writer return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, None def clip(self): GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = self.vlayerA.dataProvider() vproviderB = self.vlayerB.dataProvider() # check for crs compatibility crsA = vproviderA.crs() crsB = vproviderB.crs() if not crsA.isValid() or not crsB.isValid(): crs_match = None else: crs_match = crsA == crsB writer = QgsVectorFileWriter(self.myName, self.myEncoding, vproviderA.fields(), vproviderA.geometryType(), vproviderA.crs()) if writer.hasError(): return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, writer.errorMessage() inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() index = ftools_utils.createIndex(vproviderB) nElement = 0 # there is selection in input layer if self.mySelectionA: nFeat = self.vlayerA.selectedFeatureCount() selectionA = self.vlayerA.selectedFeatures() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # we have selection in overlay layer if self.mySelectionB: selectionB = self.vlayerB.selectedFeaturesIds() for inFeatA in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) found = False first = True for id in intersects: if id in selectionB: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: try: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(cur_geom.combine(tmpGeom)) outFeat.setGeometry(QgsGeometry(new_geom)) except: GEOS_EXCEPT = False break if found: try: 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)) try: outFeat.setGeometry(new_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False continue # we have no selection in overlay layer else: for inFeatA in selectionA: nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) found = False first = True for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: try: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(cur_geom.combine(tmpGeom)) outFeat.setGeometry(QgsGeometry(new_geom)) except: GEOS_EXCEPT = False break if found: try: 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)) try: outFeat.setGeometry(new_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False continue # there is no selection in input layer else: nFeat = vproviderA.featureCount() self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) # we have selection in overlay layer if self.mySelectionB: selectionB = self.vlayerB.selectedFeaturesIds() fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) found = False first = True for id in intersects: if id in selectionB: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: try: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(cur_geom.combine(tmpGeom)) outFeat.setGeometry(QgsGeometry(new_geom)) except: GEOS_EXCEPT = False break if found: try: 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)) try: outFeat.setGeometry(new_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False continue # we have no selection in overlay layer else: fitA = vproviderA.getFeatures() while fitA.nextFeature(inFeatA): nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) geom = QgsGeometry(inFeatA.geometry()) atMap = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) first = True found = False if len(intersects) > 0: for id in intersects: vproviderB.getFeatures(QgsFeatureRequest().setFilterFid(int(id))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: try: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(cur_geom.combine(tmpGeom)) outFeat.setGeometry(QgsGeometry(new_geom)) except: GEOS_EXCEPT = False break if found: try: 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)) try: outFeat.setGeometry(new_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: FEATURE_EXCEPT = False continue except: GEOS_EXCEPT = False continue del writer return GEOS_EXCEPT, FEATURE_EXCEPT, crs_match, None def checkParameter(self, layer, param): if self.myFunction == 1: if isinstance(param, unicode): check = layer.dataProvider().fieldNameIndex(param) if check == -1: return (None, False) else: return (check, True) else: if isinstance(param, float) or isinstance(param, int): return (param, False) else: return (None, False) elif self.myFunction == 2: if param is not None: if isinstance(param, unicode): check = layer.dataProvider().fieldNameIndex(param) if check == -1: return (None, False) else: return (check, True) else: return (None, False) else: return (True, False) elif self.myFunction == 4: if isinstance(param, unicode): check = layer.dataProvider().fieldNameIndex(param) if check == -1: return (check, False) else: return (check, True) else: return (None, False) def simpleMeasure(self, inGeom): if inGeom.wkbType() == QGis.WKBPoint: pt = QgsPoint() pt = inGeom.asPoint() attr1 = pt.x() attr2 = pt.y() else: measure = QgsDistanceArea() attr1 = measure.measure(inGeom) if inGeom.type() == QGis.Polygon: attr2 = self.perimMeasure(inGeom, measure) else: attr2 = attr1 return (attr1, attr2) def perimMeasure(self, inGeom, measure): value = 0.00 if inGeom.isMultipart(): poly = inGeom.asMultiPolygon() for k in poly: for j in k: value = value + measure.measureLine(j) else: poly = inGeom.asPolygon() for k in poly: value = value + measure.measureLine(k) return value