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))
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)
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)
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 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)
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
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
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)>')
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
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
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)
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()
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()
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()
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())
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
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