def __init__(self, canvas):
        # some stuff we need from qgis
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        self.snapper = QgsSnappingUtils()
        # some stuff to control our state
        self.mCtrl = False
        self.started = False
        self.firstTimeOnSegment = True
        self.lastPointMustStay = False
        # some stuff to put our temp output
        self.lastPoint = None
        self.rb = None
        self.isPolygon = False

        # our own fancy cursor
        self.cursor = QCursor(
            QPixmap([
                "16 16 3 1", "      c None", ".     c #00FF00",
                "+     c #FFFFFF", "                ", "       +.+      ",
                "      ++.++     ", "     +.....+    ", "    +.     .+   ",
                "   +.   .   .+  ", "  +.    .    .+ ", " ++.    .    .++",
                " ... ...+... ...", " ++.    .    .++", "  +.    .    .+ ",
                "   +.   .   .+  ", "   ++.     .+   ", "    ++.....+    ",
                "      ++.++     ", "       +.+      "
            ]))
Beispiel #2
0
    def __updateList(self):
        """
        To update the line layers list that we can use for interpolation
        """
        self.__layerList = []
        legend = self.__iface.legendInterface()
        scale = self.__iface.mapCanvas().scale()
        for layer in self.__iface.mapCanvas().layers():
            noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \
                QgsProject.instance().snapSettingsForLayer(layer.id())
            if isinstance(layer, QgsVectorLayer) and layer.hasGeometryType() \
                    and layer.geometryType() == QGis.Line:
                if not layer.hasScaleBasedVisibility(
                ) or layer.minimumScale() < scale <= layer.maximumScale():
                    if legend.isLayerVisible(layer) and enabled:
                        layerConfig = QgsSnappingUtils.LayerConfig(
                            layer, QgsPointLocator.Vertex, tolerance, unitType)
                        self.__layerList.append(layerConfig)

        if self.__ownSettings and self.__ownSettings.linesLayer():
            noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \
                QgsProject.instance().snapSettingsForLayer(self.__ownSettings.linesLayer().id())
            self.__linesConfig = QgsSnappingUtils.LayerConfig(
                self.__ownSettings.linesLayer(), QgsPointLocator.Vertex,
                tolerance, unitType)
Beispiel #3
0
    def set_up_snapper(snap_layers, map_canvas, snap_tolerance=10):

        layer_configs = []
        for layer, snap_type in snap_layers.iteritems():
            # point_locator = QgsPointLocator(snap_layers[l])
            layer_configs.append(QgsSnappingUtils.LayerConfig(layer, snap_type, snap_tolerance, QgsTolerance.MapUnits))
        snapper = QgsSnappingUtils()
        snapper.setMapSettings(map_canvas.mapSettings())
        snapper.setLayers(layer_configs)
        snapper.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)

        return snapper
Beispiel #4
0
    def snap_to_segment(self, pos):
        """ Temporarily override snapping config and snap to vertices and edges
         of any editable vector layer, to allow selection of node for editing
         (if snapped to edge, it would offer creation of a new vertex there).
        """
        map_point = self.toMapCoordinates(pos)
        tol = QgsTolerance.vertexSearchRadius(self.canvas.mapSettings())
        snap_type = QgsPointLocator.Type(QgsPointLocator.Edge)

        snap_layers = []
        for layer in self.canvas.layers():
            if not isinstance(layer, QgsVectorLayer):
                continue
            snap_layers.append(
                QgsSnappingUtils.LayerConfig(layer, snap_type, tol,
                                             QgsTolerance.ProjectUnits))

        snap_util = self.canvas.snappingUtils()
        old_layers = snap_util.layers()
        old_mode = snap_util.snapToMapMode()
        old_inter = snap_util.snapOnIntersections()
        snap_util.setLayers(snap_layers)
        snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)
        snap_util.setSnapOnIntersections(False)
        m = snap_util.snapToMap(map_point)
        snap_util.setLayers(old_layers)
        snap_util.setSnapToMapMode(old_mode)
        snap_util.setSnapOnIntersections(old_inter)
        return m
Beispiel #5
0
    def snap_to_dimension_layer(self, pos):
        """ Temporarily override snapping config and snap to vertices and edges
            of any editable vector layer, to allow selection of node for editing
            (if snapped to edge, it would offer creation of a new vertex there).
           """
        map_point = self.toMapCoordinates(pos)
        tol = QgsTolerance.vertexSearchRadius(self.canvas().mapSettings())
        snap_type = QgsPointLocator.Type(QgsPointLocator.Edge)

        snap_layers = [
            QgsSnappingUtils.LayerConfig(self.layer, snap_type, tol,
                                         QgsTolerance.ProjectUnits)
        ]

        snap_util = self.canvas().snappingUtils()
        old_layers = snap_util.layers()
        old_mode = snap_util.snapToMapMode()
        old_inter = snap_util.snapOnIntersections()
        snap_util.setLayers(snap_layers)
        snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)
        snap_util.setSnapOnIntersections(False)
        m = snap_util.snapToMap(map_point)
        snap_util.setLayers(old_layers)
        snap_util.setSnapToMapMode(old_mode)
        snap_util.setSnapOnIntersections(old_inter)

        f = QgsFeature()
        if m.featureId() is not None:
            self.layer.getFeatures(QgsFeatureRequest().setFilterFid(
                m.featureId())).nextFeature(f)
        return f
Beispiel #6
0
 def canvasMoveEvent(self, event):
     """
     When the mouse is moved
     :param event: mouse event
     """
     if not self.__isEditing:
         laySettings = QgsSnappingUtils.LayerConfig(self.__layer,
                                                    QgsPointLocator.All, 10,
                                                    QgsTolerance.Pixels)
         f_l = Finder.findClosestFeatureAt(event.mapPoint(), self.canvas(),
                                           [laySettings])
         if f_l is not None:
             self.__lastFeatureId = f_l[0].id()
             self.__layer.setSelectedFeatures([f_l[0].id()])
             self.__rubber.reset()
             geom = f_l[0].geometry()
             index = geom.closestVertex(event.mapPoint())[1]
             line_v2, curved = GeometryV2.asLineV2(geom, self.__iface)
             num_p = line_v2.numPoints()
             if num_p > 2 and (index == 0 or index == (num_p - 1)):
                 self.__rubber.setIcon(4)
                 self.__rubber.setToGeometry(
                     QgsGeometry(line_v2.pointN(index)), None)
         else:
             self.__layer.removeSelection()
             self.__rubber.reset()
             self.__lastFeatureId = None
Beispiel #7
0
 def canvasReleaseEvent(self, event):
     """
     When the mouse is clicked
     :param event: mouse event
     """
     types = [QgsWKBTypes.PointZ, QgsWKBTypes.LineStringZ, QgsWKBTypes.CircularStringZ, QgsWKBTypes.CompoundCurveZ,
              QgsWKBTypes.CurvePolygonZ, QgsWKBTypes.PolygonZ]
     display = ""
     for layer in self.canvas().layers():
         if layer.type() == QgsMapLayer.VectorLayer and QGis.fromOldWkbType(layer.wkbType()) in types:
             layerConfig = QgsSnappingUtils.LayerConfig(layer, QgsPointLocator.Vertex, 10, QgsTolerance.Pixels)
             features = Finder.findFeaturesAt(event.mapPoint(), layerConfig, self)
             if len(features) > 0:
                 display += layer.name() + " : \n"
                 for f in features:
                     if f.geometry().type() == QGis.Point:
                         alt = f.geometry().geometry().z()
                     elif f.geometry().type() == QGis.Line:
                         closest = f.geometry().closestVertex(event.mapPoint())
                         alt = f.geometry().geometry().zAt(closest[1])
                     elif f.geometry().type() == QGis.Polygon:
                         self.__iface.messageBar().pushMessage(
                             QCoreApplication.translate("VDLTools", "Polygon not yet implemented"),
                             level=QgsMessageBar.WARNING)
                         continue
                     else:
                         continue
                     display += "    " + str(f.id()) + " | " + str(alt) + " m.\n"
     if display != "":
         QMessageBox.information(None, QCoreApplication.translate("VDLTools", "Id | Elevation"), display)
