# How can I calculate the shortest path between 2 points and insert the line result as a feature in a layer?

I try to make a script to find the shortest path between two bridges in a network. The goal is to get after each calculation a line that I insert as an entity in a predefined layer. For now I do well to make calculations but when I change the coordinates to make another calculation nothing appears even if I heard the new entity that is inserted in my table.

``````from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from qgis.networkanalysis import *

#building the graph**
vl = qgis.utils.iface.mapCanvas().currentLayer()
director = QgsLineVectorLayerDirector(vl, -1, '', '', '', 3)
properter = QgsDistanceArcProperter()
director.addProperter(properter)
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()
builder = QgsGraphBuilder(crs)

#coordinates of the Start point and endPoint**
pStart = QgsPoint(4.820590,45.838684)
pStop = QgsPoint(4.822459,45.837933)
tiedPoints = director.makeGraph(builder, [pStart, pStop])
graph = builder.graph()

#Calculation of the shortest path**
tStart = tiedPoints
tStop = tiedPoints

idStart = graph.findVertex(tStart)
idStop = graph.findVertex(tStop)

(tree, cost) = QgsGraphAnalyzer.dijkstra(graph, idStart, 0)

if tree[idStop] == -1:
print "Path not found"
else:
p = []
curPos = idStop
while curPos != idStart:
pnt = graph.vertex(graph.arc(tree[curPos]).inVertex()).point()

p.append(pnt)

curPos = graph.arc(tree[curPos]).outVertex()

p.append(tStart)

# Object generated after the calculation a qgsRubberBand**
rb = QgsRubberBand(qgis.utils.iface.mapCanvas())
rb.setColor(Qt.red)

#I build here a polyline based on the points in the p[] array
geom = QgsGeometry.fromPolyline(p)

for pnt in p:
rb.addPoint(pnt)

# I add here my result in a memory layer called cable and i want to do it for every feature i get after transforming the qgsrubberband object

v_layer = None
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
if layer.name() == 'cable':
v_layer = layer
if v_layer is None:
v_layer = QgsVectorLayer("LineString", "cable", "memory")
v_layer.addAttribute(QgsField("id", QVariant.String))
v_layer.addAttribute(QgsField("type", QVariant.String))
QgsMapLayerRegistry.instance().addMapLayers([v_layer])

pr = v_layer.dataProvider()
v_layer.startEditing()

seg = QgsFeature()
seg.setGeometry(geom)
pr.addFeatures( [seg] )

v_layer.commitChanges()
``````
• I just realized that nothing was displayed because my script inserts each time the same entity in my table and not the new line created. By calculating the length of the fields I saw that it was always the same – hounto Jul 4 '17 at 12:08
• Can you comment your code step by step with # so we can understand what you are trying to do? thank's – YoLecomte Jul 4 '17 at 13:35
• I have already comment the code. tks – hounto Jul 4 '17 at 13:46
• Why do you use a QgsRubberBand? – YoLecomte Jul 4 '17 at 14:29

## 1 Answer

Your code is working for me without problem. I've try it in the QGIS python console.

When i run it with a first start and end point, i get the red line in the cable layer then i run the script with others start and end point and i get the yellow line added in the same layer. and what i get in the attribute table (length and geom calculate with the field calculator) I just remove the part of the code using QgsRubberBand as it was useless. The code I used:

``````from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from qgis.networkanalysis import *

#building the graph**
vl = qgis.utils.iface.mapCanvas().currentLayer()
director = QgsLineVectorLayerDirector(vl, -1, '', '', '', 3)
properter = QgsDistanceArcProperter()
director.addProperter(properter)
crs = qgis.utils.iface.mapCanvas().mapRenderer().destinationCrs()
builder = QgsGraphBuilder(crs)

#coordinates of the Start point and endPoint**
pStart = QgsPoint(-1.041,0.916)
pStop = QgsPoint(-0.813,0.152)
tiedPoints = director.makeGraph(builder, [pStart, pStop])
graph = builder.graph()

#Calculation of the shortest path**
tStart = tiedPoints
tStop = tiedPoints

idStart = graph.findVertex(tStart)
idStop = graph.findVertex(tStop)

(tree, cost) = QgsGraphAnalyzer.dijkstra(graph, idStart, 0)

if tree[idStop] == -1:
print "Path not found"
else:
p = []
curPos = idStop
while curPos != idStart:
pnt = graph.vertex(graph.arc(tree[curPos]).inVertex()).point()

p.append(pnt)

curPos = graph.arc(tree[curPos]).outVertex()

p.append(tStart)

#I build here a polyline based on the points in the p[] array
geom = QgsGeometry.fromPolyline(p)

# I add here my result in a memory layer called cable and i want to do it for every feature i get after transforming the qgsrubberband object

v_layer = None
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
if layer.name() == 'cable':
v_layer = layer
if v_layer is None:
v_layer = QgsVectorLayer("LineString", "cable", "memory")
v_layer.addAttribute(QgsField("id", QVariant.String))
v_layer.addAttribute(QgsField("type", QVariant.String))
QgsMapLayerRegistry.instance().addMapLayers([v_layer])

pr = v_layer.dataProvider()
v_layer.startEditing()

seg = QgsFeature()
seg.setGeometry(geom)
pr.addFeatures( [seg] )

v_layer.commitChanges()
``````
• I used your code but still get the same problem. i dn't understnd why? which coordinates of points du yo use? – hounto Jul 4 '17 at 17:15
• I just change the pStart and pStop coordinate ans run the script again – YoLecomte Jul 4 '17 at 17:46
• It is exactly what i did.i get the feature but they are not displayed and have the same lenght – hounto Jul 4 '17 at 18:04
• Are you sure your cable layer is not below other? This may explain the fact that nothing is display. The two length you're suppose to get are really différent? Add screenshots might help... – YoLecomte Jul 4 '17 at 18:31
• Sometimes it works sometimes it does not. Sometimes i get Dum error. i will try untill tommorow and let you know. How can i do if i want to get the start point and the end point just by clicking on the screen. how can i build a useful plug in using this script. Do you get some idea? thanks – hounto Jul 4 '17 at 19:01