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)
Exemple #2
0
 def __init__(self,
              iface,
              toolBar,
              icon,
              tooltip,
              iconBatch,
              tooltipBatch,
              geometryTypes=[0, 1, 2],
              numVertices=1,
              dtName=None):
     DtDualTool.__init__(self, iface, toolBar, icon, tooltip, iconBatch,
                         tooltipBatch, geometryTypes, dtName)
     self.tool = DtSelectVertexTool(self.canvas, numVertices)
Exemple #3
0
 def __init__(self, iface,  toolBar):
     # Save reference to the QGIS interface
     self.iface = iface
     self.canvas = self.iface.mapCanvas()
     self.tool = DtSelectVertexTool(self.canvas)
     self.doIgnoreTool = False
     #create action
     self.act_fillGap = QtGui.QAction(QtGui.QIcon(":/fillGap.png"),
         QtCore.QCoreApplication.translate("digitizingtools", "Fill gap"),  self.iface.mainWindow())
     self.act_fillGap.setCheckable(True)
     self.canvas.mapToolSet.connect(self.deactivate)
     self.act_fillGap.triggered.connect(self.run)
     self.iface.currentLayerChanged.connect(self.enable)
     toolBar.addAction(self.act_fillGap)
     self.enable()
Exemple #4
0
class DtFillGap():
    '''Fill gaps between selected features of the active layer with new features'''
    def __init__(self, iface,  toolBar):
        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.tool = DtSelectVertexTool(self.canvas)
        self.doIgnoreTool = False
        #create action
        self.act_fillGap = QtGui.QAction(QtGui.QIcon(":/fillGap.png"),
            QtCore.QCoreApplication.translate("digitizingtools", "Fill gap"),  self.iface.mainWindow())
        self.act_fillGap.setCheckable(True)
        self.canvas.mapToolSet.connect(self.deactivate)
        self.act_fillGap.triggered.connect(self.run)
        self.iface.currentLayerChanged.connect(self.enable)
        toolBar.addAction(self.act_fillGap)
        self.enable()

    def deactivate(self,  thisTool):
        if thisTool != self.tool:
            self.tool.clear()
            self.act_fillGap.setChecked(False)
            try:
                self.tool.vertexFound.disconnect(self.vertexSnapped)
            except:
                pass


    def run(self):
        '''Function that does all the real work'''
        self.title = QtCore.QCoreApplication.translate("digitizingtools", "Fill gap")
        self.canvas.setMapTool(self.tool)
        layer = self.iface.activeLayer()
        self.doIgnoreTool = True
        try:
            self.tool.vertexFound.disconnect(self.vertexSnapped)
            # disconnect if it was already connectedd, so slot gets called only once!
        except:
            pass
        self.tool.vertexFound.connect(self.vertexSnapped)
        self.act_fillGap.setChecked(True)

        if layer.selectedFeatureCount() == 0:
            QtGui.QMessageBox.information(None,  self.title,  dtutils.dtGetNoSelMessage()[0] + " " + layer.name() + ".\n" + \
                                          QtCore.QCoreApplication.translate("digitizingtools", "Please select all features that surround the gap to be filled."))
            return None
        else:
            reply = QtGui.QMessageBox.question(None, self.title,  QtCore.QCoreApplication.translate("digitizingtools",
                "Fill all gaps between selected polygons?"),  QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)

            if reply == QtGui.QMessageBox.Yes:
                self.fillGaps()
                return None
            elif reply == QtGui.QMessageBox.No:
                self.doIgnoreTool = False


    def vertexSnapped(self,  snapResult):
        if not self.doIgnoreTool:
            snappedVertex = snapResult[0][0]
            self.fillGaps(snappedVertex)

        self.tool.clear()

    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 deleteRings(self,  poly):
        outGeom = QgsGeometry.fromPolygon(poly)

        if len(poly) > 1:
            # we have rings
            rings = dtutils.dtExtractRings(outGeom)
            for aRing in rings:
                outGeom = outGeom.combine(aRing)

        return outGeom


    def enable(self):
        '''Enables/disables the corresponding button.'''
        # Disable the Button by default
        self.act_fillGap.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:
                    self.act_fillGap.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)
class DtFillRing():
    '''Fill selected ring/all rings in selected feature in active polygon layer'''
    def __init__(self, iface,  toolBar):
        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        #create action
        self.act_fillRing = QtGui.QAction(QtGui.QIcon(":/fillRing.png"),
            QtCore.QCoreApplication.translate("digitizingtools", "Fill ring"),  self.iface.mainWindow())
        self.act_fillRing.setCheckable(True)
        self.canvas.mapToolSet.connect(self.deactivate)
        self.act_fillRing.triggered.connect(self.run)
        self.iface.currentLayerChanged.connect(self.enable)
        toolBar.addAction(self.act_fillRing)
        self.enable()
        self.tool = DtSelectVertexTool(self.canvas)
        self.doIgnoreTool = False

    def deactivate(self,  thisTool):
        self.tool.clear()

        if thisTool != self.tool:
            self.act_fillRing.setChecked(False)
            try:
                self.tool.vertexFound.disconnect(self.vertexSnapped)
            except:
                pass

    def run(self):
        '''Function that does all the real work'''
        title = QtCore.QCoreApplication.translate("digitizingtools", "Fill ring")
        layer = self.iface.activeLayer()

        self.canvas.setMapTool(self.tool)
        #Connect to the DtSelectVertexTool
        self.doIgnoreTool = False
        try:
            self.tool.vertexFound.disconnect(self.vertexSnapped)
            # disconnect if it was already connectedd, so slot gets called only once!
        except:
            pass
        self.tool.vertexFound.connect(self.vertexSnapped)
        self.act_fillRing.setChecked(True)

        if layer.selectedFeatureCount() > 0:
            reply = QtGui.QMessageBox.question(None, title,  QtCore.QCoreApplication.translate("digitizingtools",
                "Fill all rings in all selected polygons?"),  QtGui.QMessageBox.Yes | QtGui.QMessageBox.No | QtGui.QMessageBox.Cancel)

            if reply == QtGui.QMessageBox.Yes:
                self.fillRings(layer.selectedFeaturesIds())
                self.doIgnoreTool = True
            elif reply == QtGui.QMessageBox.No:
                layer.removeSelection()
                self.canvas.refresh()
            else:
                self.doIgnoreTool = True

    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 fillRings(self,  forFids):
        layer = self.iface.activeLayer()
        newFeat = dtutils.dtCreateFeature(layer)
        layer.beginEditCommand(QtCore.QCoreApplication.translate("editcommand", "Fill rings"))

        if self.iface.openFeatureForm(layer,  newFeat):
            for fid in forFids:
                featureToFill = dtutils.dtGetFeatureForId(layer,  fid)

                if featureToFill != None:
                    geom = featureToFill.geometry()
                    rings = dtutils.dtExtractRings(geom)

                    for aRing in rings:
                        aFeat = dtutils.dtCopyFeature(layer,  newFeat)
                        aFeat.setGeometry(aRing)
                        #for i in range(layer.pendingFields().count()):

                        layer.addFeature(aFeat)

            layer.endEditCommand()
            self.canvas.refresh()
        else:
            layer.destroyEditCommand()

    def enable(self):
        '''Enables/disables the corresponding button.'''
        # Disable the Button by default
        self.act_fillRing.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:
                    self.act_fillRing.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)