Beispiel #8
0
    def snap(mapPoint, mapCanvas, snapIntersections):

        snap_layers = []
        for layer in mapCanvas.layers():
            types = [0, 1, 2]
            if isinstance(layer,
                          QgsVectorLayer) and layer.geometryType() in types:
                noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = QgsProject.instance(
                ).snapSettingsForLayer(layer.id())
                if isinstance(layer, QgsVectorLayer) and enabled:
                    if snappingType == QgsSnapper.SnapToVertex:
                        snap_type = QgsPointLocator.Vertex
                    elif snappingType == QgsSnapper.SnapToSegment:
                        snap_type = QgsPointLocator.Edge
                    else:
                        snap_type = QgsPointLocator.All
                    snap_layers.append(
                        QgsSnappingUtils.LayerConfig(layer, snap_type,
                                                     tolerance, unitType))

        snap_util = mapCanvas.snappingUtils()
        old_layers = snap_util.layers()
        old_mode = snap_util.snapToMapMode()
        old_inter = snap_util.snapOnIntersections()
        snap_util.setLayers(snap_layers)
        snap_util.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)
        snap_util.setSnapOnIntersections(snapIntersections)
        match = snap_util.snapToMap(mapPoint)
        snap_util.setLayers(old_layers)
        snap_util.setSnapToMapMode(old_mode)
        snap_util.setSnapOnIntersections(old_inter)

        return match
Beispiel #9
0
 def __lineVertices(self):
     availableLayers = self.__getPointLayers()
     pointLayers = []
     self.__points = []
     self.__selectedStarts = []
     num = 0
     num_lines = len(self.__selectedIds)
     for iden in self.__selectedIds:
         self.__selectedStarts.append(max(0, len(self.__points) - 1))
         direction = self.__selectedDirections[num]
         selected = None
         for f in self.__lineLayer.selectedFeatures():
             if f.id() == iden:
                 selected = f
                 break
         if selected is None:
             self.__iface.messageBar().pushMessage(
                 QCoreApplication.translate("VDLTools", "Error"),
                 QCoreApplication.translate("VDLTools",
                                            "error on selected"),
                 level=QgsMessageBar.CRITICAL)
             continue
         line_v2, curved = GeometryV2.asLineV2(selected.geometry())
         if direction:
             rg = xrange(line_v2.numPoints())
         else:
             rg = xrange(line_v2.numPoints() - 1, -1, -1)
         for i in rg:
             pt_v2 = line_v2.pointN(i)
             x = pt_v2.x()
             y = pt_v2.y()
             doublon = False
             for item in self.__points:
                 if item['x'] == x and item['y'] == y:
                     item['z'][num] = pt_v2.z()
                     doublon = True
                     break
             if not doublon:
                 z = []
                 for j in xrange(num_lines):
                     if j == num:
                         z.append(pt_v2.z())
                     else:
                         z.append(None)
                 self.__points.append({'x': x, 'y': y, 'z': z})
                 for layer in availableLayers:
                     laySettings = QgsSnappingUtils.LayerConfig(
                         layer, QgsPointLocator.Vertex, 0.03,
                         QgsTolerance.LayerUnits)
                     point = Finder.findClosestFeatureAt(
                         self.toMapCoordinates(layer, QgsPoint(x, y)),
                         laySettings, self)
                     if point is not None:
                         if layer not in pointLayers:
                             pointLayers.append(layer)
         num += 1
     return pointLayers
Beispiel #10
0
    def setSnapLayers(self, snapper, layers):
        snap_layers = list()
        for layer in layers:
            if layer:
                snap_layer = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.All, 16, QgsTolerance.Pixels)
                snap_layers.append(snap_layer)

        snapper.setLayers(snap_layers)
        snapper.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)
Beispiel #11
0
 def __updateList(self):
     """
     To update the line layers list that we can use for interpolation
     """
     self.__layerList = []
     for layer in self.canvas().layers():
         if layer.type() == QgsMapLayer.VectorLayer and layer.hasGeometryType() \
                 and layer.geometryType() == QGis.Line:
             self.__layerList.append(
                 QgsSnappingUtils.LayerConfig(layer, QgsPointLocator.All,
                                              10, QgsTolerance.Pixels))
Beispiel #12
0
 def __updateList(self):
     """
     To update the snapping options of the layer
     """
     noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \
         QgsProject.instance().snapSettingsForLayer(self.__layer.id())
     self.__layerConfig = QgsSnappingUtils.LayerConfig(self.__layer, QgsPointLocator.Vertex, tolerance, unitType)
     if not enabled or tolerance == 0:
         self.__iface.messageBar().pushMessage(
             QCoreApplication.translate("VDLTools", "Error"),
             QCoreApplication.translate("VDLTools", "This layer has no snapping options"),
             level=QgsMessageBar.CRITICAL)
Beispiel #13
0
    def snap_to_layer(self, layer, point_locator=QgsPointLocator.All, set_settings=False):
        """ Set snapping to @layer """

        if layer is None:
            return

        QgsSnappingUtils.LayerConfig(layer, point_locator, 15, QgsTolerance.Pixels)
        if set_settings:
            layer_settings = self.snapping_config.individualLayerSettings(layer)
            layer_settings.setEnabled(True)
            self.snapping_config.setIndividualLayerSettings(layer, layer_settings)
            return layer_settings
Beispiel #14
0
    def canvasMoveEvent(self, event):
        """
        When the mouse is moved
        :param event: mouse event
        """
        if not self.__isChoosed:
            if self.__lineLayer is not None:
                noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \
                    QgsProject.instance().snapSettingsForLayer(self.__lineLayer.id())
                layerConfig = QgsSnappingUtils.LayerConfig(
                    self.__lineLayer, QgsPointLocator.Vertex, tolerance,
                    unitType)
                f = Finder.findClosestFeatureAt(event.mapPoint(), layerConfig,
                                                self)
                if not self.__inSelection:
                    if f is not None and self.__lastFeatureId != f.id():
                        self.__lastFeature = f
                        self.__lastFeatureId = f.id()
                        self.__lineLayer.setSelectedFeatures([f.id()])
                    if f is None:
                        self.__lineLayer.removeSelection()
                        self.__lastFeatureId = None
                        self.__selectedIds = None
                        self.__selectedDirections = None
                        self.__startVertex = None
                        self.__endVertex = None
                else:
                    if f is not None and (not self.__selectedIds
                                          or f.id() not in self.__selectedIds):
                        line = f.geometry().asPolyline()
                        if self.contains(line, self.__endVertex) > -1:
                            self.__lastFeature = f
                            self.__lastFeatureId = f.id()
                            features = self.__selectedIds + [f.id()]
                            self.__lineLayer.setSelectedFeatures(features)

                        elif self.contains(line, self.__startVertex) > -1:
                            self.__lastFeature = f
                            self.__lastFeatureId = f.id()
                            features = self.__selectedIds + [f.id()]
                            self.__lineLayer.setSelectedFeatures(features)

                        else:
                            self.__lineLayer.setSelectedFeatures(
                                self.__selectedIds)
                            self.__lastFeatureId = None
                            self.__lastFeature = None

                    if f is None and self.__selectedIds is not None:
                        self.__lineLayer.setSelectedFeatures(
                            self.__selectedIds)
                        self.__lastFeatureId = None
                        self.__lastFeature = None
    def test_signalConnection(self):
        # remove all layers
        QgsProject.instance().removeAllMapLayers()
        # set dependencies and add back layers
        self.pointsLayer = QgsVectorLayer("dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points", "spatialite")
        assert (self.pointsLayer.isValid())
        self.linesLayer = QgsVectorLayer("dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines", "spatialite")
        assert (self.linesLayer.isValid())
        self.pointsLayer2 = QgsVectorLayer("dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2", "spatialite")
        assert (self.pointsLayer2.isValid())
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())])
        # this should update connections between layers
        QgsProject.instance().addMapLayers([self.pointsLayer])
        QgsProject.instance().addMapLayers([self.linesLayer])
        QgsProject.instance().addMapLayers([self.pointsLayer2])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(self.pointsLayer,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        cfg.setIndividualLayerSettings(self.pointsLayer2,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(4)
        geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is OK
        m = u.snapToMap(QPoint(75, 100 - 0))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.8, 0.0))

        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
