2

I ask for your help with the PyQGIS API. Being a new user of GIS I would like to carry out an operation.

It is for me to look for the shortest path in a graph using the DIJKSTRA algorithm.

The code of the QGIS doc after some small adaptations works well except that I do not recover anything at the end if it is not a graphic plot. After the execution I would like to retrieve the shortest path found (the result) as an entity that I insert in a table and so on for possibly other shorter paths that I will calculate.

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

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)

pStart = QgsPoint(-0.835953, 0.15679)
pStop = QgsPoint(-1.1027, 0.699986)
tiedPoints = director.makeGraph(builder, [pStart, pStop])
graph = builder.graph()
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:
    p.append(graph.vertex(graph.arc(tree[curPos]).inVertex()).point())
    curPos = graph.arc(tree[curPos]).outVertex();
  p.append(tStart)
  rb = QgsRubberBand(qgis.utils.iface.mapCanvas())
  rb.setColor(Qt.red)
  for pnt in p:
    rb.addPoint(pnt)

May somebody help?

1 Answer 1

1

This applies for QGIS 2.18: You may first create a (memory) layer (if you don't already have one) and a data provider and add it to the registry and the layer list using the following code:

my_lyr = QgsVectorLayer('Linestring?crs=epsg:31468', 'network result', 'memory')
# 31468 is only an example, set the epsg code you require
my_lyr_dp = my_lyr.dataProvider()

root = QgsProject.instance().layerTreeRoot()
network_analysis_group = root.addGroup('Network results')

QgsMapLayerRegistry.instance().addMapLayer(my_lyr, False)
network_analysis_group.addLayer(my_lyr)

You need the data provider to add new features, so if you already have a layer you wish to add features to, you can e.g. select it in the legend and create a data provider by

selected_lyr = iface.activeLayer()
my_lyr_dp = selected_lyr.dataProvider() #cp. above

Then from the p in your code above (a list made of QgsPoint() entities) you can create a feature in your layer like

f = QgsFeature()
geom = QgsGeometry().fromPolyline(p) #this is your p
f.setGeometry(geom)
my_lyr_dp.addFeatures([f])
my_lyr.updateExtents()
iface.mapCanvas().refreshAllLayers()

If you want to 'clear' the layer (delete all previous network analysis results) you can do this by

fids = [f.id() for f in my_lyr.getFeatures()]
my_lyr_dp.deleteFeatures(fids)
my_lyr.updateExtents()
iface.mapCanvas().refreshAllLayers()

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.