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 460 - (show annotations) (download) (as text)
Sat Jul 24 10:09:07 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 23898 byte(s)
Finished slim mode for the router by adding ways.

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

Properties

Name Value
cvs:description Route optimiser.