def testOperators(self):
        rect1 = QgsRectangle(10, 20, 40, 40)
        rect2 = rect1 + QgsVector(3, 5.5)
        self.assertEqual(rect2, QgsRectangle(13, 25.5, 43, 45.5))

        # Subtracting the center point, so it becomes zero.
        rect1 -= rect1.center() - QgsPointXY(0, 0)
        self.assertEqual(rect1.center(), QgsPointXY(0, 0))
Beispiel #2
0
    def canvasMoveEvent(self, event):

        self.mouse_pt = self.toMapCoordinates(event.pos())

        elev = raster_utils.read_layer_val_from_coord(self.params.dem_rlay, self.mouse_pt, 1)
        if elev is not None:
            self.elev = elev
            self.dock_widget.lbl_elev_val.setText("{0:.2f}".format(self.elev))
        else:
            self.elev = None
            self.dock_widget.lbl_elev_val.setText('-')

        # Mouse not clicked
        if not self.mouse_clicked:

            match = self.snapper.snapToMap(self.mouse_pt)
            if match.isValid():

                self.snap_results = match
                # snapped_pt = self.snap_results[0].snappedVertex
                snapped_vertex = match.point()

                self.vertex_marker.setCenter(QgsPoint(snapped_vertex.x(), snapped_vertex.y()))
                self.vertex_marker.setColor(QColor(255, 0, 0))
                self.vertex_marker.setIconSize(10)
                self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE)  # or ICON_CROSS, ICON_X
                self.vertex_marker.setPenWidth(3)
                self.vertex_marker.show()
            else:
                self.snap_results = None
                self.selected_node_ft = None
                self.vertex_marker.hide()

        # Mouse clicked
        else:

            # Update rubber band
            if self.snap_results is not None and self.rubber_band:

                snapped_pt = self.snap_results.point()

                # In 2.16+: self.delta_vec = QgsVector(self.mouse_pt - snapped_pt)
                self.delta_vec = QgsVector(self.mouse_pt.x() - snapped_pt.x(),
                                           self.mouse_pt.y() - snapped_pt.y())

                self.move_rubber_band_pt(self.rubber_band)
Beispiel #3
0
    def testOperators(self):
        rect1 = QgsRectangle(10, 20, 40, 40)
        rect2 = rect1 + QgsVector(3, 5.5)
        assert rect2 == QgsRectangle(13, 25.5, 43, 45.5), "QgsRectangle + operator does no work"

        # Subtracting the center point, so it becomes zero.
        rect1 -= rect1.center() - QgsPointXY(0, 0)
        assert rect1.center() == QgsPointXY(0, 0)
