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 89 - (hide annotations) (download) (as text)
Wed Jan 28 18:46:55 2009 UTC (16 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 35195 byte(s)
Intermediate version while transitioning data format for nodes and segments.

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

Properties

Name Value
cvs:description Route optimiser.