19
19
20
20
import com .carrotsearch .hppc .IntArrayList ;
21
21
import com .carrotsearch .hppc .cursors .IntCursor ;
22
- import com .graphhopper .routing .util .*;
22
+ import com .graphhopper .routing .util .CarFlagEncoder ;
23
+ import com .graphhopper .routing .util .EncodingManager ;
24
+ import com .graphhopper .routing .util .FlagEncoder ;
25
+ import com .graphhopper .routing .util .TraversalMode ;
23
26
import com .graphhopper .routing .weighting .FastestWeighting ;
24
27
import com .graphhopper .routing .weighting .TurnWeighting ;
25
28
import com .graphhopper .routing .weighting .Weighting ;
28
31
import com .graphhopper .storage .GraphHopperStorage ;
29
32
import com .graphhopper .storage .TurnCostExtension ;
30
33
import com .graphhopper .util .EdgeIteratorState ;
34
+ import org .junit .Assume ;
31
35
import org .junit .Test ;
32
36
import org .junit .runner .RunWith ;
33
37
import org .junit .runners .Parameterized ;
@@ -55,6 +59,8 @@ public EdgeBasedRoutingAlgorithmTest(String algo) {
55
59
@ Parameters (name = "{0}" )
56
60
public static Collection <Object []> configs () {
57
61
return Arrays .asList (new Object [][]{
62
+ // todo: make this test run also for edge-based CH or otherwise make sure time calculation is tested also for edge-based CH (at the moment it will fail!)
63
+ // todo: make this test run also for ALT or otherwise make sure time calculation is tested also for ALT (at the moment it will fail?!)
58
64
{DIJKSTRA },
59
65
{DIJKSTRA_BI },
60
66
{ASTAR },
@@ -81,7 +87,7 @@ public static void initGraph(Graph g) {
81
87
g .edge (6 , 7 , 1 , true );
82
88
}
83
89
84
- EncodingManager createEncodingManager (boolean restrictedOnly ) {
90
+ private EncodingManager createEncodingManager (boolean restrictedOnly ) {
85
91
if (restrictedOnly )
86
92
carEncoder = new CarFlagEncoder (5 , 5 , 1 );
87
93
else
@@ -95,38 +101,36 @@ public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
95
101
return new RoutingAlgorithmFactorySimple ().createAlgo (g , opts );
96
102
}
97
103
98
- protected GraphHopperStorage createStorage (EncodingManager em ) {
104
+ private GraphHopperStorage createStorage (EncodingManager em ) {
99
105
return new GraphBuilder (em ).create ();
100
106
}
101
107
102
- private void initTurnRestrictions (Graph g , TurnCostExtension tcs , TurnCostEncoder tEncoder ) {
103
- long tflags = tEncoder .getTurnFlags (true , 0 );
104
-
108
+ private void initTurnRestrictions (Graph g , TurnCostExtension tcs ) {
105
109
// only forward from 2-3 to 3-4 => limit 2,3->3,6 and 2,3->3,1
106
- tcs . addTurnInfo ( getEdge ( g , 2 , 3 ). getEdge () , 3 , getEdge ( g , 3 , 6 ). getEdge (), tflags );
107
- tcs . addTurnInfo ( getEdge ( g , 2 , 3 ). getEdge () , 3 , getEdge ( g , 3 , 1 ). getEdge (), tflags );
110
+ addTurnRestriction ( g , tcs , 2 , 3 , 6 );
111
+ addTurnRestriction ( g , tcs , 2 , 3 , 1 );
108
112
109
113
// only right from 5-2 to 2-3 => limit 5,2->2,0
110
- tcs . addTurnInfo ( getEdge ( g , 5 , 2 ). getEdge () , 2 , getEdge ( g , 2 , 0 ). getEdge (), tflags );
114
+ addTurnRestriction ( g , tcs , 5 , 2 , 0 );
111
115
112
116
// only right from 7-6 to 6-3 => limit 7,6->6,5
113
- tcs . addTurnInfo ( getEdge ( g , 7 , 6 ). getEdge () , 6 , getEdge ( g , 6 , 5 ). getEdge (), tflags );
117
+ addTurnRestriction ( g , tcs , 7 , 6 , 5 );
114
118
115
119
// no 5-6 to 6-3
116
- tcs . addTurnInfo ( getEdge ( g , 5 , 6 ). getEdge () , 6 , getEdge ( g , 6 , 3 ). getEdge (), tflags );
120
+ addTurnRestriction ( g , tcs , 5 , 6 , 3 );
117
121
// no 4-3 to 3-1
118
- tcs . addTurnInfo ( getEdge ( g , 4 , 3 ). getEdge () , 3 , getEdge ( g , 3 , 1 ). getEdge (), tflags );
122
+ addTurnRestriction ( g , tcs , 4 , 3 , 1 );
119
123
// no 4-3 to 3-2
120
- tcs . addTurnInfo ( getEdge ( g , 4 , 3 ). getEdge () , 3 , getEdge ( g , 3 , 2 ). getEdge (), tflags );
124
+ addTurnRestriction ( g , tcs , 4 , 3 , 2 );
121
125
122
126
// no u-turn at 6-7
123
- tcs . addTurnInfo ( getEdge ( g , 6 , 7 ). getEdge () , 7 , getEdge ( g , 7 , 6 ). getEdge (), tflags );
127
+ addTurnRestriction ( g , tcs , 6 , 7 , 6 );
124
128
125
129
// no u-turn at 3-6
126
- tcs . addTurnInfo ( getEdge ( g , 3 , 6 ). getEdge () , 6 , getEdge ( g , 6 , 3 ). getEdge (), tflags );
130
+ addTurnRestriction ( g , tcs , 3 , 6 , 3 );
127
131
}
128
132
129
- Weighting createWeighting (FlagEncoder encoder , TurnCostExtension tcs , double uTurnCosts ) {
133
+ private Weighting createWeighting (FlagEncoder encoder , TurnCostExtension tcs , double uTurnCosts ) {
130
134
return new TurnWeighting (new FastestWeighting (encoder ), tcs ).setDefaultUTurnCost (uTurnCosts );
131
135
}
132
136
@@ -135,52 +139,93 @@ public void testBasicTurnRestriction() {
135
139
GraphHopperStorage g = createStorage (createEncodingManager (true ));
136
140
initGraph (g );
137
141
TurnCostExtension tcs = (TurnCostExtension ) g .getExtension ();
138
- initTurnRestrictions (g , tcs , carEncoder );
142
+ initTurnRestrictions (g , tcs );
139
143
Path p = createAlgo (g , AlgorithmOptions .start ().
140
144
weighting (createWeighting (carEncoder , tcs , 40 )).
141
145
traversalMode (TraversalMode .EDGE_BASED_2DIR ).build ()).
142
146
calcPath (5 , 1 );
143
- assertEquals (IntArrayList .from (new int []{ 5 , 2 , 3 , 4 , 7 , 6 , 3 , 1 } ), p .calcNodes ());
147
+ assertEquals (IntArrayList .from (5 , 2 , 3 , 4 , 7 , 6 , 3 , 1 ), p .calcNodes ());
144
148
145
149
// test 7-6-5 and reverse
146
150
p = createAlgo (g , AlgorithmOptions .start ().
147
151
weighting (createWeighting (carEncoder , tcs , 40 )).
148
152
traversalMode (TraversalMode .EDGE_BASED_1DIR ).build ()).
149
153
calcPath (5 , 7 );
150
- assertEquals (IntArrayList .from (new int []{ 5 , 6 , 7 } ), p .calcNodes ());
154
+ assertEquals (IntArrayList .from (5 , 6 , 7 ), p .calcNodes ());
151
155
152
156
p = createAlgo (g , AlgorithmOptions .start ().
153
157
weighting (createWeighting (carEncoder , tcs , 40 )).
154
158
traversalMode (TraversalMode .EDGE_BASED_1DIR ).build ()).
155
159
calcPath (7 , 5 );
156
- assertEquals (IntArrayList .from (new int []{7 , 6 , 3 , 2 , 5 }), p .calcNodes ());
160
+ assertEquals (IntArrayList .from (7 , 6 , 3 , 2 , 5 ), p .calcNodes ());
161
+ }
162
+
163
+ @ Test
164
+ public void testTurnCosts_timeCalculation () {
165
+ // 0 - 1 - 2 - 3 - 4
166
+ GraphHopperStorage g = createStorage (createEncodingManager (false ));
167
+ TurnCostExtension tcs = (TurnCostExtension ) g .getExtension ();
168
+ final int distance = 100 ;
169
+ final int turnCosts = 2 ;
170
+ g .edge (0 , 1 , distance , true );
171
+ g .edge (1 , 2 , distance , true );
172
+ g .edge (2 , 3 , distance , true );
173
+ g .edge (3 , 4 , distance , true );
174
+ addTurnCost (g , tcs , turnCosts , 1 , 2 , 3 );
175
+
176
+ AlgorithmOptions opts = AlgorithmOptions .start ()
177
+ .weighting (createWeighting (carEncoder , tcs , 40 ))
178
+ .traversalMode (TraversalMode .EDGE_BASED_2DIR )
179
+ .build ();
180
+
181
+ {
182
+ // simple case where turn cost is encountered during forward search
183
+ Path p14 = createAlgo (g , opts ).calcPath (1 , 4 );
184
+ assertDistTimeWeight (p14 , 3 , distance , 6 , turnCosts );
185
+ assertEquals (20 , p14 .getWeight (), 1.e-6 );
186
+ assertEquals (20000 , p14 .getTime ());
187
+ }
188
+
189
+ {
190
+ // this test is more involved for bidir algos: the turn costs have to be taken into account also at the
191
+ // node where fwd and bwd searches meet
192
+ Path p04 = createAlgo (g , opts ).calcPath (0 , 4 );
193
+ assertDistTimeWeight (p04 , 4 , distance , 6 , turnCosts );
194
+ assertEquals (26 , p04 .getWeight (), 1.e-6 );
195
+ assertEquals (26000 , p04 .getTime ());
196
+ }
197
+ }
198
+
199
+ private void assertDistTimeWeight (Path path , int numEdges , double distPerEdge , double weightPerEdge , int turnCost ) {
200
+ assertEquals ("wrong distance" , numEdges * distPerEdge , path .getDistance (), 1.e-6 );
201
+ assertEquals ("wrong weight" , numEdges * weightPerEdge + turnCost , path .getWeight (), 1.e-6 );
202
+ assertEquals ("wrong time" , 1000 * (numEdges * weightPerEdge + turnCost ), path .getTime (), 1.e-6 );
157
203
}
158
204
159
205
160
- private void blockNode3 (Graph g , TurnCostExtension tcs , TurnCostEncoder tEncoder ) {
206
+ private void blockNode3 (Graph g , TurnCostExtension tcs ) {
161
207
// Totally block this node (all 9 turn relations)
162
- final long BLOCK = tEncoder .getTurnFlags (true , 0 );
163
- tcs .addTurnInfo (getEdge (g , 2 , 3 ).getEdge (), 3 , getEdge (g , 3 , 1 ).getEdge (), BLOCK );
164
- tcs .addTurnInfo (getEdge (g , 2 , 3 ).getEdge (), 3 , getEdge (g , 3 , 4 ).getEdge (), BLOCK );
165
- tcs .addTurnInfo (getEdge (g , 4 , 3 ).getEdge (), 3 , getEdge (g , 3 , 1 ).getEdge (), BLOCK );
166
- tcs .addTurnInfo (getEdge (g , 4 , 3 ).getEdge (), 3 , getEdge (g , 3 , 2 ).getEdge (), BLOCK );
167
- tcs .addTurnInfo (getEdge (g , 6 , 3 ).getEdge (), 3 , getEdge (g , 3 , 1 ).getEdge (), BLOCK );
168
- tcs .addTurnInfo (getEdge (g , 6 , 3 ).getEdge (), 3 , getEdge (g , 3 , 4 ).getEdge (), BLOCK );
169
- tcs .addTurnInfo (getEdge (g , 1 , 3 ).getEdge (), 3 , getEdge (g , 3 , 6 ).getEdge (), BLOCK );
170
- tcs .addTurnInfo (getEdge (g , 1 , 3 ).getEdge (), 3 , getEdge (g , 3 , 2 ).getEdge (), BLOCK );
171
- tcs .addTurnInfo (getEdge (g , 1 , 3 ).getEdge (), 3 , getEdge (g , 3 , 4 ).getEdge (), BLOCK );
208
+ addTurnRestriction (g , tcs , 2 , 3 , 1 );
209
+ addTurnRestriction (g , tcs , 2 , 3 , 4 );
210
+ addTurnRestriction (g , tcs , 4 , 3 , 1 );
211
+ addTurnRestriction (g , tcs , 4 , 3 , 2 );
212
+ addTurnRestriction (g , tcs , 6 , 3 , 1 );
213
+ addTurnRestriction (g , tcs , 6 , 3 , 4 );
214
+ addTurnRestriction (g , tcs , 1 , 3 , 6 );
215
+ addTurnRestriction (g , tcs , 1 , 3 , 2 );
216
+ addTurnRestriction (g , tcs , 1 , 3 , 4 );
172
217
}
173
218
174
219
@ Test
175
220
public void testBlockANode () {
176
221
GraphHopperStorage g = createStorage (createEncodingManager (true ));
177
222
initGraph (g );
178
223
TurnCostExtension tcs = (TurnCostExtension ) g .getExtension ();
179
- blockNode3 (g , tcs , carEncoder );
180
- for (int i = 0 ; i <= 7 ; i ++) {
181
- if (i == 3 ) continue ;
182
- for (int j = 0 ; j <= 7 ; j ++) {
183
- if (j == 3 ) continue ;
224
+ blockNode3 (g , tcs );
225
+ for (int i = 0 ; i <= 7 ; i ++) {
226
+ if (i == 3 ) continue ;
227
+ for (int j = 0 ; j <= 7 ; j ++) {
228
+ if (j == 3 ) continue ;
184
229
Path p = createAlgo (g , AlgorithmOptions .start ().
185
230
weighting (createWeighting (carEncoder , tcs , 40 )).
186
231
traversalMode (TraversalMode .EDGE_BASED_2DIR ).build ()).
@@ -199,31 +244,29 @@ public void testUTurns() {
199
244
initGraph (g );
200
245
TurnCostExtension tcs = (TurnCostExtension ) g .getExtension ();
201
246
202
- long tflags = carEncoder .getTurnFlags (true , 0 );
203
-
204
247
// force u-turn via lowering the cost for it
205
248
EdgeIteratorState e3_6 = getEdge (g , 3 , 6 );
206
249
e3_6 .setDistance (0.1 );
207
250
getEdge (g , 3 , 2 ).setDistance (864 );
208
251
getEdge (g , 1 , 0 ).setDistance (864 );
209
252
210
- tcs . addTurnInfo ( getEdge ( g , 7 , 6 ). getEdge () , 6 , getEdge ( g , 6 , 5 ). getEdge (), tflags );
211
- tcs . addTurnInfo ( getEdge ( g , 4 , 3 ). getEdge () , 3 , e3_6 . getEdge (), tflags );
253
+ addTurnRestriction ( g , tcs , 7 , 6 , 5 );
254
+ addTurnRestriction ( g , tcs , 4 , 3 , 6 );
212
255
AlgorithmOptions opts = AlgorithmOptions .start ().
213
256
weighting (createWeighting (carEncoder , tcs , 50 )).
214
257
traversalMode (TraversalMode .EDGE_BASED_2DIR_UTURN ).build ();
215
258
Path p = createAlgo (g , opts ).calcPath (7 , 5 );
216
259
217
- assertEquals (IntArrayList .from (new int []{ 7 , 6 , 3 , 6 , 5 } ), p .calcNodes ());
260
+ assertEquals (IntArrayList .from (7 , 6 , 3 , 6 , 5 ), p .calcNodes ());
218
261
219
262
// no u-turn for 6-3
220
263
opts = AlgorithmOptions .start ().
221
264
weighting (createWeighting (carEncoder , tcs , 100 )).
222
265
traversalMode (TraversalMode .EDGE_BASED_2DIR_UTURN ).build ();
223
- tcs . addTurnInfo ( getEdge ( g , 6 , 3 ). getEdge () , 3 , getEdge ( g , 3 , 6 ). getEdge (), tflags );
266
+ addTurnRestriction ( g , tcs , 6 , 3 , 6 );
224
267
p = createAlgo (g , opts ).calcPath (7 , 5 );
225
268
226
- assertEquals (IntArrayList .from (new int []{ 7 , 6 , 3 , 2 , 5 } ), p .calcNodes ());
269
+ assertEquals (IntArrayList .from (7 , 6 , 3 , 2 , 5 ), p .calcNodes ());
227
270
}
228
271
229
272
@ Test
@@ -237,19 +280,17 @@ public void testBasicTurnCosts() {
237
280
calcPath (5 , 1 );
238
281
239
282
// no restriction and costs
240
- EdgeIteratorState e3_6 = getEdge (g , 5 , 6 );
241
- e3_6 .setDistance (2 );
242
- assertEquals (IntArrayList .from (new int []{5 , 2 , 3 , 1 }), p .calcNodes ());
283
+ assertEquals (IntArrayList .from (5 , 2 , 3 , 1 ), p .calcNodes ());
243
284
244
285
// now introduce some turn costs
245
- long tflags = carEncoder . getTurnFlags ( false , 2 );
246
- tcs . addTurnInfo ( getEdge ( g , 5 , 2 ). getEdge (), 2 , getEdge ( g , 2 , 3 ). getEdge (), tflags );
286
+ getEdge ( g , 5 , 6 ). setDistance ( 2 );
287
+ addTurnCost ( g , tcs , 2 , 5 , 2 , 3 );
247
288
248
289
p = createAlgo (g , AlgorithmOptions .start ().
249
290
weighting (createWeighting (carEncoder , tcs , 40 )).
250
291
traversalMode (TraversalMode .EDGE_BASED_1DIR ).build ()).
251
292
calcPath (5 , 1 );
252
- assertEquals (IntArrayList .from (new int []{ 5 , 6 , 3 , 1 } ), p .calcNodes ());
293
+ assertEquals (IntArrayList .from (5 , 6 , 3 , 1 ), p .calcNodes ());
253
294
}
254
295
255
296
@ Test
@@ -258,13 +299,10 @@ public void testTurnCostsBug_991() {
258
299
initGraph (g );
259
300
TurnCostExtension tcs = (TurnCostExtension ) g .getExtension ();
260
301
261
- long tflags = carEncoder .getTurnFlags (false , 2 );
262
- tcs .addTurnInfo (getEdge (g , 5 , 2 ).getEdge (), 2 , getEdge (g , 2 , 3 ).getEdge (), tflags );
263
- tcs .addTurnInfo (getEdge (g , 2 , 0 ).getEdge (), 0 , getEdge (g , 0 , 1 ).getEdge (), tflags );
264
- tcs .addTurnInfo (getEdge (g , 5 , 6 ).getEdge (), 6 , getEdge (g , 6 , 3 ).getEdge (), tflags );
265
-
266
- tflags = carEncoder .getTurnFlags (false , 1 );
267
- tcs .addTurnInfo (getEdge (g , 6 , 7 ).getEdge (), 7 , getEdge (g , 7 , 4 ).getEdge (), tflags );
302
+ addTurnCost (g , tcs , 2 , 5 , 2 , 3 );
303
+ addTurnCost (g , tcs , 2 , 2 , 0 , 1 );
304
+ addTurnCost (g , tcs , 2 , 5 , 6 , 3 );
305
+ addTurnCost (g , tcs , 1 , 6 , 7 , 4 );
268
306
269
307
Path p = createAlgo (g , AlgorithmOptions .start ().
270
308
weighting (new TurnWeighting (new FastestWeighting (carEncoder ), tcs ) {
@@ -279,7 +317,23 @@ public double calcTurnWeight(int edgeFrom, int nodeVia, int edgeTo) {
279
317
}.setDefaultUTurnCost (40 )).
280
318
traversalMode (TraversalMode .EDGE_BASED_2DIR ).build ()).
281
319
calcPath (5 , 1 );
282
- assertEquals (IntArrayList .from (new int []{5 , 6 , 7 , 4 , 3 , 1 }), p .calcNodes ());
283
- assertEquals (301 , p .getTime (), .1 );
320
+ assertEquals (IntArrayList .from (5 , 6 , 7 , 4 , 3 , 1 ), p .calcNodes ());
321
+ assertEquals (5 * 0.06 + 1 , p .getWeight (), 1.e-6 );
322
+ assertEquals (1300 , p .getTime (), .1 );
323
+ }
324
+
325
+ private void addTurnRestriction (Graph g , TurnCostExtension tcs , int from , int via , int to ) {
326
+ long turnFlags = carEncoder .getTurnFlags (true , 0 );
327
+ addTurnFlags (g , tcs , from , via , to , turnFlags );
284
328
}
329
+
330
+ private void addTurnCost (Graph g , TurnCostExtension tcs , int costs , int from , int via , int to ) {
331
+ long turnFlags = carEncoder .getTurnFlags (false , costs );
332
+ addTurnFlags (g , tcs , from , via , to , turnFlags );
333
+ }
334
+
335
+ private void addTurnFlags (Graph g , TurnCostExtension tcs , int from , int via , int to , long turnFlags ) {
336
+ tcs .addTurnInfo (getEdge (g , from , via ).getEdge (), via , getEdge (g , via , to ).getEdge (), turnFlags );
337
+ }
338
+
285
339
}
0 commit comments