# -*- 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 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: Symetrical 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.symetrical_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() == 0: 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() == 0: 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() == 0: 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() == 0: 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() == 0: # 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() == 0: 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 symetrical_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() == 0: 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() == 0: 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() == 0: 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() == 0: 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