mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
The combination of touches+overlaps+contains is not enough if input layer (where selection should be done) is completely within selection layer. I have reintroduced "intersects" predicate and made it default. The processing toolbox has an improved (fixed?) version but fTools were not adapted at the same time
156 lines
6.7 KiB
Python
156 lines
6.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
#-----------------------------------------------------------
|
|
#
|
|
# fTools
|
|
# Copyright (C) 2008-2011 Carson Farmer, edited and improved by Giovanni Allegri (2014)
|
|
# EMAIL: carson.farmer (at) gmail.com
|
|
# WEB : http://www.ftools.ca/fTools.html
|
|
#
|
|
# A collection of data management and analysis tools for vector data
|
|
#
|
|
#-----------------------------------------------------------
|
|
#
|
|
# licensed under the terms of GNU GPL 2
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along
|
|
# with this program; if not, write to the Free Software Foundation, Inc.,
|
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
#
|
|
#---------------------------------------------------------------------
|
|
|
|
from PyQt4.QtCore import Qt, SIGNAL
|
|
from PyQt4.QtGui import QDialog, QDialogButtonBox, QMessageBox
|
|
import ftools_utils
|
|
from qgis.core import QGis, QgsFeature, QgsGeometry, QgsFeatureRequest
|
|
from ui_frmSelectByLocation import Ui_Dialog
|
|
|
|
class Dialog(QDialog, Ui_Dialog):
|
|
TOUCH = 1
|
|
OVERLAP = 2
|
|
WITHIN = 4
|
|
INTERSECT = 8
|
|
|
|
def __init__(self, iface):
|
|
QDialog.__init__(self, iface.mainWindow())
|
|
self.opFlags = 0
|
|
self.iface = iface
|
|
# Set up the user interface from Designer.
|
|
self.setupUi(self)
|
|
self.buttonOk = self.buttonBox.button( QDialogButtonBox.Ok )
|
|
# populate layer list
|
|
self.progressBar.setValue(0)
|
|
layers = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon])
|
|
self.inPolygon.addItems(layers)
|
|
self.inPoint.addItems(layers)
|
|
self.connect(self.inPoint, SIGNAL("currentIndexChanged(QString)"), self.updateCheck)
|
|
self.cmbModify.addItems([self.tr("creating new selection"), self.tr("adding to current selection"), self.tr("removing from current selection")])
|
|
|
|
def updateCheck(self, text):
|
|
vlayer = ftools_utils.getVectorLayerByName(text)
|
|
if vlayer.selectedFeatureCount() > 0:
|
|
self.chkSelected.setChecked(True)
|
|
else:
|
|
self.chkSelected.setChecked(False)
|
|
|
|
def accept(self):
|
|
self.buttonOk.setEnabled( False )
|
|
if self.inPolygon.currentText() == "":
|
|
QMessageBox.information(self, self.tr("Select by location"), self.tr( "Please specify input layer"))
|
|
elif self.inPoint.currentText() == "":
|
|
QMessageBox.information(self, self.tr("Select by location"), self.tr("Please specify select layer"))
|
|
else:
|
|
inLayer = self.inPolygon.currentText()
|
|
selLayer = self.inPoint.currentText()
|
|
self.compute(inLayer, selLayer, self.cmbModify.currentText(), self.chkSelected.isChecked())
|
|
self.progressBar.setValue(0)
|
|
self.buttonOk.setEnabled( True )
|
|
|
|
def compute(self, inLayer, selLayer, modify, selection):
|
|
inputLayer = ftools_utils.getVectorLayerByName(inLayer)
|
|
selectLayer = ftools_utils.getVectorLayerByName(selLayer)
|
|
inputProvider = inputLayer.dataProvider()
|
|
selectProvider = selectLayer.dataProvider()
|
|
feat = QgsFeature()
|
|
infeat = QgsFeature()
|
|
geom = QgsGeometry()
|
|
selectedSet = []
|
|
index = ftools_utils.createIndex(inputProvider)
|
|
|
|
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.INTERSECT:
|
|
intersects |= geomA.intersects(geomB)
|
|
if not intersects and (self.opFlags & self.TOUCH):
|
|
intersects |= geomA.touches(geomB)
|
|
if not intersects and (self.opFlags & self.OVERLAP):
|
|
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.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.chkTouches.checkState() == Qt.Checked:
|
|
self.opFlags |= self.TOUCH
|
|
if self.chkOverlaps.checkState() == Qt.Checked:
|
|
self.opFlags |= self.OVERLAP
|
|
if self.chkContains.checkState() == Qt.Checked:
|
|
self.opFlags |= self.WITHIN
|
|
if self.chkIntersects.checkState() == Qt.Checked:
|
|
self.opFlags |= self.INTERSECT
|
|
|
|
sp_operator = _sp_operator()
|
|
|
|
if selection:
|
|
features = selectLayer.selectedFeatures()
|
|
self.progressBar.setMaximum(len(features))
|
|
for feat in features:
|
|
geom = QgsGeometry(feat.geometry())
|
|
intersects = index.intersects(geom.boundingBox())
|
|
for id in intersects:
|
|
inputProvider.getFeatures( QgsFeatureRequest().setFilterFid( int(id) ) ).nextFeature( infeat )
|
|
tmpGeom = QgsGeometry(infeat.geometry())
|
|
if sp_operator(geom,tmpGeom):
|
|
selectedSet.append(infeat.id())
|
|
self.progressBar.setValue(self.progressBar.value()+1)
|
|
else:
|
|
self.progressBar.setMaximum(selectProvider.featureCount())
|
|
selectFit = selectProvider.getFeatures()
|
|
while selectFit.nextFeature(feat):
|
|
geom = QgsGeometry(feat.geometry())
|
|
intersects = index.intersects(geom.boundingBox())
|
|
for id in intersects:
|
|
inputProvider.getFeatures( QgsFeatureRequest().setFilterFid( int(id) ) ).nextFeature( infeat )
|
|
tmpGeom = QgsGeometry( infeat.geometry() )
|
|
if sp_operator(geom,tmpGeom):
|
|
selectedSet.append(infeat.id())
|
|
self.progressBar.setValue(self.progressBar.value()+1)
|
|
if modify == self.tr("adding to current selection"):
|
|
selectedSet = list(set(inputLayer.selectedFeaturesIds()).union(selectedSet))
|
|
elif modify == self.tr("removing from current selection"):
|
|
selectedSet = list(set(inputLayer.selectedFeaturesIds()).difference(selectedSet))
|
|
inputLayer.setSelectedFeatures(selectedSet)
|