Skip to content

Commit 35eb5f6

Browse files
committed
Improved select by location
1 parent b43d131 commit 35eb5f6

File tree

2 files changed

+215
-32
lines changed

2 files changed

+215
-32
lines changed

python/plugins/fTools/tools/doSelectByLocation.py

+48-32
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#-----------------------------------------------------------
33
#
44
# fTools
5-
# Copyright (C) 2008-2011 Carson Farmer
5+
# Copyright (C) 2008-2011 Carson Farmer, edited and improved by Giovanni Allegri (2014)
66
# EMAIL: carson.farmer (at) gmail.com
77
# WEB : http://www.ftools.ca/fTools.html
88
#
@@ -32,12 +32,16 @@
3232
from PyQt4.QtGui import *
3333
import ftools_utils
3434
from qgis.core import *
35-
from ui_frmPointsInPolygon import Ui_Dialog
35+
from ui_frmSelectByLocation import Ui_Dialog
3636

3737
class Dialog(QDialog, Ui_Dialog):
38+
TOUCH = 1
39+
OVERLAP = 2
40+
WITHIN = 4
3841

3942
def __init__(self, iface):
4043
QDialog.__init__(self, iface.mainWindow())
44+
self.opFlags = 0
4145
self.iface = iface
4246
# Set up the user interface from Designer.
4347
self.setupUi(self)
@@ -48,7 +52,6 @@ def __init__(self, iface):
4852
layers = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon])
4953
self.inPolygon.addItems(layers)
5054
self.inPoint.addItems(layers)
51-
self.updateUI()
5255
self.connect(self.inPoint, SIGNAL("currentIndexChanged(QString)"), self.updateCheck)
5356
self.cmbModify.addItems([self.tr("creating new selection"), self.tr("adding to current selection"), self.tr("removing from current selection")])
5457

@@ -59,50 +62,63 @@ def updateCheck(self, text):
5962
else:
6063
self.chkSelected.setChecked(False)
6164

62-
def updateUI(self):
63-
self.label_5.setVisible(False)
64-
self.lnField.setVisible(False)
65-
self.outShape.setVisible(False)
66-
self.toolOut.setVisible(False)
67-
self.label_2.setVisible(False)
68-
self.setWindowTitle(self.tr("Select by location"))
69-
self.label_3.setText(self.tr("Select features in:"))
70-
self.label_4.setText(self.tr("that intersect features in:"))
71-
self.label_mod = QLabel(self)
72-
self.label_mod.setObjectName("label_mod")
73-
self.label_mod.setText(self.tr("Modify current selection by:"))
74-
self.cmbModify = QComboBox(self)
75-
self.cmbModify.setObjectName("cmbModify")
76-
self.chkSelected = QCheckBox(self.tr("Use selected features only"), self)
77-
self.chkSelected.setObjectName("chkSelected")
78-
self.gridLayout.addWidget(self.chkSelected,2,0,1,1)
79-
self.gridLayout.addWidget(self.label_mod,3,0,1,1)
80-
self.gridLayout.addWidget(self.cmbModify,4,0,1,1)
81-
self.resize(381, 100)
82-
8365
def accept(self):
8466
self.buttonOk.setEnabled( False )
8567
if self.inPolygon.currentText() == "":
8668
QMessageBox.information(self, self.tr("Select by location"), self.tr( "Please specify input layer"))
8769
elif self.inPoint.currentText() == "":
8870
QMessageBox.information(self, self.tr("Select by location"), self.tr("Please specify select layer"))
8971
else:
90-
inPoly = self.inPolygon.currentText()
91-
inPts = self.inPoint.currentText()
92-
self.compute(inPoly, inPts, self.cmbModify.currentText(), self.chkSelected.isChecked())
72+
inLayer = self.inPolygon.currentText()
73+
selLayer = self.inPoint.currentText()
74+
self.compute(inLayer, selLayer, self.cmbModify.currentText(), self.chkSelected.isChecked())
9375
self.progressBar.setValue(0)
9476
self.buttonOk.setEnabled( True )
9577

