mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Restore symmetrical difference alg
This commit is contained in:
parent
66d1a588ae
commit
6be4875a82
@ -59,8 +59,8 @@ from .ImportIntoPostGIS import ImportIntoPostGIS
|
||||
from .Merge import Merge
|
||||
from .PostGISExecuteSQL import PostGISExecuteSQL
|
||||
from .RegularPoints import RegularPoints
|
||||
from .SymmetricalDifference import SymmetricalDifference
|
||||
|
||||
# from .SymmetricalDifference import SymmetricalDifference
|
||||
# from .VectorSplit import VectorSplit
|
||||
# from .RandomExtract import RandomExtract
|
||||
# from .RandomExtractWithinSubsets import RandomExtractWithinSubsets
|
||||
@ -200,7 +200,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
# RandomSelection(), RandomSelectionWithinSubsets(),
|
||||
# SelectByLocation(), RandomExtract(),
|
||||
# RandomExtractWithinSubsets(), ExtractByLocation(),
|
||||
# SpatialJoin(), SymmetricalDifference(),
|
||||
# SpatialJoin(),
|
||||
# VectorSplit(),
|
||||
# DeleteDuplicateGeometries(), TextToFloat(),
|
||||
# SelectByAttribute(),
|
||||
@ -262,7 +262,8 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
|
||||
ImportIntoPostGIS(),
|
||||
Merge(),
|
||||
PostGISExecuteSQL(),
|
||||
RegularPoints()
|
||||
RegularPoints(),
|
||||
SymmetricalDifference()
|
||||
]
|
||||
|
||||
if hasPlotly:
|
||||
|
@ -35,10 +35,12 @@ from qgis.core import (QgsFeature,
|
||||
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
|
||||
from processing.tools import vector
|
||||
|
||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
|
||||
@ -58,12 +60,14 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.addParameter(ParameterVector(self.INPUT,
|
||||
self.tr('Input layer')))
|
||||
self.addParameter(ParameterVector(self.OVERLAY,
|
||||
self.tr('Difference layer')))
|
||||
self.addOutput(OutputVector(self.OUTPUT,
|
||||
self.tr('Symmetrical 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('Symmetrical difference')))
|
||||
self.addOutput(QgsProcessingOutputVectorLayer(self.OUTPUT, self.tr('Symmetrical difference')))
|
||||
|
||||
def name(self):
|
||||
return 'symmetricaldifference'
|
||||
@ -72,32 +76,37 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
return self.tr('Symmetrical difference')
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
|
||||
layerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.OVERLAY), context)
|
||||
sourceA = self.parameterAsSource(parameters, self.INPUT, context)
|
||||
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
|
||||
|
||||
geomType = QgsWkbTypes.multiType(layerA.wkbType())
|
||||
fields = vector.combineVectorFields(layerA, layerB)
|
||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, layerA.crs(), context)
|
||||
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
|
||||
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
|
||||
|
||||
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
|
||||
fields, geomType, sourceA.sourceCrs())
|
||||
|
||||
featB = QgsFeature()
|
||||
outFeat = QgsFeature()
|
||||
|
||||
indexA = QgsProcessingUtils.createSpatialIndex(layerB, context)
|
||||
indexB = QgsProcessingUtils.createSpatialIndex(layerA, context)
|
||||
indexA = QgsSpatialIndex(sourceA)
|
||||
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
|
||||
|
||||
featuresA = QgsProcessingUtils.getFeatures(layerA, context)
|
||||
featuresB = QgsProcessingUtils.getFeatures(layerB, context)
|
||||
|
||||
total = 100.0 / (QgsProcessingUtils.featureCount(layerA, context) * QgsProcessingUtils.featureCount(layerB, context))
|
||||
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount())
|
||||
count = 0
|
||||
|
||||
for featA in featuresA:
|
||||
for featA in sourceA.getFeatures():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
geom = featA.geometry()
|
||||
diffGeom = QgsGeometry(geom)
|
||||
attrs = featA.attributes()
|
||||
intersects = indexA.intersects(geom.boundingBox())
|
||||
intersects = indexB.intersects(geom.boundingBox())
|
||||
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
|
||||
for featB in layerB.getFeatures(request):
|
||||
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))
|
||||
@ -105,7 +114,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
try:
|
||||
outFeat.setGeometry(diffGeom)
|
||||
outFeat.setAttributes(attrs)
|
||||
writer.addFeature(outFeat)
|
||||
sink.addFeature(outFeat)
|
||||
except:
|
||||
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
@ -114,16 +123,22 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
|
||||
length = len(layerA.fields())
|
||||
length = len(sourceA.fields())
|
||||
|
||||
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
for featA in featuresB:
|
||||
geom = featA.geometry()
|
||||
diffGeom = QgsGeometry(geom)
|
||||
attrs = featA.attributes()
|
||||
attrs = [NULL] * length + attrs
|
||||
intersects = indexB.intersects(geom.boundingBox())
|
||||
intersects = indexA.intersects(geom.boundingBox())
|
||||
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
|
||||
for featB in layerA.getFeatures(request):
|
||||
for featB in sourceA.getFeatures(request):
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
tmpGeom = featB.geometry()
|
||||
if diffGeom.intersects(tmpGeom):
|
||||
diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
|
||||
@ -131,7 +146,7 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
try:
|
||||
outFeat.setGeometry(diffGeom)
|
||||
outFeat.setAttributes(attrs)
|
||||
writer.addFeature(outFeat)
|
||||
sink.addFeature(outFeat)
|
||||
except:
|
||||
QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'),
|
||||
self.tr('Processing'), QgsMessageLog.WARNING)
|
||||
@ -140,4 +155,4 @@ class SymmetricalDifference(QgisAlgorithm):
|
||||
count += 1
|
||||
feedback.setProgress(int(count * total))
|
||||
|
||||
del writer
|
||||
return {self.OUTPUT: dest_id}
|
||||
|
@ -84,7 +84,7 @@ class Union(QgisAlgorithm):
|
||||
vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Union.INPUT2), context)
|
||||
|
||||
geomType = vlayerA.wkbType()
|
||||
fields = vector.combineVectorFields(vlayerA, vlayerB)
|
||||
fields = vector.combineFields(vlayerA.fields(), vlayerB.fields())
|
||||
writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context)
|
||||
inFeatA = QgsFeature()
|
||||
inFeatB = QgsFeature()
|
||||
|
@ -228,14 +228,12 @@ def simpleMeasure(geom, method=0, ellips=None, crs=None):
|
||||
return (attr1, attr2)
|
||||
|
||||
|
||||
def combineVectorFields(layerA, layerB):
|
||||
def combineFields(fieldsA, fieldsB):
|
||||
"""Create single field map from two input field maps.
|
||||
"""
|
||||
fields = []
|
||||
fieldsA = layerA.fields()
|
||||
fields.extend(fieldsA)
|
||||
namesA = [str(f.name()).lower() for f in fieldsA]
|
||||
fieldsB = layerB.fields()
|
||||
for field in fieldsB:
|
||||
name = str(field.name()).lower()
|
||||
if name in namesA:
|
||||
|
Loading…
x
Reference in New Issue
Block a user