Beispiel #1
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 #2
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 #3
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
Beispiel #4
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 #5
0
    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)
        u.setSnapToMapMode(QgsSnappingUtils.SnapAdvanced)
        layers = [
            QgsSnappingUtils.LayerConfig(self.pointsLayer,
                                         QgsPointLocator.Vertex, 20,
                                         QgsTolerance.Pixels)
        ]
        u.setLayers(layers)

        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
        layers = [
            QgsSnappingUtils.LayerConfig(self.pointsLayer,
                                         QgsPointLocator.Vertex, 20,
                                         QgsTolerance.Pixels),
            QgsSnappingUtils.LayerConfig(self.pointsLayer2,
                                         QgsPointLocator.Vertex, 20,
                                         QgsTolerance.Pixels)
        ]
        u.setLayers(layers)
        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([])