def vertexSnapped(self, snapResult): snappedVertex = snapResult[0][0] snappedFid = snapResult[2][0] layer = self.iface.activeLayer() feat = dtutils.dtGetFeatureForId(layer, snappedFid) if feat != None: geom = feat.geometry() rings = dtutils.dtExtractRings(geom) thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y( ) == snappedVertex.y(): thisRing = aRing break if thisRing != None: defaultAttributeMap = dtutils.dtGetDefaultAttributeMap(layer) layer.beginEditCommand( QtCore.QCoreApplication.translate("editcommand", "Fill ring")) if self.iface.vectorLayerTools().addFeature( layer, defaultValues=defaultAttributeMap, defaultGeometry=thisRing): layer.endEditCommand() self.canvas.refresh() else: layer.destroyEditCommand() self.tool.reset()
def vertexSnapped(self, snapResult): if not self.doIgnoreTool: snappedVertex = snapResult[0][0] snappedFid = snapResult[2][0] layer = self.iface.activeLayer() thisRing = None feat = dtutils.dtGetFeatureForId(layer, snappedFid) if feat != None: geom = feat.geometry() rings = dtutils.dtExtractRings(geom) for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y() == snappedVertex.y(): thisRing = aRing break if thisRing != None: newFeat = dtutils.dtCreateFeature(layer) layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill ring")) if self.iface.openFeatureForm(layer, newFeat, True): # let user edit attributes newFeat.setGeometry(thisRing) layer.addFeature(newFeat) layer.endEditCommand() self.canvas.refresh() else: layer.destroyEditCommand() self.tool.clear()
def vertexSnapped(self, snapResult): snappedVertex = snapResult[0][0] snappedFid = snapResult[2][0] layer = self.iface.activeLayer() feat = dtutils.dtGetFeatureForId(layer, snappedFid) if feat != None: geom = feat.geometry() rings = dtutils.dtExtractRings(geom) thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y() == snappedVertex.y(): thisRing = aRing break if thisRing != None: defaultAttributeMap = dtutils.dtGetDefaultAttributeMap(layer) layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill ring")) if self.iface.vectorLayerTools().addFeature(layer, defaultValues = defaultAttributeMap, defaultGeometry = thisRing): layer.endEditCommand() self.canvas.refresh() else: layer.destroyEditCommand() self.tool.reset()
def vertexSnapped(self, snapResult): snappedVertex = snapResult[0][0] snappedFid = snapResult[2][0] layer = self.iface.activeLayer() feat = dtutils.dtGetFeatureForId(layer, snappedFid) if feat != None: geom = feat.geometry() rings = dtutils.dtExtractRings(geom) thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y( ) == snappedVertex.y(): thisRing = aRing break if thisRing != None: newFeat = dtutils.dtCreateFeature(layer) if self.iface.openFeatureForm(layer, newFeat, True): # let user edit attributes layer.beginEditCommand( QtCore.QCoreApplication.translate( "editcommand", "Fill ring")) newFeat.setGeometry(thisRing) layer.addFeature(newFeat) layer.endEditCommand() self.canvas.refresh() self.tool.clear()
def vertexSnapped(self, snapResult): snappedVertex = snapResult[0][0] fid = snapResult[2][0] layer = self.iface.mapCanvas().currentLayer() feature = dtutils.dtGetFeatureForId(layer, fid) geom = feature.geometry() # if feature geometry is multipart start split processing if geom.isMultipart(): # Get parts from original feature parts = geom.asGeometryCollection () foundPart = False for i in range(len(parts)): # find the part that was snapped aPart = parts[i] points = dtutils.dtExtractPoints(aPart) for aPoint in points: if aPoint.x() == snappedVertex.x() and aPoint.y() == snappedVertex.y(): foundPart = True break if foundPart: break if foundPart: if geom.deletePart(i): layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Extract part")) aFeat = dtutils.dtCopyFeature(layer, feature) aFeat.setGeometry(aPart) layer.addFeature(aFeat) feature.setGeometry(geom) layer.updateFeature(feature) layer.endEditCommand() self.canvas.refresh() self.tool.reset()
def fillGaps(self, snappedVertex = None): layer = self.iface.activeLayer() if layer.selectedFeatureCount() == 0: layer.invertSelection() multiGeom = None for aFeat in layer.selectedFeatures(): aGeom = aFeat.geometry() if not aGeom.isGeosValid(): QtGui.QMessageBox.warning(None, self.title, dtutils.dtGetInvalidGeomWarning()) return None # fill rings contained in the polygon if aGeom.isMultipart(): tempGeom = None for poly in aGeom.asMultiPolygon(): noRingGeom = self.deleteRings(poly) if tempGeom == None: tempGeom = noRingGeom else: tempGeom = tempGeom.combine(noRingGeom) else: tempGeom = self.deleteRings(aGeom.asPolygon()) # make a large polygon from all selected if multiGeom == None: multiGeom = tempGeom else: multiGeom = multiGeom.combine(tempGeom) rings = dtutils.dtExtractRings(multiGeom) if len(rings) == 0: QtGui.QMessageBox.warning(None, self.title, QtCore.QCoreApplication.translate("digitizingtools", "There are no gaps between the polygons.") ) else: if snappedVertex != None: thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y() == snappedVertex.y(): thisRing = aRing break if thisRing != None: newFeat = dtutils.dtCreateFeature(layer) layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill gap")) if self.iface.openFeatureForm(layer, newFeat, True): newFeat.setGeometry(thisRing) layer.addFeature(newFeat) layer.endEditCommand() else: layer.destroyEditCommand() else: QtGui.QMessageBox.warning(None, self.title, QtCore.QCoreApplication.translate("digitizingtools", "The selected gap is not closed.") ) else: newFeat = dtutils.dtCreateFeature(layer) layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill gaps")) if self.iface.openFeatureForm(layer, newFeat): for aRing in rings: aFeat = dtutils.dtCopyFeature(layer, newFeat) aFeat.setGeometry(aRing) layer.addFeature(aFeat) layer.endEditCommand() self.canvas.refresh()
def process(self): '''Function that does all the real work''' title = QtCore.QCoreApplication.translate("digitizingtools", "Splitter") splitterLayer = dtutils.dtChooseVectorLayer(self.iface, 1, msg = QtCore.QCoreApplication.translate("digitizingtools", "splitter layer")) if splitterLayer == None: self.iface.messageBar().pushMessage(title, QtCore.QCoreApplication.translate("digitizingtools", "Please provide a line layer to split with.")) else: passiveLayer = self.iface.activeLayer() msgLst = dtutils.dtGetNoSelMessage() noSelMsg1 = msgLst[0] if splitterLayer.selectedFeatureCount() == 0: self.iface.messageBar().pushMessage(title, noSelMsg1 + " " + splitterLayer.name()) return None elif splitterLayer.selectedFeatureCount() != 1: numSelSplitMsg = dtutils.dtGetManySelMessage(splitterLayer) self.iface.messageBar().pushMessage(title, numSelSplitMsg + \ QtCore.QCoreApplication.translate("digitizingtools", " Please select only one feature to split with.")) else: if passiveLayer.selectedFeatureCount() == 0: self.iface.messageBar().pushMessage(title, noSelMsg1 + " " + passiveLayer.name() + ".\n" + \ QtCore.QCoreApplication.translate("digitizingtools", " Please select the features to be splitted.")) return None # determine srs, we work in the project's srs splitterCRSSrsid = splitterLayer.crs().srsid() passiveCRSSrsid = passiveLayer.crs().srsid() mc = self.iface.mapCanvas() renderer = mc.mapRenderer() projectCRSSrsid = renderer.destinationCrs().srsid() passiveLayer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Split features")) featuresBeingSplit = 0 featuresToAdd = [] for feat in splitterLayer.selectedFeatures(): splitterGeom = QgsGeometry(feat.geometry()) if not splitterGeom.isGeosValid(): thisWarning = dtutils.dtGetInvalidGeomWarning(splitterLayer) dtutils.dtShowWarning(self.iface, thisWarning) continue if splitterCRSSrsid != projectCRSSrsid: splitterGeom.transform(QgsCoordinateTransform(splitterCRSSrsid, projectCRSSrsid)) for selFeat in passiveLayer.selectedFeatures(): selGeom = QgsGeometry(selFeat.geometry()) if not selGeom.isGeosValid(): thisWarning = dtutils.dtGetInvalidGeomWarning(passiveLayer) dtutils.dtShowWarning(self.iface, thisWarning) continue if passiveCRSSrsid != projectCRSSrsid: selGeom.transform(QgsCoordinateTransform(passiveCRSSrsid, projectCRSSrsid)) if splitterGeom.intersects(selGeom): # we have a candidate splitterPList = dtutils.dtExtractPoints(splitterGeom) try: result, newGeometries, topoTestPoints = selGeom.splitGeometry(splitterPList, False) #QgsProject.instance().topologicalEditing()) except: self.iface.messageBar().pushMessage(title, dtutils.dtGetErrorMessage() + QtCore.QCoreApplication.translate("digitizingtools", "splitting of feature") + " " + str(selFeat.id()), level=QgsMessageBar.CRITICAL) return None if result == 0: selFeat.setGeometry(selGeom) passiveLayer.updateFeature(selFeat) if len(newGeometries) > 0: featuresBeingSplit += 1 newFeatures = dtutils.dtMakeFeaturesFromGeometries(passiveLayer, selFeat, newGeometries) for newFeat in newFeatures: newGeom = QgsGeometry(newFeat.geometry()) if passiveCRSSrsid != projectCRSSrsid: newGeom.transform(QgsCoordinateTransform( projectCRSSrsid, passiveCRSSrsid)) newFeat.setGeometry(newGeom) featuresToAdd.append(newFeat) if featuresBeingSplit > 0: passiveLayer.addFeatures(featuresToAdd, False) passiveLayer.endEditCommand() passiveLayer.removeSelection() else: passiveLayer.destroyEditCommand()
def process(self): '''Function that does all the real work''' title = QtCore.QCoreApplication.translate("digitizingtools", "Splitter") splitterLayer = dtutils.dtChooseVectorLayer( self.iface, 1, msg=QtCore.QCoreApplication.translate("digitizingtools", "splitter layer")) if splitterLayer == None: self.iface.messageBar().pushMessage( title, QtCore.QCoreApplication.translate( "digitizingtools", "Please provide a line layer to split with.")) else: passiveLayer = self.iface.activeLayer() msgLst = dtutils.dtGetNoSelMessage() noSelMsg1 = msgLst[0] if splitterLayer.selectedFeatureCount() == 0: self.iface.messageBar().pushMessage( title, noSelMsg1 + " " + splitterLayer.name()) return None elif splitterLayer.selectedFeatureCount() != 1: numSelSplitMsg = dtutils.dtGetManySelMessage(splitterLayer) self.iface.messageBar().pushMessage(title, numSelSplitMsg + \ QtCore.QCoreApplication.translate("digitizingtools", " Please select only one feature to split with.")) else: if passiveLayer.selectedFeatureCount() == 0: self.iface.messageBar().pushMessage(title, noSelMsg1 + " " + passiveLayer.name() + ".\n" + \ QtCore.QCoreApplication.translate("digitizingtools", " Please select the features to be splitted.")) return None # determine srs, we work in the project's srs splitterCRSSrsid = splitterLayer.crs().srsid() passiveCRSSrsid = passiveLayer.crs().srsid() mc = self.iface.mapCanvas() renderer = mc.mapRenderer() projectCRSSrsid = renderer.destinationCrs().srsid() passiveLayer.beginEditCommand( QtCore.QCoreApplication.translate("editcommand", "Split features")) featuresBeingSplit = 0 featuresToAdd = [] for feat in splitterLayer.selectedFeatures(): splitterGeom = feat.geometry() if splitterCRSSrsid != projectCRSSrsid: splitterGeom.transform( QgsCoordinateTransform(splitterCRSSrsid, projectCRSSrsid)) for selFeat in passiveLayer.selectedFeatures(): selGeom = selFeat.geometry() if passiveCRSSrsid != projectCRSSrsid: selGeom.transform( QgsCoordinateTransform(passiveCRSSrsid, projectCRSSrsid)) if splitterGeom.intersects( selGeom): # we have a candidate splitterPList = dtutils.dtExtractPoints( splitterGeom) try: result, newGeometries, topoTestPoints = selGeom.splitGeometry( splitterPList, False ) #QgsProject.instance().topologicalEditing()) except: self.iface.messageBar().pushMessage( title, dtutils.dtGetErrorMessage() + QtCore.QCoreApplication.translate( "digitizingtools", "splitting of feature") + " " + str(selFeat.id()), level=QgsMessageBar.CRITICAL) return None if result == 0: selFeat.setGeometry(selGeom) passiveLayer.updateFeature(selFeat) if len(newGeometries) > 0: featuresBeingSplit += 1 newFeatures = dtutils.dtMakeFeaturesFromGeometries( passiveLayer, selFeat, newGeometries) for newFeat in newFeatures: newGeom = newFeat.geometry() if passiveCRSSrsid != projectCRSSrsid: newGeom.transform( QgsCoordinateTransform( projectCRSSrsid, passiveCRSSrsid)) newFeat.setGeometry(newGeom) featuresToAdd.append(newFeat) if featuresBeingSplit > 0: passiveLayer.addFeatures(featuresToAdd, False) passiveLayer.endEditCommand() passiveLayer.removeSelection() else: passiveLayer.destroyEditCommand()
def canvasReleaseEvent(self,event): #Get the click x = event.pos().x() y = event.pos().y() layer = self.canvas.currentLayer() if layer != None: #the clicked point is our starting point startingPoint = QtCore.QPoint(x,y) found = self.getFeatureForPoint(layer, startingPoint) if len(found) > 0: feat = found[0] snappedPoints = found[1] if len(snappedPoints) > 0: snappedVertex = snappedPoints[0] else: snappedVertex = None geom = QgsGeometry(feat.geometry()) # if feature geometry is multipart start split processing if geom.isMultipart(): # Get parts from original feature parts = geom.asGeometryCollection() mapToPixel = self.canvas.getCoordinateTransform() thisQgsPoint = mapToPixel.toMapCoordinates(startingPoint) for i in range(len(parts)): # find the part that was snapped aPart = parts[i] if self.isPolygonLayer(layer): if aPart.contains(thisQgsPoint): self.partSelected.emit([feat.id(), i, aPart]) break else: points = dtutils.dtExtractPoints(aPart) for j in range(len(points)): aPoint = points[j] if snappedVertex != None: if aPoint.x() == snappedVertex.x() and \ aPoint.y() == snappedVertex.y(): self.partSelected.emit([feat.id(), i, aPart]) break else: try: nextPoint = points[j + 1] except: break if aPoint.x() == snappedPoints[0].x() and \ aPoint.y() == snappedPoints[0].y() and \ nextPoint.x() == snappedPoints[1].x() and \ nextPoint.y() == snappedPoints[1].y(): self.partSelected.emit([feat.id(), i, aPart]) break
def run(self): '''Function that does all the real work''' title = QtCore.QCoreApplication.translate("digitizingtools", "Splitter") splitterLayer = dtutils.dtChooseVectorLayer(self.iface, 1, msg = QtCore.QCoreApplication.translate("digitizingtools", "splitter layer")) if splitterLayer == None: QtGui.QMessageBox.information(None, title, QtCore.QCoreApplication.translate("digitizingtools", "Please provide a line layer to split with.")) else: passiveLayer = self.iface.activeLayer() msgLst = dtutils.dtGetNoSelMessage() noSelMsg1 = msgLst[0] noSelMsg2 = msgLst[1] if splitterLayer.selectedFeatureCount() == 0: reply = QtGui.QMessageBox.question(None, title, noSelMsg1 + " " + splitterLayer.name() + "\n" + noSelMsg2, QtGui.QMessageBox.Yes | QtGui.QMessageBox.Cancel ) if reply == QtGui.QMessageBox.Yes: splitterLayer.invertSelection() else: return None if splitterLayer.selectedFeatureCount() > 0: if passiveLayer.selectedFeatureCount() == 0: QtGui.QMessageBox.information(None, title, noSelMsg1 + " " + passiveLayer.name() + ".\n" + \ QtCore.QCoreApplication.translate("digitizingtools", "Please select the features to be splitted.")) return None # determine srs, we work in the project's srs splitterCRSSrsid = splitterLayer.crs().srsid() passiveCRSSrsid = passiveLayer.crs().srsid() mc = self.iface.mapCanvas() renderer = mc.mapRenderer() projectCRSSrsid = renderer.destinationCrs().srsid() passiveLayer.beginEditCommand(QtCore.QCoreApplication.translate("digitizingtools", "Split Features")) featuresBeingSplit = 0 featuresToAdd = [] for feat in splitterLayer.selectedFeatures(): splitterGeom = feat.geometry() if splitterCRSSrsid != projectCRSSrsid: splitterGeom.transform(QgsCoordinateTransform(splitterCRSSrsid, projectCRSSrsid)) for selFeat in passiveLayer.selectedFeatures(): selGeom = selFeat.geometry() if passiveCRSSrsid != projectCRSSrsid: selGeom.transform(QgsCoordinateTransform(passiveCRSSrsid, projectCRSSrsid)) if splitterGeom.intersects(selGeom): # we have a candidate splitterPList = dtutils.dtExtractPoints(splitterGeom) try: result, newGeometries, topoTestPoints = selGeom.splitGeometry(splitterPList, False) #QgsProject.instance().topologicalEditing()) except: QtGui.QMessageBox.warning(None, title, dtutils.dtGetErrorMessage() + QtCore.QCoreApplication.translate("digitizingtools", "splitting of feature") + " " + str(selFeat.id())) return None if result == 0: selFeat.setGeometry(selGeom) passiveLayer.updateFeature(selFeat) if len(newGeometries) > 0: featuresBeingSplit += 1 newFeatures = dtutils.dtMakeFeaturesFromGeometries(passiveLayer, selFeat, newGeometries) for newFeat in newFeatures: newGeom = newFeat.geometry() if passiveCRSSrsid != projectCRSSrsid: newGeom.transform(QgsCoordinateTransform( projectCRSSrsid, passiveCRSSrsid)) newFeat.setGeometry(newGeom) featuresToAdd.append(newFeat) if featuresBeingSplit > 0: passiveLayer.addFeatures(featuresToAdd, False) passiveLayer.endEditCommand() passiveLayer.removeSelection() else: passiveLayer.destroyEditCommand()
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 = {} topoGeoms = [] # store all new geometries in this array 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, False) except: self.iface.messageBar().pushCritical(title, dtutils.dtGetErrorMessage() + QtCore.QCoreApplication.translate( "digitizingtools", "splitting of feature") + " " + str(aFeat.id())) return None 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) 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) 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 topoGeoms = topoGeoms + newGeoms aFeat.setGeometry(keepGeom) featuresToKeep[anId] = aFeat topoGeoms.append(keepGeom) for anId, aFeat in list(featuresToKeep.items()): aGeom = aFeat.geometry() self.editLayer.updateFeature(aFeat) if len(featuresToAdd) > 0: if self.editLayer.addFeatures(featuresToAdd): if QgsProject.instance().topologicalEditing(): for aGeom in topoGeoms: self.editLayer.addTopologicalPoints(aGeom) 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 fillGaps(self, snappedVertex=None): title = QtCore.QCoreApplication.translate("digitizingtools", "Fill gap") layer = self.iface.activeLayer() hasNoSelection = (layer.selectedFeatureCount() == 0) if hasNoSelection: layer.invertSelection() multiGeom = None for aFeat in layer.selectedFeatures(): aGeom = aFeat.geometry() if not aGeom.isGeosValid(): self.iface.messageBar().pushMessage( title, dtutils.dtGetInvalidGeomWarning(layer), level=QgsMessageBar.CRITICAL) return None # fill rings contained in the polygon if aGeom.isMultipart(): tempGeom = None for poly in aGeom.asMultiPolygon(): noRingGeom = dtutils.dtDeleteRings(poly) if tempGeom == None: tempGeom = noRingGeom else: tempGeom = tempGeom.combine(noRingGeom) else: tempGeom = dtutils.dtDeleteRings(aGeom.asPolygon()) # make a large polygon from all selected if multiGeom == None: multiGeom = tempGeom else: multiGeom = multiGeom.combine(tempGeom) rings = dtutils.dtExtractRings(multiGeom) if len(rings) == 0: self.iface.messageBar().pushMessage( title, QtCore.QCoreApplication.translate( "digitizingtools", "There are no gaps between the polygons."), level=QgsMessageBar.CRITICAL) else: defaultAttributeMap = dtutils.dtGetDefaultAttributeMap(layer) if snappedVertex != None: thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y( ) == snappedVertex.y(): thisRing = aRing break if thisRing != None: layer.beginEditCommand( QtCore.QCoreApplication.translate( "editcommand", "Fill gap")) if self.iface.vectorLayerTools().addFeature( layer, defaultValues=defaultAttributeMap, defaultGeometry=thisRing): layer.endEditCommand() self.canvas.refresh() else: layer.destroyEditCommand() else: self.iface.messageBar().pushMessage( title, QtCore.QCoreApplication.translate( "digitizingtools", "The selected gap is not closed."), level=QgsMessageBar.CRITICAL) else: layer.featureAdded.connect(self.featureAdded) numRingsFilled = 0 aborted = False for aRing in rings: if numRingsFilled == 0: layer.beginEditCommand( QtCore.QCoreApplication.translate( "editcommand", "Fill gaps")) if self.iface.vectorLayerTools().addFeature( layer, defaultValues=defaultAttributeMap, defaultGeometry=aRing): layer.featureAdded.disconnect(self.featureAdded) else: layer.featureAdded.disconnect(self.featureAdded) aborted = True break else: aFeat = dtutils.dtCopyFeature(layer, srcFid=self.newFid) aFeat.setGeometry(aRing) layer.addFeature(aFeat) numRingsFilled += 1 if aborted: layer.destroyEditCommand() else: layer.endEditCommand() if hasNoSelection: layer.removeSelection() self.canvas.refresh()
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 fillGaps(self, snappedVertex = None): title = QtCore.QCoreApplication.translate("digitizingtools", "Fill gap") layer = self.iface.activeLayer() hasNoSelection = (layer.selectedFeatureCount() == 0) if hasNoSelection: layer.invertSelection() multiGeom = None for aFeat in layer.selectedFeatures(): aGeom = aFeat.geometry() if not aGeom.isGeosValid(): self.iface.messageBar().pushMessage(title, dtutils.dtGetInvalidGeomWarning(layer), level=QgsMessageBar.CRITICAL) return None # fill rings contained in the polygon if aGeom.isMultipart(): tempGeom = None for poly in aGeom.asMultiPolygon(): noRingGeom = dtutils.dtDeleteRings(poly) if tempGeom == None: tempGeom = noRingGeom else: tempGeom = tempGeom.combine(noRingGeom) else: tempGeom = dtutils.dtDeleteRings(aGeom.asPolygon()) # make a large polygon from all selected if multiGeom == None: multiGeom = tempGeom else: multiGeom = multiGeom.combine(tempGeom) rings = dtutils.dtExtractRings(multiGeom) if len(rings) == 0: self.iface.messageBar().pushMessage(title, QtCore.QCoreApplication.translate("digitizingtools", "There are no gaps between the polygons."), level=QgsMessageBar.CRITICAL) else: defaultAttributeMap = dtutils.dtGetDefaultAttributeMap(layer) if snappedVertex != None: thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y() == snappedVertex.y(): thisRing = aRing break if thisRing != None: layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill gap")) if self.iface.vectorLayerTools().addFeature(layer, defaultValues = defaultAttributeMap, defaultGeometry = thisRing): layer.endEditCommand() self.canvas.refresh() else: layer.destroyEditCommand() else: self.iface.messageBar().pushMessage(title, QtCore.QCoreApplication.translate("digitizingtools", "The selected gap is not closed."), level=QgsMessageBar.CRITICAL) else: layer.featureAdded.connect(self.featureAdded) numRingsFilled = 0 aborted = False for aRing in rings: if numRingsFilled == 0: layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill gaps")) if self.iface.vectorLayerTools().addFeature(layer, defaultValues = defaultAttributeMap, defaultGeometry = aRing): layer.featureAdded.disconnect(self.featureAdded) else: layer.featureAdded.disconnect(self.featureAdded) aborted = True break else: aFeat = dtutils.dtCopyFeature(layer, srcFid = self.newFid) aFeat.setGeometry(aRing) layer.addFeature(aFeat) numRingsFilled += 1 if aborted: layer.destroyEditCommand() else: layer.endEditCommand() if hasNoSelection: layer.removeSelection() self.canvas.refresh()
def fillGaps(self, snappedVertex=None): title = QtCore.QCoreApplication.translate("digitizingtools", "Fill gap") layer = self.iface.activeLayer() hasNoSelection = (layer.selectedFeatureCount() == 0) if hasNoSelection: layer.invertSelection() multiGeom = None for aFeat in layer.selectedFeatures(): aGeom = aFeat.geometry() if not aGeom.isGeosValid(): self.iface.messageBar().pushMessage( title, dtutils.dtGetInvalidGeomWarning(layer), level=QgsMessageBar.CRITICAL) return None # fill rings contained in the polygon if aGeom.isMultipart(): tempGeom = None for poly in aGeom.asMultiPolygon(): noRingGeom = dtutils.dtDeleteRings(poly) if tempGeom == None: tempGeom = noRingGeom else: tempGeom = tempGeom.combine(noRingGeom) else: tempGeom = dtutils.dtDeleteRings(aGeom.asPolygon()) # make a large polygon from all selected if multiGeom == None: multiGeom = tempGeom else: multiGeom = multiGeom.combine(tempGeom) rings = dtutils.dtExtractRings(multiGeom) if len(rings) == 0: self.iface.messageBar().pushMessage( title, QtCore.QCoreApplication.translate( "digitizingtools", "There are no gaps between the polygons."), level=QgsMessageBar.CRITICAL) else: if snappedVertex != None: thisRing = None for aRing in rings: for aPoint in dtutils.dtExtractPoints(aRing): if aPoint.x() == snappedVertex.x() and aPoint.y( ) == snappedVertex.y(): thisRing = aRing break if thisRing != None: newFeat = dtutils.dtCreateFeature(layer) if self.iface.openFeatureForm(layer, newFeat, True): layer.beginEditCommand( QtCore.QCoreApplication.translate( "editcommand", "Fill gap")) newFeat.setGeometry(thisRing) layer.addFeature(newFeat) layer.endEditCommand() else: self.iface.messageBar().pushMessage( title, QtCore.QCoreApplication.translate( "digitizingtools", "The selected gap is not closed."), level=QgsMessageBar.CRITICAL) else: newFeat = dtutils.dtCreateFeature(layer) if self.iface.openFeatureForm(layer, newFeat): layer.beginEditCommand( QtCore.QCoreApplication.translate( "editcommand", "Fill gaps")) for aRing in rings: aFeat = dtutils.dtCopyFeature(layer, newFeat) aFeat.setGeometry(aRing) layer.addFeature(aFeat) layer.endEditCommand() if hasNoSelection: layer.removeSelection() self.canvas.refresh()