Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/optimiser.c
Parent Directory
|
Revision Log
Revision 236 -
(hide annotations)
(download)
(as text)
Sat Aug 15 14:18:23 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 21727 byte(s)
Sat Aug 15 14:18:23 2009 UTC (15 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 21727 byte(s)
Optimise the priority queue used for routing.
1 | amb | 2 | /*************************************** |
2 | amb | 236 | $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.75 2009-08-15 14:18:23 amb Exp $ |
3 | amb | 2 | |
4 | Routing optimiser. | ||
5 | amb | 151 | |
6 | Part of the Routino routing software. | ||
7 | amb | 2 | ******************/ /****************** |
8 | amb | 151 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | amb | 2 | |
10 | amb | 151 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by | ||
12 | the Free Software Foundation, either version 3 of the License, or | ||
13 | (at your option) any later version. | ||
14 | |||
15 | This program is distributed in the hope that it will be useful, | ||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | GNU Affero General Public License for more details. | ||
19 | |||
20 | You should have received a copy of the GNU Affero General Public License | ||
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
22 | amb | 2 | ***************************************/ |
23 | |||
24 | |||
25 | amb | 109 | #include <stdio.h> |
26 | amb | 2 | |
27 | amb | 96 | #include "types.h" |
28 | amb | 109 | #include "functions.h" |
29 | #include "nodes.h" | ||
30 | #include "segments.h" | ||
31 | #include "ways.h" | ||
32 | amb | 28 | #include "results.h" |
33 | amb | 2 | |
34 | amb | 26 | |
35 | amb | 113 | /*+ The option not to print any progress information. +*/ |
36 | amb | 107 | extern int option_quiet; |
37 | amb | 2 | |
38 | amb | 113 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
39 | extern int option_quickest; | ||
40 | amb | 31 | |
41 | amb | 113 | |
42 | amb | 2 | /*++++++++++++++++++++++++++++++++++++++ |
43 | Find the optimum route between two nodes. | ||
44 | |||
45 | amb | 26 | Results *FindRoute Returns a set of results. |
46 | |||
47 | Nodes *nodes The set of nodes to use. | ||
48 | |||
49 | Segments *segments The set of segments to use. | ||
50 | |||
51 | amb | 54 | Ways *ways The set of ways to use. |
52 | |||
53 | amb | 96 | index_t start The start node. |
54 | amb | 2 | |
55 | amb | 96 | index_t finish The finish node. |
56 | amb | 54 | |
57 | amb | 82 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
58 | amb | 71 | |
59 | int all A flag to indicate that a big results structure is required. | ||
60 | amb | 2 | ++++++++++++++++++++++++++++++++++++++*/ |
61 | |||
62 | amb | 96 | Results *FindRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile,int all) |
63 | amb | 2 | { |
64 | amb | 31 | Results *results; |
65 | amb | 236 | Queue *queue; |
66 | amb | 96 | index_t node1,node2; |
67 | amb | 166 | score_t finish_score; |
68 | amb | 219 | double finish_lat,finish_lon; |
69 | amb | 2 | Result *result1,*result2; |
70 | Segment *segment; | ||
71 | amb | 54 | Way *way; |
72 | amb | 2 | |
73 | amb | 227 | if(!option_quiet) |
74 | { | ||
75 | printf("Routing: End Nodes=0"); | ||
76 | fflush(stdout); | ||
77 | } | ||
78 | |||
79 | amb | 10 | /* Set up the finish conditions */ |
80 | |||
81 | amb | 176 | finish_score=INF_SCORE; |
82 | amb | 10 | |
83 | amb | 174 | GetLatLong(nodes,finish,&finish_lat,&finish_lon); |
84 | amb | 119 | |
85 | amb | 165 | /* Create the list of results and insert the first node into the queue */ |
86 | amb | 2 | |
87 | amb | 71 | if(all) |
88 | results=NewResultsList(65536); | ||
89 | else | ||
90 | results=NewResultsList(8); | ||
91 | amb | 2 | |
92 | amb | 165 | results->start=start; |
93 | results->finish=finish; | ||
94 | |||
95 | amb | 31 | result1=InsertResult(results,start); |
96 | amb | 28 | |
97 | amb | 166 | ZeroResult(result1); |
98 | amb | 2 | |
99 | amb | 236 | queue=NewQueueList(); |
100 | amb | 2 | |
101 | amb | 236 | InsertInQueue(queue,result1); |
102 | |||
103 | amb | 2 | /* Loop across all nodes in the queue */ |
104 | |||
105 | amb | 236 | while((result1=PopFromQueue(queue))) |
106 | amb | 2 | { |
107 | amb | 168 | if(result1->sortby>finish_score) |
108 | amb | 119 | continue; |
109 | |||
110 | amb | 43 | node1=result1->node; |
111 | amb | 2 | |
112 | amb | 174 | segment=FirstSegment(segments,nodes,node1); |
113 | amb | 2 | |
114 | while(segment) | ||
115 | { | ||
116 | amb | 170 | score_t segment_score,cumulative_score; |
117 | amb | 59 | |
118 | amb | 95 | if(!IsNormalSegment(segment)) |
119 | amb | 90 | goto endloop; |
120 | |||
121 | amb | 105 | if(profile->oneway && IsOnewayTo(segment,node1)) |
122 | amb | 64 | goto endloop; |
123 | |||
124 | amb | 105 | node2=OtherNode(segment,node1); |
125 | amb | 2 | |
126 | amb | 113 | if(result1->prev==node2) |
127 | amb | 64 | goto endloop; |
128 | |||
129 | amb | 96 | way=LookupWay(ways,segment->way); |
130 | amb | 54 | |
131 | amb | 82 | if(!(way->allow&profile->allow)) |
132 | amb | 54 | goto endloop; |
133 | |||
134 | amb | 168 | if(!profile->highway[HIGHWAY(way->type)]) |
135 | amb | 75 | goto endloop; |
136 | |||
137 | amb | 197 | if(way->weight && way->weight<profile->weight) |
138 | amb | 135 | goto endloop; |
139 | |||
140 | amb | 197 | if((way->height && way->height<profile->height) || |
141 | (way->width && way->width <profile->width ) || | ||
142 | (way->length && way->length<profile->length)) | ||
143 | amb | 135 | goto endloop; |
144 | |||
145 | amb | 166 | if(option_quickest==0) |
146 | amb | 170 | segment_score=(score_t)DISTANCE(segment->distance)/profile->highway[HIGHWAY(way->type)]; |
147 | amb | 166 | else |
148 | amb | 170 | segment_score=(score_t)Duration(segment,way,profile)/profile->highway[HIGHWAY(way->type)]; |
149 | amb | 59 | |
150 | amb | 170 | cumulative_score=result1->score+segment_score; |
151 | amb | 166 | |
152 | if(cumulative_score>finish_score) | ||
153 | amb | 2 | goto endloop; |
154 | |||
155 | amb | 42 | result2=FindResult(results,node2); |
156 | |||
157 | amb | 2 | if(!result2) /* New end node */ |
158 | { | ||
159 | amb | 31 | result2=InsertResult(results,node2); |
160 | amb | 113 | result2->prev=node1; |
161 | amb | 176 | result2->next=NO_NODE; |
162 | amb | 170 | result2->score=cumulative_score; |
163 | result2->segment=segment; | ||
164 | amb | 2 | |
165 | if(node2==finish) | ||
166 | { | ||
167 | amb | 170 | finish_score=cumulative_score; |
168 | amb | 2 | } |
169 | else | ||
170 | amb | 119 | { |
171 | amb | 219 | double lat,lon; |
172 | amb | 166 | distance_t direct; |
173 | |||
174 | amb | 174 | GetLatLong(nodes,node2,&lat,&lon); |
175 | amb | 166 | direct=Distance(lat,lon,finish_lat,finish_lon); |
176 | amb | 119 | |
177 | if(option_quickest==0) | ||
178 | amb | 173 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
179 | amb | 119 | else |
180 | amb | 173 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
181 | amb | 119 | |
182 | amb | 236 | InsertInQueue(queue,result2); |
183 | amb | 119 | } |
184 | amb | 2 | } |
185 | amb | 166 | else if(cumulative_score<result2->score) /* New end node is better */ |
186 | amb | 2 | { |
187 | amb | 166 | result2->prev=node1; |
188 | amb | 170 | result2->score=cumulative_score; |
189 | result2->segment=segment; | ||
190 | amb | 166 | |
191 | if(node2==finish) | ||
192 | amb | 2 | { |
193 | amb | 166 | finish_score=cumulative_score; |
194 | amb | 2 | } |
195 | amb | 166 | else if(!all) |
196 | amb | 2 | { |
197 | amb | 236 | InsertInQueue(queue,result2); |
198 | amb | 166 | } |
199 | else | ||
200 | { | ||
201 | amb | 219 | double lat,lon; |
202 | amb | 166 | distance_t direct; |
203 | amb | 2 | |
204 | amb | 174 | GetLatLong(nodes,node2,&lat,&lon); |
205 | amb | 166 | direct=Distance(lat,lon,finish_lat,finish_lon); |
206 | |||
207 | if(option_quickest==0) | ||
208 | amb | 173 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
209 | amb | 2 | else |
210 | amb | 173 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
211 | amb | 119 | |
212 | amb | 236 | if(result2->sortby<finish_score) |
213 | InsertInQueue(queue,result2); | ||
214 | amb | 2 | } |
215 | } | ||
216 | |||
217 | endloop: | ||
218 | |||
219 | amb | 107 | if(!option_quiet && !(results->number%10000)) |
220 | amb | 95 | { |
221 | amb | 170 | printf("\rRouting: End Nodes=%d",results->number); |
222 | amb | 95 | fflush(stdout); |
223 | } | ||
224 | |||
225 | amb | 104 | segment=NextSegment(segments,segment,node1); |
226 | amb | 2 | } |
227 | } | ||
228 | |||
229 | amb | 107 | if(!option_quiet) |
230 | amb | 31 | { |
231 | amb | 170 | printf("\rRouted: End Nodes=%d\n",results->number); |
232 | amb | 31 | fflush(stdout); |
233 | } | ||
234 | |||
235 | amb | 236 | FreeQueueList(queue); |
236 | |||
237 | amb | 77 | /* Check it worked */ |
238 | |||
239 | result2=FindResult(results,finish); | ||
240 | |||
241 | amb | 88 | if(!result2) |
242 | amb | 77 | { |
243 | FreeResultsList(results); | ||
244 | return(NULL); | ||
245 | } | ||
246 | |||
247 | amb | 170 | /* Create the forward links for the optimum path */ |
248 | amb | 31 | |
249 | result2=FindResult(results,finish); | ||
250 | |||
251 | do | ||
252 | { | ||
253 | amb | 176 | if(result2->prev!=NO_NODE) |
254 | amb | 31 | { |
255 | amb | 113 | index_t node1=result2->prev; |
256 | amb | 31 | |
257 | result1=FindResult(results,node1); | ||
258 | |||
259 | amb | 113 | result1->next=result2->node; |
260 | amb | 31 | |
261 | result2=result1; | ||
262 | } | ||
263 | else | ||
264 | result2=NULL; | ||
265 | } | ||
266 | while(result2); | ||
267 | |||
268 | return(results); | ||
269 | amb | 2 | } |
270 | |||
271 | |||
272 | /*++++++++++++++++++++++++++++++++++++++ | ||
273 | amb | 34 | Find the optimum route between two nodes. |
274 | |||
275 | Results *FindRoute3 Returns a set of results. | ||
276 | |||
277 | amb | 95 | Nodes *nodes The set of nodes to use. |
278 | amb | 34 | |
279 | amb | 95 | Segments *segments The set of segments to use. |
280 | amb | 34 | |
281 | amb | 95 | Ways *ways The set of ways to use. |
282 | amb | 54 | |
283 | amb | 34 | Results *begin The initial portion of the route. |
284 | |||
285 | Results *end The final portion of the route. | ||
286 | amb | 54 | |
287 | amb | 82 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
288 | amb | 34 | ++++++++++++++++++++++++++++++++++++++*/ |
289 | |||
290 | amb | 165 | Results *FindRoute3(Nodes *nodes,Segments *segments,Ways *ways,Results *begin,Results *end,Profile *profile) |
291 | amb | 34 | { |
292 | Results *results; | ||
293 | amb | 236 | Queue *queue; |
294 | amb | 96 | index_t node1,node2; |
295 | amb | 166 | score_t finish_score; |
296 | amb | 219 | double finish_lat,finish_lon; |
297 | amb | 34 | Result *result1,*result2,*result3; |
298 | Segment *segment; | ||
299 | amb | 54 | Way *way; |
300 | amb | 34 | |
301 | amb | 227 | if(!option_quiet) |
302 | { | ||
303 | printf("Routing: End Nodes=0"); | ||
304 | fflush(stdout); | ||
305 | } | ||
306 | |||
307 | amb | 34 | /* Set up the finish conditions */ |
308 | |||
309 | amb | 170 | finish_score=~(distance_t)0; |
310 | amb | 34 | |
311 | amb | 174 | GetLatLong(nodes,end->finish,&finish_lat,&finish_lon); |
312 | amb | 119 | |
313 | amb | 165 | /* Create the list of results and insert the first node into the queue */ |
314 | amb | 34 | |
315 | amb | 71 | results=NewResultsList(65536); |
316 | amb | 34 | |
317 | amb | 165 | results->start=begin->start; |
318 | results->finish=end->finish; | ||
319 | amb | 34 | |
320 | amb | 165 | result1=InsertResult(results,begin->start); |
321 | result3=FindResult(begin,begin->start); | ||
322 | |||
323 | amb | 81 | *result1=*result3; |
324 | amb | 34 | |
325 | amb | 236 | queue=NewQueueList(); |
326 | |||
327 | amb | 34 | /* Insert the finish points of the beginning part of the path into the queue */ |
328 | |||
329 | amb | 79 | result3=FirstResult(begin); |
330 | |||
331 | while(result3) | ||
332 | { | ||
333 | amb | 174 | if(IsSuperNode(nodes,result3->node)) |
334 | amb | 45 | { |
335 | amb | 81 | if(!(result2=FindResult(results,result3->node))) |
336 | amb | 34 | { |
337 | amb | 81 | result2=InsertResult(results,result3->node); |
338 | amb | 34 | |
339 | amb | 81 | *result2=*result3; |
340 | amb | 34 | |
341 | amb | 165 | result2->prev=begin->start; |
342 | amb | 119 | |
343 | amb | 166 | result2->sortby=result2->score; |
344 | amb | 47 | } |
345 | amb | 34 | |
346 | amb | 236 | InsertInQueue(queue,result2); |
347 | amb | 45 | } |
348 | amb | 34 | |
349 | amb | 79 | result3=NextResult(begin,result3); |
350 | } | ||
351 | |||
352 | amb | 95 | /* Loop across all nodes in the queue */ |
353 | amb | 34 | |
354 | amb | 236 | while((result1=PopFromQueue(queue))) |
355 | amb | 34 | { |
356 | amb | 168 | if(result1->sortby>finish_score) |
357 | amb | 119 | continue; |
358 | |||
359 | amb | 43 | node1=result1->node; |
360 | amb | 34 | |
361 | amb | 174 | segment=FirstSegment(segments,nodes,node1); |
362 | amb | 34 | |
363 | while(segment) | ||
364 | { | ||
365 | amb | 170 | score_t segment_score,cumulative_score; |
366 | amb | 59 | |
367 | amb | 95 | if(!IsSuperSegment(segment)) |
368 | goto endloop; | ||
369 | |||
370 | amb | 105 | if(profile->oneway && IsOnewayTo(segment,node1)) |
371 | amb | 64 | goto endloop; |
372 | |||
373 | amb | 105 | node2=OtherNode(segment,node1); |
374 | amb | 34 | |
375 | amb | 113 | if(result1->prev==node2) |
376 | amb | 64 | goto endloop; |
377 | |||
378 | amb | 96 | way=LookupWay(ways,segment->way); |
379 | amb | 54 | |
380 | amb | 82 | if(!(way->allow&profile->allow)) |
381 | amb | 54 | goto endloop; |
382 | |||
383 | amb | 168 | if(!profile->highway[HIGHWAY(way->type)]) |
384 | amb | 75 | goto endloop; |
385 | |||
386 | amb | 197 | if(way->weight && way->weight<profile->weight) |
387 | amb | 135 | goto endloop; |
388 | |||
389 | amb | 197 | if((way->height && way->height<profile->height) || |
390 | (way->width && way->width <profile->width ) || | ||
391 | (way->length && way->length<profile->length)) | ||
392 | amb | 135 | goto endloop; |
393 | |||
394 | amb | 166 | if(option_quickest==0) |
395 | amb | 170 | segment_score=(score_t)DISTANCE(segment->distance)/profile->highway[HIGHWAY(way->type)]; |
396 | amb | 166 | else |
397 | amb | 170 | segment_score=(score_t)Duration(segment,way,profile)/profile->highway[HIGHWAY(way->type)]; |
398 | amb | 34 | |
399 | amb | 170 | cumulative_score=result1->score+segment_score; |
400 | amb | 166 | |
401 | if(cumulative_score>finish_score) | ||
402 | amb | 34 | goto endloop; |
403 | |||
404 | amb | 42 | result2=FindResult(results,node2); |
405 | |||
406 | amb | 34 | if(!result2) /* New end node */ |
407 | { | ||
408 | result2=InsertResult(results,node2); | ||
409 | amb | 113 | result2->prev=node1; |
410 | amb | 176 | result2->next=NO_NODE; |
411 | amb | 170 | result2->score=cumulative_score; |
412 | result2->segment=segment; | ||
413 | amb | 34 | |
414 | amb | 113 | if((result3=FindResult(end,node2))) |
415 | { | ||
416 | amb | 170 | finish_score=result2->score+result3->score; |
417 | amb | 113 | } |
418 | else | ||
419 | amb | 119 | { |
420 | amb | 219 | double lat,lon; |
421 | amb | 166 | distance_t direct; |
422 | |||
423 | amb | 174 | GetLatLong(nodes,node2,&lat,&lon); |
424 | amb | 166 | direct=Distance(lat,lon,finish_lat,finish_lon); |
425 | amb | 119 | |
426 | if(option_quickest==0) | ||
427 | amb | 173 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
428 | amb | 119 | else |
429 | amb | 173 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
430 | amb | 119 | |
431 | amb | 236 | InsertInQueue(queue,result2); |
432 | amb | 119 | } |
433 | amb | 34 | } |
434 | amb | 166 | else if(cumulative_score<result2->score) /* New end node is better */ |
435 | amb | 34 | { |
436 | amb | 166 | result2->prev=node1; |
437 | amb | 170 | result2->score=cumulative_score; |
438 | result2->segment=segment; | ||
439 | amb | 166 | |
440 | if((result3=FindResult(end,node2))) | ||
441 | amb | 34 | { |
442 | amb | 166 | if((result2->score+result3->score)<finish_score) |
443 | amb | 113 | { |
444 | amb | 166 | finish_score=result2->score+result3->score; |
445 | amb | 113 | } |
446 | amb | 34 | } |
447 | amb | 166 | else |
448 | amb | 34 | { |
449 | amb | 219 | double lat,lon; |
450 | amb | 166 | distance_t direct; |
451 | amb | 34 | |
452 | amb | 174 | GetLatLong(nodes,node2,&lat,&lon); |
453 | amb | 166 | direct=Distance(lat,lon,finish_lat,finish_lon); |
454 | |||
455 | if(option_quickest==0) | ||
456 | amb | 173 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
457 | amb | 113 | else |
458 | amb | 173 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
459 | amb | 119 | |
460 | amb | 236 | if(result2->sortby<finish_score) |
461 | InsertInQueue(queue,result2); | ||
462 | amb | 34 | } |
463 | } | ||
464 | |||
465 | endloop: | ||
466 | |||
467 | amb | 107 | if(!option_quiet && !(results->number%10000)) |
468 | amb | 95 | { |
469 | amb | 170 | printf("\rRouting: End Nodes=%d",results->number); |
470 | amb | 95 | fflush(stdout); |
471 | } | ||
472 | amb | 34 | |
473 | amb | 104 | segment=NextSegment(segments,segment,node1); |
474 | amb | 34 | } |
475 | } | ||
476 | |||
477 | amb | 107 | if(!option_quiet) |
478 | amb | 34 | { |
479 | amb | 170 | printf("\rRouted: End Super-Nodes=%d\n",results->number); |
480 | amb | 34 | fflush(stdout); |
481 | } | ||
482 | |||
483 | /* Finish off the end part of the route. */ | ||
484 | |||
485 | amb | 165 | if(!FindResult(results,end->finish)) |
486 | amb | 47 | { |
487 | amb | 165 | result2=InsertResult(results,end->finish); |
488 | result3=FindResult(end,end->finish); | ||
489 | amb | 34 | |
490 | amb | 81 | *result2=*result3; |
491 | amb | 47 | |
492 | amb | 170 | result2->score=~(distance_t)0; |
493 | amb | 54 | |
494 | amb | 79 | result3=FirstResult(end); |
495 | |||
496 | while(result3) | ||
497 | { | ||
498 | amb | 174 | if(IsSuperNode(nodes,result3->node)) |
499 | amb | 79 | if((result1=FindResult(results,result3->node))) |
500 | amb | 170 | if((result1->score+result3->score)<result2->score) |
501 | amb | 47 | { |
502 | amb | 170 | result2->score=result1->score+result3->score; |
503 | result2->prev=result1->node; | ||
504 | amb | 47 | } |
505 | amb | 79 | |
506 | result3=NextResult(end,result3); | ||
507 | } | ||
508 | amb | 47 | } |
509 | amb | 34 | |
510 | amb | 236 | FreeQueueList(queue); |
511 | |||
512 | amb | 77 | /* Check it worked */ |
513 | |||
514 | amb | 176 | result2=FindResult(results,end->finish); |
515 | |||
516 | if(!result2) | ||
517 | amb | 77 | { |
518 | FreeResultsList(results); | ||
519 | return(NULL); | ||
520 | } | ||
521 | |||
522 | amb | 170 | /* Create the forward links for the optimum path */ |
523 | amb | 34 | |
524 | do | ||
525 | { | ||
526 | amb | 176 | if(result2->prev!=NO_NODE) |
527 | amb | 34 | { |
528 | amb | 113 | index_t node1=result2->prev; |
529 | amb | 34 | |
530 | result1=FindResult(results,node1); | ||
531 | |||
532 | amb | 113 | result1->next=result2->node; |
533 | amb | 34 | |
534 | result2=result1; | ||
535 | } | ||
536 | else | ||
537 | result2=NULL; | ||
538 | } | ||
539 | while(result2); | ||
540 | |||
541 | return(results); | ||
542 | } | ||
543 | |||
544 | |||
545 | /*++++++++++++++++++++++++++++++++++++++ | ||
546 | amb | 95 | Find all routes from a specified node to any super-node. |
547 | amb | 3 | |
548 | amb | 126 | Results *FindStartRoutes Returns a set of results. |
549 | amb | 31 | |
550 | Nodes *nodes The set of nodes to use. | ||
551 | |||
552 | Segments *segments The set of segments to use. | ||
553 | |||
554 | amb | 54 | Ways *ways The set of ways to use. |
555 | |||
556 | amb | 96 | index_t start The start node. |
557 | amb | 31 | |
558 | amb | 82 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
559 | amb | 31 | ++++++++++++++++++++++++++++++++++++++*/ |
560 | |||
561 | amb | 126 | Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile) |
562 | amb | 31 | { |
563 | Results *results; | ||
564 | amb | 236 | Queue *queue; |
565 | amb | 96 | index_t node1,node2; |
566 | amb | 31 | Result *result1,*result2; |
567 | Segment *segment; | ||
568 | amb | 54 | Way *way; |
569 | amb | 31 | |
570 | /* Insert the first node into the queue */ | ||
571 | |||
572 | amb | 71 | results=NewResultsList(8); |
573 | amb | 31 | |
574 | amb | 165 | results->start=start; |
575 | |||
576 | amb | 31 | result1=InsertResult(results,start); |
577 | |||
578 | amb | 166 | ZeroResult(result1); |
579 | amb | 31 | |
580 | amb | 236 | queue=NewQueueList(); |
581 | amb | 31 | |
582 | amb | 236 | InsertInQueue(queue,result1); |
583 | |||
584 | amb | 31 | /* Loop across all nodes in the queue */ |
585 | |||
586 | amb | 236 | while((result1=PopFromQueue(queue))) |
587 | amb | 31 | { |
588 | amb | 43 | node1=result1->node; |
589 | amb | 31 | |
590 | amb | 174 | segment=FirstSegment(segments,nodes,node1); |
591 | amb | 31 | |
592 | while(segment) | ||
593 | { | ||
594 | amb | 170 | score_t segment_score,cumulative_score; |
595 | amb | 59 | |
596 | amb | 95 | if(!IsNormalSegment(segment)) |
597 | goto endloop; | ||
598 | |||
599 | amb | 105 | if(profile->oneway && IsOnewayTo(segment,node1)) |
600 | amb | 64 | goto endloop; |
601 | |||
602 | amb | 105 | node2=OtherNode(segment,node1); |
603 | amb | 31 | |
604 | amb | 113 | if(result1->prev==node2) |
605 | amb | 64 | goto endloop; |
606 | |||
607 | amb | 96 | way=LookupWay(ways,segment->way); |
608 | amb | 54 | |
609 | amb | 82 | if(!(way->allow&profile->allow)) |
610 | amb | 54 | goto endloop; |
611 | |||
612 | amb | 168 | if(!profile->highway[HIGHWAY(way->type)]) |
613 | amb | 75 | goto endloop; |
614 | |||
615 | amb | 197 | if(way->weight && way->weight<profile->weight) |
616 | amb | 135 | goto endloop; |
617 | |||
618 | amb | 197 | if((way->height && way->height<profile->height) || |
619 | (way->width && way->width <profile->width ) || | ||
620 | (way->length && way->length<profile->length)) | ||
621 | amb | 135 | goto endloop; |
622 | |||
623 | amb | 166 | if(option_quickest==0) |
624 | amb | 170 | segment_score=(score_t)DISTANCE(segment->distance)/profile->highway[HIGHWAY(way->type)]; |
625 | amb | 166 | else |
626 | amb | 170 | segment_score=(score_t)Duration(segment,way,profile)/profile->highway[HIGHWAY(way->type)]; |
627 | amb | 59 | |
628 | amb | 170 | cumulative_score=result1->score+segment_score; |
629 | amb | 166 | |
630 | amb | 31 | result2=FindResult(results,node2); |
631 | |||
632 | if(!result2) /* New end node */ | ||
633 | { | ||
634 | result2=InsertResult(results,node2); | ||
635 | amb | 113 | result2->prev=node1; |
636 | amb | 176 | result2->next=NO_NODE; |
637 | amb | 170 | result2->score=cumulative_score; |
638 | result2->segment=segment; | ||
639 | amb | 31 | |
640 | amb | 174 | if(!IsSuperNode(nodes,node2)) |
641 | amb | 119 | { |
642 | amb | 166 | result2->sortby=result2->score; |
643 | amb | 236 | InsertInQueue(queue,result2); |
644 | amb | 119 | } |
645 | amb | 31 | } |
646 | amb | 166 | else if(cumulative_score<result2->score) /* New end node is better */ |
647 | amb | 31 | { |
648 | amb | 166 | result2->prev=node1; |
649 | amb | 170 | result2->score=cumulative_score; |
650 | result2->segment=segment; | ||
651 | amb | 31 | |
652 | amb | 174 | if(!IsSuperNode(nodes,node2)) |
653 | amb | 31 | { |
654 | amb | 166 | result2->sortby=result2->score; |
655 | amb | 236 | InsertInQueue(queue,result2); |
656 | amb | 31 | } |
657 | } | ||
658 | |||
659 | endloop: | ||
660 | |||
661 | amb | 104 | segment=NextSegment(segments,segment,node1); |
662 | amb | 31 | } |
663 | } | ||
664 | |||
665 | amb | 236 | FreeQueueList(queue); |
666 | |||
667 | amb | 112 | /* Check it worked */ |
668 | |||
669 | if(results->number==1) | ||
670 | { | ||
671 | FreeResultsList(results); | ||
672 | return(NULL); | ||
673 | } | ||
674 | |||
675 | amb | 31 | return(results); |
676 | amb | 2 | } |
677 | |||
678 | |||
679 | /*++++++++++++++++++++++++++++++++++++++ | ||
680 | amb | 95 | Find all routes from any super-node to a specific node. |
681 | amb | 34 | |
682 | amb | 126 | Results *FindFinishRoutes Returns a set of results. |
683 | amb | 34 | |
684 | Nodes *nodes The set of nodes to use. | ||
685 | |||
686 | Segments *segments The set of segments to use. | ||
687 | |||
688 | amb | 54 | Ways *ways The set of ways to use. |
689 | |||
690 | amb | 96 | index_t finish The finishing node. |
691 | amb | 54 | |
692 | amb | 82 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
693 | amb | 34 | ++++++++++++++++++++++++++++++++++++++*/ |
694 | |||
695 | amb | 126 | Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t finish,Profile *profile) |
696 | amb | 34 | { |
697 | Results *results; | ||
698 | amb | 236 | Queue *queue; |
699 | amb | 96 | index_t node1,node2; |
700 | amb | 34 | Result *result1,*result2; |
701 | Segment *segment; | ||
702 | amb | 54 | Way *way; |
703 | amb | 34 | |
704 | /* Insert the first node into the queue */ | ||
705 | |||
706 | amb | 71 | results=NewResultsList(8); |
707 | amb | 34 | |
708 | amb | 165 | results->finish=finish; |
709 | |||
710 | amb | 34 | result1=InsertResult(results,finish); |
711 | |||
712 | amb | 166 | ZeroResult(result1); |
713 | amb | 34 | |
714 | amb | 236 | queue=NewQueueList(); |
715 | amb | 34 | |
716 | amb | 236 | InsertInQueue(queue,result1); |
717 | |||
718 | amb | 34 | /* Loop across all nodes in the queue */ |
719 | |||
720 | amb | 236 | while((result1=PopFromQueue(queue))) |
721 | amb | 34 | { |
722 | amb | 43 | node1=result1->node; |
723 | amb | 34 | |
724 | amb | 174 | segment=FirstSegment(segments,nodes,node1); |
725 | amb | 34 | |
726 | while(segment) | ||
727 | { | ||
728 | amb | 170 | score_t segment_score,cumulative_score; |
729 | amb | 59 | |
730 | amb | 104 | if(!IsNormalSegment(segment)) |
731 | amb | 34 | goto endloop; |
732 | |||
733 | amb | 105 | if(profile->oneway && IsOnewayFrom(segment,node1)) |
734 | amb | 95 | goto endloop; |
735 | |||
736 | amb | 105 | node2=OtherNode(segment,node1); |
737 | amb | 64 | |
738 | amb | 113 | if(result1->next==node2) |
739 | amb | 64 | goto endloop; |
740 | |||
741 | amb | 104 | way=LookupWay(ways,segment->way); |
742 | amb | 54 | |
743 | amb | 82 | if(!(way->allow&profile->allow)) |
744 | amb | 54 | goto endloop; |
745 | |||
746 | amb | 168 | if(!profile->highway[HIGHWAY(way->type)]) |
747 | amb | 75 | goto endloop; |
748 | |||
749 | amb | 197 | if(way->weight && way->weight<profile->weight) |
750 | amb | 135 | goto endloop; |
751 | |||
752 | amb | 197 | if((way->height && way->height<profile->height) || |
753 | (way->width && way->width <profile->width ) || | ||
754 | (way->length && way->length<profile->length)) | ||
755 | amb | 135 | goto endloop; |
756 | |||
757 | amb | 166 | if(option_quickest==0) |
758 | amb | 170 | segment_score=(score_t)DISTANCE(segment->distance)/profile->highway[HIGHWAY(way->type)]; |
759 | amb | 166 | else |
760 | amb | 170 | segment_score=(score_t)Duration(segment,way,profile)/profile->highway[HIGHWAY(way->type)]; |
761 | amb | 59 | |
762 | amb | 170 | cumulative_score=result1->score+segment_score; |
763 | amb | 166 | |
764 | amb | 34 | result2=FindResult(results,node2); |
765 | |||
766 | if(!result2) /* New end node */ | ||
767 | { | ||
768 | result2=InsertResult(results,node2); | ||
769 | amb | 176 | result2->prev=NO_NODE; |
770 | amb | 113 | result2->next=node1; |
771 | amb | 170 | result2->score=cumulative_score; |
772 | result2->segment=segment; | ||
773 | amb | 34 | |
774 | amb | 174 | if(!IsSuperNode(nodes,node2)) |
775 | amb | 119 | { |
776 | amb | 166 | result2->sortby=result2->score; |
777 | amb | 236 | InsertInQueue(queue,result2); |
778 | amb | 119 | } |
779 | amb | 34 | } |
780 | amb | 166 | else if(cumulative_score<result2->score) /* New end node is better */ |
781 | amb | 34 | { |
782 | amb | 166 | result2->next=node1; |
783 | amb | 170 | result2->score=cumulative_score; |
784 | result2->segment=segment; | ||
785 | amb | 34 | |
786 | amb | 174 | if(!IsSuperNode(nodes,node2)) |
787 | amb | 34 | { |
788 | amb | 166 | result2->sortby=result2->score; |
789 | amb | 236 | InsertInQueue(queue,result2); |
790 | amb | 34 | } |
791 | } | ||
792 | |||
793 | endloop: | ||
794 | |||
795 | amb | 104 | segment=NextSegment(segments,segment,node1); |
796 | amb | 34 | } |
797 | } | ||
798 | |||
799 | amb | 236 | FreeQueueList(queue); |
800 | |||
801 | amb | 112 | /* Check it worked */ |
802 | |||
803 | if(results->number==1) | ||
804 | { | ||
805 | FreeResultsList(results); | ||
806 | return(NULL); | ||
807 | } | ||
808 | |||
809 | amb | 34 | return(results); |
810 | } | ||
811 | |||
812 | |||
813 | /*++++++++++++++++++++++++++++++++++++++ | ||
814 | amb | 95 | Create an optimum route given the set of super-nodes to follow. |
815 | amb | 31 | |
816 | amb | 58 | Results *CombineRoutes Returns the results from joining the super-nodes. |
817 | amb | 55 | |
818 | amb | 58 | Results *results The set of results from the super-nodes. |
819 | amb | 31 | |
820 | Nodes *nodes The list of nodes. | ||
821 | |||
822 | Segments *segments The set of segments to use. | ||
823 | |||
824 | Ways *ways The list of ways. | ||
825 | |||
826 | amb | 82 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
827 | amb | 31 | ++++++++++++++++++++++++++++++++++++++*/ |
828 | |||
829 | amb | 165 | Results *CombineRoutes(Results *results,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile) |
830 | amb | 31 | { |
831 | Result *result1,*result2,*result3,*result4; | ||
832 | Results *combined; | ||
833 | amb | 107 | int quiet=option_quiet; |
834 | amb | 31 | |
835 | amb | 71 | combined=NewResultsList(64); |
836 | amb | 31 | |
837 | amb | 165 | combined->start=results->start; |
838 | combined->finish=results->finish; | ||
839 | |||
840 | amb | 170 | /* Don't print any output for this part */ |
841 | |||
842 | amb | 107 | option_quiet=1; |
843 | amb | 31 | |
844 | amb | 113 | /* Sort out the combined route */ |
845 | amb | 31 | |
846 | amb | 165 | result1=FindResult(results,results->start); |
847 | amb | 31 | |
848 | amb | 165 | result3=InsertResult(combined,results->start); |
849 | amb | 31 | |
850 | amb | 166 | ZeroResult(result3); |
851 | amb | 36 | |
852 | amb | 58 | do |
853 | { | ||
854 | amb | 176 | if(result1->next!=NO_NODE) |
855 | amb | 31 | { |
856 | amb | 113 | Results *results2=FindRoute(nodes,segments,ways,result1->node,result1->next,profile,0); |
857 | amb | 31 | |
858 | result2=FindResult(results2,result1->node); | ||
859 | |||
860 | amb | 113 | result3->next=result2->next; |
861 | amb | 36 | |
862 | amb | 113 | result2=FindResult(results2,result2->next); |
863 | amb | 36 | |
864 | amb | 31 | do |
865 | { | ||
866 | amb | 58 | result4=InsertResult(combined,result2->node); |
867 | amb | 31 | |
868 | amb | 113 | *result4=*result2; |
869 | amb | 170 | result4->score+=result3->score; |
870 | amb | 31 | |
871 | amb | 176 | if(result2->next!=NO_NODE) |
872 | amb | 113 | result2=FindResult(results2,result2->next); |
873 | amb | 31 | else |
874 | result2=NULL; | ||
875 | } | ||
876 | while(result2); | ||
877 | |||
878 | FreeResultsList(results2); | ||
879 | |||
880 | amb | 113 | result1=FindResult(results,result1->next); |
881 | amb | 58 | |
882 | result3=result4; | ||
883 | amb | 31 | } |
884 | else | ||
885 | result1=NULL; | ||
886 | } | ||
887 | while(result1); | ||
888 | |||
889 | /* Now print out the result normally */ | ||
890 | |||
891 | amb | 107 | option_quiet=quiet; |
892 | amb | 31 | |
893 | amb | 55 | return(combined); |
894 | amb | 31 | } |
Properties
Name | Value |
---|---|
cvs:description | Route optimiser. |