Routino SVN Repository Browser

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

ViewVC logotype

Annotation of /trunk/src/optimiser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 149 - (hide annotations) (download) (as text)
Sat Mar 28 14:31:06 2009 UTC (16 years ago) by amb
File MIME type: text/x-csrc
File size: 31657 byte(s)
Fix file headers (again) and fix segment distance/duration for abbreviated text
output.

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

Properties

Name Value
cvs:description Route optimiser.