Skip to content
Permalink
Browse files

Merge pull request #1759 from arnaud-morvan/processing_bylocation_ope…

…rators

Processing bylocation operators
  • Loading branch information
volaya committed Feb 8, 2015
2 parents b1a2ccd + 84936e5 commit afd21cd79f35c22018426bf1f91ec2cba6b3061a
@@ -28,7 +28,7 @@
from qgis.core import QGis, QgsFeatureRequest, QgsGeometry
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterGeometryPredicate
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector

@@ -37,100 +37,86 @@ class ExtractByLocation(GeoAlgorithm):

INPUT = 'INPUT'
INTERSECT = 'INTERSECT'
TOUCHES = 'TOUCHES'
OVERLAPS = 'OVERLAPS'
WITHIN = 'WITHIN'
PREDICATE = 'PREDICATE'
OUTPUT = 'OUTPUT'

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

def defineCharacteristics(self):
self.name = 'Extract by location'
self.group = 'Vector selection tools'
self.addParameter(ParameterVector(self.INPUT,
self.tr('Layer to select from'), [ParameterVector.VECTOR_TYPE_ANY]))
self.tr('Layer to select from'),
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterVector(self.INTERSECT,
self.tr('Additional layer (intersection layer)'),
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterBoolean(
self.TOUCHES,
self.tr('Include input features that touch the selection features'),
[True]))
self.addParameter(ParameterBoolean(
self.OVERLAPS,
self.tr('Include input features that overlap/cross the selection features'),
[True]))
self.addParameter(ParameterBoolean(
self.WITHIN,
self.tr('Include input features completely within the selection features'),
[True]))
self.addParameter(ParameterGeometryPredicate(self.PREDICATE,
self.tr('Geometric predicate'),
left=self.INPUT, right=self.INTERSECT))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Selection')))

def processAlgorithm(self, progress):
filename = self.getParameterValue(self.INPUT)
layer = dataobjects.getObjectFromUri(filename)
filename = self.getParameterValue(self.INTERSECT)
selectLayer = dataobjects.getObjectFromUri(filename)
index = vector.spatialindex(layer)
predicates = self.getParameterValue(self.PREDICATE)

def _points_op(geomA,geomB):
return geomA.intersects(geomB)

def _poly_lines_op(geomA,geomB):
if geomA.disjoint(geomB):
return False
intersects = False
if self.opFlags & self.operators['TOUCHES']:
intersects |= geomA.touches(geomB)
if not intersects and (self.opFlags & self.operators['OVERLAPS']):
if geomB.type() == QGis.Line or geomA.type() == QGis.Line:
intersects |= geomA.crosses(geomB)
else:
intersects |= geomA.overlaps(geomB)
if not intersects and (self.opFlags & self.operators['WITHIN']):
intersects |= geomA.contains(geomB)
return intersects

def _sp_operator():
if layer.geometryType() == QGis.Point:
return _points_op
else:
return _poly_lines_op

self.opFlags = 0
if self.getParameterValue(self.TOUCHES):
self.opFlags |= self.operators['TOUCHES']
if self.getParameterValue(self.OVERLAPS):
self.opFlags |= self.operators['OVERLAPS']
if self.getParameterValue(self.WITHIN):
self.opFlags |= self.operators['WITHIN']

sp_operator = _sp_operator()
index = vector.spatialindex(layer)

output = self.getOutputFromName(self.OUTPUT)
writer = output.getVectorWriter(layer.pendingFields(),
layer.dataProvider().geometryType(), layer.crs())

if 'disjoint' in predicates:
disjoinSet = []
for feat in vector.features(layer):
disjoinSet.append(feat.id())

geom = QgsGeometry()
selectedSet = []
current = 0
features = vector.features(selectLayer)
featureCount = len(features)
total = 100.0 / float(len(features))
for current,f in enumerate(features):
for current, f in enumerate(features):
geom = QgsGeometry(f.geometry())
intersects = index.intersects(geom.boundingBox())
for i in intersects:
request = QgsFeatureRequest().setFilterFid(i)
feat = layer.getFeatures(request).next()
tmpGeom = QgsGeometry(feat.geometry())
if sp_operator(geom,tmpGeom):
selectedSet.append(feat.id())
res = False
for predicate in predicates:
if predicate == 'disjoint':
if tmpGeom.intersects(geom):
try:
disjoinSet.remove(feat.id())
except:
pass # already removed
else:
if predicate == 'intersects':
res = tmpGeom.intersects()
elif predicate == 'contains':
res = tmpGeom.contains(geom)
elif predicate == 'equals':
res = tmpGeom.equals(geom)
elif predicate == 'touches':
res = tmpGeom.touches(geom)
elif predicate == 'overlaps':
res = tmpGeom.overlaps(geom)
elif predicate == 'within':
res = tmpGeom.within(geom)
elif predicate == 'crosses':
res = tmpGeom.crosses(geom)
if res:
selectedSet.append(feat.id())
break

progress.setPercentage(int(current * total))

if 'disjoint' in predicates:
selectedSet = selectedSet + disjoinSet

