Страница 1 из 1
Анализ сетей
Добавлено: 04 ноя 2015, 18:48
Евгений Брусникин
Добрый день, уважаемое сообщество. Столкнулся с проблемой реализации (в виде расширения) алгоритма сетевого анализа из библиотеки QGIS network-analysis.
В статье
http://gis-lab.info/qa/qgis-network-analysis-lib.html, дан алгоритм такого анализа. Ввиду моего плохого знания питона, прошу помощи с решением проблемы, как это реализовать в виде работающего скрипта. Думаю, многим будет полезно.
Алгоритм должен находить оптимальный маршрут от одной из вершин графа до всех остальных. Выбор начальной вершины, задается щелчком мыши. Выдаваемый результат должен отображаться в виде отдельного слоя.
Код: Выделить всё
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)
Re: Анализ сетей
Добавлено: 04 ноя 2015, 19:04
Евгений Брусникин
есть еще некий код, ShortestPath, но он, к сожалению не работает на qgis>1.8
Код: Выделить всё
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
import qgis.utils
from qgis.networkanalysis import *
from packageUI import PackageUI
#initialize Qt resources from file resouces.py
import resources
class networking:
def __init__(self, iface):
self.iface=iface
self.canvas=self.iface.mapCanvas()
self.pin=QgsMapToolEmitPoint(self.canvas)
self.haveDotLayer=False
self.userPoints=[]
self.havePLayer=False
def initGui(self):
#create action that will start plugin configuration
self.action=QAction(QIcon(":/plugins/ShortestPath/pin.png"), "Find Shortest Path", self.iface.mainWindow())
self.action.setWhatsThis("Configuration for test plugin")
self.action.setStatusTip("Find the Shortest Path")
QObject.connect(self.action, SIGNAL("triggered()"),self.run)
#add toolbar button and menu item
self.iface.addToolBarIcon(self.action)
self.iface.addPluginToMenu("&Find Shortest Path", self.action)
#connect to signal renderComplete which is emitted when canvas rendering is done
QObject.connect(self.pin, SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"), self.placePin)
def unload(self):
#remove the plugin menu item and icon
self.iface.removePluginMenu("&Add Two Points", self.action)
self.iface.removeToolBarIcon(self.action)
#disconnect from signal of the canvas
QObject.disconnect(self.pin,SIGNAL("canvasClicked(const QgsPoint &, Qt::MouseButton)"),self.placePin)
def run(self):
#create and show a configuration dialog or something similar
print "NAPlug: run called"
self.myVLayer=self.iface.activeLayer()
if self.myVLayer is None:
reply=QMessageBox.warning(self.iface.mainWindow(),
"Error",
"Please load a vector line Layer")
else:
#Call the UI Dialog
self.myCrs=self.myVLayer.crs()
self.dialog=PackageUI()
#Show the dialog for the information
self.dialog.show()
QObject.connect(self.dialog.ui.btnRouting,
SIGNAL("clicked()"),
self.act)
#Change the mouse cursor to pinTool so that user can place points on map
self.canvas.setMapTool(self.pin)
def createPLayer(self):
self.pLayer=QgsVectorLayer("Point","Pins","memory")
self.provider=self.pLayer.dataProvider()
self.provider.addAttributes([
QgsField("id",QVariant.Int),
QgsField("x",QVariant.Double),
QgsField("y",QVariant.Double)
])
self.pLayer.updateFieldMap()
QgsMapLayerRegistry.instance().addMapLayer(self.pLayer)
result=QObject.connect(self.pLayer, SIGNAL("layerDeleted()"),self.DeletePLayer)
self.havePLayer=True
def DeletePLayer(self):
self.havePLayer=False
#Place Pins on the map
def placePin(self, point):
x=point.x()
y=point.y()
self.userPoints.append([x,y])
if self.havePLayer==False:
self.createPLayer()
fc=int(self.provider.featureCount())
feature=QgsFeature()
feature.setGeometry(QgsGeometry.fromPoint(point))
feature.setAttributeMap( {
0 : QVariant(fc),
1 : QVariant(x),
2 : QVariant(y)})
self.provider.addFeatures([feature])
self.pLayer.updateExtents()
self.pLayer.setCacheImage(None)
self.canvas.refresh()
def act(self):
print "act is running"
print self.userPoints
self.pointsCount=len(self.userPoints)
print str(self.pointsCount)
for i in range (self.pointsCount-1):
self.pathGraphBuild(self.userPoints[i],self.userPoints[i+1],(i+1))
def pathGraphBuild(self,startPoint,endPoint,pid):
self.director=QgsLineVectorLayerDirector(self.myVLayer,-1,'','','',3)
self.properter=QgsDistanceArcProperter()
self.director.addProperter(self.properter)
self.builder=QgsGraphBuilder(self.myCrs)
#Get the Start and End Points for each two pair of points
sx=startPoint[0]
sy=startPoint[1]
ex=endPoint[0]
ey=endPoint[1]
sp=QgsPoint(sx,sy)
ep=QgsPoint(ex,ey)
tiedPoints=self.director.makeGraph(self.builder,[sp,ep])
self.graph=self.builder.graph()
tStart=tiedPoints[0]
tEnd=tiedPoints[1]
idStart=self.graph.findVertex(tStart)
idEnd=self.graph.findVertex(tEnd)
(tree, cost)=QgsGraphAnalyzer.dijkstra(self.graph, idStart, 0)
if tree[idEnd]==-1:
print "Path not found"
else:
p=[]
curPos=idEnd
while curPos != idStart:
p.append(self.graph.vertex(self.graph.arc(tree[curPos]).inVertex()).point())
curPos=self.graph.arc(tree[curPos]).outVertex();
p.append(tStart)
rb=QgsRubberBand(self.iface.mapCanvas())
rb.setColor(Qt.red)
for pnt in p:
rb.addPoint(pnt)
Re: Анализ сетей
Добавлено: 04 ноя 2015, 20:36
Евгений Брусникин
Вроде все получилось. Вечером залью архив. У кого будет время - потестируйте, пожалуйста.
Может кому пригодится

Re: Анализ сетей
Добавлено: 09 ноя 2015, 20:03
Евгений Брусникин
Есть кто может помочь, с созданием векторного слоя из построенного графа? как реализовать?
Re: Анализ сетей
Добавлено: 09 ноя 2015, 21:43
Дмитрий Барышников
А у вас есть собственно геометрии (вектора)?
Ведь граф - это узлы и ребра - некие идентификаторы и не более. А вот к чему они относятся - зависит от вас.
Re: Анализ сетей
Добавлено: 09 ноя 2015, 21:51
Евгений Брусникин
Дмитрий Барышников писал(а):А у вас есть собственно геометрии (вектора)?
Код: Выделить всё
def pathGraphBuild(self,startPoint,endPoint):
self.director=QgsLineVectorLayerDirector(self.myVLayer,5,"2","0","1",1)
self.properter=QgsDistanceArcProperter()
self.director.addProperter(self.properter)
self.builder=QgsGraphBuilder(self.myCrs)
sx=startPoint[0]
sy=startPoint[1]
sp=QgsPoint(sx,sy)
pStart = self.userPoints[0]
tiedPoint = self.director.makeGraph(self.builder,[sp])
pStart = tiedPoint[0]
self.graph = self.builder.graph()
idStart = self.graph.findVertex( pStart )
( tree, costs ) = QgsGraphAnalyzer.dijkstra( self.graph, idStart, 0 )
for edgeId in tree:
if edgeId == -1:
continue
rb = QgsRubberBand( qgis.utils.iface.mapCanvas() )
rb.setColor ( Qt.red )
rb.setWidth (4)
rb.addPoint ( self.graph.vertex( self.graph.arc( edgeId ).inVertex() ).point() )
rb.addPoint ( self.graph.vertex( self.graph.arc( edgeId ).outVertex() ).point() )
Это код класса, отвечающий за построение графа.
У него есть идентификаторы начального узла и идентификаторы сегментов: idStart и edgeID. Также имеются point и line слои. По линейному слою строится граф, а точечный слой, это его узлы
Re: Анализ сетей
Добавлено: 10 ноя 2015, 21:33
Дмитрий Барышников
На сколько я понимаю в QGIS один тип геометрии - один слой. Так что вы можете выбранные линии и точки в 2 слоя записать. Можно попробовать записать в Geometry Collection - типа sqlite - но потом в чем с этим работать?
Re: Анализ сетей
Добавлено: 13 ноя 2015, 17:43
5Nap
посмотрите pgRouting. Он ровно для анализа сетей и сделан. вот здесь:
http://anitagraser.com/2013/07/07/publi ... pgrouting/ есть начальное описание работы. Как-то тестил - маршрут строит, выборку точек по расстоянию делает.
Re: Анализ сетей
Добавлено: 13 ноя 2015, 19:28
Дмитрий Барышников
QGIS никак не связан с pgRouting. Это можно и
OSRM,
grapghhopper,
gdal GNM смотреть. Да и ArcGIS geography model до кучи.