Skip to content

Commit 0823bb4

Browse files
committedDec 13, 2016
[processing] adopt algorithm to changes in QGIS API
1 parent a60048c commit 0823bb4

File tree

2 files changed

+112
-31
lines changed

2 files changed

+112
-31
lines changed
 

‎python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@
184184
from .BasicStatistics import BasicStatisticsForField
185185
from .Heatmap import Heatmap
186186
from .Orthogonalize import Orthogonalize
187+
from .ShortestPath import ShortestPath
187188

188189
pluginPath = os.path.normpath(os.path.join(
189190
os.path.split(os.path.dirname(__file__))[0], os.pardir))
@@ -249,7 +250,7 @@ def __init__(self):
249250
ExtractSpecificNodes(), GeometryByExpression(), SnapGeometriesToLayer(),
250251
PoleOfInaccessibility(), CreateAttributeIndex(), DropGeometry(),
251252
BasicStatisticsForField(), RasterCalculator(), Heatmap(),
252-
Orthogonalize()
253+
Orthogonalize(), ShortestPath()
253254
]
254255

255256
if hasMatplotlib:

‎python/plugins/processing/algs/qgis/ShortestPath.py

Lines changed: 110 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@
2929

3030
from qgis.PyQt.QtGui import QIcon
3131

32-
from qgis.analysis import (QgsLineVectorLayerDirector,
33-
QgsDistanceArcProperter,
32+
from qgis.core import QgsWkbTypes, QgsFeature, QgsGeometry, QgsPoint
33+
from qgis.analysis import (QgsVectorLayerDirector,
34+
QgsNetworkDistanceStrategy,
3435
QgsGraphBuilder,
3536
QgsGraphAnalyzer
3637
)
38+
from qgis.utils import iface
3739

3840
from processing.core.GeoAlgorithm import GeoAlgorithm
41+
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
3942
from processing.core.parameters import (ParameterVector,
4043
ParameterPoint,
4144
ParameterNumber,
@@ -57,24 +60,25 @@ class ShortestPath(GeoAlgorithm):
5760
START_POINT = 'START_POINT'
5861
END_POINT = 'END_POINT'
5962
DIRECTION_FIELD = 'DIRECTION_FIELD'
60-
VALUE_DIRECT = 'VALUE_DIRECT'
61-
VALUE_REVERSED = 'VALUE_REVERSED'
62-
VALUE_BIDIRECTIONAL = 'VALUE_BIDIRECTIONAL'
63+
VALUE_FORWARD = 'VALUE_FORWARD'
64+
VALUE_BACKWARD = 'VALUE_BACKWARD'
65+
VALUE_BOTH = 'VALUE_BOTH'
6366
DEFAULT_DIRECTION = 'DEFAULT_DIRECTION'
67+
TOLERANCE = 'TOLERANCE'
6468
PATH_LENGTH = 'PATH_LENGTH'
6569
OUTPUT_LAYER = 'OUTPUT_LAYER'
6670

6771
def getIcon(self):
6872
return QIcon(os.path.join(pluginPath, 'images', 'networkanalysis.png'))
6973

7074
def defineCharacteristics(self):
71-
self.DIRECTIONS = {1: self.tr('Direct direction'),
72-
2: self.tr('Inverse direction'),
73-
3: self.tr('Bidirectional')
75+
self.DIRECTIONS = {self.tr('Forward direction'): QgsVectorLayerDirector.DirectionForward,
76+
self.tr('Backward direction'): QgsVectorLayerDirector.DirectionForward,
77+
self.tr('Both directions'): QgsVectorLayerDirector.DirectionForward
7478
}
7579

76-
self.UNITS = {0: self.tr('Meters'),
77-
1: self.tr('Kilometers')
80+
self.UNITS = {self.tr('Meters'): 1,
81+
self.tr('Kilometers'): 1000
7882
}
7983

8084
self.name, self.i18n_name = self.trAlgorithm('Shortest path')
@@ -88,21 +92,35 @@ def defineCharacteristics(self):
8892
self.addParameter(ParameterPoint(self.END_POINT,
8993
self.tr('End point')))
9094

91-
self.addParameter(ParameterTableField(self.DIRECTION_FIELD,
92-
self.tr('Road direction field'),
93-
self.INPUT_VECTOR))
94-
self.addParameter(ParameterString(self.VALUE_DIRECT,
95-
self.tr('Value for direct direction road'),
96-
''))
97-
self.addParameter(ParameterString(self.VALUE_REVERSED,
98-
self.tr('Value for reversed direction road'),
99-
''))
100-
self.addParameter(ParameterString(self.VALUE_BIDIRECTIONAL,
101-
self.tr('Value for bidirectional road'),
102-
''))
103-
self.addParameter(ParameterSelection(self.DEFAULT_DIRECTION,
104-
self.tr('Default road direction'),
105-
list(self.DIRECTIONS.keys())))
95+
params = []
96+
params.append(ParameterTableField(self.DIRECTION_FIELD,
97+
self.tr('Road direction field'),
98+
self.INPUT_VECTOR,
99+
optional=True))
100+
params.append(ParameterString(self.VALUE_FORWARD,
101+
self.tr('Value for forward direction'),
102+
'',
103+
optional=True))
104+
params.append(ParameterString(self.VALUE_BACKWARD,
105+
self.tr('Value for backward direction'),
106+
'',
107+
optional=True))
108+
params.append(ParameterString(self.VALUE_BOTH,
109+
self.tr('Value for both directions'),
110+
'',
111+
optional=True))
112+
params.append(ParameterSelection(self.DEFAULT_DIRECTION,
113+
self.tr('Default road direction'),
114+
list(self.DIRECTIONS.keys()),
115+
default=2))
116+
params.append(ParameterNumber(self.TOLERANCE,
117+
self.tr('Topology tolerance'),
118+
0.0, 0.0, 99999999.999999))
119+
120+
121+
for p in params:
122+
p.isAdvanced = True
123+
self.addParameter(p)
106124

107125
self.addOutput(OutputNumber(self.PATH_LENGTH,
108126
self.tr('Path length')))
@@ -113,8 +131,70 @@ def defineCharacteristics(self):
113131
def processAlgorithm(self, progress):
114132
layer = dataobjects.getObjectFromUri(
115133
self.getParameterValue(self.INPUT_VECTOR))
116-
fielName = self.getParameterValue(self.RASTER_BAND)
117-
columnPrefix = self.getParameterValue(self.COLUMN_PREFIX)
118-
st = self.getParameterValue(self.STATISTICS)
119-
120-
vectorLayer = dataobjects.getObjectFromUri(vectorPath)
134+
startPoint = self.getParameterValue(self.START_POINT)
135+
endPoint = self.getParameterValue(self.END_POINT)
136+
137+
fieldName = self.getParameterValue(self.DIRECTION_FIELD)
138+
forwardValue = self.getParameterValue(self.VALUE_FORWARD)
139+
backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
140+
bothValue = self.getParameterValue(self.VALUE_BOTH)
141+
defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
142+
tolerance = self.getParameterValue(self.TOLERANCE)
143+
144+
writer = self.getOutputFromName(
145+
self.OUTPUT_LAYER).getVectorWriter(
146+
layer.fields().toList(),
147+
QgsWkbTypes.LineString,
148+
layer.crs())
149+
150+
tmp = startPoint.split(',')
151+
startPoint = QgsPoint(float(tmp[0]), float(tmp[1]))
152+
tmp = endPoint.split(',')
153+
endPoint = QgsPoint(float(tmp[0]), float(tmp[1]))
154+
field = -1
155+
if fieldName is not None:
156+
field = layer.fields().lookupField(fieldName)
157+
158+
director = QgsVectorLayerDirector(layer,
159+
field,
160+
forwardValue,
161+
backwardValue,
162+
bothValue,
163+
defaultDirection)
164+
strategy = QgsNetworkDistanceStrategy()
165+
director.addStrategy(strategy)
166+
builder = QgsGraphBuilder(iface.mapCanvas().mapSettings().destinationCrs(),
167+
iface.mapCanvas().hasCrsTransformEnabled(),
168+
tolerance)
169+
progress.setInfo(self.tr('Building graph...'))
170+
snappedPoints = director.makeGraph(builder, [startPoint, endPoint])
171+
172+
progress.setInfo(self.tr('Calculating shortest path...'))
173+
graph = builder.graph()
174+
idxStart = graph.findVertex(snappedPoints[0])
175+
idxEnd = graph.findVertex(snappedPoints[1])
176+
177+
tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
178+
if tree[idxEnd] == -1:
179+
raise GeoAlgorithmExecutionException(
180+
self.tr('There is no route from start point to end point.'))
181+
182+
route = []
183+
cost = 0.0
184+
current = idxEnd
185+
while current != idxStart:
186+
cost += graph.edge(tree[current]).cost(0)
187+
route.append(graph.vertex(graph.edge(tree[current]).inVertex()).point())
188+
current = graph.edge(tree[current]).outVertex()
189+
190+
route.append(snappedPoints[0])
191+
route.reverse()
192+
193+
self.setOutputValue(self.PATH_LENGTH, cost)
194+
195+
progress.setInfo(self.tr('Writting results...'))
196+
geom = QgsGeometry.fromPolyline(route)
197+
feat = QgsFeature()
198+
feat.setGeometry(geom)
199+
writer.addFeature(feat)
200+
del writer

0 commit comments

Comments
 (0)
Please sign in to comment.