Routino SVN Repository Browser

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

ViewVC logotype

Contents of /trunk/src/optimiser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download) (as text)
Sat Nov 27 14:56:37 2010 UTC (14 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 24916 byte(s)
Split functions.h into fakes.h, sorting.h and the remainder in functions.h.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.96 2010-11-27 14:56:37 amb Exp $
3
4 Routing optimiser.
5
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008-2010 Andrew M. Bishop
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Affero General Public License for more details.
19
20 You should have received a copy of the GNU Affero General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 ***************************************/
23
24
25 #include <stdio.h>
26
27 #include "types.h"
28 #include "nodes.h"
29 #include "segments.h"
30 #include "ways.h"
31
32 #include "logging.h"
33 #include "functions.h"
34 #include "fakes.h"
35 #include "results.h"
36
37
38 /*+ The option not to print any progress information. +*/
39 extern int option_quiet;
40
41 /*+ The option to calculate the quickest route insted of the shortest. +*/
42 extern int option_quickest;
43
44
45 /*++++++++++++++++++++++++++++++++++++++
46 Find the optimum route between two nodes not passing through a super-node.
47
48 Results *FindNormalRoute Returns a set of results.
49
50 Nodes *nodes The set of nodes to use.
51
52 Segments *segments The set of segments to use.
53
54 Ways *ways The set of ways to use.
55
56 index_t start The start node.
57
58 index_t finish The finish node.
59
60 Profile *profile The profile containing the transport type, speeds and allowed highways.
61 ++++++++++++++++++++++++++++++++++++++*/
62
63 Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile)
64 {
65 Results *results;
66 Queue *queue;
67 index_t node1,node2;
68 score_t finish_score;
69 double finish_lat,finish_lon;
70 Result *result1,*result2;
71 Node *node;
72 Segment *segment;
73 Way *way;
74
75 /* Set up the finish conditions */
76
77 finish_score=INF_SCORE;
78
79 if(IsFakeNode(finish))
80 GetFakeLatLong(finish,&finish_lat,&finish_lon);
81 else
82 GetLatLong(nodes,finish,&finish_lat,&finish_lon);
83
84 /* Create the list of results and insert the first node into the queue */
85
86 results=NewResultsList(8);
87
88 results->start=start;
89 results->finish=finish;
90
91 result1=InsertResult(results,start);
92
93 ZeroResult(result1);
94
95 queue=NewQueueList();
96
97 InsertInQueue(queue,result1);
98
99 /* Loop across all nodes in the queue */
100
101 while((result1=PopFromQueue(queue)))
102 {
103 if(result1->score>finish_score)
104 continue;
105
106 node1=result1->node;
107
108 if(IsFakeNode(node1))
109 segment=FirstFakeSegment(node1);
110 else
111 segment=FirstSegment(segments,nodes,node1);
112
113 while(segment)
114 {
115 score_t segment_pref,segment_score,cumulative_score;
116 int i;
117
118 node2=OtherNode(segment,node1); /* need this here because we use node2 later */
119
120 if(!IsNormalSegment(segment))
121 goto endloop;
122
123 if(profile->oneway && IsOnewayTo(segment,node1))
124 goto endloop;
125
126 if(result1->prev==node2)
127 goto endloop;
128
129 if(node2!=finish && !IsFakeNode(node2) && IsSuperNode(nodes,node2))
130 goto endloop;
131
132 way=LookupWay(ways,segment->way,1);
133
134 if(!(way->allow&profile->allow))
135 goto endloop;
136
137 if(!profile->highway[HIGHWAY(way->type)])
138 goto endloop;
139
140 if(way->weight && way->weight<profile->weight)
141 goto endloop;
142
143 if((way->height && way->height<profile->height) ||
144 (way->width && way->width <profile->width ) ||
145 (way->length && way->length<profile->length))
146 goto endloop;
147
148 segment_pref=profile->highway[HIGHWAY(way->type)];
149
150 for(i=1;i<Property_Count;i++)
151 if(ways->file.props & PROPERTIES(i))
152 {
153 if(way->props & PROPERTIES(i))
154 segment_pref*=profile->props_yes[i];
155 else
156 segment_pref*=profile->props_no[i];
157 }
158
159 if(segment_pref==0)
160 goto endloop;
161
162 if(!IsFakeNode(node2))
163 {
164 node=LookupNode(nodes,node2,1);
165
166 if(!(node->allow&profile->allow))
167 goto endloop;
168 }
169
170 if(option_quickest==0)
171 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
172 else
173 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
174
175 cumulative_score=result1->score+segment_score;
176
177 if(cumulative_score>finish_score)
178 goto endloop;
179
180 result2=FindResult(results,node2);
181
182 if(!result2) /* New end node */
183 {
184 result2=InsertResult(results,node2);
185 result2->prev=node1;
186 result2->next=NO_NODE;
187 result2->score=cumulative_score;
188 if(IsFakeNode(node1) || IsFakeNode(node2))
189 result2->segment=IndexFakeSegment(segment);
190 else
191 result2->segment=IndexSegment(segments,segment);
192
193 if(node2==finish)
194 {
195 finish_score=cumulative_score;
196 }
197 else
198 {
199 result2->sortby=result2->score;
200
201 InsertInQueue(queue,result2);
202 }
203 }
204 else if(cumulative_score<result2->score) /* New end node is better */
205 {
206 result2->prev=node1;
207 result2->score=cumulative_score;
208 if(IsFakeNode(node1) || IsFakeNode(node2))
209 result2->segment=IndexFakeSegment(segment);
210 else
211 result2->segment=IndexSegment(segments,segment);
212
213 if(node2==finish)
214 {
215 finish_score=cumulative_score;
216 }
217 else
218 {
219 result2->sortby=result2->score;
220
221 if(result2->score<finish_score)
222 InsertInQueue(queue,result2);
223 }
224 }
225
226 endloop:
227
228 if(IsFakeNode(node1))
229 segment=NextFakeSegment(segment,node1);
230 else if(IsFakeNode(node2))
231 segment=NULL; /* cannot call NextSegment() with a fake segment */
232 else
233 {
234 segment=NextSegment(segments,segment,node1);
235
236 if(!segment && IsFakeNode(finish))
237 segment=ExtraFakeSegment(node1,finish);
238 }
239 }
240 }
241
242 FreeQueueList(queue);
243
244 /* Check it worked */
245
246 if(!FindResult(results,finish))
247 {
248 FreeResultsList(results);
249 return(NULL);
250 }
251
252 FixForwardRoute(results,finish);
253
254 return(results);
255 }
256
257
258 /*++++++++++++++++++++++++++++++++++++++
259 Find the optimum route between two nodes where the start and end are a set of pre-routed super-nodes.
260
261 Results *FindMiddleRoute Returns a set of results.
262
263 Nodes *nodes The set of nodes to use.
264
265 Segments *segments The set of segments to use.
266
267 Ways *ways The set of ways to use.
268
269 Results *begin The initial portion of the route.
270
271 Results *end The final portion of the route.
272
273 Profile *profile The profile containing the transport type, speeds and allowed highways.
274 ++++++++++++++++++++++++++++++++++++++*/
275
276 Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *begin,Results *end,Profile *profile)
277 {
278 Results *results;
279 Queue *queue;
280 index_t node1,node2;
281 index_t end_prev;
282 score_t finish_score;
283 double finish_lat,finish_lon;
284 Result *result1,*result2,*result3;
285 Node *node;
286 Segment *segment;
287 Way *way;
288
289 if(!option_quiet)
290 printf_first("Routing: Super-Nodes checked = 0");
291
292 /* Set up the finish conditions */
293
294 finish_score=INF_DISTANCE;
295 end_prev=NO_NODE;
296
297 if(IsFakeNode(end->finish))
298 GetFakeLatLong(end->finish,&finish_lat,&finish_lon);
299 else
300 GetLatLong(nodes,end->finish,&finish_lat,&finish_lon);
301
302 /* Create the list of results and insert the first node into the queue */
303
304 results=NewResultsList(2048);
305
306 results->start=begin->start;
307 results->finish=end->finish;
308
309 result1=InsertResult(results,begin->start);
310 result3=FindResult(begin,begin->start);
311
312 *result1=*result3;
313
314 queue=NewQueueList();
315
316 /* Insert the finish points of the beginning part of the path into the queue */
317
318 result3=FirstResult(begin);
319
320 while(result3)
321 {
322 if(result3->node!=begin->start && !IsFakeNode(result3->node) && IsSuperNode(nodes,result3->node))
323 {
324 result2=InsertResult(results,result3->node);
325
326 *result2=*result3;
327
328 result2->prev=begin->start;
329
330 result2->sortby=result2->score;
331
332 InsertInQueue(queue,result2);
333 }
334
335 result3=NextResult(begin,result3);
336 }
337
338 if(begin->number==1)
339 InsertInQueue(queue,result1);
340
341 /* Loop across all nodes in the queue */
342
343 while((result1=PopFromQueue(queue)))
344 {
345 if(result1->score>finish_score)
346 continue;
347
348 node1=result1->node;
349
350 segment=FirstSegment(segments,nodes,node1);
351
352 while(segment)
353 {
354 score_t segment_pref,segment_score,cumulative_score;
355 int i;
356
357 if(!IsSuperSegment(segment))
358 goto endloop;
359
360 if(profile->oneway && IsOnewayTo(segment,node1))
361 goto endloop;
362
363 node2=OtherNode(segment,node1);
364
365 if(result1->prev==node2)
366 goto endloop;
367
368 way=LookupWay(ways,segment->way,1);
369
370 if(!(way->allow&profile->allow))
371 goto endloop;
372
373 if(!profile->highway[HIGHWAY(way->type)])
374 goto endloop;
375
376 if(way->weight && way->weight<profile->weight)
377 goto endloop;
378
379 if((way->height && way->height<profile->height) ||
380 (way->width && way->width <profile->width ) ||
381 (way->length && way->length<profile->length))
382 goto endloop;
383
384 segment_pref=profile->highway[HIGHWAY(way->type)];
385
386 for(i=1;i<Property_Count;i++)
387 if(ways->file.props & PROPERTIES(i))
388 {
389 if(way->props & PROPERTIES(i))
390 segment_pref*=profile->props_yes[i];
391 else
392 segment_pref*=profile->props_no[i];
393 }
394
395 if(segment_pref==0)
396 goto endloop;
397
398 node=LookupNode(nodes,node2,1);
399
400 if(!(node->allow&profile->allow))
401 goto endloop;
402
403 if(option_quickest==0)
404 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
405 else
406 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
407
408 cumulative_score=result1->score+segment_score;
409
410 if(cumulative_score>finish_score)
411 goto endloop;
412
413 result2=FindResult(results,node2);
414
415 if(!result2) /* New end node */
416 {
417 result2=InsertResult(results,node2);
418 result2->prev=node1;
419 result2->next=NO_NODE;
420 result2->score=cumulative_score;
421 result2->segment=IndexSegment(segments,segment);
422
423 if((result3=FindResult(end,node2)))
424 {
425 if((result2->score+result3->score)<finish_score)
426 {
427 finish_score=result2->score+result3->score;
428 end_prev=node2;
429 }
430 }
431 else
432 {
433 double lat,lon;
434 distance_t direct;
435
436 GetLatLong(nodes,node2,&lat,&lon);
437 direct=Distance(lat,lon,finish_lat,finish_lon);
438
439 if(option_quickest==0)
440 result2->sortby=result2->score+(score_t)direct/profile->max_pref;
441 else
442 result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
443
444 InsertInQueue(queue,result2);
445 }
446 }
447 else if(cumulative_score<result2->score) /* New end node is better */
448 {
449 result2->prev=node1;
450 result2->score=cumulative_score;
451 result2->segment=IndexSegment(segments,segment);
452
453 if((result3=FindResult(end,node2)))
454 {
455 if((result2->score+result3->score)<finish_score)
456 {
457 finish_score=result2->score+result3->score;
458 end_prev=node2;
459 }
460 }
461 else if(result2->score<finish_score)
462 {
463 double lat,lon;
464 distance_t direct;
465
466 GetLatLong(nodes,node2,&lat,&lon);
467 direct=Distance(lat,lon,finish_lat,finish_lon);
468
469 if(option_quickest==0)
470 result2->sortby=result2->score+(score_t)direct/profile->max_pref;
471 else
472 result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
473
474 InsertInQueue(queue,result2);
475 }
476 }
477
478 endloop:
479
480 if(!option_quiet && !(results->number%10000))
481 printf_middle("Routing: Super-Nodes checked = %d",results->number);
482
483 segment=NextSegment(segments,segment,node1);
484 }
485 }
486
487 if(!option_quiet)
488 printf_last("Routing: Super-Nodes checked = %d",results->number);
489
490 /* Finish off the end part of the route. */
491
492 if(!FindResult(results,end->finish) && end_prev!=NO_NODE)
493 {
494 result2=InsertResult(results,end->finish);
495 result3=FindResult(end,end->finish);
496
497 *result2=*result3;
498
499 result2->prev=end_prev;
500 result2->score=finish_score;
501 }
502
503 FreeQueueList(queue);
504
505 /* Check it worked */
506
507 if(end_prev==NO_NODE)
508 {
509 FreeResultsList(results);
510 return(NULL);
511 }
512
513 FixForwardRoute(results,end->finish);
514
515 return(results);
516 }
517
518
519 /*++++++++++++++++++++++++++++++++++++++
520 Find all routes from a specified node to any super-node.
521
522 Results *FindStartRoutes Returns a set of results.
523
524 Nodes *nodes The set of nodes to use.
525
526 Segments *segments The set of segments to use.
527
528 Ways *ways The set of ways to use.
529
530 index_t start The start node.
531
532 Profile *profile The profile containing the transport type, speeds and allowed highways.
533 ++++++++++++++++++++++++++++++++++++++*/
534
535 Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile)
536 {
537 Results *results;
538 Queue *queue;
539 index_t node1,node2;
540 Result *result1,*result2;
541 Node *node;
542 Segment *segment;
543 Way *way;
544
545 /* Create the results and insert the start node */
546
547 results=NewResultsList(8);
548
549 results->start=start;
550
551 result1=InsertResult(results,start);
552
553 ZeroResult(result1);
554
555 /* Take a shortcut if the first node is a super-node. */
556
557 if(!IsFakeNode(start) && IsSuperNode(nodes,start))
558 return(results);
559
560 /* Insert the first node into the queue */
561
562 queue=NewQueueList();
563
564 InsertInQueue(queue,result1);
565
566 /* Loop across all nodes in the queue */
567
568 while((result1=PopFromQueue(queue)))
569 {
570 node1=result1->node;
571
572 if(IsFakeNode(node1))
573 segment=FirstFakeSegment(node1);
574 else
575 segment=FirstSegment(segments,nodes,node1);
576
577 while(segment)
578 {
579 score_t segment_pref,segment_score,cumulative_score;
580 int i;
581
582 if(!IsNormalSegment(segment))
583 goto endloop;
584
585 if(profile->oneway && IsOnewayTo(segment,node1))
586 goto endloop;
587
588 node2=OtherNode(segment,node1);
589
590 if(result1->prev==node2)
591 goto endloop;
592
593 way=LookupWay(ways,segment->way,1);
594
595 if(!(way->allow&profile->allow))
596 goto endloop;
597
598 if(!profile->highway[HIGHWAY(way->type)])
599 goto endloop;
600
601 if(way->weight && way->weight<profile->weight)
602 goto endloop;
603
604 if((way->height && way->height<profile->height) ||
605 (way->width && way->width <profile->width ) ||
606 (way->length && way->length<profile->length))
607 goto endloop;
608
609 segment_pref=profile->highway[HIGHWAY(way->type)];
610
611 for(i=1;i<Property_Count;i++)
612 if(ways->file.props & PROPERTIES(i))
613 {
614 if(way->props & PROPERTIES(i))
615 segment_pref*=profile->props_yes[i];
616 else
617 segment_pref*=profile->props_no[i];
618 }
619
620 if(segment_pref==0)
621 goto endloop;
622
623 if(!IsFakeNode(node2))
624 {
625 node=LookupNode(nodes,node2,1);
626
627 if(!(node->allow&profile->allow))
628 goto endloop;
629 }
630
631 if(option_quickest==0)
632 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
633 else
634 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
635
636 cumulative_score=result1->score+segment_score;
637
638 result2=FindResult(results,node2);
639
640 if(!result2) /* New end node */
641 {
642 result2=InsertResult(results,node2);
643 result2->prev=node1;
644 result2->next=NO_NODE;
645 result2->score=cumulative_score;
646 if(IsFakeNode(node1) || IsFakeNode(node2))
647 result2->segment=IndexFakeSegment(segment);
648 else
649 result2->segment=IndexSegment(segments,segment);
650
651 if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2))
652 {
653 result2->sortby=result2->score;
654 InsertInQueue(queue,result2);
655 }
656 }
657 else if(cumulative_score<result2->score) /* New end node is better */
658 {
659 result2->prev=node1;
660 result2->score=cumulative_score;
661 if(IsFakeNode(node1) || IsFakeNode(node2))
662 result2->segment=IndexFakeSegment(segment);
663 else
664 result2->segment=IndexSegment(segments,segment);
665
666 if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2))
667 {
668 result2->sortby=result2->score;
669 InsertInQueue(queue,result2);
670 }
671 }
672
673 endloop:
674
675 if(IsFakeNode(node1))
676 segment=NextFakeSegment(segment,node1);
677 else
678 segment=NextSegment(segments,segment,node1);
679 }
680 }
681
682 FreeQueueList(queue);
683
684 /* Check it worked */
685
686 if(results->number==1)
687 {
688 FreeResultsList(results);
689 return(NULL);
690 }
691
692 return(results);
693 }
694
695
696 /*++++++++++++++++++++++++++++++++++++++
697 Find all routes from any super-node to a specific node.
698
699 Results *FindFinishRoutes Returns a set of results.
700
701 Nodes *nodes The set of nodes to use.
702
703 Segments *segments The set of segments to use.
704
705 Ways *ways The set of ways to use.
706
707 index_t finish The finishing node.
708
709 Profile *profile The profile containing the transport type, speeds and allowed highways.
710 ++++++++++++++++++++++++++++++++++++++*/
711
712 Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t finish,Profile *profile)
713 {
714 Results *results;
715 Queue *queue;
716 index_t node1,node2;
717 Result *result1,*result2;
718 Node *node;
719 Segment *segment;
720 Way *way;
721
722 /* Create the results and insert the finish node */
723
724 results=NewResultsList(8);
725
726 results->finish=finish;
727
728 result1=InsertResult(results,finish);
729
730 ZeroResult(result1);
731
732 /* Take a shortcut if the first node is a super-node. */
733
734 if(!IsFakeNode(finish) && IsSuperNode(nodes,finish))
735 return(results);
736
737 /* Insert the first node into the queue */
738
739 queue=NewQueueList();
740
741 InsertInQueue(queue,result1);
742
743 /* Loop across all nodes in the queue */
744
745 while((result1=PopFromQueue(queue)))
746 {
747 node1=result1->node;
748
749 if(IsFakeNode(node1))
750 segment=FirstFakeSegment(node1);
751 else
752 segment=FirstSegment(segments,nodes,node1);
753
754 while(segment)
755 {
756 score_t segment_pref,segment_score,cumulative_score;
757 int i;
758
759 if(!IsNormalSegment(segment))
760 goto endloop;
761
762 if(profile->oneway && IsOnewayFrom(segment,node1))
763 goto endloop;
764
765 node2=OtherNode(segment,node1);
766
767 if(result1->next==node2)
768 goto endloop;
769
770 way=LookupWay(ways,segment->way,1);
771
772 if(!(way->allow&profile->allow))
773 goto endloop;
774
775 if(!profile->highway[HIGHWAY(way->type)])
776 goto endloop;
777
778 if(way->weight && way->weight<profile->weight)
779 goto endloop;
780
781 if((way->height && way->height<profile->height) ||
782 (way->width && way->width <profile->width ) ||
783 (way->length && way->length<profile->length))
784 goto endloop;
785
786 segment_pref=profile->highway[HIGHWAY(way->type)];
787
788 for(i=1;i<Property_Count;i++)
789 if(ways->file.props & PROPERTIES(i))
790 {
791 if(way->props & PROPERTIES(i))
792 segment_pref*=profile->props_yes[i];
793 else
794 segment_pref*=profile->props_no[i];
795 }
796
797 if(segment_pref==0)
798 goto endloop;
799
800 if(!IsFakeNode(node2))
801 {
802 node=LookupNode(nodes,node2,1);
803
804 if(!(node->allow&profile->allow))
805 goto endloop;
806 }
807
808 if(option_quickest==0)
809 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
810 else
811 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
812
813 cumulative_score=result1->score+segment_score;
814
815 result2=FindResult(results,node2);
816
817 if(!result2) /* New end node */
818 {
819 result2=InsertResult(results,node2);
820 result2->prev=NO_NODE;
821 result2->next=node1;
822 result2->score=cumulative_score;
823 if(IsFakeNode(node1) || IsFakeNode(node2))
824 result2->segment=IndexFakeSegment(segment);
825 else
826 result2->segment=IndexSegment(segments,segment);
827
828 if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2))
829 {
830 result2->sortby=result2->score;
831 InsertInQueue(queue,result2);
832 }
833 }
834 else if(cumulative_score<result2->score) /* New end node is better */
835 {
836 result2->next=node1;
837 result2->score=cumulative_score;
838 if(IsFakeNode(node1) || IsFakeNode(node2))
839 result2->segment=IndexFakeSegment(segment);
840 else
841 result2->segment=IndexSegment(segments,segment);
842
843 if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2))
844 {
845 result2->sortby=result2->score;
846 InsertInQueue(queue,result2);
847 }
848 }
849
850 endloop:
851
852 if(IsFakeNode(node1))
853 segment=NextFakeSegment(segment,node1);
854 else
855 segment=NextSegment(segments,segment,node1);
856 }
857 }
858
859 FreeQueueList(queue);
860
861 /* Check it worked */
862
863 if(results->number==1)
864 {
865 FreeResultsList(results);
866 return(NULL);
867 }
868
869 return(results);
870 }
871
872
873 /*++++++++++++++++++++++++++++++++++++++
874 Create an optimum route given the set of super-nodes to follow.
875
876 Results *CombineRoutes Returns the results from joining the super-nodes.
877
878 Results *results The set of results from the super-nodes.
879
880 Nodes *nodes The list of nodes.
881
882 Segments *segments The set of segments to use.
883
884 Ways *ways The list of ways.
885
886 Profile *profile The profile containing the transport type, speeds and allowed highways.
887 ++++++++++++++++++++++++++++++++++++++*/
888
889 Results *CombineRoutes(Results *results,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile)
890 {
891 Result *result1,*result2,*result3,*result4;
892 Results *combined;
893
894 combined=NewResultsList(64);
895
896 combined->start=results->start;
897 combined->finish=results->finish;
898
899 /* Sort out the combined route */
900
901 result1=FindResult(results,results->start);
902
903 result3=InsertResult(combined,results->start);
904
905 ZeroResult(result3);
906
907 do
908 {
909 if(result1->next!=NO_NODE)
910 {
911 Results *results2=FindNormalRoute(nodes,segments,ways,result1->node,result1->next,profile);
912
913 result2=FindResult(results2,result1->node);
914
915 result3->next=result2->next;
916
917 result2=FindResult(results2,result2->next);
918
919 do
920 {
921 result4=InsertResult(combined,result2->node);
922
923 *result4=*result2;
924 result4->score+=result3->score;
925
926 if(result2->next!=NO_NODE)
927 result2=FindResult(results2,result2->next);
928 else
929 result2=NULL;
930 }
931 while(result2);
932
933 FreeResultsList(results2);
934
935 result1=FindResult(results,result1->next);
936
937 result3=result4;
938 }
939 else
940 result1=NULL;
941 }
942 while(result1);
943
944 return(combined);
945 }
946
947
948 /*++++++++++++++++++++++++++++++++++++++
949 Fx the forward route (i.e. setup next nodes for forward path from prev nodes on reverse path).
950
951 Results *results The set of results to update.
952
953 index_t finish The finish point.
954 ++++++++++++++++++++++++++++++++++++++*/
955
956 void FixForwardRoute(Results *results,index_t finish)
957 {
958 Result *result2=FindResult(results,finish);
959 Result *result1;
960
961 /* Create the forward links for the optimum path */
962
963 do
964 {
965 if(result2->prev!=NO_NODE)
966 {
967 index_t node1=result2->prev;
968
969 result1=FindResult(results,node1);
970
971 result1->next=result2->node;
972
973 result2=result1;
974 }
975 else
976 result2=NULL;
977 }
978 while(result2);
979
980 results->finish=finish;
981 }

Properties

Name Value
cvs:description Route optimiser.