Beispiel #16
0
    def test_signalConnection(self):
        # remove all layers
        QgsProject.instance().removeAllMapLayers()
        # set dependencies and add back layers
        self.pointsLayer = QgsVectorLayer("dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points", "spatialite")
        assert self.pointsLayer.isValid()
        self.linesLayer = QgsVectorLayer("dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines", "spatialite")
        assert self.linesLayer.isValid()
        self.pointsLayer2 = QgsVectorLayer(
            "dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2", "spatialite"
        )
        assert self.pointsLayer2.isValid()
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())])
        # this should update connections between layers
        QgsProject.instance().addMapLayers([self.pointsLayer])
        QgsProject.instance().addMapLayers([self.linesLayer])
        QgsProject.instance().addMapLayers([self.pointsLayer2])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(
            self.pointsLayer,
            QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels),
        )
        cfg.setIndividualLayerSettings(
            self.pointsLayer2,
            QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels),
        )
        u.setConfig(cfg)
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setFeatureId(4)
        geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is ok
        m = u.snapToMap(QPoint(75, 100 - 0))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(0.8, 0.0))

        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
Beispiel #17
0
    def canvasMoveEvent(self, event):
        """
        When the mouse is moved
        :param event: mouse event
        """
        if not self.__isChoosed:
            if self.ownSettings.drawdownLayer is not None:
                laySettings = QgsSnappingUtils.LayerConfig(
                    self.ownSettings.drawdownLayer, QgsPointLocator.All, 10,
                    QgsTolerance.Pixels)
                feat = Finder.findClosestFeatureAt(event.mapPoint(),
                                                   laySettings, self)
                if not self.__inSelection:
                    if feat is not None and self.__lastFeatureId != feat.id():
                        self.__lastFeature = feat
                        self.__lastFeatureId = feat.id()
                        self.ownSettings.drawdownLayer.setSelectedFeatures(
                            [feat.id()])
                    if feat is None:
                        self.__cancel()
                else:
                    if feat is not None and (self.__selectedIds is None
                                             or feat.id()
                                             not in self.__selectedIds):
                        line = feat.geometry().asPolyline()
                        if self.__contains(line, self.__endVertex) > -1:
                            self.__lastFeature = feat
                            self.__lastFeatureId = feat.id()
                            features = self.__selectedIds + [feat.id()]
                            self.ownSettings.drawdownLayer.setSelectedFeatures(
                                features)

                        elif self.__contains(line, self.__startVertex) > -1:
                            self.__lastFeature = feat
                            self.__lastFeatureId = feat.id()
                            features = self.__selectedIds + [feat.id()]
                            self.ownSettings.drawdownLayer.setSelectedFeatures(
                                features)

                        else:
                            self.ownSettings.drawdownLayer.setSelectedFeatures(
                                self.__selectedIds)
                            self.__lastFeatureId = None
                            self.__lastFeature = None

                if feat is None:
                    if self.__selectedIds is not None:
                        self.ownSettings.drawdownLayer.setSelectedFeatures(
                            self.__selectedIds)
                    self.__lastFeatureId = None
                    self.__lastFeature = None
Beispiel #18
0
    def snapCurvedIntersections(mapPoint,
                                mapCanvas,
                                mapTool,
                                checkForAFeature=False,
                                featureId=None):
        snap_layers = []
        for layer in mapCanvas.layers():
            types = [0, 1, 2]
            if isinstance(layer,
                          QgsVectorLayer) and layer.geometryType() in types:
                noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = QgsProject.instance(
                ).snapSettingsForLayer(layer.id())
                if isinstance(layer, QgsVectorLayer) and enabled:
                    if snappingType == QgsSnapper.SnapToVertex:
                        snap_type = QgsPointLocator.Vertex
                    elif snappingType == QgsSnapper.SnapToSegment:
                        snap_type = QgsPointLocator.Edge
                    else:
                        snap_type = QgsPointLocator.All
                    snap_layers.append(
                        QgsSnappingUtils.LayerConfig(layer, snap_type,
                                                     tolerance, unitType))

        features = Finder.findFeaturesLayersAt(mapPoint, snap_layers, mapTool)
        if len(features) > 1:
            if len(features) > 2:
                one = [-1, 9999999]
                two = [-1, 9999999]
                for i in xrange(len(features)):
                    d = Finder.sqrDistForPoints(
                        mapPoint, features[i].geometry().asPoint())
                    if d > one[1]:
                        two = one
                        one[0] = i
                        one[1] = d
                    elif d > two[1]:
                        two[0] = i
                        two[1] = d
                feat1 = features[one[0]]
                feat2 = features[two[0]]
            else:
                feat1 = features[0]
                feat2 = features[1]
            if not checkForAFeature or feat1.id() == featureId or feat2.id(
            ) == featureId:
                return Finder.intersect(feat1.geometry(), feat2.geometry(),
                                        mapPoint)
            else:
                return None
        else:
            return None
def qgis_manage_snapping_layer(layername, snapping_type=0, tolerance=15.0):
    """ Manage snapping of @layername """

    layer = qgis_get_layer_by_tablename(layername)
    if not layer:
        return
    if snapping_type == 0:
        snapping_type = QgsPointLocator.Vertex
    elif snapping_type == 1:
        snapping_type = QgsPointLocator.Edge
    elif snapping_type == 2:
        snapping_type = QgsPointLocator.All

    QgsSnappingUtils.LayerConfig(layer, snapping_type, tolerance,
                                 QgsTolerance.Pixels)
Beispiel #20
0
 def canvasMoveEvent(self, event):
     """
     When the mouse is moved
     :param event: mouse event
     """
     if not self.__isEditing:
         laySettings = QgsSnappingUtils.LayerConfig(self.__layer, QgsPointLocator.All, 10,
                                                    QgsTolerance.Pixels)
         f_l = Finder.findClosestFeatureAt(event.mapPoint(), self.canvas(), [laySettings])
         if f_l is not None and self.__lastFeatureId != f_l[0].id():
             self.__lastFeatureId = f_l[0].id()
             self.__layer.setSelectedFeatures([f_l[0].id()])
         if f_l is None:
             self.__layer.removeSelection()
             self.__lastFeatureId = None
Beispiel #21
0
    def __updateProfile(self):
        """
        To update the profile in the dock after adjustments
        """
        self.__lineVertices()
        for p in range(len(self.__points)):
            pt = self.__points[p]
            x = pt['x']
            y = pt['y']
            z = pt['z']

            for layer in self.__layers:
                laySettings = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.All, self.SEARCH_TOLERANCE,
                    QgsTolerance.LayerUnits)
                fs = Finder.findFeaturesAt(QgsPoint(x, y), laySettings, self)
                if len(fs) == 0:
                    z.append(None)
                else:
                    zz = []
                    for f in fs:
                        if layer == self.ownSettings.drawdownLayer:
                            if f.id() not in self.__selectedIds:
                                closest = f.geometry().closestVertex(
                                    QgsPoint(x, y))
                                if closest[4] < self.SEARCH_TOLERANCE:
                                    line, curved = GeometryV2.asLineV2(
                                        f.geometry(), self.__iface)
                                    zp = line.zAt(closest[1])
                                    if zp is None or zp != zp:
                                        zz.append(0)
                                    else:
                                        zz.append(zp)
                        else:
                            zp = GeometryV2.asPointV2(f.geometry(),
                                                      self.__iface).z()
                            if zp is None or zp != zp:
                                zp = 0
                            zz.append(zp)

                    if len(zz) == 0:
                        z.append(None)
                    elif len(zz) == 1:
                        z.append(zz[0])
                    else:
                        z.append(zz)
        self.__calculateProfile()
