0

I am looking for a method to automatically select the lines of a shortest path between two points. Theoretically it is the Road Graph plugin, which is now the "shortest path point to point" function in QGIS. My problem is that I don't want to create a new shapefile. I want to select the lines in the shapefile I am working with to insert data into the attribute table.

How can I solve this problem? I tried using Python, but I am new to Python and the scripts I tried don't work. For example, I found this script(https://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/network_analysis.html?highlight=shortest#finding-shortest-paths). But nothing happens when I run it.

from qgis.core import *
from qgis.gui import *
from qgis.analysis import *

from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *

vectorLayer = QgsVectorLayer('testdata/network.gpkg|layername=network_lines', 'lines')
builder = QgsGraphBuilder(vectorLayer.sourceCrs())
director = QgsVectorLayerDirector(vectorLayer, -1, '', '', '', QgsVectorLayerDirector.DirectionBoth)

startPoint = QgsPointXY(1179661.925139,5419188.074362)
endPoint = QgsPointXY(1180942.970617,5420040.097560)

tiedPoints = director.makeGraph(builder, [startPoint, endPoint])
tStart, tStop = tiedPoints

graph = builder.graph()
idxStart = graph.findVertex(tStart)

tree = QgsGraphAnalyzer.shortestTree(graph, idxStart, 0)

idxStart = tree.findVertex(tStart)
idxEnd = tree.findVertex(tStop)

if idxEnd == -1:
    raise Exception('No route!')

# Add last point
route = [tree.vertex(idxEnd).point()]

# Iterate the graph
while idxEnd != idxStart:
    edgeIds = tree.vertex(idxEnd).incomingEdges()
    if len(edgeIds) == 0:
        break
    edge = tree.edge(edgeIds[0])
    route.insert(0, tree.vertex(edge.fromVertex()).point())
    idxEnd = edge.fromVertex()

# Display
rb = QgsRubberBand(iface.mapCanvas())
rb.setColor(Qt.green)

# This may require coordinate transformation if project's CRS
# is different than layer's CRS
for p in route:
    rb.addPoint(p)

1 Answer 1

-1
from qgis.core import QgsProject, QgsVectorLayer, QgsPointXY
from qgis.analysis import QgsNetworkAnalyzer


network_layer_path = '/path/to/network_layer.shp'
start_point = QgsPointXY(10, 10)
end_point = QgsPointXY(20, 20)


network_layer = QgsVectorLayer(network_layer_path, 'Network Layer', 'ogr')
network_analyzer = QgsNetworkAnalyzer()
director = network_analyzer.buildNetwork(network_layer, [], [], [], QgsNetworkAnalyzer.DirectionFlagBoth, 5)

# Find the closest graph points to the start and end points
start_id = director.nearestNodeOnNetwork(start_point, QgsNetworkAnalyzer.DirectionFlagBoth)
end_id = director.nearestNodeOnNetwork(end_point, QgsNetworkAnalyzer.DirectionFlagBoth)
(success, path) = network_analyzer.shortestPath(start_id, end_id)
line_ids = path.links()
network_layer.selectByIds(line_ids)
network_layer.triggerRepaint()

# Save the selected lines to a new layer if needed
selected_layer_path = '/path/to/selected_lines.shp'
QgsVectorLayer.exportNamedLayerDefinition(network_layer, selected_layer_path)
2
  • Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Jun 28, 2023 at 11:18
  • Unfortunately I get the error message that QgsNetworkAnalyzer cannot be imported. I use QGIS 3.28.6 Traceback (most recent call last): File "C:\PROGRA~1\QGIS32~1.6\apps\Python39\lib\code.py", line 90, in runcode exec(code, self.locals) File "<input>", line 1, in <module> File "<string>", line 2, in <module> ImportError: cannot import name 'QgsNetworkAnalyzer' from 'qgis.analysis' (C:\PROGRA~1/QGIS32~1.6/apps/qgis-ltr/./python\qgis\analysis_init_.py)
    – lena
    Commented Jun 28, 2023 at 11:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.