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 99 - (show annotations) (download) (as text)
Wed Feb 4 18:23:33 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 32674 byte(s)
Sort the nodes geographically and take coordinates as command line arguments.

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

Properties

Name Value
cvs:description Route optimiser.