[processing] restore difference algorithm

This commit is contained in:
Mathieu Pellerin 2017-07-11 17:00:44 +07:00 committed by GitHub
parent 1bc0b365d6
commit 18b52b22f1
2 changed files with 54 additions and 39 deletions

View File

@ -29,16 +29,19 @@ import os
from qgis.PyQt.QtGui import QIcon
from qgis.core import (QgsFeatureRequest,
QgsFeature,
from qgis.core import (QgsFeature,
QgsFeatureSink,
QgsGeometry,
QgsFeatureRequest,
NULL,
QgsWkbTypes,
QgsMessageLog,
QgsProcessingUtils)
QgsProcessingUtils,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputVectorLayer,
QgsSpatialIndex)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@ -47,7 +50,6 @@ class Difference(QgisAlgorithm):
INPUT = 'INPUT'
OVERLAY = 'OVERLAY'
IGNORE_INVALID = 'IGNORE_INVALID'
OUTPUT = 'OUTPUT'
def icon(self):
@ -60,11 +62,13 @@ class Difference(QgisAlgorithm):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(Difference.INPUT,
self.tr('Input layer')))
self.addParameter(ParameterVector(Difference.OVERLAY,
self.tr('Difference layer')))
self.addOutput(OutputVector(Difference.OUTPUT, self.tr('Difference')))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY,
self.tr('Difference layer')))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Difference')))
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Difference')))
def name(self):
return 'difference'
@ -73,37 +77,47 @@ class Difference(QgisAlgorithm):
return self.tr('Difference')
def processAlgorithm(self, parameters, context, feedback):
layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Difference.INPUT), context)
layerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Difference.OVERLAY), context)
sourceA = self.parameterAsSource(parameters, self.INPUT, context)
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
geomType = QgsWkbTypes.multiType(layerA.wkbType())
writer = self.getOutputFromName(
Difference.OUTPUT).getVectorWriter(layerA.fields(), geomType, layerA.crs(), context)
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
sourceA.fields(), geomType, sourceA.sourceCrs())
featB = QgsFeature()
outFeat = QgsFeature()
index = QgsProcessingUtils.createSpatialIndex(layerB, context)
selectionA = QgsProcessingUtils.getFeatures(layerA, context)
total = 100.0 / layerA.featureCount() if layerA.featureCount() else 0
for current, inFeatA in enumerate(selectionA):
geom = inFeatA.geometry()
diff_geom = QgsGeometry(geom)
attrs = inFeatA.attributes()
intersections = index.intersects(geom.boundingBox())
request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([])
for inFeatB in layerB.getFeatures(request):
tmpGeom = inFeatB.geometry()
if diff_geom.intersects(tmpGeom):
diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
try:
outFeat.setGeometry(diff_geom)
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
count = 0
for featA in sourceA.getFeatures():
if feedback.isCanceled():
break
if featA.hasGeometry():
geom = featA.geometry()
diffGeom = QgsGeometry(geom)
attrs = featA.attributes()
intersects = indexB.intersects(geom.boundingBox())
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
request.setDestinationCrs(sourceA.sourceCrs())
for featB in sourceB.getFeatures(request):
if feedback.isCanceled():
break
tmpGeom = featB.geometry()
if diffGeom.intersects(tmpGeom):
diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
outFeat.setGeometry(diffGeom)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
except:
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING)
continue
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
else:
sink.addFeature(featA, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
count += 1
feedback.setProgress(int(count * total))
del writer
return {self.OUTPUT: dest_id}

View File

@ -54,6 +54,7 @@ from .DeleteColumn import DeleteColumn
from .DeleteHoles import DeleteHoles
from .DensifyGeometries import DensifyGeometries
from .DensifyGeometriesInterval import DensifyGeometriesInterval
from .Difference import Difference
from .DropGeometry import DropGeometry
from .ExtentFromLayer import ExtentFromLayer
from .FixGeometry import FixGeometry
@ -96,7 +97,6 @@ from .ZonalStatistics import ZonalStatistics
# from .ConvexHull import ConvexHull
# from .FixedDistanceBuffer import FixedDistanceBuffer
# from .VariableDistanceBuffer import VariableDistanceBuffer
# from .Difference import Difference
# from .Intersection import Intersection
# from .RandomSelection import RandomSelection
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
@ -193,7 +193,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# , SinglePartsToMultiparts(),
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
# ConvexHull(), FixedDistanceBuffer(),
# VariableDistanceBuffer(), Difference(),
# VariableDistanceBuffer(),
# Intersection(), Union(),
# RandomSelection(), RandomSelectionWithinSubsets(),
# SelectByLocation(),
@ -253,6 +253,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
DeleteHoles(),
DensifyGeometries(),
DensifyGeometriesInterval(),
Difference(),
DropGeometry(),
ExtentFromLayer(),
FixGeometry(),