Thursday, 12 May 2016

qgis - 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[0]
tStop = tiedPoints[1]


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

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. enter image description here


and what i get in the attribute table (length and geom calculate with the field calculator) enter image description here


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[0]
tStop = tiedPoints[1]


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

No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...