Beispiel #4
0
    def __init__(self, button, iface, projectDirectory, netwName):
        QgsMapTool.__init__(self, iface.mapCanvas())
        self.iface = iface
        self.ProjectDirectory = projectDirectory
        self.NetworkName = netwName
        self.toolbarButton = button

        self.snapper = None
        self.vertexMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.vertexMarker.setColor(QColor(255, 87, 51))
        self.vertexMarker.setIconSize(15)
        self.vertexMarker.setIconType(
            QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.vertexMarker.setPenWidth(3)
        self.vertexMarker.hide()

        self.pipeSnapper = None
        self.pipeMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.pipeMarker.setColor(QColor(143, 0, 255))
        self.pipeMarker.setIconSize(10)
        try:
            self.pipeMarker.setIconType(
                QgsVertexMarker.ICON_DOUBLE_TRIANGLE)  # or ICON_CROSS, ICON_X
        except:
            self.pipeMarker.setIconType(
                QgsVertexMarker.ICON_X)  # or ICON_CROSS, ICON_X
        self.pipeMarker.setPenWidth(3)
        self.pipeMarker.hide()

        self.mouseClicked = False
        self.clickedPoint = None
        self.objectSnapped = None
        self.pipeSnapped = None
        self.selectedFeature = None
        self.selectedLayer = None
        self.newPositionVector = QgsVector(0, 0)
        self.rubberBand = None
        self.newVertexMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.newVertexMarker.setColor(QColor(55, 198, 5))
        self.newVertexMarker.setIconSize(15)
        self.newVertexMarker.setIconType(
            QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.newVertexMarker.setPenWidth(3)
        self.newVertexMarker.hide()
Beispiel #5
0
    def imprimirPlanol(self, x, y, escala, rotacion, projectePlanol,
                       templateFile, fitxerSortida, tipusSortida):
        self.project.read(projectePlanol)
        template = QFile(templateFile)

        # Creem un document amb la plantilla
        doc = QDomDocument()
        doc.setContent(template, False)

        # Aquest layout no té res a veure amb els layaouts de PyQt.
        # Es una plantilla per el projecte. You must believe it.
        layout = QgsLayout(self.project)
        context = QgsReadWriteContext()
        [items, ok] = layout.loadFromTemplate(doc, context)

        if ok:
            refMap = layout.referenceMap()

            rect = refMap.extent()
            vector = QgsVector(x - rect.center().x(), y - rect.center().y())
            rect += vector
            refMap.setExtent(rect)
            refMap.setScale(escala)
            refMap.setMapRotation(rotacion)

            #Depenent del tipus de sortida...

            exporter = QgsLayoutExporter(layout)
            image_settings = exporter.ImageExportSettings()
            image_settings.dpi = 60

            # result = exporter.exportToImage('d:/dropbox/qpic/preview.png',  image_settings)
            # imatge = QPixmap('d:/dropbox/qpic/preview.png')
            t = time.localtime()

            timestamp = time.strftime('%b-%d-%Y_%H%M%S', t)

            if tipusSortida == 'PDF':
                settings = QgsLayoutExporter.PdfExportSettings()
                settings.dpi = 60
                settings.exportMetadata = False

                fitxerSortida = 'd:/dropbox/qpic/sortida_' + timestamp + '.PDF'
                result = exporter.exportToPdf(fitxerSortida, settings)

                print(fitxerSortida)

            if tipusSortida == 'PNG':
                settings = QgsLayoutExporter.ImageExportSettings()
                settings.dpi = 60

                # fitxerSortida='sortida_'+timestamp+'.PNG'
                fitxerSortida = projectePlanol[0:-4] + '.png'
                result = exporter.exportToImage(fitxerSortida, settings)
Beispiel #6
0
 def canvasMoveEvent(self, event):
     self.mousePoint = self.toMapCoordinates(event.pos())
     # Mouse not clicked
     if not self.mouseClicked:
         match = self.snapper.snapToMap(self.mousePoint)
         if match.isValid():
             self.objectSnapped = match
             vertex = match.point()
             self.vertexMarker.setCenter(QgsPointXY(vertex.x(), vertex.y()))
             self.vertexMarker.show()
         else:
             self.objectSnapped = None
             self.selectedNodeFeature = None
             self.vertexMarker.hide()
     # Mouse clicked
     else:
         # Update rubber band
         if self.objectSnapped is not None and self.rubberBand is not None:
             snappedPoint = self.objectSnapped.point()
             self.newPositionVector = QgsVector(
                 self.mousePoint.x() - snappedPoint.x(),
                 self.mousePoint.y() - snappedPoint.y())
             self.updateRubberBand()
    def processFeature(self, feature, context, feedback): #pylint: disable=no-self-use,unused-argument,missing-docstring

        cursor = 0.0
        length = self.dynamicParameterAsDouble(self.LENGTH, context)
        interval = self.dynamicParameterAsDouble(self.INTERVAL, context)
        geometry = feature.geometry()
        transects = list()

        while cursor < geometry.length():

            origin = geometry.interpolate(cursor).asPoint()
            angle = geometry.interpolateAngle(cursor)
            direction = QgsVector(-math.cos(angle), math.sin(angle))

            new_feature = QgsFeature()
            new_feature.setAttributes(feature.attributes())
            new_feature.setGeometry(transect(origin, direction, length))
            transects.append(new_feature)

            cursor += interval

        return transects
Beispiel #8
0
    def processFeature(self, feature, context, feedback):  #pylint: disable=no-self-use,unused-argument,missing-docstring

        transects = []
        length = self.dynamicParameterAsDouble(self.LENGTH, context)
        point = feature.geometry()

        nearest_line = None
        min_distance = float('inf')

        rect = point.boundingBox()
        rect.grow(self.search_distance)
        candidates = self.line_index.intersects(rect)
        request = QgsFeatureRequest().setFilterFids(candidates)

        for line in self.lines.getFeatures(request):

            distance = line.geometry().distance(point)

            if distance < self.search_distance and distance < min_distance:

                min_distance = distance
                nearest_line = line

        if nearest_line:

            geometry = nearest_line.geometry()
            cursor = geometry.lineLocatePoint(point)
            # origin = geometry.interpolate(cursor)
            angle = geometry.interpolateAngle(cursor)
            direction = QgsVector(-math.cos(angle), math.sin(angle))

            new_feature = QgsFeature()
            new_feature.setAttributes(feature.attributes())
            # new_feature.setGeometry(transect(origin.asPoint(), direction, length))
            new_feature.setGeometry(
                transect(point.asPoint(), direction, length))
            transects.append(new_feature)

        return transects
Beispiel #9
0
    def testQgsVector(self):
        v = QgsVector(1, 2)
        self.assertEqual(v.__repr__(), '<QgsVector: Vector (1, 2)>')

        v = QgsVector3D(1, 2, 3)
        self.assertEqual(v.__repr__(), '<QgsVector3D: Vector3D (1, 2, 3)>')
Beispiel #10
0
    def compute_compatibilty_matrix(self, feedback):
        """
        Compatibility is stored in a matrix (rows = edges, columns = edges).
        Every coordinate in the matrix tells whether the two edges (r,c)/(c,r)
        are compatible, or not. The diagonal is always zero, and the other fields
        are filled with either -1 (not compatible) or 1 (compatible).
        The matrix is symmetric.
        """
        feedback.setProgressText("Compute compatibility matrix")
        edges_as_geom = []
        edges_as_vect = []
        for e_idx, edge in enumerate(self.edges):
            if feedback.isCanceled(): return
            geom = edge.geometry()
            edges_as_geom.append(geom)
            edges_as_vect.append(
                QgsVector(
                    geom.vertexAt(1).x() - geom.vertexAt(0).x(),
                    geom.vertexAt(1).y() - geom.vertexAt(0).y()))
            self.edge_lengths.append(edges_as_vect[e_idx].length())

        progress = 0
        for i in range(self.E - 1):
            if feedback.isCanceled(): return
            feedback.setProgress(100.0 * (i + 1) / (self.E - 1))
            for j in range(i + 1, self.E):
                if feedback.isCanceled(): return
                # Parameters
                lavg = (self.edge_lengths[i] + self.edge_lengths[j]) / 2.0
                dot = edges_as_vect[i].normalized(
                ) * edges_as_vect[j].normalized()

                # Angle compatibility
                angle_comp = abs(dot)

                # Scale compatibility
                scale_comp = 2.0 / (
                    lavg / min(self.edge_lengths[i], self.edge_lengths[j]) +
                    max(self.edge_lengths[i], self.edge_lengths[j]) / lavg)

                # Position compatibility
                i0 = edges_as_geom[i].vertexAt(0)
                i1 = edges_as_geom[i].vertexAt(1)
                j0 = edges_as_geom[j].vertexAt(0)
                j1 = edges_as_geom[j].vertexAt(1)
                e1_mid = QgsPoint((i0.x() + i1.x()) / 2.0,
                                  (i0.y() + i1.y()) / 2.0)
                e2_mid = QgsPoint((j0.x() + j1.x()) / 2.0,
                                  (j0.y() + j1.y()) / 2.0)
                diff = QgsVector(e2_mid.x() - e1_mid.x(),
                                 e2_mid.y() - e1_mid.y())
                pos_comp = lavg / (lavg + diff.length())

                # Visibility compatibility
                mid_E1 = edges_as_geom[i].centroid()
                mid_E2 = edges_as_geom[j].centroid()
                #dist = mid_E1.distance(mid_E2)
                I0 = MiscUtils.project_point_on_line(j0, edges_as_geom[i])
                I1 = MiscUtils.project_point_on_line(j1, edges_as_geom[i])
                mid_I = QgsGeometry.fromPolyline([I0, I1]).centroid()
                dist_I = I0.distance(I1)
                if dist_I == 0.0:
                    visibility1 = 0.0
                else:
                    visibility1 = max(
                        0, 1 - ((2 * mid_E1.distance(mid_I)) / dist_I))
                J0 = MiscUtils.project_point_on_line(i0, edges_as_geom[j])
                J1 = MiscUtils.project_point_on_line(i1, edges_as_geom[j])
                mid_J = QgsGeometry.fromPolyline([J0, J1]).centroid()
                dist_J = J0.distance(J1)
                if dist_J == 0.0:
                    visibility2 = 0.0
                else:
                    visibility2 = max(
                        0, 1 - ((2 * mid_E2.distance(mid_J)) / dist_J))
                visibility_comp = min(visibility1, visibility2)

                # Compatibility score
                comp_score = angle_comp * scale_comp * pos_comp * visibility_comp

                # Fill values into the matrix (1 = yes, -1 = no) and use matrix symmetry (i/j = j/i)
                if comp_score >= self.compatibility:
                    self.compatibility_matrix[i, j] = 1
                    self.compatibility_matrix[j, i] = 1
                else:
                    self.compatibility_matrix[i, j] = -1
                    self.compatibility_matrix[j, i] = -1

                # Store direction
                distStart1 = j0.distance(i0)
                distStart2 = j1.distance(i0)
                if distStart1 > distStart2:
                    self.direction_matrix[i, j] = -1
                    self.direction_matrix[j, i] = -1
                else:
                    self.direction_matrix[i, j] = 1
                    self.direction_matrix[j, i] = 1
Beispiel #11
0
def readInput():
    # pylint: disable=too-many-locals
    # pylint: disable=too-many-return-statements
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-statements
    # pylint: disable=too-many-nested-blocks
    # pylint: disable=eval-used

    # First open and read the .ini file to get the name of the data file
    iniFile = "./ff.ini"

    # TODO test for file opening
    fpIni = open(iniFile, "r")

    dataLine = 0
    for inData in fpIni:
        inData = inData.strip()

        data = checkDataLine(inData, iniFile)
        if data == -1:
            continue

        if dataLine == 0:
            shared.dataInputFile = data

        elif dataLine == 1:
            shared.textOutputFile = data

        dataLine += 1

    fpIni.close()

    # Before reading the data file, do some initialisation
    shared.extentRect = QgsRectangle()

    shared.sourceFields = []

    shared.outFlowMarkerPointLayer = QgsVector()
    shared.outFlowLineLayer = QgsVector()

    shared.vectorFileName = []
    shared.vectorFileTable = []
    shared.vectorFileTitle = []
    shared.vectorFileType = []
    shared.vectorFileStyle = []
    shared.vectorFileOpacity = []
    shared.vectorFileCategory = []

    shared.rasterFileName = []
    shared.rasterFileTitle = []
    shared.rasterFileStyle = []
    shared.rasterFileOpacity = []
    shared.rasterFileCategory = []

    shared.vectorInputLayers = []
    shared.vectorInputLayersCategory = []
    shared.vectorInputLayerIndex = []
    shared.rasterInputLayers = []
    shared.rasterInputLayersCategory = []
    shared.rasterInputData = []

    shared.LEFlowInteractionFlowFrom = []
    shared.fieldObservationCategory = []
    shared.fieldObservationValidCategories = [
        LE_FLOW_INTERACTION_CATEGORY_BOUNDARY,
        LE_FLOW_INTERACTION_CATEGORY_CULVERT,
        LE_FLOW_INTERACTION_CATEGORY_PATH, LE_FLOW_INTERACTION_CATEGORY_ROAD,
        LE_FLOW_INTERACTION_CATEGORY_STREAM,
        LE_FLOW_INTERACTION_CATEGORY_BLIND_PIT,
        LE_FLOW_INTERACTION_CATEGORY_FORCING
    ]
    shared.fieldObservationBehaviour = []
    shared.fieldObservationValidBehaviours = [
        LE_FLOW_INTERACTION_BEHAVIOUR_ALONG,
        LE_FLOW_INTERACTION_BEHAVIOUR_UNDER,
        LE_FLOW_INTERACTION_BEHAVIOUR_ACROSS,
        LE_FLOW_INTERACTION_BEHAVIOUR_ENTER,
        LE_FLOW_INTERACTION_BEHAVIOUR_THROUGH,
        LE_FLOW_INTERACTION_BEHAVIOUR_LEAVE,
        LE_FLOW_INTERACTION_BEHAVIOUR_OVERTOP,
        LE_FLOW_INTERACTION_BEHAVIOUR_FORCING
    ]
    shared.fieldObservationDescription = []
    shared.LEFlowInteractionFlowTo = []

    # Now open and read the data file TODO test for file opening
    fpData = open(shared.dataInputFile, "r")

    dataLine = 0
    while True:
        inData = fpData.readline()
        if not inData:
            break

        inData = inData.strip()
        #print(str(dataLine) + " '" + inData + "'")

        if inData.find(EOF_LE_FLOW_INTERACTIONS) >= 0:
            break

        data = checkDataLine(inData, shared.dataInputFile)
        if data == -1:
            continue

        elif dataLine == 0:
            shared.runTitle = data
            dataLine += 1

        elif dataLine == 1:
            if data:
                dataSplit = data.split(',')
                for fld in dataSplit:
                    shared.sourceFields.append(fld.strip())
            dataLine += 1

        elif dataLine == 2:
            shared.weightBoundary = float(data)
            if shared.weightBoundary > 1:
                printStr = "ERROR: flow start weighting must be less than or equal to 1.0\n"
                print(printStr)

                return -1
            dataLine += 1

        elif dataLine == 3:
            # Consider LE-flow interactions?
            tempStr = data.upper().strip()
            if tempStr == "Y":
                shared.considerLEFlowInteractions = True
            elif tempStr == "N":
                shared.considerLEFlowInteractions = False
            else:
                printStr = "ERROR: consider LE-flow interactions = " + tempStr + ", it must be Y or N\n"
                print(printStr)

                return -1
            dataLine += 1

        elif dataLine == 4:
            # Fill blind pits?
            if shared.considerLEFlowInteractions:
                shared.FillBlindPits = False
            else:
                tempStr = data.upper().strip()
                if tempStr == "Y":
                    shared.FillBlindPits = True
                elif tempStr == "N":
                    shared.FillBlindPits = False
                else:
                    printStr = "ERROR: fill blind pits = " + tempStr + ", it must be Y or N\n"
                    print(printStr)

                    return -1
            dataLine += 1

        elif dataLine == 5:
            # Consider watercourses?
            if shared.considerLEFlowInteractions:
                shared.considerWatercourses = True
            else:
                tempStr = data.upper().strip()
                if tempStr == "Y":
                    shared.considerWatercourses = True
                elif tempStr == "N":
                    shared.considerWatercourses = False
                else:
                    printStr = "ERROR: consider watercourses = " + tempStr + ", it must be Y or N\n"
                    print(printStr)

                    return -1
            dataLine += 1

        elif dataLine == 6:
            # Consider ditches?
            if shared.considerLEFlowInteractions:
                shared.considerDitches = True
            else:
                tempStr = data.upper().strip()
                if tempStr == "Y":
                    shared.considerDitches = True
                elif tempStr == "N":
                    shared.considerDitches = False
                else:
                    printStr = "ERROR: consider ditches = " + tempStr + ", it must be Y or N\n"
                    print(printStr)

                    return -1
            dataLine += 1

        elif dataLine == 7:
            # Consider roads?
            if shared.considerLEFlowInteractions:
                shared.considerRoads = True
            else:
                tempStr = data.upper().strip()
                if tempStr == "Y":
                    shared.considerRoads = True
                elif tempStr == "N":
                    shared.considerRoads = False
                else:
                    printStr = "ERROR: consider roads = " + tempStr + ", it must be Y or N\n"
                    print(printStr)

                    return -1
            dataLine += 1

        elif dataLine == 8:
            # Consider tracks and paths?
            if shared.considerLEFlowInteractions:
                shared.considerTracks = True
            else:
                tempStr = data.upper().strip()
                if tempStr == "Y":
                    shared.considerTracks = True
                elif tempStr == "N":
                    shared.considerTracks = False
                else:
                    printStr = "ERROR: consider tracks and paths = " + tempStr + ", it must be Y or N\n"
                    print(printStr)

                    return -1
            dataLine += 1

        elif dataLine == 9:
            # Consider field boundaries?
            if shared.considerLEFlowInteractions:
                shared.considerFieldBoundaries = True
            else:
                tempStr = data.upper().strip()
                if tempStr == "Y":
                    shared.considerFieldBoundaries = True
                elif tempStr == "N":
                    shared.considerFieldBoundaries = False
                else:
                    printStr = "ERROR: consider field boundaries = " + tempStr + ", it must be Y or N\n"
                    print(printStr)

                    return -1
            dataLine += 1

        elif dataLine == 10:
            # The resolution of the DEM layer (m)
            shared.resolutionOfDEM = float(data)
            dataLine += 1

        elif dataLine == 11:
            # Distance to search (metres)
            shared.searchDist = float(data)
            dataLine += 1

        elif dataLine == 12:
            # Path to all GIS data
            shared.GISPath = data
            dataLine += 1

        elif dataLine == 13:
            # Output shapefile for flow marker points
            shared.outFileFlowMarkerPoints = shared.GISPath + data
            dataLine += 1

        elif dataLine == 14:
            # Style for Output shapefile for flow marker points
            shared.outFileFlowMarkerPointsStyle = shared.GISPath + data
            dataLine += 1

        elif dataLine == 15:
            shared.outFileFlowMarkerPointsOpacity = (100.0 - int(data)) / 100.0
            dataLine += 1

        elif dataLine == 16:
            # Output shapefile for flow lines
            shared.outFileFlowLines = shared.GISPath + data
            dataLine += 1

        elif dataLine == 17:
            # Style for output shapefile for flow lines
            shared.outFileFlowLinesStyle = shared.GISPath + data
            dataLine += 1

        elif dataLine == 18:
            shared.outFileFlowLinesOpacity = (100.0 - int(data)) / 100.0
            dataLine += 1

        elif dataLine == 19:
            shared.windowWidth = int(data)
            dataLine += 1

        elif dataLine == 20:
            shared.windowHeight = int(data)
            dataLine += 1

        elif dataLine == 21:
            shared.windowMagnification = float(data)
            dataLine += 1

        elif dataLine == 22:
            # External coordinate reference system
            shared.externalCRS = data
            dataLine += 1

        elif dataLine == 23:
            # Coordinates of SW corner of area displayed
            coords = data.split(',')
            shared.extentRect.setXMinimum(int(coords[0]))
            shared.extentRect.setYMinimum(int(coords[1]))
            dataLine += 1

        elif dataLine == 24:
            # Coordinates of NE corner of area displayed
            coords = data.split(',')
            shared.extentRect.setXMaximum(int(coords[0]))
            shared.extentRect.setYMaximum(int(coords[1]))
            dataLine += 1

        elif dataLine == 25:
            # Vector files
            first = True
            vecLine = 0

            while True:
                if first:
                    inVecData = inData
                    first = False
                else:
                    inVecData = fpData.readline()

                if not inVecData:
                    break

                if inVecData.find(EOF_VECTOR_DATA) >= 0:
                    break

                inVecData = inVecData.strip()
                #print(str(dataLine) + " " + str(vecLine) + " '" + inVecData + "'")

                data = checkDataLine(inVecData, shared.dataInputFile)
                if data == -1:
                    continue

                if vecLine == 0:
                    shared.vectorFileName.append(shared.GISPath + data)
                elif vecLine == 1:
                    shared.vectorFileTable.append(data)
                elif vecLine == 2:
                    shared.vectorFileTitle.append(data)
                elif vecLine == 3:
                    shared.vectorFileType.append(data)
                elif vecLine == 4:
                    shared.vectorFileStyle.append(shared.GISPath + data)
                elif vecLine == 5:
                    shared.vectorFileOpacity.append(
                        (100.0 - int(data)) / 100.0)
                elif vecLine == 6:
                    shared.vectorFileCategory.append(eval(data))

                vecLine += 1
                if vecLine == 7:
                    vecLine = 0

            dataLine += 1

        elif dataLine == 26:
            # Raster files
            first = True
            rasLine = 0

            while True:
                if first:
                    inRasData = inData
                    first = False
                else:
                    inRasData = fpData.readline()

                if not inRasData:
                    break

                if inRasData.find(EOF_RASTER_DATA) >= 0:
                    break

                inRasData = inRasData.strip()
                #print("Raster " + str(dataLine) + " " + str(rasLine) + " '" + inRasData + "'")

                data = checkDataLine(inRasData, shared.dataInputFile)
                if data == -1:
                    continue

                if rasLine == 0:
                    shared.rasterFileName.append(shared.GISPath + data)
                elif rasLine == 1:
                    shared.rasterFileTitle.append(data)
                elif rasLine == 2:
                    shared.rasterFileStyle.append(shared.GISPath + data)
                elif rasLine == 3:
                    shared.rasterFileOpacity.append(
                        (100.0 - int(data)) / 100.0)
                elif rasLine == 4:
                    shared.rasterFileCategory.append(eval(data))

                rasLine += 1
                if rasLine == 5:
                    rasLine = 0

            dataLine += 1

        elif dataLine == 27:
            # LE-flow interactions, don't bother reading them if this is a topography-only run
            if shared.considerLEFlowInteractions == "T":
                break

            first = True
            obsLine = 0

            while True:
                if first:
                    inObsData = inData
                    first = False
                else:
                    inObsData = fpData.readline()

                if not inObsData:
                    break

                if inObsData.find(EOF_LE_FLOW_INTERACTIONS) >= 0:
                    break

                inObsData = inObsData.strip()
                #print("Field obs " + str(dataLine) + " " + str(obsLine) + " '" + inObsData + "'")

                data = checkDataLine(inObsData, shared.dataInputFile)
                if data == -1:
                    continue

                if obsLine == 0:
                    # Inflow location: check for six digits in co-ord
                    isOK = False
                    coords = data.split(',')
                    xCoord = coords[0].strip()
                    yCoord = coords[1].strip()

                    indx = xCoord.find(".")
                    if indx == -1 or indx == 6:
                        isOK = True

                    indx = yCoord.find(".")
                    if indx == -1 or indx == 6:
                        isOK = True

                    if not isOK:
                        printStr = "ERROR: '" + data + "' is not a six-figure OS grid reference"
                        print(printStr)

                        return -1

                    shared.LEFlowInteractionFlowFrom.append(
                        QgsPointXY(float(xCoord), float(yCoord)))

                elif obsLine == 1:
                    # Category
                    if data not in shared.fieldObservationValidCategories:
                        printStr = "ERROR: unknown field observation category '" + str(
                            data) + "' in field observation at " + DisplayOS(
                                shared.LEFlowInteractionFlowFrom[-1].x(),
                                shared.LEFlowInteractionFlowFrom[-1].y())
                        print(printStr)

                        return -1

                    shared.fieldObservationCategory.append(data)

                elif obsLine == 2:
                    # Behaviour
                    if data not in shared.fieldObservationValidBehaviours:
                        printStr = "ERROR: unknown field observation behaviour '" + str(
                            data) + "' in field observation at " + DisplayOS(
                                shared.LEFlowInteractionFlowFrom[-1].x(),
                                shared.LEFlowInteractionFlowFrom[-1].y())
                        print(printStr)

                        return -1

                    shared.fieldObservationBehaviour.append(data)

                elif obsLine == 3:
                    # Description
                    shared.fieldObservationDescription.append(data)

                elif obsLine == 4:
                    # Outflow location
                    if data:
                        # We have an outflow location, check for six digits in co-ord
                        isOK = False
                        coords = data.split(',')
                        xCoord = coords[0].strip()
                        yCoord = coords[1].strip()

                        indx = xCoord.find(".")
                        if indx == -1 or indx == 6:
                            isOK = True

                        indx = yCoord.find(".")
                        if indx == -1 or indx == 6:
                            isOK = True

                        if not isOK:
                            printStr = "ERROR: '" + data + "' is not a six-figure OS grid reference"
                            print(printStr)

                            return -1

                        xCoord = float(xCoord)
                        yCoord = float(yCoord)

                        if isclose(
                                shared.LEFlowInteractionFlowFrom[-1].x(),
                                xCoord) and isclose(
                                    shared.LEFlowInteractionFlowFrom[-1].y(),
                                    yCoord):
                            printStr = "ERROR: identical 'From' and 'To' coordinates '" + str(
                                data
                            ) + "' for field observation '" + shared.fieldObservationDescription[
                                -1] + "'"
                            print(printStr)

                            return -1

                        shared.LEFlowInteractionFlowTo.append(
                            QgsPointXY(xCoord, yCoord))
                    else:
                        # We do not have an outflow location. This is only allowable if the category is "along road", "along path", or "along boundary"
                        if not ((shared.fieldObservationCategory[-1]
                                 == LE_FLOW_INTERACTION_CATEGORY_ROAD
                                 and shared.fieldObservationBehaviour[-1]
                                 == LE_FLOW_INTERACTION_BEHAVIOUR_ALONG) or
                                (shared.fieldObservationCategory[-1]
                                 == LE_FLOW_INTERACTION_CATEGORY_PATH
                                 and shared.fieldObservationBehaviour[-1]
                                 == LE_FLOW_INTERACTION_BEHAVIOUR_ALONG) or
                                (shared.fieldObservationCategory[-1]
                                 == LE_FLOW_INTERACTION_CATEGORY_BOUNDARY
                                 and shared.fieldObservationBehaviour[-1]
                                 == LE_FLOW_INTERACTION_BEHAVIOUR_ALONG)):
                            printStr = "ERROR: for field observation '" + shared.fieldObservationCategory[
                                -1] + "' '" + shared.fieldObservationBehaviour[
                                    -1] + "' '" + shared.fieldObservationDescription[
                                        -1] + "', the outflow location must be specified"
                            print(printStr)

                            return -1

                        shared.LEFlowInteractionFlowTo.append(None)

                obsLine += 1
                if obsLine == 5:
                    obsLine = 0

            dataLine += 1

    return 0
Beispiel #12
0
    def imprimirPlanol(self, x, y, escala, rotacion, midaPagina, templateFile,
                       fitxerSortida, tipusSortida):
        tInicial = time.time()

        template = QFile(templateFile)
        doc = QDomDocument()
        doc.setContent(template, False)

        layout = QgsLayout(self.project)
        # page=QgsLayoutItemPage(layout)
        # page.setPageSize(midaPagina)
        # layout.pageCollection().addPage(page)

        # layout.initializeDefaults()
        # p=layout.pageCollection().pages()[0]
        # p.setPageSize(midaPagina)

        context = QgsReadWriteContext()
        [items, ok] = layout.loadFromTemplate(doc, context)
        # p=layout.pageCollection().pages()[0]
        # p.setPageSize(midaPagina)

        if ok:
            refMap = layout.referenceMap()

            titol = layout.itemById('idNomMapa')
            dataMapa = layout.itemById('idData')
            if self.leTitol.text() != '':
                titol.setText(self.leTitol.text())  #comentat pk peta
            else:
                titol.setText('')
            try:
                t = time.localtime()
                dataMapa.setText(strftime('%b-%d-%Y %H:%M', t))
            except:
                pass

            rect = refMap.extent()
            vector = QgsVector(x - rect.center().x(), y - rect.center().y())
            rect += vector
            refMap.setExtent(rect)
            refMap.setScale(escala)
            refMap.setMapRotation(rotacion)
            #Depenent del tipus de sortida...

            exporter = QgsLayoutExporter(layout)
            # image_settings = exporter.ImageExportSettings()
            # image_settings.dpi = 30

            # result = exporter.exportToImage('d:/dropbox/qpic/preview.png',  image_settings)
            # imatge = QPixmap('d:/dropbox/qpic/preview.png')
            # self.ui.lblImatgeResultat.setPixmap(imatge)

            if tipusSortida == 'PDF':
                settings = QgsLayoutExporter.PdfExportSettings()
                settings.dpi = 300
                settings.exportMetadata = False

                # fitxerSortida='d:/sortida_'+timestamp+'.PDF'
                fitxerSortida += '.PDF'
                result = exporter.exportToPdf(
                    fitxerSortida, settings)  #Cal desar el resultat (???)

                print(fitxerSortida)

            if tipusSortida == 'PNG':
                settings = QgsLayoutExporter.ImageExportSettings()
                settings.dpi = 300

                # fitxerSortida='d:/sortida_'+timestamp+'.PNG'
                fitxerSortida += '.PNG'
                result = exporter.exportToImage(
                    fitxerSortida, settings)  #Cal desar el resultat (???)

            #Obra el document si està marcat checkObrirResultat
            QDesktopServices().openUrl(QUrl(fitxerSortida))

            segonsEmprats = round(time.time() - tInicial, 1)  #???
            layersTemporals = self.project.mapLayersByName(
                "Capa temporal d'impressió")

            estatDirtybit = self.parent.canvisPendents
            for layer in layersTemporals:
                self.project.removeMapLayer(layer.id())
            self.parent.setDirtyBit(estatDirtybit)
Beispiel #13
0
class QGISRedEditLinksGeometryTool(QgsMapTool):
    ownMainLayers = ["Pipes", "Valves", "Pumps", "ServiceConnections"]

    def __init__(self, button, iface, projectDirectory, netwName):
        QgsMapTool.__init__(self, iface.mapCanvas())
        self.iface = iface
        self.ProjectDirectory = projectDirectory
        self.NetworkName = netwName
        self.toolbarButton = button

        self.snapper = None
        self.vertexMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.vertexMarker.setColor(QColor(255, 87, 51))
        self.vertexMarker.setIconSize(15)
        self.vertexMarker.setIconType(
            QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.vertexMarker.setPenWidth(3)
        self.vertexMarker.hide()

        self.pipeSnapper = None
        self.pipeMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.pipeMarker.setColor(QColor(143, 0, 255))
        self.pipeMarker.setIconSize(10)
        try:
            self.pipeMarker.setIconType(
                QgsVertexMarker.ICON_DOUBLE_TRIANGLE)  # or ICON_CROSS, ICON_X
        except:
            self.pipeMarker.setIconType(
                QgsVertexMarker.ICON_X)  # or ICON_CROSS, ICON_X
        self.pipeMarker.setPenWidth(3)
        self.pipeMarker.hide()

        self.mouseClicked = False
        self.clickedPoint = None
        self.objectSnapped = None
        self.pipeSnapped = None
        self.selectedFeature = None
        self.selectedLayer = None
        self.newPositionVector = QgsVector(0, 0)
        self.rubberBand = None
        self.newVertexMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.newVertexMarker.setColor(QColor(55, 198, 5))
        self.newVertexMarker.setIconSize(15)
        self.newVertexMarker.setIconType(
            QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.newVertexMarker.setPenWidth(3)
        self.newVertexMarker.hide()

    def activate(self):
        cursor = QCursor()
        cursor.setShape(Qt.ArrowCursor)
        self.iface.mapCanvas().setCursor(cursor)

        myLayers = []
        # Editing
        layers = self.getLayers()
        for layer in layers:
            openedLayerPath = self.getLayerPath(layer)
            for name in self.ownMainLayers:
                layerPath = self.generatePath(
                    self.ProjectDirectory,
                    self.NetworkName + "_" + name + ".shp")
                if openedLayerPath == layerPath:
                    myLayers.append(layer)
                    if not layer.isEditable():
                        layer.startEditing()
        # Snapping
        self.snapper = QgsMapCanvasSnappingUtils(self.iface.mapCanvas())
        self.snapper.setMapSettings(self.iface.mapCanvas().mapSettings())
        config = QgsSnappingConfig(QgsProject.instance())
        config.setType(2)  # Vertex
        config.setMode(2)  # All layers
        config.setTolerance(10)
        config.setUnits(1)  # Pixels
        config.setEnabled(True)
        self.snapper.setConfig(config)

        self.pipeSnapper = QgsMapCanvasSnappingUtils(self.iface.mapCanvas())
        self.pipeSnapper.setMapSettings(self.iface.mapCanvas().mapSettings())
        config = QgsSnappingConfig(QgsProject.instance())
        config.setType(2)  # Vertex
        config.setMode(2)  # All layers
        config.setTolerance(10)
        config.setUnits(1)  # Pixels
        config.setEnabled(True)
        self.pipeSnapper.setConfig(config)

    def deactivate(self):
        self.toolbarButton.setChecked(False)
        # End Editing
        layers = self.getLayers()
        for layer in layers:
            openedLayerPath = self.getLayerPath(layer)
            for name in self.ownMainLayers:
                layerPath = self.generatePath(
                    self.ProjectDirectory,
                    self.NetworkName + "_" + name + ".shp")
                if openedLayerPath == layerPath:
                    if layer.isModified():
                        layer.commitChanges()
                    else:
                        layer.rollBack()

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True

    """Methods"""

    def getUniformedPath(self, path):
        return QGISRedUtils().getUniformedPath(path)

    def getLayerPath(self, layer):
        return QGISRedUtils().getLayerPath(layer)

    def generatePath(self, folder, fileName):
        return QGISRedUtils().generatePath(folder, fileName)

    def getLayers(self):
        return QGISRedUtils().getLayers()

    def areOverlapedPoints(self, point1, point2):
        tolerance = 0.1
        if point1.distance(point2) < tolerance:
            return True
        else:
            return False

    def isInPath(self, point1, point2, myPoint):
        width = point2.x() - point1.x()
        height = point2.y() - point1.y()
        widthM = myPoint.x() - point1.x()
        heightM = myPoint.y() - point1.y()
        if abs(width) >= abs(height):
            yEst = widthM * height / width + point1.y()
            if abs(yEst - myPoint.y()) < 1E-9:
                return True
        else:
            xEst = heightM * width / height + point1.x()
            if abs(xEst - myPoint.x()) < 1E-9:
                return True
        return False

    def createRubberBand(self, points):
        myPoints = points
        if isinstance(points[0], QgsPointXY):
            myPoints = []
            for p in points:
                myPoints.append(QgsPoint(p.x(), p.y()))
        self.rubberBand = QgsRubberBand(self.iface.mapCanvas(), False)
        self.rubberBand.setToGeometry(QgsGeometry.fromPolyline(myPoints), None)
        self.rubberBand.setColor(QColor(55, 198, 5))
        self.rubberBand.setWidth(1)
        self.rubberBand.setLineStyle(Qt.DashLine)
        self.newVertexMarker.setCenter(QgsPointXY(points[0].x(),
                                                  points[0].y()))
        self.newVertexMarker.show()

    def updateRubberBand(self):
        newX = self.clickedPoint.x() + self.newPositionVector.x()
        newY = self.clickedPoint.y() + self.newPositionVector.y()
        self.rubberBand.movePoint(1, QgsPointXY(newX, newY))
        self.newVertexMarker.setCenter(QgsPointXY(newX, newY))

    def moveVertexLink(self, layer, feature, newPosition, vertexIndex):
        if layer.isEditable():
            layer.beginEditCommand("Update link geometry")
            try:
                edit_utils = QgsVectorLayerEditUtils(layer)
                edit_utils.moveVertex(newPosition.x(), newPosition.y(),
                                      feature.id(), vertexIndex)
            except Exception as e:
                layer.destroyEditCommand()
                raise e
            layer.endEditCommand()

    def deleteVertexLink(self, layer, feature, vertexIndex):
        if layer.isEditable():
            layer.beginEditCommand("Update link geometry")
            try:
                edit_utils = QgsVectorLayerEditUtils(layer)
                edit_utils.deleteVertex(feature.id(), vertexIndex)
            except Exception as e:
                layer.destroyEditCommand()
                raise e
            layer.endEditCommand()

    def insertVertexLink(self, layer, feature, newPoint):
        if layer.isEditable():
            layer.beginEditCommand("Update link geometry")
            vertex = -1
            if layer.geometryType() == 1:  # Line
                featureGeometry = self.selectedFeature.geometry()
                if featureGeometry.isMultipart():
                    parts = featureGeometry.get()
                    for part in parts:  # only one part
                        for i in range(len(part) - 1):
                            if self.isInPath(
                                    QgsPointXY(part[i].x(), part[i].y()),
                                    QgsPointXY(part[i + 1].x(),
                                               part[i + 1].y()), newPoint):
                                vertex = i + 1
            try:
                edit_utils = QgsVectorLayerEditUtils(layer)
                edit_utils.insertVertex(newPoint.x(), newPoint.y(),
                                        feature.id(), vertex)
            except Exception as e:
                layer.destroyEditCommand()
                raise e
            layer.endEditCommand()

    """Events"""

    def canvasPressEvent(self, event):
        if self.objectSnapped is None:
            self.clickedPoint = None
            return

        if event.button() == Qt.RightButton:
            self.mouseClicked = False
            self.clickedPoint = None

        if event.button() == Qt.LeftButton:
            self.clickedPoint = self.objectSnapped.point()
            if self.vertexIndex == -1:
                return
            self.mouseClicked = True
            self.createRubberBand(
                [self.objectSnapped.point(),
                 self.objectSnapped.point()])

    def canvasMoveEvent(self, event):
        mousePoint = self.toMapCoordinates(event.pos())
        # Mouse not clicked
        if not self.mouseClicked:
            self.pipeSnappedOn = False
            matchSnapper = self.snapper.snapToMap(mousePoint)
            if matchSnapper.isValid():
                valid = False
                layer = matchSnapper.layer()
                snapLayerPath = self.getLayerPath(layer)
                for name in self.ownMainLayers:
                    layerPath = self.generatePath(
                        self.ProjectDirectory,
                        self.NetworkName + "_" + name + ".shp")
                    if snapLayerPath == layerPath:
                        valid = True
                if valid:
                    self.objectSnapped = matchSnapper
                    self.selectedLayer = layer

                    vertex = matchSnapper.point()
                    featureId = matchSnapper.featureId()
                    request = QgsFeatureRequest().setFilterFid(featureId)
                    nodes = list(layer.getFeatures(request))
                    self.selectedFeature = QgsFeature(nodes[0])
                    # #Ver aquí si es el nudo inicial y final
                    middleNode = False
                    self.vertexIndex = -1
                    if layer.geometryType() == 1:  # Line
                        featureGeometry = self.selectedFeature.geometry()
                        if featureGeometry.isMultipart():
                            parts = featureGeometry.get()
                            for part in parts:  # only one part
                                if middleNode:
                                    break
                                i = -1
                                for v in part:
                                    i = i + 1
                                    if (
                                            i == 0 or i == len(part) - 1
                                    ) and "ServiceConnections" not in snapLayerPath:
                                        continue

                                    matchedPoint = QgsPointXY(
                                        vertex.x(), vertex.y())
                                    if self.areOverlapedPoints(
                                            QgsGeometry.fromPointXY(
                                                matchedPoint),
                                            QgsGeometry.fromPointXY(
                                                QgsPointXY(v.x(), v.y()))):
                                        middleNode = True
                                        self.vertexIndex = i
                                        if (
                                                i == 0 or i == len(part) - 1
                                        ) and "ServiceConnections" in snapLayerPath:
                                            self.pipeSnappedOn = True
                                        break
                    if middleNode:
                        self.vertexMarker.setCenter(
                            QgsPointXY(vertex.x(), vertex.y()))
                        self.vertexMarker.show()
                    else:
                        self.vertexMarker.hide()
                else:
                    self.objectSnapped = None
                    self.selectedFeature = None
                    self.selectedLayer = None
                    self.vertexMarker.hide()
            else:
                self.objectSnapped = None
                self.selectedFeature = None
                self.selectedLayer = None
                self.vertexMarker.hide()
        # Mouse clicked
        else:
            # Snap pipe layer
            if self.pipeSnappedOn:
                matchSnapper = self.pipeSnapper.snapToMap(mousePoint)
                if matchSnapper.isValid():
                    valid = False
                    layer = matchSnapper.layer()
                    snapLayerPath = self.getLayerPath(layer)
                    for name in self.ownMainLayers:
                        layerPath = self.generatePath(
                            self.ProjectDirectory,
                            self.NetworkName + "_Pipes.shp")
                        if snapLayerPath == layerPath:
                            valid = True
                    if valid:
                        self.pipeSnapped = matchSnapper
                        self.pipeMarker.setCenter(matchSnapper.point())
                        self.pipeMarker.show()
                    else:
                        self.pipeMarker.hide()
                else:
                    self.pipeMarker.hide()
                    self.pipeSnapped = None

            # # Update rubber band
            if self.objectSnapped is not None and self.rubberBand is not None:
                snappedPoint = self.objectSnapped.point()
                self.newPositionVector = QgsVector(
                    mousePoint.x() - snappedPoint.x(),
                    mousePoint.y() - snappedPoint.y())
                self.updateRubberBand()

    def canvasReleaseEvent(self, event):
        if self.mouseClicked:
            if event.button() == 1:
                mousePoint = self.toMapCoordinates(event.pos())
                if (self.pipeSnapped is not None):
                    mousePoint = self.pipeSnapped.point()
                self.mouseClicked = False
                if self.objectSnapped is not None:
                    self.moveVertexLink(self.selectedLayer,
                                        self.selectedFeature, mousePoint,
                                        self.vertexIndex)
        elif event.button() == 2:
            if self.objectSnapped is not None:
                self.deleteVertexLink(self.selectedLayer, self.selectedFeature,
                                      self.vertexIndex)
        elif event.button() == 1:
            if self.objectSnapped is not None:
                self.insertVertexLink(self.selectedLayer, self.selectedFeature,
                                      self.objectSnapped.point())
        self.objectSnapped = None
        self.pipeSnapped = None
        self.selectedFeature = None
        self.selectedLayer = None
        self.vertexIndex = -1
        self.iface.mapCanvas().refresh()
        # Remove vertex marker and rubber band
        self.vertexMarker.hide()
        self.iface.mapCanvas().scene().removeItem(self.rubberBand)
        self.newVertexMarker.hide()
        self.pipeMarker.hide()
Beispiel #14
0
    def canvasMoveEvent(self, event):
        mousePoint = self.toMapCoordinates(event.pos())
        # Mouse not clicked
        if not self.mouseClicked:
            self.pipeSnappedOn = False
            matchSnapper = self.snapper.snapToMap(mousePoint)
            if matchSnapper.isValid():
                valid = False
                layer = matchSnapper.layer()
                snapLayerPath = self.getLayerPath(layer)
                for name in self.ownMainLayers:
                    layerPath = self.generatePath(
                        self.ProjectDirectory,
                        self.NetworkName + "_" + name + ".shp")
                    if snapLayerPath == layerPath:
                        valid = True
                if valid:
                    self.objectSnapped = matchSnapper
                    self.selectedLayer = layer

                    vertex = matchSnapper.point()
                    featureId = matchSnapper.featureId()
                    request = QgsFeatureRequest().setFilterFid(featureId)
                    nodes = list(layer.getFeatures(request))
                    self.selectedFeature = QgsFeature(nodes[0])
                    # #Ver aquí si es el nudo inicial y final
                    middleNode = False
                    self.vertexIndex = -1
                    if layer.geometryType() == 1:  # Line
                        featureGeometry = self.selectedFeature.geometry()
                        if featureGeometry.isMultipart():
                            parts = featureGeometry.get()
                            for part in parts:  # only one part
                                if middleNode:
                                    break
                                i = -1
                                for v in part:
                                    i = i + 1
                                    if (
                                            i == 0 or i == len(part) - 1
                                    ) and "ServiceConnections" not in snapLayerPath:
                                        continue

                                    matchedPoint = QgsPointXY(
                                        vertex.x(), vertex.y())
                                    if self.areOverlapedPoints(
                                            QgsGeometry.fromPointXY(
                                                matchedPoint),
                                            QgsGeometry.fromPointXY(
                                                QgsPointXY(v.x(), v.y()))):
                                        middleNode = True
                                        self.vertexIndex = i
                                        if (
                                                i == 0 or i == len(part) - 1
                                        ) and "ServiceConnections" in snapLayerPath:
                                            self.pipeSnappedOn = True
                                        break
                    if middleNode:
                        self.vertexMarker.setCenter(
                            QgsPointXY(vertex.x(), vertex.y()))
                        self.vertexMarker.show()
                    else:
                        self.vertexMarker.hide()
                else:
                    self.objectSnapped = None
                    self.selectedFeature = None
                    self.selectedLayer = None
                    self.vertexMarker.hide()
            else:
                self.objectSnapped = None
                self.selectedFeature = None
                self.selectedLayer = None
                self.vertexMarker.hide()
        # Mouse clicked
        else:
            # Snap pipe layer
            if self.pipeSnappedOn:
                matchSnapper = self.pipeSnapper.snapToMap(mousePoint)
                if matchSnapper.isValid():
                    valid = False
                    layer = matchSnapper.layer()
                    snapLayerPath = self.getLayerPath(layer)
                    for name in self.ownMainLayers:
                        layerPath = self.generatePath(
                            self.ProjectDirectory,
                            self.NetworkName + "_Pipes.shp")
                        if snapLayerPath == layerPath:
                            valid = True
                    if valid:
                        self.pipeSnapped = matchSnapper
                        self.pipeMarker.setCenter(matchSnapper.point())
                        self.pipeMarker.show()
                    else:
                        self.pipeMarker.hide()
                else:
                    self.pipeMarker.hide()
                    self.pipeSnapped = None

            # # Update rubber band
            if self.objectSnapped is not None and self.rubberBand is not None:
                snappedPoint = self.objectSnapped.point()
                self.newPositionVector = QgsVector(
                    mousePoint.x() - snappedPoint.x(),
                    mousePoint.y() - snappedPoint.y())
                self.updateRubberBand()
Beispiel #15
0
class QGISRedMoveNodesTool(QgsMapTool):
    ownMainLayers = [
        "Pipes", "Valves", "Pumps", "Junctions", "Tanks", "Reservoirs",
        "Demands", "Sources"
    ]
    myNodeLayers = ["Junctions", "Tanks", "Reservoirs", "Demands", "Sources"]

    def __init__(self, button, iface, projectDirectory, netwName):
        QgsMapTool.__init__(self, iface.mapCanvas())
        self.iface = iface
        self.ProjectDirectory = projectDirectory
        self.NetworkName = netwName
        self.toolbarButton = button

        self.snapper = None
        self.vertexMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.vertexMarker.setColor(QColor(255, 87, 51))
        self.vertexMarker.setIconSize(15)
        self.vertexMarker.setIconType(
            QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.vertexMarker.setPenWidth(3)
        self.vertexMarker.hide()
        self.mousePoint = None

        self.mouseClicked = False
        self.clickedPoint = None
        self.objectSnapped = None
        self.selectedNodeFeature = None
        self.selectedNodeLayer = None
        self.adjacentFeatures = None
        self.newPositionVector = QgsVector(0, 0)
        self.rubberBand = None
        self.newVertexMarker = QgsVertexMarker(self.iface.mapCanvas())
        self.newVertexMarker.setColor(QColor(55, 198, 5))
        self.newVertexMarker.setIconSize(15)
        self.newVertexMarker.setIconType(
            QgsVertexMarker.ICON_BOX)  # or ICON_CROSS, ICON_X
        self.newVertexMarker.setPenWidth(3)
        self.newVertexMarker.hide()

    def activate(self):
        cursor = QCursor()
        cursor.setShape(Qt.ArrowCursor)
        self.iface.mapCanvas().setCursor(cursor)

        myLayers = []
        # Editing
        layers = self.getLayers()
        for layer in layers:
            openedLayerPath = self.getLayerPath(layer)
            for name in self.ownMainLayers:
                layerPath = self.generatePath(
                    self.ProjectDirectory,
                    self.NetworkName + "_" + name + ".shp")
                if openedLayerPath == layerPath:
                    myLayers.append(layer)
                    if not layer.isEditable():
                        layer.startEditing()
        # Snapping
        self.snapper = QgsMapCanvasSnappingUtils(self.iface.mapCanvas())
        self.snapper.setMapSettings(self.iface.mapCanvas().mapSettings())
        config = QgsSnappingConfig(QgsProject.instance())
        config.setType(1)  # Vertex
        config.setMode(2)  # All layers
        config.setTolerance(1)
        config.setUnits(2)  # Pixels
        config.setEnabled(True)
        self.snapper.setConfig(config)

    def deactivate(self):
        self.toolbarButton.setChecked(False)
        # End Editing
        layers = self.getLayers()
        for layer in layers:
            openedLayerPath = self.getLayerPath(layer)
            for name in self.ownMainLayers:
                layerPath = self.generatePath(
                    self.ProjectDirectory,
                    self.NetworkName + "_" + name + ".shp")
                if openedLayerPath == layerPath:
                    if layer.isModified():
                        layer.commitChanges()
                    else:
                        layer.rollBack()

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True

    """Methods"""

    def getUniformedPath(self, path):
        return QGISRedUtils().getUniformedPath(path)

    def getLayerPath(self, layer):
        return QGISRedUtils().getLayerPath(layer)

    def generatePath(self, folder, fileName):
        return QGISRedUtils().generatePath(folder, fileName)

    def getLayers(self):
        return QGISRedUtils().getLayers()

    def findAdjacentElements(self, nodeGeometry):
        adjacentElements = {}
        layers = self.getLayers()
        for layer in layers:
            openedLayerPath = self.getLayerPath(layer)
            for name in self.ownMainLayers:
                layePath = self.generatePath(
                    self.ProjectDirectory,
                    self.NetworkName + "_" + name + ".shp")
                if openedLayerPath == layePath:
                    adjacentFeatures = []
                    for feature in layer.getFeatures():
                        featureGeometry = feature.geometry()
                        if layer.geometryType() == 0:  # Point
                            if self.areOverlapedPoints(nodeGeometry,
                                                       featureGeometry):
                                adjacentFeatures.append(feature)
                        elif layer.geometryType() == 1:
                            if featureGeometry.isMultipart():
                                for part in featureGeometry.get(
                                ):  # only one part
                                    first_vertex = part[0]
                                    last_vertex = part[-1]
                            else:
                                first_vertex = featureGeometry.get()[0]
                                last_vertex = featureGeometry.get()[-1]

                            firsVertex = QgsGeometry.fromPointXY(
                                QgsPointXY(first_vertex.x(), first_vertex.y()))
                            lastVertex = QgsGeometry.fromPointXY(
                                QgsPointXY(last_vertex.x(), last_vertex.y()))
                            if self.areOverlapedPoints(nodeGeometry, firsVertex) or\
                                    self.areOverlapedPoints(nodeGeometry, lastVertex):
                                adjacentFeatures.append(feature)
                    if len(adjacentFeatures) > 0:
                        adjacentElements[layer] = adjacentFeatures

        return adjacentElements

    def areOverlapedPoints(self, point1, point2):
        tolerance = 0.1
        if point1.distance(point2) < tolerance:
            return True
        else:
            return False

    def createRubberBand(self, points):
        myPoints = points
        if isinstance(points[0], QgsPointXY):
            myPoints = []
            for p in points:
                myPoints.append(QgsPoint(p.x(), p.y()))
        self.rubberBand = QgsRubberBand(self.iface.mapCanvas(), False)
        self.rubberBand.setToGeometry(QgsGeometry.fromPolyline(myPoints), None)
        self.rubberBand.setColor(QColor(55, 198, 5))
        self.rubberBand.setWidth(1)
        self.rubberBand.setLineStyle(Qt.DashLine)
        self.newVertexMarker.setCenter(QgsPointXY(points[0].x(),
                                                  points[0].y()))
        self.newVertexMarker.show()

    def updateRubberBand(self):
        newX = self.clickedPoint.x() + self.newPositionVector.x()
        newY = self.clickedPoint.y() + self.newPositionVector.y()
        self.rubberBand.movePoint(1, QgsPointXY(newX, newY))
        self.newVertexMarker.setCenter(QgsPointXY(newX, newY))

    def moveNodePoint(self, layer, nodeFeature, newPosition):
        if layer.isEditable():
            layer.beginEditCommand('Move node')
            try:
                edit_utils = QgsVectorLayerEditUtils(layer)
                edit_utils.moveVertex(newPosition.x(), newPosition.y(),
                                      nodeFeature.id(), 0)
            except Exception as e:
                layer.destroyEditCommand()
                raise e
            layer.endEditCommand()

    def moveVertexLink(self, layer, feature, newPosition, vertexIndex):
        if layer.isEditable():
            layer.beginEditCommand("Update link geometry")
            try:
                edit_utils = QgsVectorLayerEditUtils(layer)
                edit_utils.moveVertex(newPosition.x(), newPosition.y(),
                                      feature.id(), vertexIndex)
            except Exception as e:
                layer.destroyEditCommand()
                raise e
            layer.endEditCommand()

    """Events"""

    def canvasPressEvent(self, event):
        if self.objectSnapped is None:
            self.clickedPoint = None
            return

        if event.button() == Qt.RightButton:
            self.mouseClicked = False
            self.clickedPoint = None

        if event.button() == Qt.LeftButton:
            self.mouseClicked = True
            self.clickedPoint = self.objectSnapped.point()

            self.selectedNodeFeature = None
            self.adjacentFeatures = None

            foundNode = False
            layers = self.getLayers()
            for layer in layers:
                openedLayerPath = self.getLayerPath(layer)
                for name in self.myNodeLayers:
                    layerPath = self.generatePath(
                        self.ProjectDirectory,
                        self.NetworkName + "_" + name + ".shp")
                    if openedLayerPath == layerPath:
                        locatedPoint = self.snapper.locatorForLayer(layer)
                        match = locatedPoint.nearestVertex(
                            self.objectSnapped.point(), 1)
                        if match.isValid():
                            featureId = match.featureId()
                            request = QgsFeatureRequest().setFilterFid(
                                featureId)
                            node = list(layer.getFeatures(request))
                            self.selectedNodeLayer = layer
                            foundNode = True

            if not foundNode:
                return

            self.selectedNodeFeature = QgsFeature(node[0])
            self.adjacentFeatures = self.findAdjacentElements(
                self.selectedNodeFeature.geometry())
            self.createRubberBand(
                [self.objectSnapped.point(),
                 self.objectSnapped.point()])

    def canvasMoveEvent(self, event):
        self.mousePoint = self.toMapCoordinates(event.pos())
        # Mouse not clicked
        if not self.mouseClicked:
            match = self.snapper.snapToMap(self.mousePoint)
            if match.isValid():
                self.objectSnapped = match
                vertex = match.point()
                self.vertexMarker.setCenter(QgsPointXY(vertex.x(), vertex.y()))
                self.vertexMarker.show()
            else:
                self.objectSnapped = None
                self.selectedNodeFeature = None
                self.vertexMarker.hide()
        # Mouse clicked
        else:
            # Update rubber band
            if self.objectSnapped is not None and self.rubberBand is not None:
                snappedPoint = self.objectSnapped.point()
                self.newPositionVector = QgsVector(
                    self.mousePoint.x() - snappedPoint.x(),
                    self.mousePoint.y() - snappedPoint.y())
                self.updateRubberBand()

    def canvasReleaseEvent(self, event):
        mousePoint = self.toMapCoordinates(event.pos())
        if not self.mouseClicked:
            return

        if event.button() == 1:
            self.mouseClicked = False

            if self.objectSnapped is not None:
                if self.selectedNodeFeature is not None:
                    for adjLayer in self.adjacentFeatures:
                        for feature in self.adjacentFeatures[adjLayer]:
                            if adjLayer.geometryType() == 0:  # Point
                                self.moveNodePoint(adjLayer, feature,
                                                   mousePoint)
                            else:
                                nodeGeometry = self.selectedNodeFeature.geometry(
                                )
                                featureGeometry = feature.geometry()

                                if featureGeometry.isMultipart():
                                    for part in featureGeometry.get(
                                    ):  # only one part
                                        firstVertex = part[0]
                                        vertices = len(part)
                                else:
                                    firstVertex = featureGeometry.get()[0]
                                    vertices = 2
                                firstPoint = QgsGeometry.fromPointXY(
                                    QgsPointXY(firstVertex.x(),
                                               firstVertex.y()))
                                if self.areOverlapedPoints(
                                        nodeGeometry, firstPoint):
                                    index = 0
                                else:
                                    index = vertices - 1
                                self.moveVertexLink(adjLayer, feature,
                                                    mousePoint, index)
                self.objectSnapped = None
                self.selectedNodeFeature = None
                self.iface.mapCanvas().refresh()

            # Remove vertex marker and rubber band
            self.vertexMarker.hide()
            self.iface.mapCanvas().scene().removeItem(self.rubberBand)
            self.newVertexMarker.hide()
Beispiel #16
0
    def getMatchingFeatures(self, geometry, contains, singleSelect):
        newFeatures = []
        if geometry.type() != QgsWkbTypes.PolygonGeometry:
            return newFeatures

        layer = self.canvas.currentLayer()
        if layer is None:
            return newFeatures

        selectGeomTrans = QgsGeometry(geometry)
        try:
            ct = QgsCoordinateTransform(self.canvas.mapSettings().destinationCrs(), layer.crs(), QgsProject.instance())
            if not ct.isShortCircuited() and selectGeomTrans.type() == QgsWkbTypes.PolygonGeometry:
                poly = selectGeomTrans.asPolygon()
                if len(poly) == 1 and len(poly[0]) == 5:
                    ringIn = poly[0]
                    ringOut = []
                    ringOut.append(ringIn[0])
                    i = 1
                    for j in range(1, 5):
                        v = QgsVector((ringIn[j] - ringIn[j - 1]) / 10.0)
                        for k in range(9):
                            ringOut.append(ringOut[i - 1] + v)
                            i += 1
                        ringOut.append(ringIn[j])
                        i += 1
                    selectGeomTrans = QgsGeometry.fromPolygonXY([ringOut])

            selectGeomTrans.transform(ct)
        except QgsCsException as e:
            QgsMessageLog.logMessage("Selection extends beyond layer's coordinate system")
            return newFeatures

        context = QgsRenderContext.fromMapSettings(self.canvas.mapSettings())
        context.expressionContext().appendScope(QgsExpressionContextUtils.layerScope(layer))

        r = None
        if layer.renderer():
            r = layer.renderer().clone()
            r.startRender(context, layer.fields())

        request = QgsFeatureRequest()
        request.setFilterRect(selectGeomTrans.boundingBox())
        request.setFlags(QgsFeatureRequest.ExactIntersect)

        if r:
            request.setSubsetOfAttributes(r.usedAttributes(context), layer.fields())
        else:
            request.setSubsetOfAttributes([])

        closestFeatureId = 0
        foundSingleFeature = False
        closestFeatureDist = sys.float_info.max
        for f in layer.getFeatures(request):
            context.expressionContext().setFeature(f)
            if r and  not r.willRenderFeature(f, context):
                continue

            g = f.geometry()
            if contains:
                if not selectGeomTrans.contains(g):
                    continue

            else:
                if not selectGeomTrans.intersects(g):
                    continue

            if singleSelect:
                foundSingleFeature = True
                distance = g.distance(selectGeomTrans)
                if distance <= closestFeatureDist:
                    closestFeatureDist = distance
                    closestFeatureId = f.id()
            else:
                newFeatures.append(f.id())

        if singleSelect and foundSingleFeature:
            newFeatures.append(closestFeatureId)

        if r:
            r.stopRender(context)

        return newFeatures
def qgs_vector(p0, p1):
    return QgsVector(p1.x() - p0.x(), p1.y() - p0.y())
Beispiel #18
0
class MoveTool(QgsMapTool):

    def __init__(self, data_dock, params):
        QgsMapTool.__init__(self, data_dock.iface.mapCanvas())

        self.iface = data_dock.iface
        """:type : QgisInterface"""
        self.dock_widget = data_dock
        """:type : DataDock"""
        self.params = params

        self.elev = None
        self.vertex_marker = QgsVertexMarker(self.canvas())
        self.mouse_clicked = False
        self.snapper = None

        self.clicked_pt = None

        self.snap_results = None

        self.selected_node_ft = None
        self.selected_node_ft_lay = None
        self.mouse_pt = None
        self.pump_valve_selected = False
        self.pump_or_valve = None
        self.pump_valve_ft = None
        self.adj_links_fts = None
        self.adj_junctions = None
        self.delta_vec = QgsVector(0, 0)
        self.adj_links_fts_d = {}

        # self.rubber_bands_d = {}
        # self.rubber_bands_geoms_d = {}

        self.rubber_band = None

        self.logger = logging.getLogger('Logger1')

    def canvasPressEvent(self, event):

        if self.snap_results is None:
            self.clicked_pt = None
            return

        if event.button() == Qt.RightButton:
            self.mouse_clicked = False
            self.clicked_pt = None

        if event.button() == Qt.LeftButton:

            self.mouse_clicked = True
            self.clicked_pt = self.snap_results.point()

            # Check if a node was snapped: it can be just one
            self.selected_node_ft = None
            self.adj_links_fts = None

            # Check if I snapped on a node
            snapped_layer_name = self.snap_results.layer().name()

            self.selected_node_ft = None

            pt_locator_ju = self.snapper.locatorForLayer(self.params.junctions_vlay)
            pt_locator_re = self.snapper.locatorForLayer(self.params.reservoirs_vlay)
            pt_locator_ta = self.snapper.locatorForLayer(self.params.tanks_vlay)
            match_ju = pt_locator_ju.nearestVertex(self.snap_results.point(), 1)
            match_re = pt_locator_re.nearestVertex(self.snap_results.point(), 1)
            match_ta = pt_locator_ta.nearestVertex(self.snap_results.point(), 1)

            if match_ju.isValid() or match_re.isValid() or match_ta.isValid():

                if match_ju.isValid():
                    node_feat_id = match_ju.featureId()
                    request = QgsFeatureRequest().setFilterFid(node_feat_id)
                    node = list(self.params.junctions_vlay.getFeatures(request))
                    self.selected_node_ft_lay = self.params.junctions_vlay

                if match_re.isValid():
                    node_feat_id = match_re.featureId()
                    request = QgsFeatureRequest().setFilterFid(node_feat_id)
                    node = list(self.params.reservoirs_vlay.getFeatures(request))
                    self.selected_node_ft_lay = self.params.reservoirs_vlay

                if match_ta.isValid():
                    node_feat_id = match_ta.featureId()
                    request = QgsFeatureRequest().setFilterFid(node_feat_id)
                    node = list(self.params.tanks_vlay.getFeatures(request))
                    self.selected_node_ft_lay = self.params.tanks_vlay

                self.selected_node_ft = QgsFeature(node[0])

                # self.selected_node_ft_lay = self.snap_results.layer()
                self.adj_links_fts = NetworkUtils.find_adjacent_links(self.params, self.selected_node_ft.geometry())

            # No selected nodes: it's just a vertex
            if self.selected_node_ft is None:

                snapped_ft = vector_utils.get_feats_by_id(self.snap_results.layer(), self.snap_results.featureId())[0]
                snapped_ft_geom = snapped_ft.geometry()

                points = []
                if self.snap_results.vertexIndex() - 1 >= 0 and self.snap_results.vertexIndex() - 1 < len(snapped_ft_geom.asPolyline()):
                    vertex_index = 1
                    vertex_before = snapped_ft_geom.vertexAt(self.snap_results.vertexIndex() - 1)
                    points.append(vertex_before)

                vertex_at = snapped_ft_geom.vertexAt(self.snap_results.vertexIndex())
                points.append(vertex_at)

                if self.snap_results.vertexIndex() + 1 >= 0 and self.snap_results.vertexIndex() + 1 < len(snapped_ft_geom.asPolyline()):
                    vertex_index = 0
                    vertex_after = snapped_ft_geom.vertexAt(self.snap_results.vertexIndex() + 1)
                    points.append(vertex_after)

                if self.snap_results.vertexIndex() > 0 and self.snap_results.vertexIndex() < len(snapped_ft_geom.asPolyline()) - 1:
                    vertex_index = 1

                # self.rubber_bands_d[0] = (self.build_rubber_band(points), [vertex_index], [vertex_at])
                self.rubber_band = self.build_rubber_band([self.snap_results.point(), self.snap_results.point()])

            # It's a node
            else:

                # It's an isolated node: no rubber band!
                if self.adj_links_fts is None or (not self.adj_links_fts['pipes'] and not self.adj_links_fts['pumps'] and not self.adj_links_fts['valves']):
                    # self.rubber_bands_d.clear()
                    self.rubber_band = self.build_rubber_band([self.snap_results.point(), self.snap_results.point()])
                    return

                # Adjacent links are neither pumps nor valves: find the two pipes adjacent to the node
                # OR node adjacent to pump or valve and NOT using block logic
                if (not self.adj_links_fts['pumps'] and not self.adj_links_fts['valves']) or not self.params.block_logic:

                    self.pump_valve_selected = False

                    rb_points = []

                    for adjacent_pipes_ft in self.adj_links_fts['pipes']:
                        closest = adjacent_pipes_ft.geometry().closestVertex(self.selected_node_ft.geometry().asPoint())
                        self.adj_links_fts_d[adjacent_pipes_ft] = (closest[1], self.params.pipes_vlay)
                        if closest[1] == 0:
                            next_vertext_id = closest[1] + 1
                        else:
                            next_vertext_id = closest[1] - 1
                        rb_points.append(adjacent_pipes_ft.geometry().vertexAt(next_vertext_id))

                    for adj_pumps_ft in self.adj_links_fts['pumps']:
                        closest = adj_pumps_ft.geometry().closestVertex(self.selected_node_ft.geometry().asPoint())
                        self.adj_links_fts_d[adj_pumps_ft] = (closest[1], self.params.pumps_vlay)
                        if closest[1] == 0:
                            next_vertext_id = closest[1] + 1
                        else:
                            next_vertext_id = closest[1] - 1
                        rb_points.append(adj_pumps_ft.geometry().vertexAt(next_vertext_id))

                    for adj_valves_ft in self.adj_links_fts['valves']:
                        closest = adj_valves_ft.geometry().closestVertex(self.selected_node_ft.geometry().asPoint())
                        self.adj_links_fts_d[adj_valves_ft] = (closest[1], self.params.valves_vlay)
                        if closest[1] == 0:
                            next_vertext_id = closest[1] + 1
                        else:
                            next_vertext_id = closest[1] - 1
                        rb_points.append(adj_valves_ft.geometry().vertexAt(next_vertext_id))

                    rb_points.insert(1, self.selected_node_ft.geometry().asPoint())
                    # self.rubber_bands_d[0] = (self.build_rubber_band(rb_points), [1], [self.selected_node_ft.geometry().asPoint()])
                    self.rubber_band = self.build_rubber_band([self.snap_results.point(), self.snap_results.point()])

                # Node adjacent to pump or valve and using block logic
                else:

                    self.pump_valve_selected = True

                    # Find the pipes adjacent to the pump/valve
                    if self.adj_links_fts['pumps']:
                        self.pump_valve_ft = self.adj_links_fts['pumps'][0]
                        self.pump_or_valve = 'pump'
                        adj_links = NetworkUtils.find_links_adjacent_to_link(self.params, self.params.pumps_vlay, self.pump_valve_ft, False, True, True)
                    elif self.adj_links_fts['valves']:
                        self.pump_valve_ft = self.adj_links_fts['valves'][0]
                        self.pump_or_valve = 'valve'
                        adj_links = NetworkUtils.find_links_adjacent_to_link(self.params, self.params.valves_vlay, self.pump_valve_ft, False, True, True)
                    else:
                        return

                    pump_valve_pts = self.pump_valve_ft.geometry().asPolyline()

                    # self.rubber_bands_d[0] = (self.build_rubber_band(pump_valve_pts), range(len(pump_valve_pts)), pump_valve_pts)
                    self.rubber_band = self.build_rubber_band([self.snap_results.point(), self.snap_results.point()])

                    rb_index = 1
                    if 'pipes' in adj_links:
                        for adj_link_ft in adj_links['pipes']:
                            self.process_adj(adj_link_ft, self.params.pipes_vlay, rb_index)
                            rb_index += 1
                    if 'pumps' in adj_links:
                        for adj_link_ft in adj_links['pumps']:
                            self.process_adj(adj_link_ft, self.params.pumps_vlay, rb_index)
                            rb_index += 1
                    if 'valves' in adj_links:
                        for adj_link_ft in adj_links['valves']:
                            self.process_adj(adj_link_ft, self.params.valves_vlay, rb_index)
                            rb_index += 1

                    # Find the nodes adjacent to the pump/valve
                    self.adj_junctions = NetworkUtils.find_start_end_nodes_w_layer(self.params, self.pump_valve_ft.geometry())

    def process_adj(self, adj_link_ft, layer, rb_index):
        adj_link_pts = adj_link_ft.geometry().asPolyline()
        pump_valve_pts = self.pump_valve_ft.geometry().asPolyline()

        if NetworkUtils.points_overlap(QgsGeometry.fromPoint(pump_valve_pts[0]), adj_link_pts[0], self.params.tolerance):
            self.adj_links_fts_d[adj_link_ft] = (0, layer)
            # rb_pts = [pump_valve_pts[0], adj_link_pts[1]]
            # self.rubber_bands_d[rb_index] = (self.build_rubber_band(rb_pts), [0], [pump_valve_pts[0]])

        if NetworkUtils.points_overlap(QgsGeometry.fromPoint(pump_valve_pts[-1]), adj_link_pts[0], self.params.tolerance):
            self.adj_links_fts_d[adj_link_ft] = (0, layer)
            # rb_pts = [pump_valve_pts[-1], adj_link_pts[1]]
            # self.rubber_bands_d[rb_index] = (self.build_rubber_band(rb_pts), [0], [pump_valve_pts[-1]])

        if NetworkUtils.points_overlap(QgsGeometry.fromPoint(pump_valve_pts[0]), adj_link_pts[-1], self.params.tolerance):
            self.adj_links_fts_d[adj_link_ft] = (len(adj_link_pts)-1, layer)
            # rb_pts = [pump_valve_pts[0], adj_link_pts[-2]]
            # self.rubber_bands_d[rb_index] = (self.build_rubber_band(rb_pts), [0], [pump_valve_pts[0]])

        if NetworkUtils.points_overlap(QgsGeometry.fromPoint(pump_valve_pts[-1]), adj_link_pts[-1], self.params.tolerance):
            self.adj_links_fts_d[adj_link_ft] = (len(adj_link_pts)-1, layer)
            # rb_pts = [pump_valve_pts[-1], adj_link_pts[-2]]
            # self.rubber_bands_d[rb_index] = (self.build_rubber_band(rb_pts), [0], [pump_valve_pts[-1]])

    def canvasMoveEvent(self, event):

        self.mouse_pt = self.toMapCoordinates(event.pos())

        elev = raster_utils.read_layer_val_from_coord(self.params.dem_rlay, self.mouse_pt, 1)
        if elev is not None:
            self.elev = elev
            self.dock_widget.lbl_elev_val.setText("{0:.2f}".format(self.elev))
        else:
            self.elev = None
            self.dock_widget.lbl_elev_val.setText('-')

        # Mouse not clicked
        if not self.mouse_clicked:

            match = self.snapper.snapToMap(self.mouse_pt)
            if match.isValid():

                self.snap_results = match
                # snapped_pt = self.snap_results[0].snappedVertex
                snapped_vertex = match.point()

                self.vertex_marker.setCenter(QgsPoint(snapped_vertex.x(), snapped_vertex.y()))
                self.vertex_marker.setColor(QColor(255, 0, 0))
                self.vertex_marker.setIconSize(10)
                self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE)  # or ICON_CROSS, ICON_X
                self.vertex_marker.setPenWidth(3)
                self.vertex_marker.show()
            else:
                self.snap_results = None
                self.selected_node_ft = None
                self.vertex_marker.hide()

        # Mouse clicked
        else:

            # Update rubber band
            if self.snap_results is not None and self.rubber_band:

                snapped_pt = self.snap_results.point()

                # In 2.16+: self.delta_vec = QgsVector(self.mouse_pt - snapped_pt)
                self.delta_vec = QgsVector(self.mouse_pt.x() - snapped_pt.x(),
                                           self.mouse_pt.y() - snapped_pt.y())

                self.move_rubber_band_pt(self.rubber_band)

                # if self.adj_links_fts is None or (not self.adj_links_fts['pipes'] and not self.adj_links_fts['pumps'] and not self.adj_links_fts['valves']):
                #     # There are no adjacent links
                #     self.move_rubber_band_pt(self.rubber_bands_d[0])
                # else:
                #
                #     # It's just a junction
                #     if not self.pump_valve_selected:
                #         for key, value in self.rubber_bands_d.iteritems():
                #             self.move_rubber_band_pt(self.rubber_bands_d[key])
                #
                #     # It's a pump/valve
                #     else:
                #
                #         # Adjacent links are neither pumps nor valves: find the two pipes adjacent to the node
                #         # Or node adjacent to pump or valve and NOT using block logic
                #         if (not self.adj_links_fts['pumps'] and not self.adj_links_fts['valves']) or not self.params.block_logic:
                #
                #             for key, value in self.rubber_bands_d.iteritems():
                #                 self.move_rubber_band_pt(self.rubber_bands_d[key])
                #                 # in 2.16: self.rubber_bands_d[key].movePoint(1, snapped_pt + self.delta_vec)
                #                 # self.rubber_bands_d[key].movePoint(2, QgsPoint(snapped_pt.x() + self.delta_vec.x(), snapped_pt.y() + self.delta_vec.y()))
                #
                #         # Node adjacent to pump or valve and using block logic
                #         else:
                #             for key, value in self.rubber_bands_d.iteritems():
                #                 self.move_rubber_band_pt(self.rubber_bands_d[key])

    def move_rubber_band_pt(self, rubber_band_v):
        # rubber_band = rubber_band_v[0]
        # pt_indices = rubber_band_v[1]
        # start_pts = rubber_band_v[2]

        # for i in range(len(pt_indices)):
        #     rubber_band.movePoint(pt_indices[i], QgsPoint(start_pts[i].x() + self.delta_vec.x(), start_pts[i].y() + self.delta_vec.y()))

        rubber_band_v.movePoint(1, QgsPoint(self.clicked_pt.x() + self.delta_vec.x(), self.clicked_pt.y() + self.delta_vec.y()))

    def canvasReleaseEvent(self, event):

        mouse_pt = self.toMapCoordinates(event.pos())

        if not self.mouse_clicked:
            return

        if event.button() == 1:
            self.mouse_clicked = False

            if self.snap_results is not None:

                snap_results = self.snap_results
                selected_node_ft = self.selected_node_ft
                selected_node_ft_lay = self.selected_node_ft_lay

                # Check elev
                if self.elev is None and self.params.dem_rlay is not None:
                    self.iface.messageBar().pushMessage(
                        Parameters.plug_in_name,
                        'Elevation value not available: element elevation set to 0.',
                        QgsMessageBar.WARNING,
                        5)  # TODO: softcode

                # It's just a pipe vertex
                if selected_node_ft is None:

                    feat = vector_utils.get_feats_by_id(snap_results.layer(), snap_results.featureId())
                    vertex_id = QgsVertexId(0, 0, snap_results.vertexIndex(), QgsVertexId.SegmentVertex)
                    vertex_v2 = feat[0].geometry().geometry().vertexAt(vertex_id)
                    new_pos_pt_v2 = QgsPointV2(mouse_pt.x(), mouse_pt.y())
                    new_pos_pt_v2.addZValue(vertex_v2.z())
                    LinkHandler.move_link_vertex(self.params, self.params.pipes_vlay, feat[0], new_pos_pt_v2,
                                                 snap_results.vertexIndex())

                # There are adjacent links: it's a node
                else:

                    # Not pump or valve: plain junction
                    if not self.pump_valve_selected:

                        # Update junction geometry
                        NodeHandler.move_element(
                            selected_node_ft_lay,
                            self.params.dem_rlay,
                            selected_node_ft,
                            mouse_pt)

                        # Update pipes
                        for feat, (vertex_index, layer) in self.adj_links_fts_d.iteritems():

                            vertex_id = QgsVertexId(0, 0, vertex_index, QgsVertexId.SegmentVertex)
                            vertex_v2 = feat.geometry().geometry().vertexAt(vertex_id)
                            new_pos_pt_v2 = QgsPointV2(mouse_pt.x(), mouse_pt.y())
                            new_pos_pt_v2.addZValue(vertex_v2.z())

                            LinkHandler.move_link_vertex(self.params, layer, feat, new_pos_pt_v2, vertex_index)

                    # Pump or valve
                    else:

                        # Update junctions geometry
                        NodeHandler.move_element(self.adj_junctions[0][1],
                                                 self.params.dem_rlay,
                                                 self.adj_junctions[0][0],
                                                 QgsPoint(
                                                    self.adj_junctions[0][0].geometry().asPoint().x() + self.delta_vec.x(),
                                                    self.adj_junctions[0][0].geometry().asPoint().y() + self.delta_vec.y()))

                        NodeHandler.move_element(self.adj_junctions[1][1],
                                                 self.params.dem_rlay,
                                                 self.adj_junctions[1][0],
                                                 QgsPoint(
                                                     self.adj_junctions[1][0].geometry().asPoint().x() + self.delta_vec.x(),
                                                     self.adj_junctions[1][0].geometry().asPoint().y() + self.delta_vec.y()))

                        # in 2.16: NodeHandler.move_element(Parameters.junctions_vlay, self.adj_links_fts[0], self.adj_links_fts[0].geometry().asPoint() + self.delta_vec)

                        if self.pump_or_valve == 'pump':
                            lay = self.params.pumps_vlay
                        elif self.pump_or_valve == 'valve':
                            lay = self.params.valves_vlay

                        # Move the pump/valve
                        LinkHandler.move_pump_valve(lay, self.pump_valve_ft, self.delta_vec)

                        # Move the adjacent pipes' vertices
                        for feat, (vertex_index, layer) in self.adj_links_fts_d.iteritems():

                            vertex_id = QgsVertexId(0, 0, vertex_index, QgsVertexId.SegmentVertex)
                            vertex_v2 = feat.geometry().geometry().vertexAt(vertex_id)
                            new_pos_pt_v2 = QgsPointV2(
                                feat.geometry().vertexAt(vertex_index).x() + self.delta_vec.x(),
                                feat.geometry().vertexAt(vertex_index).y() + self.delta_vec.y())
                            new_pos_pt_v2.addZValue(vertex_v2.z())

                            LinkHandler.move_link_vertex(self.params, layer, feat, new_pos_pt_v2, vertex_index)
                            # In 2.16: LinkHandler.move_pipe_vertex(feat, feat.geometry().vertexAt(vertex_index) + self.delta_vec, vertex_index)

                    self.adj_links_fts_d.clear()

                symbology.refresh_layer(self.iface.mapCanvas(), self.params.junctions_vlay)
                symbology.refresh_layer(self.iface.mapCanvas(), self.params.reservoirs_vlay)
                symbology.refresh_layer(self.iface.mapCanvas(), self.params.tanks_vlay)
                symbology.refresh_layer(self.iface.mapCanvas(), self.params.pipes_vlay)
                symbology.refresh_layer(self.iface.mapCanvas(), self.params.pumps_vlay)
                symbology.refresh_layer(self.iface.mapCanvas(), self.params.valves_vlay)

            # Remove vertex marker and rubber band
            self.vertex_marker.hide()
            self.iface.mapCanvas().scene().removeItem(self.rubber_band)

    def activate(self):

        cursor = QCursor()
        cursor.setShape(Qt.ArrowCursor)
        self.iface.mapCanvas().setCursor(cursor)

        # Snapping
        layers = {
            self.params.junctions_vlay: QgsPointLocator.Vertex,
            self.params.reservoirs_vlay: QgsPointLocator.Vertex,
            self.params.tanks_vlay: QgsPointLocator.Vertex,
            self.params.pipes_vlay: QgsPointLocator.Vertex}
        self.snapper = NetworkUtils.set_up_snapper(layers, self.iface.mapCanvas(), self.params.snap_tolerance)

        # Editing
        if not self.params.junctions_vlay.isEditable():
            self.params.junctions_vlay.startEditing()
        if not self.params.reservoirs_vlay.isEditable():
            self.params.reservoirs_vlay.startEditing()
        if not self.params.tanks_vlay.isEditable():
            self.params.tanks_vlay.startEditing()
        if not self.params.pipes_vlay.isEditable():
            self.params.pipes_vlay.startEditing()
        if not self.params.pumps_vlay.isEditable():
            self.params.pumps_vlay.startEditing()
        if not self.params.valves_vlay.isEditable():
            self.params.valves_vlay.startEditing()

    def deactivate(self):
        # self.rubber_bands.clear()
        self.canvas().scene().removeItem(self.vertex_marker)
        self.dock_widget.btn_move_element.setChecked(False)

    def isZoomTool(self):
        return False

    def isTransient(self):
        return False

    def isEditTool(self):
        return True

    def build_rubber_band(self, points):
        rubber_band = QgsRubberBand(self.canvas(), False)  # False = not a polygon
        rubber_band.setToGeometry(QgsGeometry.fromPolyline(points), None)
        # for point in points:
        #     rubber_band.addPoint(point)
        rubber_band.setColor(QColor(255, 128, 128))
        rubber_band.setWidth(1)
        rubber_band.setBrushStyle(Qt.Dense4Pattern)
        return rubber_band
Beispiel #19
0
    def testQgsVector(self):
        v = QgsVector(1, 2)
        self.assertEqual(v.__repr__(), '<QgsVector: Vector (1, 2)>')

        v = QgsVector3D(1, 2, 3)
        self.assertEqual(v.__repr__(), '<QgsVector3D: Vector3D (1, 2, 3)>')
Beispiel #20
0
    def getIntersection(self, p1, p2):
        """
        Get intersection on segment
        :param p1: QgsPointV2
        :param p2: QgsPointV2
        :param inter: QgsPointV2 reference
        :return: bool
        """
        q1 = self.idxFrom.point()
        q2 = self.idxTo.point()
        v = QgsVector(p2.x() - p1.x(), p2.y() - p1.y())
        w = QgsVector(q2.x() - q1.x(), q2.y() - q1.y())
        vl = v.length()
        wl = w.length()

        if self.isclose(vl, 0.) or self.isclose(wl, 0.):
            return None

        v = v / vl
        w = w / wl

        d = v.y() * w.x() - v.x() * w.y()

        if d == 0:
            return None

        dx = q1.x() - p1.x()
        dy = q1.y() - p1.y()
        k = (dy * w.x() - dx * w.y()) / d

        inter = QgsPointV2(p1.x() + v.x() * k, p1.y() + v.y() * k)

        lambdav = QgsVector(inter.x() - p1.x(), inter.y() - p1.y()) * v
        if lambdav < 0. + 1E-8 or lambdav > vl - 1E-8:
            return None

        lambdaw = QgsVector(inter.x() - q1.x(), inter.y() - q1.y()) * w
        if lambdaw < 0. + 1E-8 or lambdaw >= wl - 1E-8:
            return None

        return inter