Beispiel #22
0
    def __layOk(self):
        self.__features = []

        for points in self.__points:
            feat = []
            x = points['x']
            y = points['y']
            z = points['z']
            for layer in self.__layers:
                laySettings = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.Vertex, 0.03,
                    QgsTolerance.LayerUnits)
                point = Finder.findClosestFeatureAt(
                    self.toMapCoordinates(layer, QgsPoint(x, y)), laySettings,
                    self)
                feat.append(point)
                if point is None:
                    z.append(None)
                else:
                    point_v2 = GeometryV2.asPointV2(point.geometry())
                    zp = point_v2.z()
                    if zp is None or zp != zp:
                        z.append(0)
                    else:
                        z.append(zp)
            self.__features.append(feat)

        # points = []
        # for key, p in pointz.items():
        #     if p is not None:
        #         pt = p[0].geometry().asPoint()
        #         i = 0
        #         for l in layers:
        #             if l == p[1]:
        #                 break
        #             i += 1
        #         attName = attributes[i]
        #         z = p[0].attribute(attName)
        #         points.append({'x': pt.x(), 'y': pt.y(), 'z': z})
        names = [self.__lineLayer.name()]
        for layer in self.__layers:
            names.append(layer.name())
        self.__calculateProfile(names)
        self.__isChoosed = 0
Beispiel #23
0
 def getLayersSettings(mapCanvas, types, snapType=None):
     """
     To get the snapping config from different layers
     :param mapCanvas: the used QgsMapCanvas
     :param types: geometry types in use
     :param snapType: snapping type
     :return: list of layers config
     """
     snap_layers = []
     for layer in mapCanvas.layers():
         if layer.type() == QgsMapLayer.VectorLayer and layer.geometryType(
         ) in types:
             snap_util = mapCanvas.snappingUtils()
             mode = snap_util.snapToMapMode()
             if mode == QgsSnappingUtils.SnapCurrentLayer and layer.id(
             ) != mapCanvas.currentLayer().id():
                 continue
             if mode == QgsSnappingUtils.SnapAllLayers:
                 snap_index, tolerance, unitType = snap_util.defaultSettings(
                 )
                 snap_type = QgsPointLocator.Type(snap_index)
             else:
                 noUse, enabled, snappingType, unitType, tolerance, avoidIntersection = \
                     QgsProject.instance().snapSettingsForLayer(layer.id())
                 if layer.type() == QgsMapLayer.VectorLayer and enabled:
                     if snapType is None:
                         if snappingType == QgsSnapper.SnapToVertex:
                             snap_type = QgsPointLocator.Vertex
                         elif snappingType == QgsSnapper.SnapToSegment:
                             snap_type = QgsPointLocator.Edge
                         elif snappingType == QgsSnapper.SnapToVertexAndSegment:
                             snap_type = QgsPointLocator.Edge and QgsPointLocator.Vertex
                         else:
                             snap_type = QgsPointLocator.All
                     else:
                         snap_type = snapType
                 else:
                     continue
             snap_layers.append(
                 QgsSnappingUtils.LayerConfig(layer, snap_type, tolerance,
                                              unitType))
     return snap_layers
Beispiel #24
0
    def processAlgorithm(self, progress):
        points_layer = self.getParameterValue(self.POINTS)
        points_layer = getObjectFromUri(points_layer)

        add_attribute = self.getParameterValue(self.SNAPPED)

        fields = points_layer.dataProvider().fields()

        if add_attribute:
            fields.append(QgsField('snapped', QVariant.String))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields,
            QGis.WKBPoint,
            points_layer.crs())

        snapper = QgsSnappingUtils()


        snapping_type = QgsSnapper.SnapToSegment
        tolerance = 1
        unit = QgsTolerance.LayerUnits
        layer_config = QgsSnappingUtils.LayerConfig(layer_edge, snapping_type, tolerance, unit)
        snapper.setLayers([layer_config])
        snap_mode = QgsSnappingUtils.SnapAdvanced
        snapper.setSnapToMapMode(snap_mode)

        for feature in vector.features(points_layer):
            f = QgsFeature()
            attributes = feature.attributes()
            result = snapper.snapToMap(feature.geometry().asPoint())
            if result.type() == 2:
                f.setGeometry(QgsGeometry.fromPoint(result.point()))
                if add_attribute:
                    attributes.append('True')
            else:
                f.setGeometry(feature.geometry())
                if add_attribute:
                    attributes.append('False')
            f.setAttributes(attributes)
            writer.addFeature(f)
        del writer
# coding: utf-8

from qgis.core import QgsSnappingUtils
from qgis.gui import QgsMapCanvasSnappingUtils
from qgis.utils import iface

canvas = iface.mapCanvas()

snapping_utils = QgsSnappingUtils()
print(snapping_utils.snapToMapMode())
# Change the mode through the GUI
print(snapping_utils.snapToMapMode())
# Retrieve information from the project
snapping_utils.readConfigFromProject()

# Alternate way to above code
snapping_utils = canvas.snappingUtils()  # TODO: cast QgsMapCanvasSnappingUtils
snapping_utils.defaultSettings()

# Find the mode in a readable way
print([
    i for i in ['SnapCurrentLayer', 'SnapAdvanced', 'SnapAllLayers']
    if snapping_utils.snapToMapMode() == getattr(QgsSnappingUtils, i)
][0])

print(snapping_utils.layers())
print(snapping_utils.defaultSettings()
      )  # where values are type, tolerance and unit

map_canvas_snapping_utils = QgsMapCanvasSnappingUtils(canvas)
    def test_resetSnappingIndex(self):
        self.pointsLayer.setDependencies([])
        self.linesLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(self.pointsLayer,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)

        m = u.snapToMap(QPoint(95, 100))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(1, 0))

        f = QgsFeature(self.linesLayer.fields())
        f.setFeatureId(1)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()

        l1 = len([f for f in self.pointsLayer.getFeatures()])
        self.assertEqual(l1, 4)
        m = u.snapToMap(QPoint(95, 0))
        # snapping not updated
        self.pointsLayer.setDependencies([])
        self.assertEqual(m.isValid(), False)

        # set layer dependencies
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setFeatureId(2)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the snapped point is ok
        m = u.snapToMap(QPoint(45, 50))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(0.5, 0.5))
        self.pointsLayer.setDependencies([])

        # test chained layer dependencies A -> B -> C
        cfg.setIndividualLayerSettings(self.pointsLayer2,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setFeatureId(3)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is ok
        m = u.snapToMap(QPoint(75, 100 - 80))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPoint(0.7, 0.8))
        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
    def test_resetSnappingIndex(self):
        self.pointsLayer.setDependencies([])
        self.linesLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])

        ms = QgsMapSettings()
        ms.setOutputSize(QSize(100, 100))
        ms.setExtent(QgsRectangle(0, 0, 1, 1))
        self.assertTrue(ms.hasValidSettings())

        u = QgsSnappingUtils()
        u.setMapSettings(ms)
        cfg = u.config()
        cfg.setEnabled(True)
        cfg.setMode(QgsSnappingConfig.AdvancedConfiguration)
        cfg.setIndividualLayerSettings(self.pointsLayer,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)

        m = u.snapToMap(QPoint(95, 100))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(1, 0))

        f = QgsFeature(self.linesLayer.fields())
        f.setId(1)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()

        l1 = len([f for f in self.pointsLayer.getFeatures()])
        self.assertEqual(l1, 4)
        m = u.snapToMap(QPoint(95, 0))
        # snapping not updated
        self.pointsLayer.setDependencies([])
        self.assertEqual(m.isValid(), False)

        # set layer dependencies
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(2)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the snapped point is OK
        m = u.snapToMap(QPoint(45, 50))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.5, 0.5))
        self.pointsLayer.setDependencies([])

        # test chained layer dependencies A -> B -> C
        cfg.setIndividualLayerSettings(self.pointsLayer2,
                                       QgsSnappingConfig.IndividualLayerSettings(True,
                                                                                 QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels))
        u.setConfig(cfg)
        self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())])
        self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())])
        # add another line
        f = QgsFeature(self.linesLayer.fields())
        f.setId(3)
        geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)")
        f.setGeometry(geom)
        self.linesLayer.startEditing()
        self.linesLayer.addFeatures([f])
        self.linesLayer.commitChanges()
        # check the second snapped point is OK
        m = u.snapToMap(QPoint(75, 100 - 80))
        self.assertTrue(m.isValid())
        self.assertTrue(m.hasVertex())
        self.assertEqual(m.point(), QgsPointXY(0.7, 0.8))
        self.pointsLayer.setDependencies([])
        self.pointsLayer2.setDependencies([])
