Skip to content

Commit 24c1c95

Browse files
committed
improved processing extract/select by location
1 parent 35eb5f6 commit 24c1c95

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

python/plugins/processing/algs/qgis/ftools/ExtractByLocation.py

+52-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from qgis.core import *
3030
from processing.core.GeoAlgorithm import GeoAlgorithm
3131
from processing.parameters.ParameterVector import ParameterVector
32+
from processing.parameters.ParameterBoolean import ParameterBoolean
3233
from processing.outputs.OutputVector import OutputVector
3334
from processing.tools import dataobjects, vector
3435

@@ -37,7 +38,15 @@ class ExtractByLocation(GeoAlgorithm):
3738

3839
INPUT = 'INPUT'
3940
INTERSECT = 'INTERSECT'
41+
TOUCHES = 'TOUCHES'
42+
OVERLAPS = 'OVERLAPS'
43+
WITHIN = 'WITHIN'
4044
OUTPUT = 'OUTPUT'
45+
46+
METHODS = ['creating new selection', 'adding to current selection',
47+
'removing from current selection']
48+
opFlags = 0
49+
operators = {'TOUCHES':1,'OVERLAPS':2,'WITHIN':4}
4150

4251
def defineCharacteristics(self):
4352
self.name = 'Extract by location'
@@ -47,6 +56,15 @@ def defineCharacteristics(self):
4756
self.addParameter(ParameterVector(self.INTERSECT,
4857
'Additional layer (intersection layer)',
4958
[ParameterVector.VECTOR_TYPE_ANY]))
59+
self.addParameter(ParameterBoolean(self.TOUCHES,
60+
'Include input features that touch the selection features',
61+
[True]))
62+
self.addParameter(ParameterBoolean(self.OVERLAPS,
63+
'Include input features that overlap/cross the selection features',
64+
[True]))
65+
self.addParameter(ParameterBoolean(self.WITHIN,
66+
'Include input features completely within the selection features',
67+
[True]))
5068
self.addOutput(OutputVector(self.OUTPUT, 'Selection'))
5169

5270
def processAlgorithm(self, progress):
@@ -55,6 +73,39 @@ def processAlgorithm(self, progress):
5573
filename = self.getParameterValue(self.INTERSECT)
5674
selectLayer = dataobjects.getObjectFromUri(filename)
5775
index = vector.spatialindex(layer)
76+
77+
def _points_op(geomA,geomB):
78+
return geomA.intersects(geomB)
79+
80+
def _poly_lines_op(geomA,geomB):
81+
if geomA.disjoint(geomB):
82+
return False
83+
intersects = False
84+
if self.opFlags & self.operators['TOUCHES']:
85+
intersects |= geomA.touches(geomB)
86+
if not intersects and (self.opFlags & self.operators['OVERLAPS']):
87+
if geomB.type() == QGis.Line or geomA.type() == QGis.Line:
88+
intersects |= geomA.crosses(geomB)
89+
intersects |= geomA.overlaps(geomB)
90+
if not intersects and (self.opFlags & self.operators['WITHIN']):
91+
intersects |= geomA.contains(geomB)
92+
return intersects
93+
94+
def _sp_operator():
95+
if layer.geometryType() == QGis.Point:
96+
return _points_op
97+
else:
98+
return _poly_lines_op
99+
100+
self.opFlags = 0
101+
if self.getParameterValue(self.TOUCHES):
102+
self.opFlags |= self.operators['TOUCHES']
103+
if self.getParameterValue(self.OVERLAPS):
104+
self.opFlags |= self.operators['OVERLAPS']
105+
if self.getParameterValue(self.WITHIN):
106+
self.opFlags |= self.operators['WITHIN']
107+
108+
sp_operator = _sp_operator()
58109

