| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- # -*- coding: utf-8 -*-
- """
- dtsplitfeature
- `````````````
- """
- """
- Part of DigitizingTools, a QGIS plugin that
- subsumes different tools neded during digitizing sessions
- * begin : 2017-06-12
- * copyright : (C) 2017 by Bernhard Ströbl
- * email : bernhard.stroebl@jena.de
- 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.
- """
- from builtins import str
- from builtins import range
- from qgis.PyQt import QtCore, QtGui, QtWidgets
- from qgis.core import *
- from qgis.gui import *
- import dt_icons_rc
- from dttools import DtSingleEditTool, DtSplitFeatureTool
- import dtutils
- class DtSplitFeature(DtSingleEditTool):
- '''Split feature'''
- def __init__(self, iface, toolBar):
- super().__init__(iface, toolBar,
- QtGui.QIcon(":/splitfeature.png"),
- QtCore.QCoreApplication.translate("digitizingtools", "Split Features"),
- geometryTypes = [2, 3, 5, 6], crsWarning = False, dtName = "dtSplitFeature")
- self.tool = DtSplitFeatureTool(self.iface)
- self.tool.finishedDigitizing.connect(self.digitizingFinished)
- self.reset()
- self.enable()
- def reset(self):
- self.editLayer = None
- self.feature = None
- self.rubberBand = None
- def digitizingFinished(self, splitGeom):
- title = QtCore.QCoreApplication.translate("digitizingtools", "Split Features")
- hlColor, hlFillColor, hlBuffer, hlMinWidth = dtutils.dtGetHighlightSettings()
- selIds = self.editLayer.selectedFeatureIds()
- self.editLayer.removeSelection()
- if self.editLayer.crs().srsid() != QgsProject.instance().crs().srsid():
- splitGeom.transform(QgsCoordinateTransform(
- QgsProject.instance().crs(), self.editLayer.crs(),
- QgsProject.instance()
- ))
- splitterPList = dtutils.dtExtractPoints(splitGeom)
- featuresToAdd = [] # store new features in this array
- featuresToKeep = {} # store geoms that will stay with their id as key
- featuresToSplit = {}
- topoEditEnabled = QgsProject.instance().topologicalEditing()
- topoTestPointsAll = [] # store all topoTestPoints for all parts
- for aFeat in self.editLayer.getFeatures(QgsFeatureRequest(splitGeom.boundingBox())):
- anId = aFeat.id()
- # work either on selected or all features if no selection exists
- if len(selIds) == 0 or selIds.count(anId) != 0:
- aGeom = aFeat.geometry()
- if splitGeom.intersects(aGeom):
- featuresToSplit[anId] = aFeat
- if len(featuresToSplit) > 0:
- self.editLayer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Features split"))
- for anId, aFeat in list(featuresToSplit.items()):
- aGeom = aFeat.geometry()
- wasMultipart = aGeom.isMultipart() and len(aGeom.asGeometryCollection()) > 1
- splitResult = []
- geomsToSplit = []
- if wasMultipart:
- keepGeom = None
- for aPart in aGeom.asGeometryCollection():
- if splitGeom.intersects(aPart):
- geomsToSplit.append(aPart)
- else:
- if keepGeom == None:
- keepGeom = aPart
- else:
- keepGeom = keepGeom.combine(aPart)
- else:
- geomsToSplit.append(aGeom)
- for thisGeom in geomsToSplit:
- try:
- result, newGeometries, topoTestPoints = thisGeom.splitGeometry(splitterPList, topoEditEnabled)
- except:
- self.iface.messageBar().pushCritical(title,
- dtutils.dtGetErrorMessage() + QtCore.QCoreApplication.translate(
- "digitizingtools", "splitting of feature") + " " + str(aFeat.id()))
- return None
- topoTestPointsAll.append(topoTestPoints)
- if result == 0: # success
- if len(newGeometries) > 0:
- splitResult = newGeometries
- if wasMultipart:
- splitResult.append(thisGeom)
- if wasMultipart and len(splitResult) > 1:
- takeThisOne = -1
- while takeThisOne == -1:
- for i in range(len(splitResult)):
- aNewGeom = splitResult[i]
- hl = QgsHighlight(self.iface.mapCanvas(), aNewGeom, self.editLayer)
- hl.setColor(hlColor)
- hl.setFillColor(hlFillColor)
- hl.setBuffer(hlBuffer)
- hl.setWidth(hlMinWidth)
- hl.show()
- answer = QtWidgets.QMessageBox.question(
- None, QtCore.QCoreApplication.translate("digitizingtools", "Split Multipart Feature"),
- QtCore.QCoreApplication.translate("digitizingtools", "Create new feature from this part?"),
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No | QtWidgets.QMessageBox.Cancel | QtWidgets.QMessageBox.NoToAll)
- hl.hide()
- hl = None
- if answer == QtWidgets.QMessageBox.Yes:
- takeThisOne = i
- break
- elif answer == QtWidgets.QMessageBox.NoToAll:
- keepGeom = aGeom
- newGeoms = []
- takeThisOne = -2
- break
- elif answer == QtWidgets.QMessageBox.Cancel:
- self.editLayer.destroyEditCommand()
- return None
- if takeThisOne == -2:
- break
- elif takeThisOne >= 0:
- newGeoms = [splitResult.pop(takeThisOne)]
- if len(splitResult) > 0: #should be
- for aNewGeom in splitResult:
- if keepGeom == None:
- keepGeom = aNewGeom
- else:
- keepGeom = keepGeom.combine(aNewGeom)
- else: # singlePart
- keepGeom = thisGeom
- newGeoms = newGeometries
- newFeatures = dtutils.dtMakeFeaturesFromGeometries(self.editLayer, aFeat, newGeoms)
- featuresToAdd = featuresToAdd + newFeatures
- aFeat.setGeometry(keepGeom)
- featuresToKeep[anId] = aFeat
- for anId, aFeat in list(featuresToKeep.items()):
- aGeom = aFeat.geometry()
- self.editLayer.updateFeature(aFeat)
- if len(featuresToAdd) > 0:
- if self.editLayer.addFeatures(featuresToAdd):
- for topoTestPoint in topoTestPointsAll:
- for pt in topoTestPoint:
- self.editLayer.addTopologicalPoints(pt)
- self.editLayer.endEditCommand()
- else:
- self.editLayer.destroyEditCommand()
- else:
- self.editLayer.destroyEditCommand()
- if hasattr(self.editLayer, "selectByIds"): # since QGIS 2.16
- self.editLayer.selectByIds(selIds)
- else:
- self.editLayer.setSelectedFeatures(selIds)
- def process(self):
- self.canvas.setMapTool(self.tool)
- self.act.setChecked(True)
- self.editLayer = self.iface.activeLayer()
|