improved processing extract/select by location

This commit is contained in:
giohappy 2014-06-30 19:18:25 +02:00
parent 35eb5f604d
commit 24c1c95619
2 changed files with 101 additions and 2 deletions

View File

@ -29,6 +29,7 @@ from PyQt4.QtCore import *
from qgis.core import *
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterBoolean import ParameterBoolean
from processing.outputs.OutputVector import OutputVector
from processing.tools import dataobjects, vector
@ -37,7 +38,15 @@ class ExtractByLocation(GeoAlgorithm):
INPUT = 'INPUT'
INTERSECT = 'INTERSECT'
TOUCHES = 'TOUCHES'
OVERLAPS = 'OVERLAPS'
WITHIN = 'WITHIN'
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'
@ -47,6 +56,15 @@ class ExtractByLocation(GeoAlgorithm):
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.addOutput(OutputVector(self.OUTPUT, 'Selection'))
def processAlgorithm(self, progress):
@ -55,6 +73,39 @@ class ExtractByLocation(GeoAlgorithm):
filename = self.getParameterValue(self.INTERSECT)
selectLayer = dataobjects.getObjectFromUri(filename)
index = vector.spatialindex(layer)
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)
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()
output = self.getOutputFromName(self.OUTPUT)
writer = output.getVectorWriter(layer.pendingFields(),
@ -73,7 +124,7 @@ class ExtractByLocation(GeoAlgorithm):
request = QgsFeatureRequest().setFilterFid(i)
feat = layer.getFeatures(request).next()
tmpGeom = QgsGeometry(feat.geometry())
if geom.intersects(tmpGeom):
if sp_operator(geom,tmpGeom):
selectedSet.append(feat.id())
progress.setPercentage(int(current * total))

View File

@ -30,6 +30,7 @@ from qgis.core import *
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.parameters.ParameterSelection import ParameterSelection
from processing.parameters.ParameterVector import ParameterVector
from processing.parameters.ParameterBoolean import ParameterBoolean
from processing.outputs.OutputVector import OutputVector
from processing.tools import dataobjects, vector
@ -38,11 +39,16 @@ class SelectByLocation(GeoAlgorithm):
INPUT = 'INPUT'
INTERSECT = 'INTERSECT'
TOUCHES = 'TOUCHES'
OVERLAPS = 'OVERLAPS'
WITHIN = 'WITHIN'
METHOD = 'METHOD'
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):
@ -53,6 +59,15 @@ class SelectByLocation(GeoAlgorithm):
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.addParameter(ParameterSelection(self.METHOD,
'Modify current selection by', self.METHODS, 0))
self.addOutput(OutputVector(self.OUTPUT, 'Selection', True))
@ -66,6 +81,39 @@ class SelectByLocation(GeoAlgorithm):
oldSelection = set(inputLayer.selectedFeaturesIds())
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)
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()
geom = QgsGeometry()
selectedSet = []
@ -79,7 +127,7 @@ class SelectByLocation(GeoAlgorithm):
request = QgsFeatureRequest().setFilterFid(i)
feat = inputLayer.getFeatures(request).next()
tmpGeom = QgsGeometry(feat.geometry())
if geom.intersects(tmpGeom):
if sp_operator(geom,tmpGeom):
selectedSet.append(feat.id())
current += 1
progress.setPercentage(int(current * total))