# coding: utf-8

from qgis.core import QgsSnappingUtils
from qgis.gui import QgsMapCanvasSnappingUtils
from qgis.utils import iface

canvas = iface.mapCanvas()

snapping_utils = QgsSnappingUtils()
print(snapping_utils.snapToMapMode())
# Change the mode through the GUI
print(snapping_utils.snapToMapMode())
# Retrieve information from the project
snapping_utils.readConfigFromProject()

# Alternate way to above code
snapping_utils = canvas.snappingUtils()  # TODO: cast QgsMapCanvasSnappingUtils
snapping_utils.defaultSettings()

# Find the mode in a readable way
print([
    i for i in ['SnapCurrentLayer', 'SnapAdvanced', 'SnapAllLayers']
    if snapping_utils.snapToMapMode() == getattr(QgsSnappingUtils, i)
][0])


print(snapping_utils.layers())
print(snapping_utils.defaultSettings())  # where values are type, tolerance and unit

map_canvas_snapping_utils = QgsMapCanvasSnappingUtils(canvas)
class VertexTracerTool(QgsMapTool):

    traceFound = pyqtSignal(QgsGeometry)

    def __init__(self, canvas):
        # some stuff we need from qgis
        QgsMapTool.__init__(self, canvas)
        self.canvas = canvas
        self.snapper = QgsSnappingUtils()
        # some stuff to control our state
        self.mCtrl = False
        self.started = False
        self.firstTimeOnSegment = True
        self.lastPointMustStay = False
        # some stuff to put our temp output
        self.lastPoint = None
        self.rb = None
        self.isPolygon = False

        # our own fancy cursor
        self.cursor = QCursor(
            QPixmap([
                "16 16 3 1", "      c None", ".     c #00FF00",
                "+     c #FFFFFF", "                ", "       +.+      ",
                "      ++.++     ", "     +.....+    ", "    +.     .+   ",
                "   +.   .   .+  ", "  +.    .    .+ ", " ++.    .    .++",
                " ... ...+... ...", " ++.    .    .++", "  +.    .    .+ ",
                "   +.   .   .+  ", "   ++.     .+   ", "    ++.....+    ",
                "      ++.++     ", "       +.+      "
            ]))

    # we need to know, if ctrl-key is pressed
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Control:
            self.mCtrl = True

    # and also if ctrl-key is released
    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Control:
            self.mCtrl = False
        # remove the last added point when the delete key is pressed
        if event.key() == Qt.Key_Backspace:
            self.rb.removeLastPoint()

    def canvasPressEvent(self, event):
        # on left click, we add a point
        if event.button() == 1:
            layer = self.canvas.currentLayer()
            # if it is the start of a new trace, set the rubberband up
            if not self.started:
                if layer.geometryType() == 1:
                    self.isPolygon = False
                if layer.geometryType() == 2:
                    self.isPolygon = True
                self.rb = QgsRubberBand(self.canvas, layer.geometryType())
                self.rb.setColor(QColor(255, 0, 0))
                # declare, that are we going to work, now!
            self.started = True
            if layer is not None:
                x = event.pos().x()
                y = event.pos().y()
                selPoint = QPoint(x, y)
                # try to get something snapped
                (retval,
                 result) = self.snapper.snapToBackgroundLayers(selPoint)

                # the point we want to have, is either from snapping result
                if result != []:
                    point = result[0].snappedVertex
                    # if we snapped something, it's either a vertex
                    if result[0].snappedVertexNr != -1:
                        self.firstTimeOnSegment = True
                    # or a point on a segment, so we have to declare, that a point on segment is found
                    else:
                        self.firstTimeOnSegment = False
                # or its some point from out in the wild
                else:
                    point = QgsMapToPixel.toMapCoordinates(
                        self.canvas.getCoordinateTransform(), x, y)
                    self.firstTimeOnSegment = True

                # bring the rubberband to the cursor i.e. the clicked point
                self.rb.movePoint(point)
                # and set a new point to go on with
                self.appendPoint(point)
                # try to remember that this point was on purpose i.e. clicked by the user
                self.lastPointMustStay = True
                self.firstTimeOnSegment = True

    def canvasMoveEvent(self, event):
        # QgsMessageLog.logMessage('fts: '+str(self.firstTimeOnSegment), 'state', 0)
        # QgsMessageLog.logMessage('lpc: '+str(self.lastPointMustStay), 'state', 0)
        if self.started:
            # Get the click
            x = event.pos().x()
            y = event.pos().y()
            eventPoint = QPoint(x, y)
            # only if the ctrl key is pressed
            if self.mCtrl:
                layer = self.canvas.currentLayer()
                if layer is not None:
                    (retval,
                     result) = self.snapper.snapToBackgroundLayers(eventPoint)

                # so if we have found a snapping
                if result != []:
                    # pydevd.settrace()
                    # that's the snapped point
                    point = QgsPoint(result[0].snappedVertex)
                    # if it is a vertex, not a point on a segment
                    if result[0].snappedVertexNr != -1:
                        self.rb.movePoint(point)
                        self.appendPoint(point)
                        self.lastPointMustStay = True
                        # the next point found, may  be on a segment
                        self.firstTimeOnSegment = True
                    # we are on a segment
                    else:
                        self.rb.movePoint(point)
                        # if we are on a new segment, we add the point in any case
                        if self.firstTimeOnSegment:
                            self.appendPoint(point)
                            self.lastPointMustStay = True
                            self.firstTimeOnSegment = False
                        # if we are not on a new segemnt, we have to test, if this point is realy needed
                        else:
                            # but only if we have already enough points
                            # TODO: check if this is correct for lines also (they only need two points, to be vaild)
                            if self.rb.numberOfVertices() >= 3:
                                max = self.rb.numberOfVertices()
                                lastRbP = self.rb.getPoint(0, max - 2)
                                # QgsMessageLog.logMessage(str(self.rb.getPoint(0, max-1)), 'rb', 0)
                                nextToLastRbP = self.rb.getPoint(0, max - 3)
                                # QgsMessageLog.logMessage(str(self.rb.getPoint(0, max-2)), 'rb', 0)
                                # QgsMessageLog.logMessage(str(point), 'rb', 0)
                                if not self.pointOnLine(
                                        lastRbP, nextToLastRbP,
                                        QgsPoint(point)):
                                    self.appendPoint(point)
                                    self.lastPointMustStay = False
                                else:
                                    # TODO: schauen, ob der letzte punkt ein klick war, dann nicht löschen. entsrpechend auch die "punkt auf linie" neu berechenen.
                                    if not self.lastPointMustStay:
                                        self.rb.removeLastPoint()
                                        self.rb.movePoint(point)
                                        # QgsMessageLog.logMessage('point removed', 'click', 0)
                                # else:
                                # QgsMessageLog.logMessage('sleep', 'rb', 0)
                            else:
                                self.appendPoint(point)
                                self.lastPointMustStay = False
                                self.firstTimeOnSegment = False

                else:
                    # if nothing specials happens, just update the rubberband to the cursor position
                    point = QgsMapToPixel.toMapCoordinates(
                        self.canvas.getCoordinateTransform(), x, y)
                    self.rb.movePoint(point)

            else:
                # in "not-tracing" state, just update the rubberband to the cursor position
                # but we have still to snap to act like the "normal" digitize tool
                (retval,
                 result) = self.snapper.snapToBackgroundLayers(eventPoint)
                if result != []:
                    point = QgsPoint(result[0].snappedVertex)
                else:
                    point = QgsMapToPixel.toMapCoordinates(
                        self.canvas.getCoordinateTransform(), x, y)
                self.rb.movePoint(point)

    def canvasReleaseEvent(self, event):
        # with right click the digitizing is finished
        if event.button() == 2:

            layer = self.canvas.currentLayer()
            x = event.pos().x()
            y = event.pos().y()
            if layer is not None and self.started:
                selPoint = QPoint(x, y)
                (retval,
                 result) = self.snapper.snapToBackgroundLayers(selPoint)

                if result != []:
                    point = result[0].snappedVertex
                else:
                    point = QgsMapToPixel.toMapCoordinates(
                        self.canvas.getCoordinateTransform(), x, y)

                # add this last point
                self.appendPoint(QgsPoint(point))
                self.sendGeometry()

    def appendPoint(self, point):
        # don't add the point if it is identical to the last point we added
        if not (self.lastPoint == point):
            self.rb.addPoint(point)
            self.lastPoint = QgsPoint(point)
        else:
            pass

    # see: double QgsGeometryValidator::distLine2Point( QgsPoint p, QgsVector v, QgsPoint q )
    # distance of point q from line through p in direction v
    def pointOnLine(self, pntAft, pntBef, pntTest):
        p = QgsPoint(pntAft)
        vx = pntBef.x() - pntAft.x()
        vy = pntBef.y() - pntAft.y()
        vlength = math.sqrt(vy * vy + vx * vx)
        if vlength == 0:
            return False
        q = QgsPoint(pntTest)

        res = (vx * (q.y() - p.y()) - vy * (q.x() - p.x())) / vlength
        # res = 0 means point is on line, but we are not in a perfect world, so a tolerance is needed
        # to get rid of some numerical problems. Tolerance estimated by solid engenieering work (rule of thumb...)
        if res < 1E-10:
            return True
        else:
            return False

    def sendGeometry(self):
        layer = self.canvas.currentLayer()
        coords = []

        # backward compatiblity for a bug in qgsRubberband, that was fixed in 1.7
        if Qgis.QGIS_VERSION_INT >= 10700:
            [
                coords.append(self.rb.getPoint(0, i))
                for i in range(self.rb.numberOfVertices())
            ]
        else:
            [
                coords.append(self.rb.getPoint(0, i))
                for i in range(1, self.rb.numberOfVertices())
            ]

        # On the Fly reprojection, not necessary any more, mapToLayerCoordinates is clever enough on its own
        # layerEPSG = layer.srs().epsg()
        # projectEPSG = self.canvas.mapRenderer().destinationSrs().epsg()
        # if layerEPSG != projectEPSG:
        coords_tmp = coords[:]
        coords = []
        for point in coords_tmp:
            transformedPoint = self.canvas.mapRenderer().mapToLayerCoordinates(
                layer, point)
            coords.append(transformedPoint)

        coords_tmp = coords[:]
        coords = []
        lastPt = None
        for pt in coords_tmp:
            if (lastPt != pt):
                coords.append(pt)
                lastPt = pt

        # Add geometry to feature.
        if self.isPolygon:
            g = QgsGeometry().fromPolygon([coords])
        else:
            g = QgsGeometry().fromPolyline(coords)

        self.traceFound.emit(g)
        self.rb.reset(self.isPolygon)
        self.started = False

    def activate(self):
        self.canvas.setCursor(self.cursor)

    def deactivate(self):
        try:
            self.rb.reset()
        except AttributeError:
            pass

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True
Beispiel #30
0
    def cadCanvasMoveEvent(self, event):
        """
        When the mouse is moved
        :param event: mouse event
        """

        if type(event) == QMoveEvent:
            map_point = self.toMapCoordinates(event.pos())
        else:
            map_point = event.mapPoint()

        if not self.__isEditing and not self.__findVertex and not self.__onMove:
            laySettings = QgsSnappingUtils.LayerConfig(self.__layer,
                                                       QgsPointLocator.All, 10,
                                                       QgsTolerance.Pixels)
            f_l = Finder.findClosestFeatureAt(map_point, self.canvas(),
                                              [laySettings])
            if f_l is not None and self.__lastFeatureId != f_l[0].id():
                self.__lastFeatureId = f_l[0].id()
                self.__layer.setSelectedFeatures([f_l[0].id()])
            if f_l is None:
                self.__layer.removeSelection()
                self.__lastFeatureId = None
        elif self.__findVertex:
            if self.__rubberBand is not None:
                self.__rubberBand.reset()
            closest = self.__selectedFeature.geometry().closestVertex(
                map_point)
            color = QColor("red")
            color.setAlphaF(0.78)
            self.__rubberBand.setColor(color)
            self.__rubberBand.setIcon(4)
            self.__rubberBand.setIconSize(20)
            self.__rubberBand.setToGeometry(
                QgsGeometry().fromPoint(closest[0]), None)
        elif self.__onMove:
            if self.__rubberBand is not None:
                self.__rubberBand.reset()
            if self.__layer.geometryType() == QGis.Polygon:
                self.__polygonPreview(map_point)
            elif self.__layer.geometryType() == QGis.Line:
                self.__linePreview(map_point)
            else:
                self.__pointPreview(map_point)
            color = QColor("red")
            color.setAlphaF(0.78)
            self.__rubberBand.setColor(color)
            self.__rubberBand.setWidth(2)
            if self.__layer.geometryType() != QGis.Point:
                self.__rubberBand.setLineStyle(Qt.DotLine)
            else:
                self.__rubberBand.setIcon(4)
                self.__rubberBand.setIconSize(8)
            if self.__rubberSnap is not None:
                self.__rubberSnap.reset()
            else:
                self.__rubberSnap = QgsRubberBand(self.canvas(), QGis.Point)
            self.__rubberSnap.setColor(color)
            self.__rubberSnap.setWidth(2)
            self.__rubberSnap.setIconSize(20)
            match = Finder.snap(map_point, self.canvas())
            if match.hasVertex() or match.hasEdge():
                point = match.point()
                if match.hasVertex():
                    if match.layer():
                        self.__rubberSnap.setIcon(4)
                    else:
                        self.__rubberSnap.setIcon(1)
                if match.hasEdge():
                    intersection = Finder.snapCurvedIntersections(
                        point, self.canvas(), self)
                    if intersection is not None:
                        self.__rubberSnap.setIcon(1)
                        point = intersection
                    else:
                        self.__rubberSnap.setIcon(3)
                self.__rubberSnap.setToGeometry(QgsGeometry().fromPoint(point),
                                                None)