96-
def compute(self, inPoly, inPts, modify, selection):
97-
inputLayer = ftools_utils.getVectorLayerByName(inPoly)
98-
selectLayer = ftools_utils.getVectorLayerByName(inPts)
78+
def compute(self, inLayer, selLayer, modify, selection):
79+
inputLayer = ftools_utils.getVectorLayerByName(inLayer)
80+
selectLayer = ftools_utils.getVectorLayerByName(selLayer)
9981
inputProvider = inputLayer.dataProvider()
10082
selectProvider = selectLayer.dataProvider()
10183
feat = QgsFeature()
10284
infeat = QgsFeature()
10385
geom = QgsGeometry()
10486
selectedSet = []
10587
index = ftools_utils.createIndex(inputProvider)
88+
89+
def _points_op(geomA,geomB):
90+
return geomA.intersects(geomB)
91+
92+
def _poly_lines_op(geomA,geomB):
93+
if geomA.disjoint(geomB):
94+
return False
95+
intersects = False
96+
if self.opFlags & self.TOUCH:
97+
intersects |= geomA.touches(geomB)
98+
if not intersects and (self.opFlags & self.OVERLAP):
99+
if geomB.type() == QGis.Line or geomA.type() == QGis.Line:
100+
intersects |= geomA.crosses(geomB)
101+
else:
102+
intersects |= geomA.overlaps(geomB)
103+
if not intersects and (self.opFlags & self.WITHIN):
104+
intersects |= geomA.contains(geomB)
105+
return intersects
106+
107+
def _sp_operator():
108+
if inputLayer.geometryType() == QGis.Point:
109+
return _points_op
110+
else:
111+
return _poly_lines_op
112+
113+
self.opFlags = 0
114+
if self.chkTouches.checkState() == Qt.Checked:
115+
self.opFlags |= self.TOUCH
116+
if self.chkOverlaps.checkState() == Qt.Checked:
117+
self.opFlags |= self.OVERLAP
118+
if self.chkContains.checkState() == Qt.Checked:
119+
self.opFlags |= self.WITHIN
120+
121+
sp_operator = _sp_operator()
106122

