29
29
30
30
from qgis .PyQt .QtGui import QIcon
31
31
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 ,
34
35
QgsGraphBuilder ,
35
36
QgsGraphAnalyzer
36
37
)
38
+ from qgis .utils import iface
37
39
38
40
from processing .core .GeoAlgorithm import GeoAlgorithm
41
+ from processing .core .GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
39
42
from processing .core .parameters import (ParameterVector ,
40
43
ParameterPoint ,
41
44
ParameterNumber ,
@@ -57,24 +60,25 @@ class ShortestPath(GeoAlgorithm):
57
60
START_POINT = 'START_POINT'
58
61
END_POINT = 'END_POINT'
59
62
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 '
63
66
DEFAULT_DIRECTION = 'DEFAULT_DIRECTION'
67
+ TOLERANCE = 'TOLERANCE'
64
68
PATH_LENGTH = 'PATH_LENGTH'
65
69
OUTPUT_LAYER = 'OUTPUT_LAYER'
66
70
67
71
def getIcon (self ):
68
72
return QIcon (os .path .join (pluginPath , 'images' , 'networkanalysis.png' ))
69
73
70
74
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
74
78
}
75
79
76
- self .UNITS = {0 : self .tr ('Meters' ),
77
- 1 : self .tr ('Kilometers' )
80
+ self .UNITS = {self .tr ('Meters' ): 1 ,
81
+ self .tr ('Kilometers' ): 1000
78
82
}
79
83
80
84
self .name , self .i18n_name = self .trAlgorithm ('Shortest path' )
@@ -88,21 +92,35 @@ def defineCharacteristics(self):
88
92
self .addParameter (ParameterPoint (self .END_POINT ,
89
93
self .tr ('End point' )))
90
94
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 )
106
124
107
125
self .addOutput (OutputNumber (self .PATH_LENGTH ,
108
126
self .tr ('Path length' )))
@@ -113,8 +131,70 @@ def defineCharacteristics(self):
113
131
def processAlgorithm (self , progress ):
114
132
layer = dataobjects .getObjectFromUri (
115
133
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