Beispiel #31
0
from qgis.core import QgsSnappingUtils
snapper = QgsSnappingUtils()

layer_edge = QgsMapLayerRegistry.instance().mapLayersByName('edges')[0]
snapping_type = QgsSnapper.SnapToSegment
tolerance = 1
unit = QgsTolerance.LayerUnits
layer_config = QgsSnappingUtils.LayerConfig(layer_edge, snapping_type, tolerance, unit)
snapper.setLayers([layer_config])
snap_mode = QgsSnappingUtils.SnapAdvanced
snapper.setSnapToMapMode(snap_mode)

p1 = QgsPoint(20.4529554239886, -34.0188548283715)
r = snapper.snapToMap(p1)
print r.type()

#snapper=QgsSnapper(iface.mapCanvas().mapSettings())
#snapper = setSnapMode
Beispiel #32
0
 def setSnapping(self, config):
     self.snapConfig = config
     self.snapper = QgsSnappingUtils(self.canvas)
     self.snapper.setConfig(self.snapConfig)
     self.snapper.setMapSettings(self.canvas.mapSettings())
Beispiel #33
0
class VertexTool(QgsMapTool):
    canvasReleased = pyqtSignal(QgsPointXY, bool)
    isActive = pyqtSignal(bool)

    def __init__(self, iface, canvas, useSnapped=True):
        super(VertexTool, self).__init__(canvas)

        self.snapper = None
        self.markerSnapped = None
        self.useSnapped = useSnapped
        self.iface = iface
        self.canvas = self.iface.mapCanvas()
        self.setCursor(Qt.CrossCursor)
        self.prj = QgsProject.instance()
        self.snapConfig = self.prj.snappingConfig()
        self.prj.snappingConfigChanged.connect(self.setSnapping)

        self.setSnapping(self.prj.snappingConfig())

    def setSnapping(self, config):
        self.snapConfig = config
        self.snapper = QgsSnappingUtils(self.canvas)
        self.snapper.setConfig(self.snapConfig)
        self.snapper.setMapSettings(self.canvas.mapSettings())

    def canvasMoveEvent(self, event):
        point = self.toMapCoordinates(event.pos())
        if self.snapConfig.enabled() and self.useSnapped:
            self.isSnapped(point)
        else:
            self.resetMarker()

    def canvasReleaseEvent(self, event):
        point = self.toMapCoordinates(event.pos())
        if self.useSnapped:
            point, isnaped = self.isSnapped(point)
            self.canvasReleased.emit(point, isnaped)
        else:
            self.canvasReleased.emit(point, False)

    def activate(self):
        self.isActive.emit(True)
        QgsMapTool.activate(self)

    def deactivate(self):
        self.resetMarker()
        self.isActive.emit(False)
        QgsMapTool.deactivate(self)

    def isSnapped(self, pointxy):
        self.resetMarker()
        matchres = self.snapper.snapToMap(pointxy)  # QgsPointLocator.Match
        if matchres.isValid():
            self.markerSnapped = QgsVertexMarker(self.canvas)
            self.markerSnapped.setColor(Qt.red)
            self.markerSnapped.setIconSize(7)
            self.markerSnapped.setIconType(QgsVertexMarker.ICON_BOX)
            self.markerSnapped.setPenWidth(3)
            self.markerSnapped.setCenter(matchres.point())
            self.markerSnapped.show()
            return matchres.point(), True
        else:
            return pointxy, False

    def resetMarker(self):
        self.canvas.scene().removeItem(self.markerSnapped)