107123
if selection:
108124
features = selectLayer.selectedFeatures()
@@ -113,7 +129,7 @@ def compute(self, inPoly, inPts, modify, selection):
113129
for id in intersects:
114130
inputProvider.getFeatures( QgsFeatureRequest().setFilterFid( int(id) ) ).nextFeature( infeat )
115131
tmpGeom = QgsGeometry(infeat.geometry())
116-
if geom.intersects(tmpGeom):
132+
if sp_operator(geom,tmpGeom):
117133
selectedSet.append(infeat.id())
118134
self.progressBar.setValue(self.progressBar.value()+1)
119135
else:
@@ -125,7 +141,7 @@ def compute(self, inPoly, inPts, modify, selection):
125141
for id in intersects:
126142
inputProvider.getFeatures( QgsFeatureRequest().setFilterFid( int(id) ) ).nextFeature( infeat )
127143
tmpGeom = QgsGeometry( infeat.geometry() )
128-
if geom.intersects(tmpGeom):
144+
if sp_operator(geom,tmpGeom):
129145
selectedSet.append(infeat.id())
130146
self.progressBar.setValue(self.progressBar.value()+1)
131147
if modify == self.tr("adding to current selection"):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>Dialog</class>
4+
<widget class="QDialog" name="Dialog">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>423</width>
10+
<height>308</height>
11+
</rect>
12+
</property>
13+
<property name="sizePolicy">
14+
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
15+
<horstretch>0</horstretch>
16+
<verstretch>0</verstretch>
17+
</sizepolicy>
18+
</property>
19+
<property name="minimumSize">
20+
<size>
21+
<width>0</width>
22+
<height>308</height>
23+
</size>
24+
</property>
25+
<property name="maximumSize">
26+
<size>
27+
<width>16777215</width>
28+
<height>308</height>
29+
</size>
30+
</property>
31+
<property name="windowTitle">
32+
<string>Select by location</string>
33+
</property>
34+
<layout class="QGridLayout" name="gridLayout">
35+
<item row="0" column="0">
36+
<layout class="QVBoxLayout" name="verticalLayout_2">
37+
<item>
38+
<widget class="QLabel" name="label_3">
39+
<property name="text">
40+
<string>Select features in:</string>
41+
</property>
42+
</widget>
43+
</item>
44+
<item>
45+
<widget class="QComboBox" name="inPolygon"/>
46+
</item>
47+
</layout>
48+
</item>
49+
<item row="1" column="0">
50+
<layout class="QVBoxLayout" name="verticalLayout_3">
51+
<item>
52+
<widget class="QLabel" name="label_4">
53+
<property name="text">
54+
<string>that intersect features in:</string>
55+
</property>
56+
</widget>
57+
</item>
58+
<item>
59+
<widget class="QComboBox" name="inPoint"/>
60+
</item>
61+
</layout>
62+
</item>
63+
<item row="2" column="0">
64+
<widget class="QCheckBox" name="chkTouches">
65+
<property name="text">
66+
<string>Include input features that touch the selection features</string>
67+
</property>
68+
<property name="checked">
69+
<bool>true</bool>
70+
</property>
71+
</widget>
72+
</item>
73+
<item row="3" column="0">
74+
<widget class="QCheckBox" name="chkOverlaps">
75+
<property name="text">
76+
<string>Include input features that overlap/cross the selection features</string>
77+
</property>
78+
<property name="checked">
79+
<bool>true</bool>
80+
</property>
81+
</widget>
82+
</item>
83+
<item row="4" column="0">
84+
<widget class="QCheckBox" name="chkContains">
85+
<property name="text">
86+
<string>Include input features completely within the selection features</string>
87+
</property>
88+
<property name="checked">
89+
<bool>true</bool>
90+
</property>
91+
</widget>
92+
</item>
93+
<item row="5" column="0">
94+
<widget class="QCheckBox" name="chkSelected">
95+
<property name="text">
96+
<string>Only selected features</string>
97+
</property>
98+
</widget>
99+
</item>
100+
<item row="7" column="0">
101+
<layout class="QHBoxLayout" name="horizontalLayout_2">
102+
<item>
103+
<widget class="QProgressBar" name="progressBar">
104+
<property name="value">
105+
<number>0</number>
106+
</property>
107+
<property name="alignment">
108+
<set>Qt::AlignCenter</set>
109+
</property>
110+
<property name="textVisible">
111+
<bool>true</bool>
112+
</property>
113+
</widget>
114+
</item>
115+
<item>
116+
<widget class="QDialogButtonBox" name="buttonBox">
117+
<property name="orientation">
118+
<enum>Qt::Horizontal</enum>
119+
</property>
120+
<property name="standardButtons">
121+
<set>QDialogButtonBox::Close|QDialogButtonBox::Ok</set>
122+
</property>
123+
</widget>
124+
</item>
125+
</layout>
126+
</item>
127+
<item row="6" column="0">
128+
<widget class="QComboBox" name="cmbModify"/>
129+
</item>
130+
</layout>
131+
</widget>
132+
<resources/>
133+
<connections>
134+
<connection>
135+
<sender>buttonBox</sender>
136+
<signal>accepted()</signal>
137+
<receiver>Dialog</receiver>
138+
<slot>accept()</slot>
139+
<hints>
140+
<hint type="sourcelabel">
141+
<x>248</x>
142+
<y>254</y>
143+
</hint>
144+
<hint type="destinationlabel">
145+
<x>157</x>
146+
<y>274</y>
147+
</hint>
148+
</hints>
149+
</connection>
150+
<connection>
151+
<sender>buttonBox</sender>
152+
<signal>rejected()</signal>
153+
<receiver>Dialog</receiver>
154+
<slot>reject()</slot>
155+
<hints>
156+
<hint type="sourcelabel">
157+
<x>316</x>
158+
<y>260</y>
159+
</hint>
160+
<hint type="destinationlabel">
161+
<x>286</x>
162+
<y>274</y>
163+
</hint>
164+
</hints>
165+
</connection>
166+
</connections>
167+
</ui>

0 commit comments

Comments
 (0)