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 142 - (show annotations) (download) (as text)
Sat Mar 7 14:26:55 2009 UTC (16 years ago) by amb
File MIME type: text/x-csrc
File size: 31035 byte(s)
Renamed the *.txt output to *-all.txt and added a new shorted *.txt output.

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

Properties

Name Value
cvs:description Route optimiser.