Beispiel #34
0
    def __adjust(self):
        """
        To look for adjustments and to display them
        """
        self.__layers = self.__lineVertices(True)
        self.__adjustments = []
        self.__altitudes = []

        for p in range(len(self.__points)):
            pt = self.__points[p]
            x = pt['x']
            y = pt['y']
            z = pt['z']
            num_lines = len(self.__selectedIds)
            drawdown = False
            level = None
            for layer in self.ownSettings.refLayers:
                laySettings = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.All, self.SEARCH_TOLERANCE,
                    QgsTolerance.LayerUnits)
                feature = Finder.findClosestFeatureAt(
                    self.toMapCoordinates(layer, QgsPoint(x, y)), laySettings,
                    self)
                if feature is not None:
                    point_v2 = GeometryV2.asPointV2(feature.geometry(),
                                                    self.__iface)
                    if point_v2.z() > 0:
                        if level is not None:
                            if (level - point_v2.z()) > 0.005:
                                self.__iface.messageBar(
                                ).pushMessage(QCoreApplication.translate(
                                    "VDLTools",
                                    "More than one reference point, with 2 different elevations !!"
                                ),
                                              level=QgsMessageBar.CRITICAL,
                                              duration=0)
                                self.__cancel()
                                return
                        level = point_v2.z()
                    comp = QCoreApplication.translate("VDLTools",
                                                      " (at invert)")
                    if str(feature.attribute(self.ownSettings.levelAtt)
                           ) in self.ownSettings.levelVals:
                        drawdown = True
                        comp = QCoreApplication.translate(
                            "VDLTools", " (on pipe)")
                    if point_v2.z() == 0:
                        comp = QCoreApplication.translate(
                            "VDLTools", " (no elevation)")

                    self.__adjustments.append({
                        'point': p,
                        'previous': point_v2.z(),
                        'line': False,
                        'layer': layer,
                        'comp': comp,
                        'feature': feature,
                        'delta': False
                    })
            diam = 0
            for i in range(num_lines):
                if z[i] is None:
                    continue
                id_s = self.__selectedIds[i]
                feature = QgsFeature()
                self.ownSettings.drawdownLayer.getFeatures(
                    QgsFeatureRequest().setFilterFid(id_s)).nextFeature(
                        feature)
                dtemp = feature.attribute(self.ownSettings.pipeDiam) / 1000
                if dtemp > diam:
                    diam = dtemp
                selected = None
                for f in self.ownSettings.drawdownLayer.selectedFeatures():
                    if f.id() == id_s:
                        selected = f
                        break
                self.__adjustments.append({
                    'point': p,
                    'previous': z[i],
                    'line': True,
                    'diam': dtemp,
                    'layer': self.ownSettings.drawdownLayer,
                    'feature': selected,
                    'delta': True
                })

            for layer in self.__layers:
                laySettings = QgsSnappingUtils.LayerConfig(
                    layer, QgsPointLocator.All, self.SEARCH_TOLERANCE,
                    QgsTolerance.LayerUnits)
                fs = Finder.findFeaturesAt(QgsPoint(x, y), laySettings, self)
                if len(fs) == 0:
                    z.append(None)
                else:
                    zz = []
                    for f in fs:
                        if layer == self.ownSettings.drawdownLayer:
                            if f.id() not in self.__selectedIds:
                                closest = f.geometry().closestVertex(
                                    QgsPoint(x, y))
                                if closest[4] < self.SEARCH_TOLERANCE:
                                    line, curved = GeometryV2.asLineV2(
                                        f.geometry(), self.__iface)
                                    zp = line.zAt(closest[1])
                                    dtemp = f.attribute(
                                        self.ownSettings.pipeDiam) / 1000
                                    if dtemp > diam:
                                        diam = dtemp
                                    self.__adjustments.append({
                                        'point':
                                        p,
                                        'previous':
                                        zp,
                                        'line':
                                        False,
                                        'diam':
                                        dtemp,
                                        'comp':
                                        QCoreApplication.translate(
                                            "VDLTools", " connected"),
                                        'feature':
                                        f,
                                        'layer':
                                        layer,
                                        'delta':
                                        True
                                    })
                                    if zp is None or zp != zp:
                                        zz.append(0)
                                    else:
                                        zz.append(zp)
                        else:
                            zp = GeometryV2.asPointV2(f.geometry(),
                                                      self.__iface).z()
                            if zp is None or zp != zp:
                                zp = 0
                            zz.append(zp)
                            if layer in self.ownSettings.adjLayers:
                                self.__adjustments.append({
                                    'point': p,
                                    'previous': zp,
                                    'line': False,
                                    'layer': layer,
                                    'feature': f,
                                    'delta': True
                                })
                    if len(zz) == 0:
                        z.append(None)
                    elif len(zz) == 1:
                        z.append(zz[0])
                    else:
                        z.append(zz)

            if level is not None:
                if drawdown:
                    alt = level - diam
                else:
                    alt = level
            else:
                alt = 0

            dd = None
            if drawdown:
                dd = QCoreApplication.translate("VDLTools", "drawdown")
            self.__altitudes.append({'diam': diam, 'drawdown': dd, 'alt': alt})

        last = len(self.__altitudes) - 1
        self.__extras = []
        for i in range(len(self.__altitudes)):
            if self.__altitudes[i]['alt'] is 0:
                if 0 < i < last:
                    av = None
                    j = 1
                    while True:
                        if i - j < 0:
                            break
                        if self.__altitudes[i - j]['alt'] != 0:
                            av = j
                            break
                        j += 1
                    ap = None
                    j = 1
                    while True:
                        if i + j > len(self.__points) - 1:
                            break
                        if self.__altitudes[i + j]['alt'] != 0:
                            ap = j
                            break
                        j += 1
                    if av is not None and ap is not None:
                        prev_alt = self.__altitudes[i - av]['alt']
                        next_alt = self.__altitudes[i + ap]['alt']
                        prev_pt = self.__points[i - av]
                        next_pt = self.__points[i + ap]
                        pt = self.__points[i]
                        d0 = Finder.sqrDistForCoords(pt['x'], prev_pt['x'],
                                                     pt['y'], prev_pt['y'])
                        d1 = Finder.sqrDistForCoords(next_pt['x'], pt['x'],
                                                     next_pt['y'], pt['y'])
                        inter_alt = round(
                            old_div((d0 * next_alt + d1 * prev_alt),
                                    (d0 + d1)), 3)
                        self.__altitudes[i]['alt'] = inter_alt
                        self.__altitudes[i]['drawdown'] = "interpolation"
                elif i == 0 and len(self.__altitudes) > 2:
                    alt1 = self.__altitudes[1]['alt']
                    alt2 = self.__altitudes[2]['alt']
                    if alt1 != 0 and alt2 != 0:
                        pt2 = self.__points[2]
                        pt1 = self.__points[1]
                        pt = self.__points[0]
                        big_d = Finder.sqrDistForCoords(
                            pt2['x'], pt1['x'], pt2['y'], pt1['y'])
                        small_d = Finder.sqrDistForCoords(
                            pt1['x'], pt['x'], pt1['y'], pt['y'])
                        extra_alt = round(
                            alt2 + (1 + old_div(small_d, big_d)) *
                            (alt1 - alt2), 3)
                        if small_d < (old_div(big_d, 4)):
                            self.__altitudes[i]['alt'] = extra_alt
                            self.__altitudes[i]['drawdown'] = "extrapolation"
                        else:
                            self.__extras.append([i, extra_alt])
                elif i == last and len(self.__altitudes) > 2:
                    alt1 = self.__altitudes[i - 1]['alt']
                    alt2 = self.__altitudes[i - 2]['alt']
                    if alt1 != 0 and alt2 != 0:
                        pt2 = self.__points[i - 2]
                        pt1 = self.__points[i - 1]
                        pt = self.__points[i]
                        big_d = Finder.sqrDistForCoords(
                            pt2['x'], pt1['x'], pt2['y'], pt1['y'])
                        small_d = Finder.sqrDistForCoords(
                            pt1['x'], pt['x'], pt1['y'], pt['y'])
                        extra_alt = round(
                            alt2 + (1 + old_div(small_d, big_d)) *
                            (alt1 - alt2), 3)
                        if small_d < (old_div(big_d, 4)):
                            self.__altitudes[i]['alt'] = extra_alt
                            self.__altitudes[i]['drawdown'] = "extrapolation"
                        else:
                            self.__extras.append([i, extra_alt])

        if len(self.__extras) == 0:
            self.__setAdjustements()
        else:
            self.__checkForceExtrapolation()
