QGIS/python/plugins/fTools/tools/doGeoprocessing.py
2015-11-24 16:29:35 +01:00

1639 lines
76 KiB
Python

# -*- 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(int_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(int_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(int_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(int_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(int_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