Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/optimiser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 88 - (show annotations) (download) (as text)
Tue Jan 27 18:22:37 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 34859 byte(s)
Intermediate version while transitioning data format for nodes and segments.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.38 2009-01-27 18:22:37 amb Exp $
3
4 Routing optimiser.
5 ******************/ /******************
6 Written by Andrew M. Bishop
7
8 This file Copyright 2008,2009 Andrew M. Bishop
9 It may be distributed under the GNU Public License, version 2, or
10 any higher version. See section COPYING of the GNU Public license
11 for conditions under which this file may be redistributed.
12 ***************************************/
13
14
15 #include <assert.h>
16 #include <string.h>
17 #include <stdlib.h>
18
19 #include "nodes.h"
20 #include "ways.h"
21 #include "segments.h"
22 #include "results.h"
23 #include "functions.h"
24
25
26 /*+ Print the progress? +*/
27 int print_progress=1;
28
29
30 /*++++++++++++++++++++++++++++++++++++++
31 Find the optimum route between two nodes.
32
33 Results *FindRoute Returns a set of results.
34
35 Nodes *nodes The set of nodes to use.
36
37 Segments *segments The set of segments to use.
38
39 Ways *ways The set of ways to use.
40
41 uint32_t start The start node.
42
43 uint32_t finish The finish node.
44
45 Profile *profile The profile containing the transport type, speeds and allowed highways.
46
47 int all A flag to indicate that a big results structure is required.
48 ++++++++++++++++++++++++++++++++++++++*/
49
50 Results *FindRoute(Nodes *nodes,Segments *segments,Ways *ways,uint32_t start,uint32_t finish,Profile *profile,int all)
51 {
52 Results *results;
53 uint32_t node1,node2;
54 HalfResult shortest2,quickest2;
55 HalfResult shortestfinish,quickestfinish;
56 Result *result1,*result2;
57 Segment *segment;
58 Way *way;
59
60 /* Set up the finish conditions */
61
62 shortestfinish.distance=~0;
63 shortestfinish.duration=~0;
64 quickestfinish.distance=~0;
65 quickestfinish.duration=~0;
66
67 /* Insert the first node into the queue */
68
69 if(all)
70 results=NewResultsList(65536);
71 else
72 results=NewResultsList(8);
73
74 result1=InsertResult(results,start);
75
76 result1->node=start;
77 result1->shortest.prev=0;
78 result1->shortest.next=0;
79 result1->shortest.distance=0;
80 result1->shortest.duration=0;
81 result1->quickest.prev=0;
82 result1->quickest.next=0;
83 result1->quickest.distance=0;
84 result1->quickest.duration=0;
85
86 insert_in_queue(result1);
87
88 /* Loop across all nodes in the queue */
89
90 while((result1=pop_from_queue()))
91 {
92 node1=result1->node;
93
94 segment=LookupSegment(segments,FirstSegment(nodes,node1));
95
96 while(segment)
97 {
98 duration_t segment_duration;
99
100 if(segment->distance&ONEWAY_OPPOSITE && profile->oneway)
101 goto endloop;
102
103 node2=segment->node2;
104
105 if(result1->shortest.prev==node2 && result1->quickest.prev==node2)
106 goto endloop;
107
108 way=LookupWay(ways,segment->wayindex);
109
110 if(!(way->allow&profile->allow))
111 goto endloop;
112
113 if(!profile->highways[HIGHWAY(way->type)])
114 goto endloop;
115
116 segment_duration=Duration(segment,way,profile);
117
118 shortest2.distance=result1->shortest.distance+DISTANCE(segment->distance);
119 shortest2.duration=result1->shortest.duration+segment_duration;
120 quickest2.distance=result1->quickest.distance+DISTANCE(segment->distance);
121 quickest2.duration=result1->quickest.duration+segment_duration;
122
123 if(shortest2.distance>shortestfinish.distance && quickest2.duration>quickestfinish.duration)
124 goto endloop;
125
126 result2=FindResult(results,node2);
127
128 if(!result2) /* New end node */
129 {
130 result2=InsertResult(results,node2);
131 result2->node=node2;
132 result2->shortest.prev=node1;
133 result2->shortest.next=0;
134 result2->shortest.distance=shortest2.distance;
135 result2->shortest.duration=shortest2.duration;
136 result2->quickest.prev=node1;
137 result2->quickest.next=0;
138 result2->quickest.distance=quickest2.distance;
139 result2->quickest.duration=quickest2.duration;
140
141 if(node2==finish)
142 {
143 shortestfinish.distance=shortest2.distance;
144 shortestfinish.duration=shortest2.duration;
145 quickestfinish.distance=quickest2.distance;
146 quickestfinish.duration=quickest2.duration;
147 }
148 else
149 insert_in_queue(result2);
150 }
151 else
152 {
153 if(shortest2.distance<result2->shortest.distance ||
154 (shortest2.distance==result2->shortest.distance &&
155 shortest2.duration<result2->shortest.duration)) /* New end node is shorter */
156 {
157 result2->shortest.prev=node1;
158 result2->shortest.distance=shortest2.distance;
159 result2->shortest.duration=shortest2.duration;
160
161 if(node2==finish)
162 {
163 shortestfinish.distance=shortest2.distance;
164 shortestfinish.duration=shortest2.duration;
165 }
166 else
167 insert_in_queue(result2);
168 }
169
170 if(quickest2.duration<result2->quickest.duration ||
171 (quickest2.duration==result2->quickest.duration &&
172 quickest2.distance<result2->quickest.distance)) /* New end node is quicker */
173 {
174 result2->quickest.prev=node1;
175 result2->quickest.distance=quickest2.distance;
176 result2->quickest.duration=quickest2.duration;
177
178 if(node2==finish)
179 {
180 quickestfinish.distance=quickest2.distance;
181 quickestfinish.duration=quickest2.duration;
182 }
183 else
184 insert_in_queue(result2);
185 }
186 }
187
188 endloop:
189
190 segment=NextSegment(segments,segment);
191 }
192
193 if(print_progress && !(results->number%10000))
194 {
195 printf("\rRouting: End Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin ",results->number,
196 distance_to_km(shortest2.distance),duration_to_minutes(shortest2.duration),
197 distance_to_km(quickest2.distance),duration_to_minutes(quickest2.duration));
198 fflush(stdout);
199 }
200 }
201
202 if(print_progress)
203 {
204 printf("\rRouted: End Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin\n",results->number,
205 distance_to_km(shortestfinish.distance),duration_to_minutes(shortestfinish.duration),
206 distance_to_km(quickestfinish.distance),duration_to_minutes(quickestfinish.duration));
207 fflush(stdout);
208 }
209
210 /* Check it worked */
211
212 result2=FindResult(results,finish);
213
214 if(!result2)
215 {
216 FreeResultsList(results);
217 return(NULL);
218 }
219
220 /* Reverse the results */
221
222 result2=FindResult(results,finish);
223
224 do
225 {
226 if(result2->shortest.prev)
227 {
228 uint32_t node1=result2->shortest.prev;
229
230 result1=FindResult(results,node1);
231
232 result1->shortest.next=result2->node;
233
234 result2=result1;
235 }
236 else
237 result2=NULL;
238 }
239 while(result2);
240
241 result2=FindResult(results,finish);
242
243 do
244 {
245 if(result2->quickest.prev)
246 {
247 uint32_t node1=result2->quickest.prev;
248
249 result1=FindResult(results,node1);
250
251 result1->quickest.next=result2->node;
252
253 result2=result1;
254 }
255 else
256 result2=NULL;
257 }
258 while(result2);
259
260 return(results);
261 }
262
263
264 #if 0
265
266 /*++++++++++++++++++++++++++++++++++++++
267 Find the optimum route between two nodes.
268
269 Results *FindRoute3 Returns a set of results.
270
271 Nodes *supernodes The set of supernodes to use.
272
273 Segments *supersegments The set of supersegments to use.
274
275 Ways *superways The set of superways to use.
276
277 uint32_t start The start node.
278
279 uint32_t finish The finish node.
280
281 Results *begin The initial portion of the route.
282
283 Results *end The final portion of the route.
284
285 Profile *profile The profile containing the transport type, speeds and allowed highways.
286 ++++++++++++++++++++++++++++++++++++++*/
287
288 Results *FindRoute3(Nodes *supernodes,Segments *supersegments,Ways *superways,uint32_t start,uint32_t finish,Results *begin,Results *end,Profile *profile)
289 {
290 Results *results;
291 uint32_t node1,node2;
292 HalfResult shortest2,quickest2;
293 HalfResult shortestfinish,quickestfinish;
294 Result *result1,*result2,*result3;
295 Segment *segment;
296 Way *way;
297
298 /* Set up the finish conditions */
299
300 shortestfinish.distance=~0;
301 shortestfinish.duration=~0;
302 quickestfinish.distance=~0;
303 quickestfinish.duration=~0;
304
305 /* Insert the start node */
306
307 results=NewResultsList(65536);
308
309 result1=InsertResult(results,start);
310 result3=FindResult(begin,start);
311
312 *result1=*result3;
313
314 /* Insert the finish points of the beginning part of the path into the queue */
315
316 result3=FirstResult(begin);
317
318 while(result3)
319 {
320 if(FindNode(supernodes,result3->node))
321 {
322 if(!(result2=FindResult(results,result3->node)))
323 {
324 result2=InsertResult(results,result3->node);
325
326 *result2=*result3;
327
328 result2->shortest.prev=start;
329 result2->quickest.prev=start;
330 }
331
332 insert_in_queue(result2);
333 }
334
335 result3=NextResult(begin,result3);
336 }
337
338 /* Loop across all supernodes in the queue */
339
340 while((result1=pop_from_queue()))
341 {
342 node1=result1->node;
343
344 segment=FindFirstSegment(supersegments,node1);
345
346 while(segment)
347 {
348 duration_t segment_duration;
349
350 if(segment->distance&ONEWAY_OPPOSITE && profile->oneway)
351 goto endloop;
352
353 node2=segment->node2;
354
355 if(result1->shortest.prev==node2 && result1->quickest.prev==node2)
356 goto endloop;
357
358 way=LookupWay(superways,segment->wayindex);
359
360 if(!(way->allow&profile->allow))
361 goto endloop;
362
363 if(!profile->highways[HIGHWAY(way->type)])
364 goto endloop;
365
366 segment_duration=Duration(segment,way,profile);
367
368 shortest2.distance=result1->shortest.distance+DISTANCE(segment->distance);
369 shortest2.duration=result1->shortest.duration+segment_duration;
370 quickest2.distance=result1->quickest.distance+DISTANCE(segment->distance);
371 quickest2.duration=result1->quickest.duration+segment_duration;
372
373 if(shortest2.distance>shortestfinish.distance && quickest2.duration>quickestfinish.duration)
374 goto endloop;
375
376 result2=FindResult(results,node2);
377 result3=NULL;
378
379 if(!result2) /* New end node */
380 {
381 result2=InsertResult(results,node2);
382 result2->node=node2;
383 result2->shortest.prev=node1;
384 result2->shortest.next=0;
385 result2->shortest.distance=shortest2.distance;
386 result2->shortest.duration=shortest2.duration;
387 result2->quickest.prev=node1;
388 result2->quickest.next=0;
389 result2->quickest.distance=quickest2.distance;
390 result2->quickest.duration=quickest2.duration;
391
392 if(!(result3=FindResult(end,node2)))
393 insert_in_queue(result2);
394 }
395 else
396 {
397 if(shortest2.distance<result2->shortest.distance ||
398 (shortest2.distance==result2->shortest.distance &&
399 shortest2.duration<result2->shortest.duration)) /* New end node is shorter */
400 {
401 result2->shortest.prev=node1;
402 result2->shortest.distance=shortest2.distance;
403 result2->shortest.duration=shortest2.duration;
404
405 if(!(result3=FindResult(end,node2)))
406 insert_in_queue(result2);
407 }
408
409 if(quickest2.duration<result2->quickest.duration ||
410 (quickest2.duration==result2->quickest.duration &&
411 quickest2.distance<result2->quickest.distance)) /* New end node is quicker */
412 {
413 result2->quickest.prev=node1;
414 result2->quickest.distance=quickest2.distance;
415 result2->quickest.duration=quickest2.duration;
416
417 if(!(result3=FindResult(end,node2)))
418 insert_in_queue(result2);
419 }
420 }
421
422 if(result3)
423 {
424 if((shortest2.distance+result3->shortest.distance)<shortestfinish.distance ||
425 ((shortest2.distance+result3->shortest.distance)==shortestfinish.distance &&
426 (shortest2.duration+result3->shortest.duration)<shortestfinish.duration))
427 {
428 shortestfinish.distance=shortest2.distance+result3->shortest.distance;
429 shortestfinish.duration=shortest2.duration+result3->shortest.duration;
430 }
431 if((quickest2.duration+result3->quickest.duration)<quickestfinish.duration ||
432 ((quickest2.duration+result3->quickest.duration)==quickestfinish.duration &&
433 (quickest2.distance+result3->quickest.distance)<quickestfinish.distance))
434 {
435 quickestfinish.distance=quickest2.distance+result3->quickest.distance;
436 quickestfinish.duration=quickest2.duration+result3->quickest.duration;
437 }
438 }
439
440 endloop:
441
442 segment=FindNextSegment(supersegments,segment);
443 }
444
445 if(print_progress && !(results->number%10000))
446 {
447 printf("\rRouting: End Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin ",results->number,
448 distance_to_km(shortest2.distance),duration_to_minutes(shortest2.duration),
449 distance_to_km(quickest2.distance),duration_to_minutes(quickest2.duration));
450 fflush(stdout);
451 }
452 }
453
454 if(print_progress)
455 {
456 printf("\rRouted: End Super-Nodes=%d Shortest=%.1fkm,%.0fmin Quickest=%.1fkm,%.0fmin\n",results->number,
457 distance_to_km(shortestfinish.distance),duration_to_minutes(shortestfinish.duration),
458 distance_to_km(quickestfinish.distance),duration_to_minutes(quickestfinish.duration));
459 fflush(stdout);
460 }
461
462 /* Finish off the end part of the route. */
463
464 if(!FindResult(results,finish))
465 {
466 result2=InsertResult(results,finish);
467 result3=FindResult(end,finish);
468
469 *result2=*result3;
470
471 result2->shortest.distance=~0;
472 result2->shortest.duration=~0;
473 result2->quickest.distance=~0;
474 result2->quickest.duration=~0;
475
476 result3=FirstResult(end);
477
478 while(result3)
479 {
480 if(FindNode(supernodes,result3->node))
481 if((result1=FindResult(results,result3->node)))
482 {
483 if((result1->shortest.distance+result3->shortest.distance)<result2->shortest.distance ||
484 ((result1->shortest.distance+result3->shortest.distance)==result2->shortest.distance &&
485 (result1->shortest.duration+result3->shortest.duration)<result2->shortest.duration))
486 {
487 result2->shortest.distance=result1->shortest.distance+result3->shortest.distance;
488 result2->shortest.duration=result1->shortest.duration+result3->shortest.duration;
489 result2->shortest.prev=result1->node;
490 }
491 if((result1->quickest.duration+result3->quickest.duration)<result2->quickest.duration ||
492 ((result1->quickest.duration+result3->quickest.duration)==result2->quickest.duration &&
493 (result1->quickest.distance+result3->quickest.distance)<result2->quickest.distance))
494 {
495 result2->quickest.distance=result1->quickest.distance+result3->quickest.distance;
496 result2->quickest.duration=result1->quickest.duration+result3->quickest.duration;
497 result2->quickest.prev=result1->node;
498 }
499 }
500
501 result3=NextResult(end,result3);
502 }
503 }
504
505 /* Check it worked */
506
507 result2=FindResult(results,finish);
508
509 if(!result2)
510 {
511 FreeResultsList(results);
512 return(NULL);
513 }
514
515 /* Reverse the results */
516
517 result2=FindResult(results,finish);
518
519 do
520 {
521 if(result2->shortest.prev)
522 {
523 uint32_t node1=result2->shortest.prev;
524
525 result1=FindResult(results,node1);
526
527 result1->shortest.next=result2->node;
528
529 result2=result1;
530 }
531 else
532 result2=NULL;
533 }
534 while(result2);
535
536 result2=FindResult(results,finish);
537
538 do
539 {
540 if(result2->quickest.prev)
541 {
542 uint32_t node1=result2->quickest.prev;
543
544 result1=FindResult(results,node1);
545
546 result1->quickest.next=result2->node;
547
548 result2=result1;
549 }
550 else
551 result2=NULL;
552 }
553 while(result2);
554
555 return(results);
556 }
557 #endif
558
559
560 /*++++++++++++++++++++++++++++++++++++++
561 Print the optimum route between two nodes.
562
563 Results *Results The set of results to print.
564
565 Nodes *nodes The list of nodes.
566
567 Segments *segments The set of segments to use.
568
569 Ways *ways The list of ways.
570
571 Nodes *supernodes The list of super-nodes.
572
573 uint32_t start The start node.
574
575 uint32_t finish The finish node.
576
577 Profile *profile The profile containing the transport type, speeds and allowed highways.
578 ++++++++++++++++++++++++++++++++++++++*/
579
580 void PrintRoute(Results *results,Nodes *nodes,Segments *segments,Ways *ways,Nodes *supernodes,uint32_t start,uint32_t finish,Profile *profile)
581 {
582 FILE *textfile,*gpxfile;
583 Result *result;
584
585 /* Print the result for the shortest route */
586
587 textfile=fopen("shortest.txt","w");
588 gpxfile=fopen("shortest.gpx","w");
589
590 fprintf(gpxfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
591 fprintf(gpxfile,"<gpx version=\"1.0\" creator=\"Router\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
592 fprintf(gpxfile,"<trk>\n");
593 fprintf(gpxfile,"<trkseg>\n");
594
595 result=FindResult(results,start);
596
597 do
598 {
599 Node *node=LookupNode(nodes,result->node);
600
601 fprintf(gpxfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"></trkpt>\n",node->latitude,node->longitude);
602
603 if(result->shortest.prev)
604 {
605 Segment *segment;
606 Way *way;
607
608 segment=LookupSegment(segments,FirstSegment(nodes,result->shortest.prev));
609 while(segment->node2!=result->node)
610 segment=NextSegment(segments,segment);
611
612 way=LookupWay(ways,segment->wayindex);
613
614 fprintf(textfile,"%8.4f %9.4f %10d%c %5.3f %5.2f %7.2f %5.1f %3d %s\n",node->latitude,node->longitude,
615 result->node,supernodes?'*':' ',
616 distance_to_km(segment->distance),duration_to_minutes(Duration(segment,way,profile)),
617 distance_to_km(result->shortest.distance),duration_to_minutes(result->shortest.duration),
618 profile->speed[HIGHWAY(way->type)],WayName(ways,way));
619 }
620 else
621 fprintf(textfile,"%8.4f %9.4f %10d%c %5.3f %5.2f %7.2f %5.1f\n",node->latitude,node->longitude,
622 result->node,supernodes?'*':' ',
623 0.0,0.0,0.0,0.0);
624
625 if(result->shortest.next)
626 result=FindResult(results,result->shortest.next);
627 else
628 result=NULL;
629 }
630 while(result);
631
632 fprintf(gpxfile,"</trkseg>\n");
633 fprintf(gpxfile,"</trk>\n");
634 fprintf(gpxfile,"</gpx>\n");
635
636 fclose(textfile);
637 fclose(gpxfile);
638
639 /* Print the result for the quickest route */
640
641 textfile=fopen("quickest.txt","w");
642 gpxfile=fopen("quickest.gpx","w");
643
644 fprintf(gpxfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
645 fprintf(gpxfile,"<gpx version=\"1.0\" creator=\"Router\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
646 fprintf(gpxfile,"<trk>\n");
647 fprintf(gpxfile,"<trkseg>\n");
648
649 result=FindResult(results,start);
650
651 do
652 {
653 Node *node=LookupNode(nodes,result->node);
654
655 fprintf(gpxfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"></trkpt>\n",node->latitude,node->longitude);
656
657 if(result->quickest.prev)
658 {
659 Segment *segment;
660 Way *way;
661
662 segment=LookupSegment(segments,FirstSegment(nodes,result->quickest.prev));
663 while(segment->node2!=result->node)
664 segment=NextSegment(segments,segment);
665
666 way=LookupWay(ways,segment->wayindex);
667
668 fprintf(textfile,"%8.4f %9.4f %10d%c %5.3f %5.2f %7.2f %5.1f %3d %s\n",node->latitude,node->longitude,
669 result->node,supernodes?'*':' ',
670 distance_to_km(segment->distance),duration_to_minutes(Duration(segment,way,profile)),
671 distance_to_km(result->quickest.distance),duration_to_minutes(result->quickest.duration),
672 profile->speed[HIGHWAY(way->type)],WayName(ways,way));
673 }
674 else
675 fprintf(textfile,"%8.4f %9.4f %10d%c %5.3f %5.2f %7.2f %5.1f\n",node->latitude,node->longitude,
676 result->node,supernodes?'*':' ',
677 0.0,0.0,0.0,0.0);
678
679 if(result->quickest.next)
680 result=FindResult(results,result->quickest.next);
681 else
682 result=NULL;
683 }
684 while(result);
685
686 fprintf(gpxfile,"</trkseg>\n");
687 fprintf(gpxfile,"</trk>\n");
688 fprintf(gpxfile,"</gpx>\n");
689
690 fclose(textfile);
691 fclose(gpxfile);
692 }
693
694 #if 0
695
696 /*++++++++++++++++++++++++++++++++++++++
697 Find all routes from a specified node to any node in the specified list.
698
699 Results *FindRoutes Returns a set of results.
700
701 Nodes *nodes The set of nodes to use.
702
703 Segments *segments The set of segments to use.
704
705 Ways *ways The set of ways to use.
706
707 uint32_t start The start node.
708
709 Nodes *finish The finishing nodes.
710
711 Profile *profile The profile containing the transport type, speeds and allowed highways.
712 ++++++++++++++++++++++++++++++++++++++*/
713
714 Results *FindRoutes(Nodes *nodes,Segments *segments,Ways *ways,uint32_t start,Nodes *finish,Profile *profile)
715 {
716 Results *results;
717 uint32_t node1,node2;
718 HalfResult shortest2,quickest2;
719 Result *result1,*result2;
720 Segment *segment;
721 Way *way;
722
723 /* Insert the first node into the queue */
724
725 results=NewResultsList(8);
726
727 result1=InsertResult(results,start);
728
729 result1->node=start;
730 result1->shortest.prev=0;
731 result1->shortest.next=0;
732 result1->shortest.distance=0;
733 result1->shortest.duration=0;
734 result1->quickest.prev=0;
735 result1->quickest.next=0;
736 result1->quickest.distance=0;
737 result1->quickest.duration=0;
738
739 insert_in_queue(result1);
740
741 /* Loop across all nodes in the queue */
742
743 while((result1=pop_from_queue()))
744 {
745 node1=result1->node;
746
747 segment=FindFirstSegment(segments,node1);
748
749 while(segment)
750 {
751 duration_t segment_duration;
752
753 if(segment->distance&ONEWAY_OPPOSITE && profile->oneway)
754 goto endloop;
755
756 node2=segment->node2;
757
758 if(result1->shortest.prev==node2 && result1->quickest.prev==node2)
759 goto endloop;
760
761 way=LookupWay(ways,segment->wayindex);
762
763 if(!(way->allow&profile->allow))
764 goto endloop;
765
766 if(!profile->highways[HIGHWAY(way->type)])
767 goto endloop;
768
769 segment_duration=Duration(segment,way,profile);
770
771 shortest2.distance=result1->shortest.distance+DISTANCE(segment->distance);
772 shortest2.duration=result1->shortest.duration+segment_duration;
773 quickest2.distance=result1->quickest.distance+DISTANCE(segment->distance);
774 quickest2.duration=result1->quickest.duration+segment_duration;
775
776 result2=FindResult(results,node2);
777
778 if(!result2) /* New end node */
779 {
780 result2=InsertResult(results,node2);
781 result2->node=node2;
782 result2->shortest.prev=node1;
783 result2->shortest.next=0;
784 result2->shortest.distance=shortest2.distance;
785 result2->shortest.duration=shortest2.duration;
786 result2->quickest.prev=node1;
787 result2->quickest.next=0;
788 result2->quickest.distance=quickest2.distance;
789 result2->quickest.duration=quickest2.duration;
790
791 if(!FindNode(finish,node2))
792 insert_in_queue(result2);
793 }
794 else
795 {
796 if(shortest2.distance<result2->shortest.distance ||
797 (shortest2.distance==result2->shortest.distance &&
798 shortest2.duration<result2->shortest.duration)) /* New end node is shorter */
799 {
800 result2->shortest.prev=node1;
801 result2->shortest.distance=shortest2.distance;
802 result2->shortest.duration=shortest2.duration;
803
804 if(!FindNode(finish,node2))
805 insert_in_queue(result2);
806 }
807
808 if(quickest2.duration<result2->quickest.duration ||
809 (quickest2.duration==result2->quickest.duration &&
810 quickest2.distance<result2->quickest.distance)) /* New end node is quicker */
811 {
812 result2->quickest.prev=node1;
813 result2->quickest.distance=quickest2.distance;
814 result2->quickest.duration=quickest2.duration;
815
816 if(!FindNode(finish,node2))
817 insert_in_queue(result2);
818 }
819 }
820
821 endloop:
822
823 segment=FindNextSegment(segments,segment);
824 }
825 }
826
827 return(results);
828 }
829
830
831 /*++++++++++++++++++++++++++++++++++++++
832 Find all routes from any node in the specified list to a specific node.
833
834 Results *FindReverseRoute Returns a set of results.
835
836 Nodes *nodes The set of nodes to use.
837
838 Segments *segments The set of segments to use.
839
840 Ways *ways The set of ways to use.
841
842 Nodes *start The starting nodes.
843
844 uint32_t finish The finishing node.
845
846 Profile *profile The profile containing the transport type, speeds and allowed highways.
847 ++++++++++++++++++++++++++++++++++++++*/
848
849 Results *FindReverseRoutes(Nodes *nodes,Segments *segments,Ways *ways,Nodes *start,uint32_t finish,Profile *profile)
850 {
851 Results *results;
852 uint32_t node1,node2;
853 HalfResult shortest2,quickest2;
854 Result *result1,*result2;
855 Segment *segment;
856 Way *way;
857
858 /* Insert the first node into the queue */
859
860 results=NewResultsList(8);
861
862 result1=InsertResult(results,finish);
863
864 result1->node=finish;
865 result1->shortest.prev=0;
866 result1->shortest.next=0;
867 result1->shortest.distance=0;
868 result1->shortest.duration=0;
869 result1->quickest.prev=0;
870 result1->quickest.next=0;
871 result1->quickest.distance=0;
872 result1->quickest.duration=0;
873
874 insert_in_queue(result1);
875
876 /* Loop across all nodes in the queue */
877
878 while((result1=pop_from_queue()))
879 {
880 node1=result1->node;
881
882 segment=FindFirstSegment(segments,node1);
883
884 while(segment)
885 {
886 duration_t reversesegment_duration;
887
888 /* Reverse the segment and check it exists */
889
890 uint32_t reversenode;
891 Segment *reversesegment;
892
893 reversenode=segment->node2;
894 reversesegment=FindFirstSegment(segments,reversenode);
895
896 while(reversesegment && reversesegment->node2!=node1)
897 reversesegment=FindNextSegment(segments,reversesegment);
898
899 if(!reversesegment)
900 goto endloop;
901
902 if(reversesegment->distance&ONEWAY_OPPOSITE && profile->oneway)
903 goto endloop;
904
905 node2=reversesegment->node1;
906
907 if(result1->shortest.prev==node2 && result1->quickest.prev==node2)
908 goto endloop;
909
910 way=LookupWay(ways,reversesegment->wayindex);
911
912 if(!(way->allow&profile->allow))
913 goto endloop;
914
915 if(!profile->highways[HIGHWAY(way->type)])
916 goto endloop;
917
918 reversesegment_duration=Duration(reversesegment,way,profile);
919
920 shortest2.distance=result1->shortest.distance+DISTANCE(reversesegment->distance);
921 shortest2.duration=result1->shortest.duration+reversesegment_duration;
922 quickest2.distance=result1->quickest.distance+DISTANCE(reversesegment->distance);
923 quickest2.duration=result1->quickest.duration+reversesegment_duration;
924
925 result2=FindResult(results,node2);
926
927 if(!result2) /* New end node */
928 {
929 result2=InsertResult(results,node2);
930 result2->node=node2;
931 result2->shortest.prev=0;
932 result2->shortest.next=node1;
933 result2->shortest.distance=shortest2.distance;
934 result2->shortest.duration=shortest2.duration;
935 result2->quickest.prev=0;
936 result2->quickest.next=node1;
937 result2->quickest.distance=quickest2.distance;
938 result2->quickest.duration=quickest2.duration;
939
940 if(!FindNode(start,node2))
941 insert_in_queue(result2);
942 }
943 else
944 {
945 if(shortest2.distance<result2->shortest.distance ||
946 (shortest2.distance==result2->shortest.distance &&
947 shortest2.duration<result2->shortest.duration)) /* New end node is shorter */
948 {
949 result2->shortest.next=node1;
950 result2->shortest.distance=shortest2.distance;
951 result2->shortest.duration=shortest2.duration;
952
953 if(!FindNode(start,node2))
954 insert_in_queue(result2);
955 }
956
957 if(quickest2.duration<result2->quickest.duration ||
958 (quickest2.duration==result2->quickest.duration &&
959 quickest2.distance<result2->quickest.distance)) /* New end node is quicker */
960 {
961 result2->quickest.next=node1;
962 result2->quickest.distance=quickest2.distance;
963 result2->quickest.duration=quickest2.duration;
964
965 if(!FindNode(start,node2))
966 insert_in_queue(result2);
967 }
968 }
969
970 endloop:
971
972 segment=FindNextSegment(segments,segment);
973 }
974 }
975
976 return(results);
977 }
978
979
980 /*++++++++++++++++++++++++++++++++++++++
981 Print the optimum route between two nodes.
982
983 Results *CombineRoutes Returns the results from joining the super-nodes.
984
985 Results *results The set of results from the super-nodes.
986
987 Nodes *nodes The list of nodes.
988
989 Segments *segments The set of segments to use.
990
991 Ways *ways The list of ways.
992
993 uint32_t start The start node.
994
995 uint32_t finish The finish node.
996
997 Profile *profile The profile containing the transport type, speeds and allowed highways.
998 ++++++++++++++++++++++++++++++++++++++*/
999
1000 Results *CombineRoutes(Results *results,Nodes *nodes,Segments *segments,Ways *ways,uint32_t start,uint32_t finish,Profile *profile)
1001 {
1002 Result *result1,*result2,*result3,*result4;
1003 Results *combined;
1004
1005 combined=NewResultsList(64);
1006
1007 print_progress=0;
1008
1009 /* Sort out the shortest */
1010
1011 result1=FindResult(results,start);
1012
1013 result3=InsertResult(combined,start);
1014
1015 result3->node=result1->node;
1016
1017 result3->shortest.distance=0;
1018 result3->shortest.duration=0;
1019 result3->shortest.next=0;
1020 result3->shortest.prev=0;
1021
1022 do
1023 {
1024 if(result1->shortest.next)
1025 {
1026 Results *results2=FindRoute(nodes,segments,ways,result1->node,result1->shortest.next,profile,0);
1027
1028 result2=FindResult(results2,result1->node);
1029
1030 result3->shortest.next=result2->shortest.next;
1031
1032 result2=FindResult(results2,result2->shortest.next);
1033
1034 do
1035 {
1036 result4=InsertResult(combined,result2->node);
1037
1038 result4->node=result2->node;
1039
1040 result4->shortest=result2->shortest;
1041 result4->shortest.distance+=result3->shortest.distance;
1042 result4->shortest.duration+=result3->shortest.duration;
1043
1044 if(result2->shortest.next)
1045 result2=FindResult(results2,result2->shortest.next);
1046 else
1047 result2=NULL;
1048 }
1049 while(result2);
1050
1051 FreeResultsList(results2);
1052
1053 result1=FindResult(results,result1->shortest.next);
1054
1055 result3=result4;
1056 }
1057 else
1058 result1=NULL;
1059 }
1060 while(result1);
1061
1062 /* Sort out the quickest */
1063
1064 result1=FindResult(results,start);
1065
1066 result3=FindResult(combined,start);
1067
1068 result3->quickest.distance=0;
1069 result3->quickest.duration=0;
1070 result3->quickest.next=0;
1071 result3->quickest.prev=0;
1072
1073 do
1074 {
1075 if(result1->quickest.next)
1076 {
1077 Results *results2=FindRoute(nodes,segments,ways,result1->node,result1->quickest.next,profile,0);
1078
1079 result2=FindResult(results2,result1->node);
1080
1081 result3->quickest.next=result2->quickest.next;
1082
1083 result2=FindResult(results2,result2->quickest.next);
1084
1085 do
1086 {
1087 result4=FindResult(combined,result2->node);
1088
1089 if(!result4)
1090 {
1091 result4=InsertResult(combined,result2->node);
1092
1093 result4->node=result2->node;
1094 }
1095
1096 result4->quickest=result2->quickest;
1097 result4->quickest.distance+=result3->quickest.distance;
1098 result4->quickest.duration+=result3->quickest.duration;
1099
1100 if(result2->quickest.next)
1101 result2=FindResult(results2,result2->quickest.next);
1102 else
1103 result2=NULL;
1104 }
1105 while(result2);
1106
1107 FreeResultsList(results2);
1108
1109 result1=FindResult(results,result1->quickest.next);
1110
1111 result3=result4;
1112 }
1113 else
1114 result1=NULL;
1115 }
1116 while(result1);
1117
1118 /* Now print out the result normally */
1119
1120 print_progress=1;
1121
1122 return(combined);
1123 }
1124
1125
1126 /*++++++++++++++++++++++++++++++++++++++
1127 Find all routes from a specified node to any node in the specified list that follows a certain type of way.
1128
1129 Results *FindRoutesWay Returns a set of results.
1130
1131 Nodes *nodes The set of nodes to use.
1132
1133 Segments *segments The set of segments to use.
1134
1135 Ways *ways The set of ways to use.
1136
1137 uint32_t start The start node.
1138
1139 Nodes *finish The finishing nodes.
1140
1141 Way *match The way that the route must match.
1142 ++++++++++++++++++++++++++++++++++++++*/
1143
1144 Results *FindRoutesWay(Nodes *nodes,Segments *segments,Ways *ways,uint32_t start,Nodes *finish,Way *match)
1145 {
1146 Results *results;
1147 uint32_t node1,node2;
1148 HalfResult shortest2;
1149 Result *result1,*result2;
1150 Segment *segment;
1151 Way *way;
1152
1153 /* Insert the first node into the queue */
1154
1155 results=NewResultsList(8);
1156
1157 result1=InsertResult(results,start);
1158
1159 result1->node=start;
1160 result1->shortest.prev=0;
1161 result1->shortest.next=0;
1162 result1->shortest.distance=0;
1163
1164 insert_in_queue(result1);
1165
1166 /* Loop across all nodes in the queue */
1167
1168 while((result1=pop_from_queue()))
1169 {
1170 node1=result1->node;
1171
1172 segment=FindFirstSegment(segments,node1);
1173
1174 while(segment)
1175 {
1176 if(segment->distance&ONEWAY_OPPOSITE)
1177 goto endloop;
1178
1179 node2=segment->node2;
1180
1181 if(result1->shortest.prev==node2)
1182 goto endloop;
1183
1184 way=LookupWay(ways,segment->wayindex);
1185
1186 if(way->type !=match->type ||
1187 way->allow!=match->allow ||
1188 way->limit!=match->limit)
1189 goto endloop;
1190
1191 shortest2.distance=result1->shortest.distance+DISTANCE(segment->distance);
1192
1193 result2=FindResult(results,node2);
1194
1195 if(!result2) /* New end node */
1196 {
1197 result2=InsertResult(results,node2);
1198 result2->node=node2;
1199 result2->shortest.prev=node1;
1200 result2->shortest.next=0;
1201 result2->shortest.distance=shortest2.distance;
1202
1203 if(!FindNode(finish,node2))
1204 insert_in_queue(result2);
1205 }
1206 else
1207 {
1208 if(shortest2.distance<result2->shortest.distance)
1209 {
1210 result2->shortest.prev=node1;
1211 result2->shortest.distance=shortest2.distance;
1212
1213 if(!FindNode(finish,node2))
1214 insert_in_queue(result2);
1215 }
1216 }
1217
1218 endloop:
1219
1220 segment=FindNextSegment(segments,segment);
1221 }
1222 }
1223
1224 return(results);
1225 }
1226
1227 #endif

Properties

Name Value
cvs:description Route optimiser.