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 135 - (hide annotations) (download) (as text)
Sun Mar 1 17:24:22 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 30038 byte(s)
Added more limits (weight, height, width, length).

1 amb 2 /***************************************
2 amb 135 $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.55 2009-03-01 17:24:21 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 55 FILE *textfile,*gpxfile;
634 amb 2 Result *result;
635    
636 amb 113 if(option_quickest==0)
637     {
638     /* Print the result for the shortest route */
639 amb 2
640 amb 113 textfile=fopen("shortest.txt","w");
641     gpxfile=fopen("shortest.gpx","w");
642     }
643     else
644 amb 2 {
645 amb 113 /* Print the result for the quickest route */
646 amb 43
647 amb 113 textfile=fopen("quickest.txt","w");
648     gpxfile=fopen("quickest.gpx","w");
649 amb 2 }
650    
651 amb 55 fprintf(gpxfile,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
652     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");
653     fprintf(gpxfile,"<trk>\n");
654     fprintf(gpxfile,"<trkseg>\n");
655    
656 amb 31 result=FindResult(results,start);
657 amb 2
658     do
659     {
660 amb 99 float latitude,longitude;
661 amb 88 Node *node=LookupNode(nodes,result->node);
662 amb 43
663 amb 99 GetLatLong(nodes,node,&latitude,&longitude);
664 amb 55
665 amb 121 fprintf(gpxfile,"<trkpt lat=\"%.6f\" lon=\"%.6f\"></trkpt>\n",
666     (180/M_PI)*latitude,(180/M_PI)*longitude);
667 amb 99
668 amb 113 if(result->prev)
669 amb 2 {
670 amb 6 Segment *segment;
671     Way *way;
672 amb 2
673 amb 113 segment=FirstSegment(segments,LookupNode(nodes,result->prev));
674 amb 119 while(OtherNode(segment,result->prev)!=result->node)
675 amb 113 segment=NextSegment(segments,segment,result->prev);
676 amb 2
677 amb 96 way=LookupWay(ways,segment->way);
678 amb 6
679 amb 121 fprintf(textfile,"%8.4f %9.4f %8d%c %5.3f %5.2f %7.2f %5.1f %3d %s\n",
680     (180/M_PI)*latitude,(180/M_PI)*longitude,
681 amb 90 result->node,IsSuperNode(node)?'*':' ',
682 amb 105 distance_to_km(DISTANCE(segment->distance)),duration_to_minutes(Duration(segment,way,profile)),
683 amb 113 distance_to_km(result->distance),duration_to_minutes(result->duration),
684 amb 82 profile->speed[HIGHWAY(way->type)],WayName(ways,way));
685 amb 34 }
686     else
687 amb 121 fprintf(textfile,"%8.4f %9.4f %8d%c %5.3f %5.2f %7.2f %5.1f\n",
688     (180/M_PI)*latitude,(180/M_PI)*longitude,
689 amb 90 result->node,IsSuperNode(node)?'*':' ',
690 amb 34 0.0,0.0,0.0,0.0);
691 amb 2
692 amb 113 if(result->next)
693     result=FindResult(results,result->next);
694 amb 2 else
695     result=NULL;
696     }
697 amb 113 while(result);
698 amb 2
699 amb 55 fprintf(gpxfile,"</trkseg>\n");
700     fprintf(gpxfile,"</trk>\n");
701     fprintf(gpxfile,"</gpx>\n");
702    
703     fclose(textfile);
704     fclose(gpxfile);
705 amb 31 }
706 amb 3
707    
708 amb 31 /*++++++++++++++++++++++++++++++++++++++
709 amb 95 Find all routes from a specified node to any super-node.
710 amb 3
711 amb 126 Results *FindStartRoutes Returns a set of results.
712 amb 31
713     Nodes *nodes The set of nodes to use.
714    
715     Segments *segments The set of segments to use.
716    
717 amb 54 Ways *ways The set of ways to use.
718    
719 amb 96 index_t start The start node.
720 amb 31
721 amb 82 Profile *profile The profile containing the transport type, speeds and allowed highways.
722 amb 31 ++++++++++++++++++++++++++++++++++++++*/
723    
724 amb 126 Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile)
725 amb 31 {
726     Results *results;
727 amb 96 index_t node1,node2;
728 amb 31 Result *result1,*result2;
729     Segment *segment;
730 amb 54 Way *way;
731 amb 31
732     /* Insert the first node into the queue */
733    
734 amb 71 results=NewResultsList(8);
735 amb 31
736     result1=InsertResult(results,start);
737    
738     result1->node=start;
739 amb 113 result1->prev=0;
740     result1->next=0;
741     result1->distance=0;
742     result1->duration=0;
743 amb 119 result1->sortby=0;
744 amb 31
745 amb 79 insert_in_queue(result1);
746 amb 31
747     /* Loop across all nodes in the queue */
748    
749 amb 79 while((result1=pop_from_queue()))
750 amb 31 {
751 amb 43 node1=result1->node;
752 amb 31
753 amb 95 segment=FirstSegment(segments,LookupNode(nodes,node1));
754 amb 31
755     while(segment)
756     {
757 amb 113 distance_t cumulative_distance;
758     duration_t cumulative_duration;
759 amb 59
760 amb 95 if(!IsNormalSegment(segment))
761     goto endloop;
762    
763 amb 105 if(profile->oneway && IsOnewayTo(segment,node1))
764 amb 64 goto endloop;
765    
766 amb 105 node2=OtherNode(segment,node1);
767 amb 31
768 amb 113 if(result1->prev==node2)
769 amb 64 goto endloop;
770    
771 amb 96 way=LookupWay(ways,segment->way);
772 amb 54
773 amb 82 if(!(way->allow&profile->allow))
774 amb 54 goto endloop;
775    
776 amb 82 if(!profile->highways[HIGHWAY(way->type)])
777 amb 75 goto endloop;
778    
779 amb 135 if(way->weight<profile->weight)
780     goto endloop;
781    
782     if(way->height<profile->height || way->width<profile->width || way->length<profile->length)
783     goto endloop;
784    
785 amb 113 cumulative_distance=result1->distance+DISTANCE(segment->distance);
786     cumulative_duration=result1->duration+Duration(segment,way,profile);
787 amb 59
788 amb 31 result2=FindResult(results,node2);
789    
790     if(!result2) /* New end node */
791     {
792     result2=InsertResult(results,node2);
793     result2->node=node2;
794 amb 113 result2->prev=node1;
795     result2->next=0;
796     result2->distance=cumulative_distance;
797     result2->duration=cumulative_duration;
798 amb 31
799 amb 95 if(!IsSuperNode(LookupNode(nodes,node2)))
800 amb 119 {
801     result2->sortby=result2->distance;
802 amb 79 insert_in_queue(result2);
803 amb 119 }
804 amb 31 }
805 amb 113 else if(option_quickest==0) /* shortest */
806 amb 31 {
807 amb 113 if(cumulative_distance<result2->distance ||
808     (cumulative_distance==result2->distance &&
809     cumulative_duration<result2->duration)) /* New end node is shorter */
810 amb 31 {
811 amb 113 result2->prev=node1;
812     result2->distance=cumulative_distance;
813     result2->duration=cumulative_duration;
814 amb 31
815 amb 95 if(!IsSuperNode(LookupNode(nodes,node2)))
816 amb 119 {
817     result2->sortby=result2->distance;
818 amb 79 insert_in_queue(result2);
819 amb 119 }
820 amb 31 }
821 amb 113 }
822     else if(option_quickest==1) /* quickest */
823     {
824     if(cumulative_duration<result2->duration ||
825     (cumulative_duration==result2->duration &&
826     cumulative_distance<result2->distance)) /* New end node is quicker */
827 amb 31 {
828 amb 113 result2->prev=node1;
829     result2->distance=cumulative_distance;
830     result2->duration=cumulative_duration;
831 amb 31
832 amb 95 if(!IsSuperNode(LookupNode(nodes,node2)))
833 amb 119 {
834     result2->sortby=result2->duration;
835 amb 79 insert_in_queue(result2);
836 amb 119 }
837 amb 31 }
838     }
839    
840     endloop:
841    
842 amb 104 segment=NextSegment(segments,segment,node1);
843 amb 31 }
844     }
845    
846 amb 112 /* Check it worked */
847    
848     if(results->number==1)
849     {
850     FreeResultsList(results);
851     return(NULL);
852     }
853    
854 amb 31 return(results);
855 amb 2 }
856    
857    
858     /*++++++++++++++++++++++++++++++++++++++
859 amb 95 Find all routes from any super-node to a specific node.
860 amb 34
861 amb 126 Results *FindFinishRoutes Returns a set of results.
862 amb 34
863     Nodes *nodes The set of nodes to use.
864    
865     Segments *segments The set of segments to use.
866    
867 amb 54 Ways *ways The set of ways to use.
868    
869 amb 96 index_t finish The finishing node.
870 amb 54
871 amb 82 Profile *profile The profile containing the transport type, speeds and allowed highways.
872 amb 34 ++++++++++++++++++++++++++++++++++++++*/
873    
874 amb 126 Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t finish,Profile *profile)
875 amb 34 {
876     Results *results;
877 amb 96 index_t node1,node2;
878 amb 34 Result *result1,*result2;
879     Segment *segment;
880 amb 54 Way *way;
881 amb 34
882     /* Insert the first node into the queue */
883    
884 amb 71 results=NewResultsList(8);
885 amb 34
886     result1=InsertResult(results,finish);
887    
888     result1->node=finish;
889 amb 113 result1->prev=0;
890     result1->next=0;
891     result1->distance=0;
892     result1->duration=0;
893 amb 119 result1->sortby=0;
894 amb 34
895 amb 79 insert_in_queue(result1);
896 amb 34
897     /* Loop across all nodes in the queue */
898    
899 amb 79 while((result1=pop_from_queue()))
900 amb 34 {
901 amb 43 node1=result1->node;
902 amb 34
903 amb 95 segment=FirstSegment(segments,LookupNode(nodes,node1));
904 amb 34
905     while(segment)
906     {
907 amb 113 distance_t cumulative_distance;
908     duration_t cumulative_duration;
909 amb 59
910 amb 104 if(!IsNormalSegment(segment))
911 amb 34 goto endloop;
912    
913 amb 105 if(profile->oneway && IsOnewayFrom(segment,node1))
914 amb 95 goto endloop;
915    
916 amb 105 node2=OtherNode(segment,node1);
917 amb 64
918 amb 113 if(result1->next==node2)
919 amb 64 goto endloop;
920    
921 amb 104 way=LookupWay(ways,segment->way);
922 amb 54
923 amb 82 if(!(way->allow&profile->allow))
924 amb 54 goto endloop;
925    
926 amb 82 if(!profile->highways[HIGHWAY(way->type)])
927 amb 75 goto endloop;
928    
929 amb 135 if(way->weight<profile->weight)
930     goto endloop;
931    
932     if(way->height<profile->height || way->width<profile->width || way->length<profile->length)
933     goto endloop;
934    
935 amb 113 cumulative_distance=result1->distance+DISTANCE(segment->distance);
936     cumulative_duration=result1->duration+Duration(segment,way,profile);
937 amb 59
938 amb 34 result2=FindResult(results,node2);
939    
940     if(!result2) /* New end node */
941     {
942     result2=InsertResult(results,node2);
943     result2->node=node2;
944 amb 113 result2->prev=0;
945     result2->next=node1;
946     result2->distance=cumulative_distance;
947     result2->duration=cumulative_duration;
948 amb 34
949 amb 95 if(!IsSuperNode(LookupNode(nodes,node2)))
950 amb 119 {
951     result2->sortby=result2->distance;
952 amb 79 insert_in_queue(result2);
953 amb 119 }
954 amb 34 }
955 amb 113 else if(option_quickest==0) /* shortest */
956 amb 34 {
957 amb 113 if(cumulative_distance<result2->distance ||
958     (cumulative_distance==result2->distance &&
959     cumulative_duration<result2->duration)) /* New end node is shorter */
960 amb 34 {
961 amb 113 result2->next=node1;
962     result2->distance=cumulative_distance;
963     result2->duration=cumulative_duration;
964 amb 34
965 amb 95 if(!IsSuperNode(LookupNode(nodes,node2)))
966 amb 119 {
967     result2->sortby=result2->distance;
968 amb 79 insert_in_queue(result2);
969 amb 119 }
970 amb 34 }
971 amb 113 }
972     else if(option_quickest==1) /* quickest */
973     {
974     if(cumulative_duration<result2->duration ||
975     (cumulative_duration==result2->duration &&
976     cumulative_distance<result2->distance)) /* New end node is quicker */
977 amb 34 {
978 amb 113 result2->next=node1;
979     result2->distance=cumulative_distance;
980     result2->duration=cumulative_duration;
981 amb 34
982 amb 95 if(!IsSuperNode(LookupNode(nodes,node2)))
983 amb 119 {
984     result2->sortby=result2->duration;
985 amb 79 insert_in_queue(result2);
986 amb 119 }
987 amb 34 }
988     }
989    
990     endloop:
991    
992 amb 104 segment=NextSegment(segments,segment,node1);
993 amb 34 }
994     }
995    
996 amb 112 /* Check it worked */
997    
998     if(results->number==1)
999     {
1000     FreeResultsList(results);
1001     return(NULL);
1002     }
1003    
1004 amb 34 return(results);
1005     }
1006    
1007    
1008     /*++++++++++++++++++++++++++++++++++++++
1009 amb 95 Create an optimum route given the set of super-nodes to follow.
1010 amb 31
1011 amb 58 Results *CombineRoutes Returns the results from joining the super-nodes.
1012 amb 55
1013 amb 58 Results *results The set of results from the super-nodes.
1014 amb 31
1015     Nodes *nodes The list of nodes.
1016    
1017     Segments *segments The set of segments to use.
1018    
1019     Ways *ways The list of ways.
1020    
1021 amb 96 index_t start The start node.
1022 amb 31
1023 amb 96 index_t finish The finish node.
1024 amb 54
1025 amb 82 Profile *profile The profile containing the transport type, speeds and allowed highways.
1026 amb 31 ++++++++++++++++++++++++++++++++++++++*/
1027    
1028 amb 96 Results *CombineRoutes(Results *results,Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile)
1029 amb 31 {
1030     Result *result1,*result2,*result3,*result4;
1031     Results *combined;
1032 amb 107 int quiet=option_quiet;
1033 amb 31
1034 amb 71 combined=NewResultsList(64);
1035 amb 31
1036 amb 107 option_quiet=1;
1037 amb 31
1038 amb 113 /* Sort out the combined route */
1039 amb 31
1040     result1=FindResult(results,start);
1041    
1042 amb 58 result3=InsertResult(combined,start);
1043 amb 31
1044 amb 58 result3->node=result1->node;
1045 amb 36
1046 amb 113 result3->distance=0;
1047     result3->duration=0;
1048     result3->next=0;
1049     result3->prev=0;
1050 amb 31
1051 amb 58 do
1052     {
1053 amb 113 if(result1->next)
1054 amb 31 {
1055 amb 113 Results *results2=FindRoute(nodes,segments,ways,result1->node,result1->next,profile,0);
1056 amb 31
1057     result2=FindResult(results2,result1->node);
1058    
1059 amb 113 result3->next=result2->next;
1060 amb 36
1061 amb 113 result2=FindResult(results2,result2->next);
1062 amb 36
1063 amb 31 do
1064     {
1065 amb 58 result4=InsertResult(combined,result2->node);
1066 amb 31
1067 amb 58 result4->node=result2->node;
1068 amb 36
1069 amb 113 *result4=*result2;
1070     result4->distance+=result3->distance;
1071     result4->duration+=result3->duration;
1072 amb 31
1073 amb 113 if(result2->next)
1074     result2=FindResult(results2,result2->next);
1075 amb 31 else
1076     result2=NULL;
1077     }
1078     while(result2);
1079    
1080     FreeResultsList(results2);
1081    
1082 amb 113 result1=FindResult(results,result1->next);
1083 amb 58
1084     result3=result4;
1085 amb 31 }
1086     else
1087     result1=NULL;
1088     }
1089     while(result1);
1090    
1091     /* Now print out the result normally */
1092    
1093 amb 107 option_quiet=quiet;
1094 amb 31
1095 amb 55 return(combined);
1096 amb 31 }

Properties

Name Value
cvs:description Route optimiser.