Skip to content

Commit d3ad913

Browse files
authoredJul 13, 2017
[processing] restore intersection algorithm (#4849)
1 parent 93a8025 commit d3ad913

File tree

3 files changed

+59
-43
lines changed

3 files changed

+59
-43
lines changed
 

‎python/plugins/processing/algs/qgis/Intersection.py

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@
3434
QgsFeatureSink,
3535
QgsGeometry,
3636
QgsWkbTypes,
37-
QgsMessageLog,
37+
QgsProcessingParameterFeatureSource,
38+
QgsProcessingParameterFeatureSink,
39+
QgsSpatialIndex,
3840
QgsProcessingUtils)
3941

4042
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
4143
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
42-
from processing.core.parameters import ParameterVector
43-
from processing.core.outputs import OutputVector
4444
from processing.tools import vector
4545

4646
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
@@ -58,7 +58,7 @@
5858
class Intersection(QgisAlgorithm):
5959

6060
INPUT = 'INPUT'
61-
INPUT2 = 'INPUT2'
61+
OVERLAY = 'OVERLAY'
6262
OUTPUT = 'OUTPUT'
6363

6464
def icon(self):
@@ -71,11 +71,12 @@ def __init__(self):
7171
super().__init__()
7272

7373
def initAlgorithm(self, config=None):
74-
self.addParameter(ParameterVector(self.INPUT,
75-
self.tr('Input layer')))
76-
self.addParameter(ParameterVector(self.INPUT2,
77-
self.tr('Intersect layer')))
78-
self.addOutput(OutputVector(self.OUTPUT, self.tr('Intersection')))
74+
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
75+
self.tr('Input layer')))
76+
self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY,
77+
self.tr('Intersection layer')))
78+
79+
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Intersection')))
7980

8081
def name(self):
8182
return 'intersection'
@@ -84,33 +85,45 @@ def displayName(self):
8485
return self.tr('Intersection')
8586

8687
def processAlgorithm(self, parameters, context, feedback):
87-
vlayerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
88-
vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT2), context)
88+
sourceA = self.parameterAsSource(parameters, self.INPUT, context)
89+
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
90+
91+
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
92+
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
93+
94+
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
95+
fields, geomType, sourceA.sourceCrs())
8996

90-
geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
91-
fields = vector.combineVectorFields(vlayerA, vlayerB)
92-
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context)
9397
outFeat = QgsFeature()
94-
index = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
95-
selectionA = QgsProcessingUtils.getFeatures(vlayerA, context)
96-
total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0
97-
for current, inFeatA in enumerate(selectionA):
98-
feedback.setProgress(int(current * total))
99-
geom = inFeatA.geometry()
100-
atMapA = inFeatA.attributes()
101-
intersects = index.intersects(geom.boundingBox())
98+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
99+
100+
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
101+
count = 0
102+
103+
for featA in sourceA.getFeatures():
104+
if feedback.isCanceled():
105+
break
106+
107+
geom = featA.geometry()
108+
atMapA = featA.attributes()
109+
intersects = indexB.intersects(geom.boundingBox())
110+
102111
request = QgsFeatureRequest().setFilterFids(intersects)
112+
request.setDestinationCrs(sourceA.sourceCrs())
103113

104114
engine = None
105115
if len(intersects) > 0:
106116
# use prepared geometries for faster intersection tests
107117
engine = QgsGeometry.createGeometryEngine(geom.geometry())
108118
engine.prepareGeometry()
109119

110-
for inFeatB in vlayerB.getFeatures(request):
111-
tmpGeom = inFeatB.geometry()
120+
for featB in sourceB.getFeatures(request):
121+
if feedback.isCanceled():
122+
break
123+
124+
tmpGeom = featB.geometry()
112125
if engine.intersects(tmpGeom.geometry()):
113-
atMapB = inFeatB.attributes()
126+
atMapB = featB.attributes()
114127
int_geom = QgsGeometry(geom.intersection(tmpGeom))
115128
if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
116129
int_com = geom.combine(tmpGeom)
@@ -130,11 +143,14 @@ def processAlgorithm(self, parameters, context, feedback):
130143
attrs.extend(atMapA)
131144
attrs.extend(atMapB)
132145
outFeat.setAttributes(attrs)
133-
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
146+
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
134147
except:
135148
raise GeoAlgorithmExecutionException(
136149
self.tr('Feature geometry error: One or more '
137150
'output features ignored due to invalid '
138151
'geometry.'))
139152

140-
del writer
153+
count += 1
154+
feedback.setProgress(int(count * total))
155+
156+
return {self.OUTPUT: dest_id}

‎python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
from .GridPolygon import GridPolygon
6262
from .ImportIntoPostGIS import ImportIntoPostGIS
6363
from .ImportIntoSpatialite import ImportIntoSpatialite
64+
from .Intersection import Intersection
6465
from .Merge import Merge
6566
from .PointsLayerFromTable import PointsLayerFromTable
6667
from .PostGISExecuteSQL import PostGISExecuteSQL
@@ -98,7 +99,6 @@
9899
# from .ConvexHull import ConvexHull
99100
# from .FixedDistanceBuffer import FixedDistanceBuffer
100101
# from .VariableDistanceBuffer import VariableDistanceBuffer
101-
# from .Intersection import Intersection
102102
# from .RandomSelection import RandomSelection
103103
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
104104
# from .SelectByLocation import SelectByLocation
@@ -194,7 +194,6 @@ def getAlgs(self):
194194
# PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
195195
# ConvexHull(), FixedDistanceBuffer(),
196196
# VariableDistanceBuffer(),
197-
# Intersection(),
198197
# RandomSelection(), RandomSelectionWithinSubsets(),
199198
# SelectByLocation(),
200199
# ExtractByLocation(),
@@ -260,6 +259,7 @@ def getAlgs(self):
260259
GridPolygon(),
261260
ImportIntoPostGIS(),
262261
ImportIntoSpatialite(),
262+
Intersection(),
263263
Merge(),
264264
PointsLayerFromTable(),
265265
PostGISExecuteSQL(),

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,20 +115,20 @@ tests:
115115
# # check this behavior.
116116
# # This test should stay in place because for shapefiles there should always
117117
# # be a polygon result created since it does not support geometry collections.
118-
# - name: Intersection (Collection Fallback)
119-
# algorithm: qgis:intersection
120-
# params:
121-
# INPUT:
122-
# name: multipolys.gml
123-
# type: vector
124-
# INPUT2:
125-
# name: polys.gml
126-
# type: vector
127-
# results:
128-
# OUTPUT:
129-
# name: expected/intersection_collection_fallback.shp
130-
# type: vector
131-
#
118+
- algorithm: qgis:intersection
119+
name: Intersects multipolygons with polygons
120+
params:
121+
INPUT:
122+
name: multipolys.gml
123+
type: vector
124+
OVERLAY:
125+
name: polys.gml
126+
type: vector
127+
results:
128+
OUTPUT:
129+
name: expected/intersection_collection_fallback.shp
130+
type: vector
131+
132132
- name: Densify geometries
133133
algorithm: qgis:densifygeometries
134134
params:

0 commit comments

Comments
 (0)
Please sign in to comment.