Beispiel #35
0
    def __lineVertices(self, checkLayers=False):
        """
        To check if vertices of others layers are crossing the displaying line
        :param checkLayers: if we want to get the list of the other layers in return
        :return: other layers list if requested
        """
        if checkLayers:
            otherLayers = []
        self.__points = []
        self.__selectedStarts = []
        num = 0
        num_lines = len(self.__selectedIds)
        for iden in self.__selectedIds:
            self.__selectedStarts.append(max(0, len(self.__points) - 1))
            direction = self.__selectedDirections[num]
            selected = None
            for f in self.ownSettings.drawdownLayer.selectedFeatures():
                if f.id() == iden:
                    selected = f
                    break
            if selected is None:
                self.__iface.messageBar().pushMessage(
                    QCoreApplication.translate("VDLTools",
                                               "Error on selected"),
                    level=QgsMessageBar.CRITICAL,
                    duration=0)
                continue
            line_v2, curved = GeometryV2.asLineV2(selected.geometry(),
                                                  self.__iface)
            if direction:
                rg = range(line_v2.numPoints())
            else:
                rg = range(line_v2.numPoints() - 1, -1, -1)
            rg_positions = []
            for i in rg:
                pt_v2 = line_v2.pointN(i)
                x = pt_v2.x()
                y = pt_v2.y()
                doublon = False
                for position in rg_positions:
                    if position['x'] == x and position['y'] == y and position[
                            'iden'] == iden:
                        self.__iface.messageBar().pushMessage(
                            QCoreApplication.translate(
                                "VDLTools", "Beware! the line ") + str(iden) +
                            QCoreApplication.translate(
                                "VDLTools",
                                " has 2 identical summits on the vertex ") +
                            str(i - 1) + QCoreApplication.translate(
                                "VDLTools", " same coordinates (X and Y). "
                                "Please correct the line geometry."),
                            level=QgsMessageBar.CRITICAL,
                            duration=0)
                        doublon = True
                        break
                for item in self.__points:
                    if item['x'] == x and item['y'] == y:
                        item['z'][num] = pt_v2.z()
                        rg_positions.append({'x': x, 'y': y, 'iden': iden})
                        doublon = True
                        break
                if not doublon:
                    rg_positions.append({'x': x, 'y': y, 'iden': iden})
                    z = []
                    for j in range(num_lines):
                        if j == num:
                            if pt_v2.z() == pt_v2.z():
                                z.append(pt_v2.z())
                            else:
                                z.append(0)
                        else:
                            z.append(None)
                    self.__points.append({'x': x, 'y': y, 'z': z})

                    if checkLayers:
                        combinedLayers = [self.ownSettings.drawdownLayer]
                        combinedLayers += self.ownSettings.refLayers + self.ownSettings.adjLayers
                        for layer in combinedLayers:
                            if layer in otherLayers:
                                continue
                            laySettings = QgsSnappingUtils.LayerConfig(
                                layer, QgsPointLocator.All,
                                self.SEARCH_TOLERANCE, QgsTolerance.LayerUnits)
                            fs = Finder.findFeaturesAt(QgsPoint(x, y),
                                                       laySettings, self)
                            if len(fs) > 0:
                                for f in fs:
                                    if layer == self.ownSettings.drawdownLayer:
                                        if f.id() not in self.__selectedIds:
                                            closest = f.geometry(
                                            ).closestVertex(QgsPoint(x, y))
                                            if closest[
                                                    4] < self.SEARCH_TOLERANCE:
                                                if layer not in otherLayers:
                                                    otherLayers.append(layer)
                                    elif layer not in otherLayers:
                                        otherLayers.append(layer)

            num += 1
        if checkLayers:
            return otherLayers