for i, f in enumerate(vector.features(layer)):
if f.id() in selectedSet:
writer.addFeature(f)
@@ -29,7 +29,7 @@
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterSelection
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterGeometryPredicate
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector

@@ -38,83 +38,47 @@ class SelectByLocation(GeoAlgorithm):

INPUT = 'INPUT'
INTERSECT = 'INTERSECT'
TOUCHES = 'TOUCHES'
OVERLAPS = 'OVERLAPS'
WITHIN = 'WITHIN'
PREDICATE = 'PREDICATE'
METHOD = 'METHOD'
OUTPUT = 'OUTPUT'

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


def defineCharacteristics(self):
self.name = 'Select by location'
self.group = 'Vector selection tools'
self.addParameter(ParameterVector(self.INPUT, 'Layer to select from',
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterVector(self.INPUT,
self.tr('Layer to select from'),
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterVector(self.INTERSECT,
'Additional layer (intersection layer)',
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterBoolean(self.TOUCHES,
'Include input features that touch the selection features',
[True]))
self.addParameter(ParameterBoolean(self.OVERLAPS,
'Include input features that overlap/cross the selection features',
[True]))
self.addParameter(ParameterBoolean(self.WITHIN,
'Include input features completely within the selection features',
[True]))
self.tr('Additional layer (intersection layer)'),
[ParameterVector.VECTOR_TYPE_ANY]))
self.addParameter(ParameterGeometryPredicate(self.PREDICATE,
self.tr('Geometric predicate'),
left=self.INPUT, right=self.INTERSECT))
self.addParameter(ParameterSelection(self.METHOD,
'Modify current selection by', self.METHODS, 0))
self.addOutput(OutputVector(self.OUTPUT, 'Selection', True))
self.tr('Modify current selection by'),
self.METHODS, 0))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Selection'), True))

def processAlgorithm(self, progress):
filename = self.getParameterValue(self.INPUT)
inputLayer = dataobjects.getObjectFromUri(filename)
method = self.getParameterValue(self.METHOD)
filename = self.getParameterValue(self.INTERSECT)
selectLayer = dataobjects.getObjectFromUri(filename)
predicates = self.getParameterValue(self.PREDICATE)

oldSelection = set(inputLayer.selectedFeaturesIds())
inputLayer.removeSelection()
index = vector.spatialindex(inputLayer)

def _points_op(geomA,geomB):
return geomA.intersects(geomB)

def _poly_lines_op(geomA,geomB):
if geomA.disjoint(geomB):
return False
intersects = False
if self.opFlags & self.operators['TOUCHES']:
intersects |= geomA.touches(geomB)
if not intersects and (self.opFlags & self.operators['OVERLAPS']):
if geomB.type() == QGis.Line or geomA.type() == QGis.Line:
intersects |= geomA.crosses(geomB)
else:
intersects |= geomA.overlaps(geomB)
if not intersects and (self.opFlags & self.operators['WITHIN']):
intersects |= geomA.contains(geomB)
return intersects

def _sp_operator():
if inputLayer.geometryType() == QGis.Point:
return _points_op
else:
return _poly_lines_op

self.opFlags = 0
if self.getParameterValue(self.TOUCHES):
self.opFlags |= self.operators['TOUCHES']
if self.getParameterValue(self.OVERLAPS):
self.opFlags |= self.operators['OVERLAPS']
if self.getParameterValue(self.WITHIN):
self.opFlags |= self.operators['WITHIN']

sp_operator = _sp_operator()
if 'disjoint' in predicates:
disjoinSet = []
for feat in vector.features(inputLayer):
disjoinSet.append(feat.id())

geom = QgsGeometry()
selectedSet = []
@@ -123,16 +87,45 @@ def _sp_operator():
total = 100.0 / float(len(features))
for f in features:
geom = QgsGeometry(f.geometry())

intersects = index.intersects(geom.boundingBox())
for i in intersects:
request = QgsFeatureRequest().setFilterFid(i)
feat = inputLayer.getFeatures(request).next()
tmpGeom = QgsGeometry(feat.geometry())
if sp_operator(geom,tmpGeom):
selectedSet.append(feat.id())
res = False
for predicate in predicates:
if predicate == 'disjoint':
if tmpGeom.intersects(geom):
try:
disjoinSet.remove(feat.id())
except:
pass # already removed
else:
if predicate == 'intersects':
res = tmpGeom.intersects()
elif predicate == 'contains':
res = tmpGeom.contains(geom)
elif predicate == 'equals':
res = tmpGeom.equals(geom)
elif predicate == 'touches':
res = tmpGeom.touches(geom)
elif predicate == 'overlaps':
res = tmpGeom.overlaps(geom)
elif predicate == 'within':
res = tmpGeom.within(geom)
elif predicate == 'crosses':
res = tmpGeom.crosses(geom)
if res:
selectedSet.append(feat.id())
break

current += 1
progress.setPercentage(int(current * total))

if 'disjoint' in predicates:
selectedSet = selectedSet + disjoinSet

if method == 1:
selectedSet = list(oldSelection.union(selectedSet))
elif method == 2:

0 comments on commit afd21cd

Please sign in to comment.
You can’t perform that action at this time.