59110
output = self.getOutputFromName(self.OUTPUT)
60111
writer = output.getVectorWriter(layer.pendingFields(),
@@ -73,7 +124,7 @@ def processAlgorithm(self, progress):
73124
request = QgsFeatureRequest().setFilterFid(i)
74125
feat = layer.getFeatures(request).next()
75126
tmpGeom = QgsGeometry(feat.geometry())
76-
if geom.intersects(tmpGeom):
127+
if sp_operator(geom,tmpGeom):
77128
selectedSet.append(feat.id())
78129
progress.setPercentage(int(current * total))
79130

python/plugins/processing/algs/qgis/ftools/SelectByLocation.py

+49-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
from processing.core.GeoAlgorithm import GeoAlgorithm
3131
from processing.parameters.ParameterSelection import ParameterSelection
3232
from processing.parameters.ParameterVector import ParameterVector
33+
from processing.parameters.ParameterBoolean import ParameterBoolean
3334
from processing.outputs.OutputVector import OutputVector
3435
from processing.tools import dataobjects, vector
3536

@@ -38,11 +39,16 @@ class SelectByLocation(GeoAlgorithm):
3839

3940
INPUT = 'INPUT'
4041
INTERSECT = 'INTERSECT'
42+
TOUCHES = 'TOUCHES'
43+
OVERLAPS = 'OVERLAPS'
44+
WITHIN = 'WITHIN'
4145
METHOD = 'METHOD'
4246
OUTPUT = 'OUTPUT'
4347

4448
METHODS = ['creating new selection', 'adding to current selection',
4549
'removing from current selection']
50+
opFlags = 0
51+
operators = {'TOUCHES':1,'OVERLAPS':2,'WITHIN':4}
4652

4753

4854
def defineCharacteristics(self):
@@ -53,6 +59,15 @@ def defineCharacteristics(self):
5359
self.addParameter(ParameterVector(self.INTERSECT,
5460
'Additional layer (intersection layer)',
5561
[ParameterVector.VECTOR_TYPE_ANY]))
62+
self.addParameter(ParameterBoolean(self.TOUCHES,
63+
'Include input features that touch the selection features',
64+
[True]))
65+
self.addParameter(ParameterBoolean(self.OVERLAPS,
66+
'Include input features that overlap/cross the selection features',
67+
[True]))
68+
self.addParameter(ParameterBoolean(self.WITHIN,
69+
'Include input features completely within the selection features',
70+
[True]))
5671
self.addParameter(ParameterSelection(self.METHOD,
5772
'Modify current selection by', self.METHODS, 0))
5873
self.addOutput(OutputVector(self.OUTPUT, 'Selection', True))
@@ -66,6 +81,39 @@ def processAlgorithm(self, progress):
6681

6782
oldSelection = set(inputLayer.selectedFeaturesIds())
6883
index = vector.spatialindex(inputLayer)
84+
85+
def _points_op(geomA,geomB):
86+
return geomA.intersects(geomB)
87+
88+
def _poly_lines_op(geomA,geomB):
89+
if geomA.disjoint(geomB):
90+
return False
91+
intersects = False
92+
if self.opFlags & self.operators['TOUCHES']:
93+
intersects |= geomA.touches(geomB)
94+
if not intersects and (self.opFlags & self.operators['OVERLAPS']):
95+
if geomB.type() == QGis.Line or geomA.type() == QGis.Line:
96+
intersects |= geomA.crosses(geomB)
97+
intersects |= geomA.overlaps(geomB)
98+
if not intersects and (self.opFlags & self.operators['WITHIN']):
99+
intersects |= geomA.contains(geomB)
100+
return intersects
101+
102+
def _sp_operator():
103+
if inputLayer.geometryType() == QGis.Point:
104+
return _points_op
105+
else:
106+
return _poly_lines_op
107+
108+
self.opFlags = 0
109+
if self.getParameterValue(self.TOUCHES):
110+
self.opFlags |= self.operators['TOUCHES']
111+
if self.getParameterValue(self.OVERLAPS):
112+
self.opFlags |= self.operators['OVERLAPS']
113+
if self.getParameterValue(self.WITHIN):
114+
self.opFlags |= self.operators['WITHIN']
115+
116+
sp_operator = _sp_operator()
69117

70118
geom = QgsGeometry()
71119
selectedSet = []
@@ -79,7 +127,7 @@ def processAlgorithm(self, progress):
79127
request = QgsFeatureRequest().setFilterFid(i)
80128
feat = inputLayer.getFeatures(request).next()
81129
tmpGeom = QgsGeometry(feat.geometry())
82-
if geom.intersects(tmpGeom):
130+
if sp_operator(geom,tmpGeom):
83131
selectedSet.append(feat.id())
84132
current += 1
85133
progress.setPercentage(int(current * total))

0 commit comments

Comments
 (0)