class DtMoveNodeByArea(): '''Automatically move polygon node (along a given side of polygon) in order to achieve a desired polygon area''' def __init__(self, iface, toolBar): # Save reference to the QGIS interface self.iface = iface self.canvas = self.iface.mapCanvas() self.gui = None # Points and Markers self.p1 = None self.p2 = None self.m1 = None self.m2 = None self.selected_feature = None #create action self.node_mover = QtGui.QAction(QtGui.QIcon(":/MovePolygonNodeByArea.png"), QtCore.QCoreApplication.translate("digitizingtools", "Automatically modify polygon to target area moving one node"), self.iface.mainWindow()) self.node_mover.triggered.connect(self.run) self.iface.currentLayerChanged.connect(self.enable) toolBar.addAction(self.node_mover) self.enable() self.tool = DtSelectVertexTool(self.canvas) def showDialog(self): flags = Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMaximizeButtonHint # QgisGui.ModalDialogFlags self.gui = DtMoveNodeByArea_Dialog(self.iface.mainWindow(), flags) self.gui.initGui() self.gui.show() QObject.connect(self.gui, SIGNAL("unsetTool()"), self.unsetTool) QObject.connect(self.gui, SIGNAL("moveNode()"), self.moveNode) def enableVertexTool(self): self.canvas.setMapTool(self.tool) #Connect to the DtSelectVertexTool QObject.connect(self.tool, SIGNAL("vertexFound(PyQt_PyObject)"), self.storeVertexPointsAndMarkers) def unsetTool(self): self.m1 = None self.m2 = None self.p1 = None self.p2 = None self.selected_feature = None self.canvas.unsetMapTool(self.tool) def run(self): '''Function that does all the real work''' layer = self.iface.activeLayer() title = QtCore.QCoreApplication.translate("digitizingtools", "Move polygon node by area") if layer.selectedFeatureCount() == 0: QtGui.QMessageBox.information(None, title, QtCore.QCoreApplication.translate("digitizingtools", "Please select one polygon to edit.")) elif layer.selectedFeatureCount() > 1: QtGui.QMessageBox.information(None, title, QtCore.QCoreApplication.translate("digitizingtools", "Please select only one polygon to edit.")) else: #One selected feature self.selected_feature = layer.selectedFeatures()[0] self.enableVertexTool() self.showDialog() self.gui.writeArea(self.selected_feature.geometry().area()) def storeVertexPointsAndMarkers(self, result): self.p1 = result[0] self.p2 = result[1] self.m1 = result[2] self.m2 = result[3] def enable(self): '''Enables/disables the corresponding button.''' # Disable the Button by default self.node_mover.setEnabled(False) layer = self.iface.activeLayer() if layer <> None: #Only for vector layers. if layer.type() == QgsMapLayer.VectorLayer: # only for polygon layers if layer.geometryType() == 2: # enable if editable self.node_mover.setEnabled(layer.isEditable()) try: layer.editingStarted.disconnect(self.enable) # disconnect, will be reconnected except: pass try: layer.editingStopped.disconnect(self.enable) # when it becomes active layer again except: pass layer.editingStarted.connect(self.enable) layer.editingStopped.connect(self.enable) def moveNode(self): new_a = -1.0 try: new_a = float(self.gui.targetArea.text()) except: pass if (new_a == -1.0): QMessageBox.information(None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate("digitizingtools", "Target Area not valid.")) return if self.p1 == None or self.p2 == None: QMessageBox.information(None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate("digitizingtools", "Not enough vertices selected.")) else: interp1 = self.selected_feature.geometry().intersects(QgsGeometry.fromPoint(self.p1)) interp2 = self.selected_feature.geometry().intersects(QgsGeometry.fromPoint(self.p2)) touch_p1_p2 = self.selected_feature.geometry().touches(QgsGeometry.fromPolyline([self.p1, self.p2])) if (interp1 and interp2): if (not touch_p1_p2): QMessageBox.information(None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate("digitizingtools", "Selected vertices should be consecutive on the selected polygon.")) else: new_geom = createNewGeometry(self.selected_feature.geometry(), self.p1, self.p2, new_a) fid = self.selected_feature.id() layer = self.iface.activeLayer() layer.changeGeometry(fid,new_geom) self.canvas.refresh() #wkt_tmp1 = self.selected_feature.geometry().exportToWkt() #wkt_tmp2 = new_geom.exportToWkt() #tmp_str = wkt_tmp1 + " Initial Area:" + str(self.selected_feature.geometry().area()) + " " + wkt_tmp2 + " Final Area:" + str(new_geom.area()) #title = QtCore.QCoreApplication.translate("digitizingtools", "Move polygon node by area") #QtGui.QMessageBox.information(None, title, QtCore.QCoreApplication.translate("digitizingtools", tmp_str)) else: QMessageBox.information(None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate("digitizingtools", "Vertices not on the selected polygon."))
class DtMoveNodeByArea(): '''Automatically move polygon node (along a given side of polygon) in order to achieve a desired polygon area''' def __init__(self, iface, toolBar): # Save reference to the QGIS interface self.iface = iface self.canvas = self.iface.mapCanvas() self.gui = None self.multipolygon_detected = False # Points and Markers self.p1 = None self.p2 = None self.m1 = None self.m2 = None self.selected_feature = None #create action self.node_mover = QtGui.QAction( QtGui.QIcon(":/MovePolygonNodeByArea.png"), QtCore.QCoreApplication.translate( "digitizingtools", "Move polygon node (along a side) to achieve target area"), self.iface.mainWindow()) self.node_mover.triggered.connect(self.run) self.iface.currentLayerChanged.connect(self.enable) toolBar.addAction(self.node_mover) self.enable() self.tool = DtSelectVertexTool(self.canvas, 2) def showDialog(self): flags = Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMaximizeButtonHint # QgisGui.ModalDialogFlags self.gui = DtMoveNodeByArea_Dialog(self.iface.mainWindow(), flags) self.gui.initGui() self.gui.show() QObject.connect(self.gui, SIGNAL("unsetTool()"), self.unsetTool) QObject.connect(self.gui, SIGNAL("moveNode()"), self.moveNode) def enableVertexTool(self): self.canvas.setMapTool(self.tool) #Connect to the DtSelectVertexTool QObject.connect(self.tool, SIGNAL("vertexFound(PyQt_PyObject)"), self.storeVertexPointsAndMarkers) def unsetTool(self): self.m1 = None self.m2 = None self.p1 = None self.p2 = None self.selected_feature = None self.canvas.unsetMapTool(self.tool) def run(self): '''Function that does all the real work''' layer = self.iface.activeLayer() if (layer.dataProvider().geometryType() == 6): self.multipolygon_detected = True title = QtCore.QCoreApplication.translate("digitizingtools", "Move polygon node by area") if layer.selectedFeatureCount() == 0: QtGui.QMessageBox.information( None, title, QtCore.QCoreApplication.translate( "digitizingtools", "Please select one polygon to edit.")) elif layer.selectedFeatureCount() > 1: QtGui.QMessageBox.information( None, title, QtCore.QCoreApplication.translate( "digitizingtools", "Please select only one polygon to edit.")) else: #One selected feature self.selected_feature = layer.selectedFeatures()[0] self.enableVertexTool() self.showDialog() self.gui.writeArea(self.selected_feature.geometry().area()) def storeVertexPointsAndMarkers(self, result): self.p1 = result[0][0] self.p2 = result[0][1] self.m1 = result[1][0] self.m2 = result[1][1] def enable(self): '''Enables/disables the corresponding button.''' # Disable the Button by default self.node_mover.setEnabled(False) layer = self.iface.activeLayer() if layer <> None: #Only for vector layers. if layer.type() == QgsMapLayer.VectorLayer: # only for polygon layers if layer.geometryType() == 2: # enable if editable self.node_mover.setEnabled(layer.isEditable()) try: layer.editingStarted.disconnect( self.enable) # disconnect, will be reconnected except: pass try: layer.editingStopped.disconnect( self.enable) # when it becomes active layer again except: pass layer.editingStarted.connect(self.enable) layer.editingStopped.connect(self.enable) def moveNode(self): new_a = -1.0 try: new_a = float(self.gui.targetArea.text()) except: pass if (new_a == -1.0): QMessageBox.information( None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate("digitizingtools", "Target Area not valid.")) return if self.p1 == None or self.p2 == None: QMessageBox.information( None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate("digitizingtools", "Not enough vertices selected.")) else: interp1 = self.selected_feature.geometry().intersects( QgsGeometry.fromPoint(self.p1)) interp2 = self.selected_feature.geometry().intersects( QgsGeometry.fromPoint(self.p2)) touch_p1_p2 = self.selected_feature.geometry().touches( QgsGeometry.fromPolyline([self.p1, self.p2])) if (interp1 and interp2): if (not touch_p1_p2): QMessageBox.information( None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate( "digitizingtools", "Selected vertices should be consecutive on the selected polygon." )) else: new_geom = createNewGeometry( self.selected_feature.geometry(), self.p1, self.p2, new_a, self.multipolygon_detected) fid = self.selected_feature.id() layer = self.iface.activeLayer() layer.beginEditCommand( QtCore.QCoreApplication.translate( "editcommand", "Move Node By Area")) layer.changeGeometry(fid, new_geom) self.canvas.refresh() layer.endEditCommand() #wkt_tmp1 = self.selected_feature.geometry().exportToWkt() #wkt_tmp2 = new_geom.exportToWkt() #tmp_str = wkt_tmp1 + " Initial Area:" + str(self.selected_feature.geometry().area()) + " " + wkt_tmp2 + " Final Area:" + str(new_geom.area()) #title = QtCore.QCoreApplication.translate("digitizingtools", "Move polygon node by area") #QtGui.QMessageBox.information(None, title, QtCore.QCoreApplication.translate("digitizingtools", tmp_str)) else: QMessageBox.information( None, QCoreApplication.translate("digitizingtools", "Cancel"), QCoreApplication.translate( "digitizingtools", "Vertices not on the selected polygon."))