[processing] restore intersection algorithm (#4849)

This commit is contained in:
Mathieu Pellerin 2017-07-13 11:07:01 +07:00 committed by GitHub
parent 93a8025bb2
commit d3ad9131f4
3 changed files with 59 additions and 43 deletions

View File

@ -34,13 +34,13 @@ from qgis.core import (QgsFeatureRequest,
QgsFeatureSink,
QgsGeometry,
QgsWkbTypes,
QgsMessageLog,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsSpatialIndex,
QgsProcessingUtils)
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
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,7 +58,7 @@ for key, value in list(wkbTypeGroups.items()):
class Intersection(QgisAlgorithm):
INPUT = 'INPUT'
INPUT2 = 'INPUT2'
OVERLAY = 'OVERLAY'
OUTPUT = 'OUTPUT'
def icon(self):
@ -71,11 +71,12 @@ class Intersection(QgisAlgorithm):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer')))
self.addParameter(ParameterVector(self.INPUT2,
self.tr('Intersect layer')))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Intersection')))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY,
self.tr('Intersection layer')))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Intersection')))
def name(self):
return 'intersection'
@ -84,22 +85,31 @@ class Intersection(QgisAlgorithm):
return self.tr('Intersection')
def processAlgorithm(self, parameters, context, feedback):
vlayerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT2), context)
sourceA = self.parameterAsSource(parameters, self.INPUT, context)
sourceB = self.parameterAsSource(parameters, self.OVERLAY, 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())
geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
fields = vector.combineVectorFields(vlayerA, vlayerB)
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context)
outFeat = QgsFeature()
index = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
selectionA = QgsProcessingUtils.getFeatures(vlayerA, context)
total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0
for current, inFeatA in enumerate(selectionA):
feedback.setProgress(int(current * total))
geom = inFeatA.geometry()
atMapA = inFeatA.attributes()
intersects = index.intersects(geom.boundingBox())
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
count = 0
for featA in sourceA.getFeatures():
if feedback.isCanceled():
break
geom = featA.geometry()
atMapA = featA.attributes()
intersects = indexB.intersects(geom.boundingBox())
request = QgsFeatureRequest().setFilterFids(intersects)
request.setDestinationCrs(sourceA.sourceCrs())
engine = None
if len(intersects) > 0:
@ -107,10 +117,13 @@ class Intersection(QgisAlgorithm):
engine = QgsGeometry.createGeometryEngine(geom.geometry())
engine.prepareGeometry()
for inFeatB in vlayerB.getFeatures(request):
tmpGeom = inFeatB.geometry()
for featB in sourceB.getFeatures(request):
if feedback.isCanceled():
break
tmpGeom = featB.geometry()
if engine.intersects(tmpGeom.geometry()):
atMapB = inFeatB.attributes()
atMapB = featB.attributes()
int_geom = QgsGeometry(geom.intersection(tmpGeom))
if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
int_com = geom.combine(tmpGeom)
@ -130,11 +143,14 @@ class Intersection(QgisAlgorithm):
attrs.extend(atMapA)
attrs.extend(atMapB)
outFeat.setAttributes(attrs)
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
except:
raise GeoAlgorithmExecutionException(
self.tr('Feature geometry error: One or more '
'output features ignored due to invalid '
'geometry.'))
del writer
count += 1
feedback.setProgress(int(count * total))
return {self.OUTPUT: dest_id}

View File

@ -61,6 +61,7 @@ from .FixGeometry import FixGeometry
from .GridPolygon import GridPolygon
from .ImportIntoPostGIS import ImportIntoPostGIS
from .ImportIntoSpatialite import ImportIntoSpatialite
from .Intersection import Intersection
from .Merge import Merge
from .PointsLayerFromTable import PointsLayerFromTable
from .PostGISExecuteSQL import PostGISExecuteSQL
@ -98,7 +99,6 @@ from .ZonalStatistics import ZonalStatistics
# from .ConvexHull import ConvexHull
# from .FixedDistanceBuffer import FixedDistanceBuffer
# from .VariableDistanceBuffer import VariableDistanceBuffer
# from .Intersection import Intersection
# from .RandomSelection import RandomSelection
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
# from .SelectByLocation import SelectByLocation
@ -194,7 +194,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
# ConvexHull(), FixedDistanceBuffer(),
# VariableDistanceBuffer(),
# Intersection(),
# RandomSelection(), RandomSelectionWithinSubsets(),
# SelectByLocation(),
# ExtractByLocation(),
@ -260,6 +259,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
GridPolygon(),
ImportIntoPostGIS(),
ImportIntoSpatialite(),
Intersection(),
Merge(),
PointsLayerFromTable(),
PostGISExecuteSQL(),

View File

@ -115,20 +115,20 @@ tests:
# # check this behavior.
# # This test should stay in place because for shapefiles there should always
# # be a polygon result created since it does not support geometry collections.
# - name: Intersection (Collection Fallback)
# algorithm: qgis:intersection
# params:
# INPUT:
# name: multipolys.gml
# type: vector
# INPUT2:
# name: polys.gml
# type: vector
# results:
# OUTPUT:
# name: expected/intersection_collection_fallback.shp
# type: vector
#
- algorithm: qgis:intersection
name: Intersects multipolygons with polygons
params:
INPUT:
name: multipolys.gml
type: vector
OVERLAY:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/intersection_collection_fallback.shp
type: vector
- name: Densify geometries
algorithm: qgis:densifygeometries
params: