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 955 - (hide annotations) (download) (as text)
Sat Jan 28 14:40:54 2012 UTC (13 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 37453 byte(s)
Simplify and standardise the included headers.

1 amb 2 /***************************************
2     Routing optimiser.
3 amb 151
4     Part of the Routino routing software.
5 amb 2 ******************/ /******************
6 amb 955 This file Copyright 2008-2012 Andrew M. Bishop
7 amb 2
8 amb 151 This program is free software: you can redistribute it and/or modify
9     it under the terms of the GNU Affero General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12    
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU Affero General Public License for more details.
17    
18     You should have received a copy of the GNU Affero General Public License
19     along with this program. If not, see <http://www.gnu.org/licenses/>.
20 amb 2 ***************************************/
21    
22    
23 amb 712 #include <assert.h>
24 amb 2
25 amb 96 #include "types.h"
26 amb 109 #include "nodes.h"
27     #include "segments.h"
28     #include "ways.h"
29 amb 596 #include "relations.h"
30 amb 449
31 amb 519 #include "logging.h"
32 amb 449 #include "functions.h"
33 amb 532 #include "fakes.h"
34 amb 28 #include "results.h"
35 amb 2
36 amb 26
37 amb 685 /* Global variables */
38    
39 amb 113 /*+ The option not to print any progress information. +*/
40 amb 107 extern int option_quiet;
41 amb 2
42 amb 113 /*+ The option to calculate the quickest route insted of the shortest. +*/
43     extern int option_quickest;
44 amb 31
45 amb 113
46 amb 685 /* Local functions */
47    
48 amb 721 static index_t FindSuperSegment(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t endnode,index_t endsegment);
49 amb 685
50    
51 amb 2 /*++++++++++++++++++++++++++++++++++++++
52 amb 727 Find the optimum route between two nodes not passing through a super-node.
53 amb 2
54 amb 238 Results *FindNormalRoute Returns a set of results.
55 amb 26
56     Nodes *nodes The set of nodes to use.
57    
58     Segments *segments The set of segments to use.
59    
60 amb 54 Ways *ways The set of ways to use.
61    
62 amb 542 Relations *relations The set of relations to use.
63    
64 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
65    
66 amb 605 index_t start_node The start node.
67 amb 2
68 amb 605 index_t prev_segment The previous segment before the start node.
69 amb 54
70 amb 605 index_t finish_node The finish node.
71 amb 2 ++++++++++++++++++++++++++++++++++++++*/
72    
73 amb 723 Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t start_node,index_t prev_segment,index_t finish_node)
74 amb 2 {
75 amb 31 Results *results;
76 amb 469 Queue *queue;
77 amb 166 score_t finish_score;
78 amb 219 double finish_lat,finish_lon;
79 amb 605 Result *finish_result;
80 amb 469 Result *result1,*result2;
81 amb 2
82 amb 10 /* Set up the finish conditions */
83    
84 amb 176 finish_score=INF_SCORE;
85 amb 605 finish_result=NULL;
86 amb 10
87 amb 605 if(IsFakeNode(finish_node))
88     GetFakeLatLong(finish_node,&finish_lat,&finish_lon);
89 amb 303 else
90 amb 605 GetLatLong(nodes,finish_node,&finish_lat,&finish_lon);
91 amb 119
92 amb 165 /* Create the list of results and insert the first node into the queue */
93 amb 2
94 amb 855 results=NewResultsList(64);
95 amb 2
96 amb 605 results->start_node=start_node;
97 amb 617 results->prev_segment=prev_segment;
98 amb 165
99 amb 735 result1=InsertResult(results,results->start_node,results->prev_segment);
100 amb 28
101 amb 236 queue=NewQueueList();
102 amb 2
103 amb 236 InsertInQueue(queue,result1);
104    
105 amb 2 /* Loop across all nodes in the queue */
106    
107 amb 236 while((result1=PopFromQueue(queue)))
108 amb 2 {
109 amb 885 Node *node1p=NULL;
110 amb 594 Segment *segment;
111 amb 637 index_t node1,seg1,seg1r;
112 amb 608 index_t turnrelation=NO_RELATION;
113 amb 594
114 amb 680 /* score must be better than current best score */
115 amb 238 if(result1->score>finish_score)
116 amb 119 continue;
117    
118 amb 43 node1=result1->node;
119 amb 605 seg1=result1->segment;
120 amb 2
121 amb 637 if(IsFakeSegment(seg1))
122     seg1r=IndexRealSegment(seg1);
123     else
124     seg1r=seg1;
125    
126 amb 885 if(!IsFakeNode(node1))
127     node1p=LookupNode(nodes,node1,1);
128    
129 amb 680 /* lookup if a turn restriction applies */
130 amb 885 if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
131 amb 637 turnrelation=FindFirstTurnRelation2(relations,node1,seg1r);
132 amb 596
133 amb 680 /* Loop across all segments */
134    
135 amb 303 if(IsFakeNode(node1))
136     segment=FirstFakeSegment(node1);
137     else
138 amb 885 segment=FirstSegment(segments,node1p,1);
139 amb 2
140     while(segment)
141     {
142 amb 885 Node *node2p=NULL;
143 amb 594 Way *way;
144 amb 637 index_t node2,seg2,seg2r;
145 amb 298 score_t segment_pref,segment_score,cumulative_score;
146     int i;
147 amb 59
148 amb 680 node2=OtherNode(segment,node1); /* need this here because we use node2 at the end of the loop */
149 amb 303
150 amb 680 /* must be a normal segment */
151 amb 95 if(!IsNormalSegment(segment))
152 amb 90 goto endloop;
153    
154 amb 680 /* must obey one-way restrictions (unless profile allows) */
155 amb 105 if(profile->oneway && IsOnewayTo(segment,node1))
156 amb 64 goto endloop;
157    
158 amb 605 if(IsFakeNode(node1) || IsFakeNode(node2))
159 amb 637 {
160     seg2 =IndexFakeSegment(segment);
161     seg2r=IndexRealSegment(seg2);
162     }
163 amb 605 else
164 amb 637 {
165     seg2 =IndexSegment(segments,segment);
166     seg2r=seg2;
167     }
168 amb 603
169 amb 699 /* must not perform U-turn (unless profile allows) */
170 amb 727 if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
171 amb 636 goto endloop;
172    
173 amb 680 /* must obey turn relations */
174 amb 637 if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1r,seg2r,profile->allow))
175 amb 608 goto endloop;
176 amb 596
177 amb 885 if(!IsFakeNode(node2))
178     node2p=LookupNode(nodes,node2,2);
179    
180 amb 723 /* must not pass over super-node */
181 amb 885 if(node2!=finish_node && node2p && IsSuperNode(node2p))
182 amb 238 goto endloop;
183    
184 amb 460 way=LookupWay(ways,segment->way,1);
185 amb 54
186 amb 680 /* mode of transport must be allowed on the highway */
187 amb 82 if(!(way->allow&profile->allow))
188 amb 54 goto endloop;
189    
190 amb 680 /* must obey weight restriction (if exists) */
191 amb 197 if(way->weight && way->weight<profile->weight)
192 amb 135 goto endloop;
193    
194 amb 680 /* must obey height/width/length restriction (if exists) */
195 amb 197 if((way->height && way->height<profile->height) ||
196     (way->width && way->width <profile->width ) ||
197     (way->length && way->length<profile->length))
198 amb 135 goto endloop;
199    
200 amb 298 segment_pref=profile->highway[HIGHWAY(way->type)];
201    
202     for(i=1;i<Property_Count;i++)
203 amb 460 if(ways->file.props & PROPERTIES(i))
204 amb 307 {
205 amb 406 if(way->props & PROPERTIES(i))
206 amb 307 segment_pref*=profile->props_yes[i];
207     else
208     segment_pref*=profile->props_no[i];
209     }
210 amb 298
211 amb 680 /* profile preferences must allow this highway */
212 amb 298 if(segment_pref==0)
213     goto endloop;
214    
215 amb 680 /* mode of transport must be allowed through node2 */
216 amb 885 if(node2p && !(node2p->allow&profile->allow))
217     goto endloop;
218 amb 469
219 amb 166 if(option_quickest==0)
220 amb 298 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
221 amb 166 else
222 amb 298 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
223 amb 59
224 amb 170 cumulative_score=result1->score+segment_score;
225 amb 166
226 amb 680 /* score must be better than current best score */
227 amb 166 if(cumulative_score>finish_score)
228 amb 2 goto endloop;
229    
230 amb 605 result2=FindResult(results,node2,seg2);
231 amb 42
232 amb 680 if(!result2) /* New end node/segment combination */
233 amb 2 {
234 amb 605 result2=InsertResult(results,node2,seg2);
235     result2->prev=result1;
236 amb 170 result2->score=cumulative_score;
237 amb 2
238 amb 605 if(node2==finish_node)
239 amb 2 {
240 amb 605 if(cumulative_score<finish_score)
241     {
242     finish_score=cumulative_score;
243     finish_result=result2;
244     }
245 amb 2 }
246     else
247 amb 119 {
248 amb 238 result2->sortby=result2->score;
249 amb 166
250 amb 891 if(result2->score<finish_score)
251     InsertInQueue(queue,result2);
252 amb 119 }
253 amb 2 }
254 amb 605 else if(cumulative_score<result2->score) /* New score for end node/segment combination is better */
255 amb 2 {
256 amb 605 result2->prev=result1;
257 amb 170 result2->score=cumulative_score;
258 amb 605 result2->segment=seg2;
259 amb 166
260 amb 605 if(node2==finish_node)
261 amb 2 {
262 amb 605 if(cumulative_score<finish_score)
263     {
264     finish_score=cumulative_score;
265     finish_result=result2;
266     }
267 amb 2 }
268 amb 166 else
269     {
270 amb 238 result2->sortby=result2->score;
271 amb 2
272 amb 238 if(result2->score<finish_score)
273 amb 236 InsertInQueue(queue,result2);
274 amb 2 }
275     }
276    
277     endloop:
278    
279 amb 303 if(IsFakeNode(node1))
280     segment=NextFakeSegment(segment,node1);
281     else if(IsFakeNode(node2))
282     segment=NULL; /* cannot call NextSegment() with a fake segment */
283     else
284     {
285     segment=NextSegment(segments,segment,node1);
286    
287 amb 605 if(!segment && IsFakeNode(finish_node))
288     segment=ExtraFakeSegment(node1,finish_node);
289 amb 303 }
290 amb 2 }
291     }
292    
293 amb 236 FreeQueueList(queue);
294    
295 amb 77 /* Check it worked */
296    
297 amb 605 if(!finish_result)
298 amb 77 {
299     FreeResultsList(results);
300     return(NULL);
301     }
302    
303 amb 605 FixForwardRoute(results,finish_result);
304 amb 31
305     return(results);
306 amb 2 }
307    
308    
309     /*++++++++++++++++++++++++++++++++++++++
310 amb 680 Find the optimum route between two nodes where the start and end are a set of pre/post-routed super-nodes.
311 amb 34
312 amb 238 Results *FindMiddleRoute Returns a set of results.
313 amb 34
314 amb 95 Nodes *nodes The set of nodes to use.
315 amb 34
316 amb 95 Segments *segments The set of segments to use.
317 amb 34
318 amb 95 Ways *ways The set of ways to use.
319 amb 54
320 amb 542 Relations *relations The set of relations to use.
321    
322 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
323    
324 amb 34 Results *begin The initial portion of the route.
325    
326     Results *end The final portion of the route.
327     ++++++++++++++++++++++++++++++++++++++*/
328    
329 amb 721 Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Results *begin,Results *end)
330 amb 34 {
331     Results *results;
332 amb 469 Queue *queue;
333 amb 605 Result *finish_result;
334 amb 166 score_t finish_score;
335 amb 219 double finish_lat,finish_lon;
336 amb 632 Result *result1,*result2,*result3,*result4;
337 amb 34
338 amb 227 if(!option_quiet)
339 amb 519 printf_first("Routing: Super-Nodes checked = 0");
340 amb 227
341 amb 34 /* Set up the finish conditions */
342    
343 amb 302 finish_score=INF_DISTANCE;
344 amb 605 finish_result=NULL;
345 amb 34
346 amb 605 if(IsFakeNode(end->finish_node))
347     GetFakeLatLong(end->finish_node,&finish_lat,&finish_lon);
348 amb 303 else
349 amb 605 GetLatLong(nodes,end->finish_node,&finish_lat,&finish_lon);
350 amb 119
351 amb 165 /* Create the list of results and insert the first node into the queue */
352 amb 34
353 amb 860 results=NewResultsList(65536);
354 amb 34
355 amb 605 results->start_node=begin->start_node;
356     results->prev_segment=begin->prev_segment;
357 amb 34
358 amb 688 if(begin->number==1)
359     {
360 amb 828 if(begin->prev_segment==NO_SEGMENT)
361     results->prev_segment=NO_SEGMENT;
362     else
363     {
364     index_t superseg=FindSuperSegment(nodes,segments,ways,relations,profile,begin->start_node,begin->prev_segment);
365 amb 34
366 amb 828 results->prev_segment=superseg;
367     }
368 amb 688 }
369    
370     result1=InsertResult(results,results->start_node,results->prev_segment);
371    
372 amb 236 queue=NewQueueList();
373    
374 amb 685 /* Insert the finish points of the beginning part of the path into the queue,
375     translating the segments into super-segments. */
376 amb 34
377 amb 79 result3=FirstResult(begin);
378    
379     while(result3)
380     {
381 amb 735 if((results->start_node!=result3->node || results->prev_segment!=result3->segment) &&
382 amb 885 !IsFakeNode(result3->node) && IsSuperNode(LookupNode(nodes,result3->node,5)))
383 amb 45 {
384 amb 722 Result *result5=result1;
385 amb 721 index_t superseg=FindSuperSegment(nodes,segments,ways,relations,profile,result3->node,result3->segment);
386 amb 34
387 amb 722 if(superseg!=result3->segment)
388     {
389     result5=InsertResult(results,result3->node,result3->segment);
390    
391     result5->prev=result1;
392     }
393    
394 amb 703 if(!FindResult(results,result3->node,superseg))
395     {
396     result2=InsertResult(results,result3->node,superseg);
397 amb 722 result2->prev=result5;
398 amb 685
399 amb 703 result2->score=result3->score;
400     result2->sortby=result3->score;
401 amb 119
402 amb 703 InsertInQueue(queue,result2);
403 amb 632
404 amb 703 if((result4=FindResult(end,result2->node,result2->segment)))
405 amb 632 {
406 amb 703 if((result2->score+result4->score)<finish_score)
407     {
408     finish_score=result2->score+result4->score;
409     finish_result=result2;
410     }
411 amb 632 }
412     }
413 amb 45 }
414 amb 34
415 amb 79 result3=NextResult(begin,result3);
416     }
417    
418 amb 238 if(begin->number==1)
419     InsertInQueue(queue,result1);
420    
421 amb 95 /* Loop across all nodes in the queue */
422 amb 34
423 amb 236 while((result1=PopFromQueue(queue)))
424 amb 34 {
425 amb 885 Node *node1p;
426     Segment *segment;
427 amb 605 index_t node1,seg1;
428 amb 596 index_t turnrelation=NO_RELATION;
429 amb 594
430 amb 680 /* score must be better than current best score */
431 amb 238 if(result1->score>finish_score)
432 amb 119 continue;
433    
434 amb 43 node1=result1->node;
435 amb 605 seg1=result1->segment;
436 amb 34
437 amb 885 node1p=LookupNode(nodes,node1,1); /* node1 cannot be a fake node (must be a super-node) */
438    
439 amb 680 /* lookup if a turn restriction applies */
440 amb 885 if(profile->turns && IsTurnRestrictedNode(node1p)) /* node1 cannot be a fake node (must be a super-node) */
441 amb 605 turnrelation=FindFirstTurnRelation2(relations,node1,seg1);
442 amb 596
443 amb 680 /* Loop across all segments */
444 amb 34
445 amb 885 segment=FirstSegment(segments,node1p,1); /* node1 cannot be a fake node (must be a super-node) */
446 amb 680
447 amb 34 while(segment)
448     {
449 amb 885 Node *node2p;
450 amb 610 Way *way;
451 amb 603 index_t node2,seg2;
452 amb 298 score_t segment_pref,segment_score,cumulative_score;
453     int i;
454 amb 59
455 amb 680 /* must be a super segment */
456 amb 95 if(!IsSuperSegment(segment))
457     goto endloop;
458    
459 amb 680 /* must obey one-way restrictions (unless profile allows) */
460 amb 105 if(profile->oneway && IsOnewayTo(segment,node1))
461 amb 64 goto endloop;
462    
463 amb 105 node2=OtherNode(segment,node1);
464 amb 34
465 amb 680 seg2=IndexSegment(segments,segment); /* node2 cannot be a fake node (must be a super-node) */
466 amb 603
467 amb 699 /* must not perform U-turn */
468 amb 680 if(seg1==seg2) /* No fake segments, applies to all profiles */
469 amb 636 goto endloop;
470    
471 amb 680 /* must obey turn relations */
472 amb 605 if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1,seg2,profile->allow))
473 amb 596 goto endloop;
474    
475 amb 460 way=LookupWay(ways,segment->way,1);
476 amb 54
477 amb 680 /* transport must be allowed on the highway */
478 amb 82 if(!(way->allow&profile->allow))
479 amb 54 goto endloop;
480    
481 amb 680 /* must obey weight restriction (if exists) */
482 amb 197 if(way->weight && way->weight<profile->weight)
483 amb 135 goto endloop;
484    
485 amb 680 /* must obey height/width/length restriction (if exists) */
486 amb 197 if((way->height && way->height<profile->height) ||
487     (way->width && way->width <profile->width ) ||
488     (way->length && way->length<profile->length))
489 amb 135 goto endloop;
490    
491 amb 298 segment_pref=profile->highway[HIGHWAY(way->type)];
492    
493     for(i=1;i<Property_Count;i++)
494 amb 460 if(ways->file.props & PROPERTIES(i))
495 amb 307 {
496 amb 406 if(way->props & PROPERTIES(i))
497 amb 307 segment_pref*=profile->props_yes[i];
498     else
499     segment_pref*=profile->props_no[i];
500     }
501 amb 298
502 amb 680 /* profile preferences must allow this highway */
503 amb 298 if(segment_pref==0)
504     goto endloop;
505    
506 amb 885 node2p=LookupNode(nodes,node2,2); /* node2 cannot be a fake node (must be a super-node) */
507 amb 469
508 amb 680 /* mode of transport must be allowed through node2 */
509 amb 885 if(!(node2p->allow&profile->allow))
510 amb 469 goto endloop;
511    
512 amb 166 if(option_quickest==0)
513 amb 298 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
514 amb 166 else
515 amb 298 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
516 amb 34
517 amb 170 cumulative_score=result1->score+segment_score;
518 amb 166
519 amb 680 /* score must be better than current best score */
520 amb 166 if(cumulative_score>finish_score)
521 amb 34 goto endloop;
522    
523 amb 605 result2=FindResult(results,node2,seg2);
524 amb 42
525 amb 680 if(!result2) /* New end node/segment pair */
526 amb 34 {
527 amb 605 result2=InsertResult(results,node2,seg2);
528     result2->prev=result1;
529 amb 170 result2->score=cumulative_score;
530 amb 34
531 amb 605 if((result3=FindResult(end,node2,seg2)))
532 amb 113 {
533 amb 442 if((result2->score+result3->score)<finish_score)
534     {
535     finish_score=result2->score+result3->score;
536 amb 605 finish_result=result2;
537 amb 442 }
538 amb 113 }
539     else
540 amb 119 {
541 amb 219 double lat,lon;
542 amb 166 distance_t direct;
543    
544 amb 680 GetLatLong(nodes,node2,&lat,&lon); /* node2 cannot be a fake node (must be a super-node) */
545    
546 amb 166 direct=Distance(lat,lon,finish_lat,finish_lon);
547 amb 119
548     if(option_quickest==0)
549 amb 173 result2->sortby=result2->score+(score_t)direct/profile->max_pref;
550 amb 119 else
551 amb 173 result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
552 amb 119
553 amb 891 if(result2->sortby<finish_score)
554     InsertInQueue(queue,result2);
555 amb 119 }
556 amb 34 }
557 amb 605 else if(cumulative_score<result2->score) /* New end node/segment pair is better */
558 amb 34 {
559 amb 605 result2->prev=result1;
560 amb 170 result2->score=cumulative_score;
561 amb 166
562 amb 605 if((result3=FindResult(end,node2,seg2)))
563 amb 34 {
564 amb 166 if((result2->score+result3->score)<finish_score)
565 amb 113 {
566 amb 166 finish_score=result2->score+result3->score;
567 amb 605 finish_result=result2;
568 amb 113 }
569 amb 34 }
570 amb 238 else if(result2->score<finish_score)
571 amb 34 {
572 amb 219 double lat,lon;
573 amb 166 distance_t direct;
574 amb 34
575 amb 680 GetLatLong(nodes,node2,&lat,&lon); /* node2 cannot be a fake node (must be a super-node) */
576    
577 amb 166 direct=Distance(lat,lon,finish_lat,finish_lon);
578    
579     if(option_quickest==0)
580 amb 173 result2->sortby=result2->score+(score_t)direct/profile->max_pref;
581 amb 113 else
582 amb 173 result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
583 amb 119
584 amb 891 if(result2->sortby<finish_score)
585     InsertInQueue(queue,result2);
586 amb 34 }
587     }
588    
589 amb 757 if(!option_quiet && !(results->number%1000))
590 amb 519 printf_middle("Routing: Super-Nodes checked = %d",results->number);
591 amb 34
592 amb 627 endloop:
593    
594 amb 680 segment=NextSegment(segments,segment,node1); /* node1 cannot be a fake node (must be a super-node) */
595 amb 34 }
596     }
597    
598 amb 107 if(!option_quiet)
599 amb 519 printf_last("Routing: Super-Nodes checked = %d",results->number);
600 amb 34
601 amb 236 FreeQueueList(queue);
602    
603 amb 77 /* Check it worked */
604    
605 amb 605 if(!finish_result)
606 amb 77 {
607     FreeResultsList(results);
608     return(NULL);
609     }
610    
611 amb 680 /* Finish off the end part of the route */
612 amb 34
613 amb 616 if(finish_result->node!=end->finish_node)
614     {
615     result3=InsertResult(results,end->finish_node,NO_SEGMENT);
616 amb 605
617 amb 616 result3->prev=finish_result;
618     result3->score=finish_score;
619 amb 605
620 amb 616 finish_result=result3;
621     }
622 amb 605
623 amb 616 FixForwardRoute(results,finish_result);
624    
625 amb 34 return(results);
626     }
627    
628    
629     /*++++++++++++++++++++++++++++++++++++++
630 amb 685 Find the super-segment that represents the route that contains a particular segment.
631    
632     index_t FindSuperSegment Returns the index of the super-segment.
633    
634     Nodes *nodes The set of nodes to use.
635    
636     Segments *segments The set of segments to use.
637    
638     Ways *ways The set of ways to use.
639    
640     Relations *relations The set of relations to use.
641    
642 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
643    
644 amb 685 index_t endnode The super-node that the route ends at.
645    
646     index_t endsegment The segment that the route ends with.
647     ++++++++++++++++++++++++++++++++++++++*/
648    
649 amb 721 static index_t FindSuperSegment(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t endnode,index_t endsegment)
650 amb 685 {
651 amb 885 Node *node=LookupNode(nodes,endnode,5); /* endnode cannot be a fake node (must be a super-node) */
652 amb 685 Segment *segment;
653    
654 amb 699 if(IsFakeSegment(endsegment))
655     endsegment=IndexRealSegment(endsegment);
656    
657 amb 707 segment=LookupSegment(segments,endsegment,2);
658 amb 687
659     if(IsSuperSegment(segment))
660     return(endsegment);
661    
662 amb 685 /* Loop across all segments */
663    
664 amb 885 segment=FirstSegment(segments,node,3); /* endnode cannot be a fake node (must be a super-node) */
665 amb 685
666     while(segment)
667     {
668     if(IsSuperSegment(segment))
669     {
670     Results *results;
671     index_t startnode;
672    
673     startnode=OtherNode(segment,endnode);
674    
675 amb 723 results=FindNormalRoute(nodes,segments,ways,relations,profile,startnode,NO_SEGMENT,endnode);
676 amb 685
677     if(results && results->last_segment==endsegment)
678 amb 798 {
679     FreeResultsList(results);
680 amb 685 return(IndexSegment(segments,segment));
681 amb 798 }
682    
683     if(results)
684     FreeResultsList(results);
685 amb 685 }
686    
687     segment=NextSegment(segments,segment,endnode); /* endnode cannot be a fake node (must be a super-node) */
688     }
689    
690 amb 687 return(endsegment);
691 amb 685 }
692    
693    
694     /*++++++++++++++++++++++++++++++++++++++
695 amb 95 Find all routes from a specified node to any super-node.
696 amb 3
697 amb 126 Results *FindStartRoutes Returns a set of results.
698 amb 31
699     Nodes *nodes The set of nodes to use.
700    
701     Segments *segments The set of segments to use.
702    
703 amb 54 Ways *ways The set of ways to use.
704    
705 amb 542 Relations *relations The set of relations to use.
706    
707 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
708    
709 amb 605 index_t start_node The start node.
710 amb 31
711 amb 605 index_t prev_segment The previous segment before the start node.
712    
713 amb 729 index_t finish_node The finish node.
714    
715     int *nsuper Returns the number of super-nodes seen.
716 amb 31 ++++++++++++++++++++++++++++++++++++++*/
717    
718 amb 734 Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t start_node,index_t prev_segment,index_t finish_node,int *nsuper)
719 amb 31 {
720     Results *results;
721 amb 469 Queue *queue;
722     Result *result1,*result2;
723 amb 734 int found_finish=0;
724 amb 31
725 amb 531 /* Create the results and insert the start node */
726 amb 31
727 amb 855 results=NewResultsList(64);
728 amb 31
729 amb 605 results->start_node=start_node;
730     results->prev_segment=prev_segment;
731 amb 165
732 amb 735 result1=InsertResult(results,results->start_node,results->prev_segment);
733 amb 31
734 amb 531 /* Insert the first node into the queue */
735    
736 amb 236 queue=NewQueueList();
737 amb 31
738 amb 236 InsertInQueue(queue,result1);
739    
740 amb 31 /* Loop across all nodes in the queue */
741    
742 amb 236 while((result1=PopFromQueue(queue)))
743 amb 31 {
744 amb 885 Node *node1p=NULL;
745     Segment *segment;
746 amb 637 index_t node1,seg1,seg1r;
747 amb 719 index_t turnrelation=NO_RELATION;
748 amb 594
749 amb 43 node1=result1->node;
750 amb 605 seg1=result1->segment;
751 amb 31
752 amb 637 if(IsFakeSegment(seg1))
753     seg1r=IndexRealSegment(seg1);
754     else
755     seg1r=seg1;
756    
757 amb 885 if(!IsFakeNode(node1))
758     node1p=LookupNode(nodes,node1,1);
759    
760 amb 719 /* lookup if a turn restriction applies */
761 amb 885 if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
762 amb 719 turnrelation=FindFirstTurnRelation2(relations,node1,seg1r);
763 amb 680
764     /* Loop across all segments */
765    
766 amb 303 if(IsFakeNode(node1))
767     segment=FirstFakeSegment(node1);
768     else
769 amb 885 segment=FirstSegment(segments,node1p,1);
770 amb 31
771     while(segment)
772     {
773 amb 885 Node *node2p=NULL;
774 amb 610 Way *way;
775 amb 637 index_t node2,seg2,seg2r;
776 amb 298 score_t segment_pref,segment_score,cumulative_score;
777     int i;
778 amb 59
779 amb 734 node2=OtherNode(segment,node1); /* need this here because we use node2 at the end of the loop */
780    
781 amb 680 /* must be a normal segment */
782 amb 95 if(!IsNormalSegment(segment))
783     goto endloop;
784    
785 amb 680 /* must obey one-way restrictions (unless profile allows) */
786 amb 105 if(profile->oneway && IsOnewayTo(segment,node1))
787 amb 64 goto endloop;
788    
789 amb 605 if(IsFakeNode(node1) || IsFakeNode(node2))
790 amb 637 {
791     seg2 =IndexFakeSegment(segment);
792     seg2r=IndexRealSegment(seg2);
793     }
794 amb 605 else
795 amb 637 {
796     seg2 =IndexSegment(segments,segment);
797     seg2r=seg2;
798     }
799 amb 603
800 amb 699 /* must not perform U-turn (unless profile allows) */
801 amb 734 if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
802 amb 636 goto endloop;
803    
804 amb 719 /* must obey turn relations */
805     if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1r,seg2r,profile->allow))
806     goto endloop;
807 amb 596
808 amb 460 way=LookupWay(ways,segment->way,1);
809 amb 54
810 amb 680 /* mode of transport must be allowed on the highway */
811 amb 82 if(!(way->allow&profile->allow))
812 amb 54 goto endloop;
813    
814 amb 680 /* must obey weight restriction (if exists) */
815 amb 197 if(way->weight && way->weight<profile->weight)
816 amb 135 goto endloop;
817    
818 amb 680 /* must obey height/width/length restriction (if exists) */
819 amb 197 if((way->height && way->height<profile->height) ||
820     (way->width && way->width <profile->width ) ||
821     (way->length && way->length<profile->length))
822 amb 135 goto endloop;
823    
824 amb 298 segment_pref=profile->highway[HIGHWAY(way->type)];
825    
826     for(i=1;i<Property_Count;i++)
827 amb 460 if(ways->file.props & PROPERTIES(i))
828 amb 307 {
829 amb 406 if(way->props & PROPERTIES(i))
830 amb 307 segment_pref*=profile->props_yes[i];
831     else
832     segment_pref*=profile->props_no[i];
833     }
834 amb 298
835 amb 680 /* profile preferences must allow this highway */
836 amb 298 if(segment_pref==0)
837     goto endloop;
838    
839 amb 471 if(!IsFakeNode(node2))
840 amb 885 node2p=LookupNode(nodes,node2,2);
841 amb 469
842 amb 885 /* mode of transport must be allowed through node2 */
843     if(node2p && !(node2p->allow&profile->allow))
844     goto endloop;
845 amb 469
846 amb 166 if(option_quickest==0)
847 amb 298 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
848 amb 166 else
849 amb 298 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
850 amb 59
851 amb 170 cumulative_score=result1->score+segment_score;
852 amb 166
853 amb 605 result2=FindResult(results,node2,seg2);
854 amb 31
855 amb 680 if(!result2) /* New end node/segment combination */
856 amb 31 {
857 amb 605 result2=InsertResult(results,node2,seg2);
858     result2->prev=result1;
859 amb 170 result2->score=cumulative_score;
860 amb 31
861 amb 885 if(node2p && IsSuperNode(node2p))
862 amb 729 (*nsuper)++;
863    
864 amb 885 if(node2p && !IsSuperNode(node2p))
865 amb 119 {
866 amb 166 result2->sortby=result2->score;
867 amb 236 InsertInQueue(queue,result2);
868 amb 119 }
869 amb 734
870     if(node2==finish_node)
871     found_finish=1;
872 amb 31 }
873 amb 605 else if(cumulative_score<result2->score) /* New end node/segment combination is better */
874 amb 31 {
875 amb 605 result2->prev=result1;
876 amb 170 result2->score=cumulative_score;
877 amb 31
878 amb 885 if(node2p && !IsSuperNode(node2p))
879 amb 31 {
880 amb 166 result2->sortby=result2->score;
881 amb 236 InsertInQueue(queue,result2);
882 amb 31 }
883     }
884    
885     endloop:
886    
887 amb 303 if(IsFakeNode(node1))
888     segment=NextFakeSegment(segment,node1);
889 amb 729 else if(IsFakeNode(node2))
890     segment=NULL; /* cannot call NextSegment() with a fake segment */
891 amb 303 else
892 amb 729 {
893 amb 303 segment=NextSegment(segments,segment,node1);
894 amb 678
895 amb 729 if(!segment && IsFakeNode(finish_node))
896     segment=ExtraFakeSegment(node1,finish_node);
897     }
898 amb 31 }
899     }
900    
901 amb 236 FreeQueueList(queue);
902    
903 amb 112 /* Check it worked */
904    
905 amb 734 if(results->number==1 || (*nsuper==0 && found_finish==0))
906 amb 112 {
907     FreeResultsList(results);
908     return(NULL);
909     }
910    
911 amb 31 return(results);
912 amb 2 }
913    
914    
915     /*++++++++++++++++++++++++++++++++++++++
916 amb 680 Find all routes from any super-node to a specific node (by working backwards from the specific node to all super-nodes).
917 amb 34
918 amb 126 Results *FindFinishRoutes Returns a set of results.
919 amb 34
920     Nodes *nodes The set of nodes to use.
921    
922     Segments *segments The set of segments to use.
923    
924 amb 54 Ways *ways The set of ways to use.
925    
926 amb 542 Relations *relations The set of relations to use.
927    
928 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
929    
930 amb 605 index_t finish_node The finishing node.
931 amb 34 ++++++++++++++++++++++++++++++++++++++*/
932    
933 amb 721 Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t finish_node)
934 amb 34 {
935 amb 605 Results *results,*results2;
936 amb 469 Queue *queue;
937 amb 605 Result *result1,*result2,*result3;
938 amb 34
939 amb 531 /* Create the results and insert the finish node */
940 amb 34
941 amb 855 results=NewResultsList(64);
942 amb 34
943 amb 605 results->finish_node=finish_node;
944 amb 165
945 amb 605 result1=InsertResult(results,finish_node,NO_SEGMENT);
946 amb 34
947 amb 531 /* Insert the first node into the queue */
948    
949 amb 236 queue=NewQueueList();
950 amb 34
951 amb 236 InsertInQueue(queue,result1);
952    
953 amb 34 /* Loop across all nodes in the queue */
954    
955 amb 236 while((result1=PopFromQueue(queue)))
956 amb 34 {
957 amb 885 Node *node1p=NULL;
958     Segment *segment;
959 amb 637 index_t node1,seg1,seg1r;
960 amb 596 index_t turnrelation=NO_RELATION;
961 amb 594
962 amb 43 node1=result1->node;
963 amb 605 seg1=result1->segment;
964 amb 34
965 amb 637 if(IsFakeSegment(seg1))
966     seg1r=IndexRealSegment(seg1);
967     else
968     seg1r=seg1;
969    
970 amb 885 if(!IsFakeNode(node1))
971     node1p=LookupNode(nodes,node1,1);
972    
973 amb 680 /* lookup if a turn restriction applies */
974 amb 885 if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
975 amb 596 turnrelation=FindFirstTurnRelation1(relations,node1); /* working backwards => turn relation sort order doesn't help */
976    
977 amb 680 /* Loop across all segments */
978    
979 amb 303 if(IsFakeNode(node1))
980     segment=FirstFakeSegment(node1);
981     else
982 amb 885 segment=FirstSegment(segments,node1p,1);
983 amb 34
984     while(segment)
985     {
986 amb 885 Node *node2p=NULL;
987 amb 610 Way *way;
988 amb 637 index_t node2,seg2,seg2r;
989 amb 298 score_t segment_pref,segment_score,cumulative_score;
990     int i;
991 amb 59
992 amb 680 /* must be a normal segment */
993 amb 885 if((IsFakeNode(node1) || !IsSuperNode(node1p)) && !IsNormalSegment(segment))
994 amb 34 goto endloop;
995    
996 amb 680 /* must obey one-way restrictions (unless profile allows) */
997 amb 596 if(profile->oneway && IsOnewayFrom(segment,node1)) /* Disallow oneway from node2 *to* node1 */
998 amb 95 goto endloop;
999    
1000 amb 105 node2=OtherNode(segment,node1);
1001 amb 64
1002 amb 605 if(IsFakeNode(node1) || IsFakeNode(node2))
1003 amb 637 {
1004     seg2 =IndexFakeSegment(segment);
1005     seg2r=IndexRealSegment(seg2);
1006     }
1007 amb 605 else
1008 amb 637 {
1009     seg2 =IndexSegment(segments,segment);
1010     seg2r=seg2;
1011     }
1012 amb 605
1013 amb 699 /* must not perform U-turn (unless profile allows) */
1014 amb 727 if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
1015 amb 636 goto endloop;
1016    
1017 amb 680 /* must obey turn relations */
1018 amb 596 if(turnrelation!=NO_RELATION)
1019     {
1020 amb 637 index_t turnrelation2=FindFirstTurnRelation2(relations,node1,seg2r); /* node2 -> node1 -> result1->next->node */
1021 amb 596
1022 amb 637 if(turnrelation2!=NO_RELATION && !IsTurnAllowed(relations,turnrelation2,node1,seg2r,seg1r,profile->allow))
1023 amb 596 goto endloop;
1024     }
1025    
1026 amb 460 way=LookupWay(ways,segment->way,1);
1027 amb 54
1028 amb 680 /* mode of transport must be allowed on the highway */
1029 amb 82 if(!(way->allow&profile->allow))
1030 amb 54 goto endloop;
1031    
1032 amb 680 /* must obey weight restriction (if exists) */
1033 amb 197 if(way->weight && way->weight<profile->weight)
1034 amb 135 goto endloop;
1035    
1036 amb 680 /* must obey height/width/length restriction (if exists) */
1037 amb 197 if((way->height && way->height<profile->height) ||
1038     (way->width && way->width <profile->width ) ||
1039     (way->length && way->length<profile->length))
1040 amb 135 goto endloop;
1041    
1042 amb 298 segment_pref=profile->highway[HIGHWAY(way->type)];
1043    
1044     for(i=1;i<Property_Count;i++)
1045 amb 460 if(ways->file.props & PROPERTIES(i))
1046 amb 307 {
1047 amb 406 if(way->props & PROPERTIES(i))
1048 amb 307 segment_pref*=profile->props_yes[i];
1049     else
1050     segment_pref*=profile->props_no[i];
1051     }
1052 amb 298
1053 amb 680 /* profile preferences must allow this highway */
1054 amb 298 if(segment_pref==0)
1055     goto endloop;
1056    
1057 amb 471 if(!IsFakeNode(node2))
1058 amb 885 node2p=LookupNode(nodes,node2,2);
1059 amb 469
1060 amb 885 /* mode of transport must be allowed through node2 */
1061     if(node2p && !(node2p->allow&profile->allow))
1062     goto endloop;
1063 amb 469
1064 amb 166 if(option_quickest==0)
1065 amb 298 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
1066 amb 166 else
1067 amb 298 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
1068 amb 59
1069 amb 170 cumulative_score=result1->score+segment_score;
1070 amb 166
1071 amb 605 result2=FindResult(results,node2,seg2);
1072 amb 34
1073 amb 680 if(!result2) /* New end node */
1074 amb 34 {
1075 amb 605 result2=InsertResult(results,node2,seg2);
1076     result2->next=result1; /* working backwards */
1077 amb 170 result2->score=cumulative_score;
1078 amb 34
1079 amb 885 if(IsFakeNode(node1) || (!IsFakeNode(node1) && !IsSuperNode(node1p))) /* Overshoot by one segment */
1080 amb 119 {
1081 amb 166 result2->sortby=result2->score;
1082 amb 236 InsertInQueue(queue,result2);
1083 amb 119 }
1084 amb 34 }
1085 amb 166 else if(cumulative_score<result2->score) /* New end node is better */
1086 amb 34 {
1087 amb 605 result2->next=result1; /* working backwards */
1088 amb 170 result2->score=cumulative_score;
1089 amb 34
1090 amb 885 if(IsFakeNode(node1) || (!IsFakeNode(node1) && !IsSuperNode(node1p))) /* Overshoot by one segment */
1091 amb 34 {
1092 amb 166 result2->sortby=result2->score;
1093 amb 236 InsertInQueue(queue,result2);
1094 amb 34 }
1095     }
1096    
1097     endloop:
1098    
1099 amb 303 if(IsFakeNode(node1))
1100     segment=NextFakeSegment(segment,node1);
1101     else
1102     segment=NextSegment(segments,segment,node1);
1103 amb 34 }
1104     }
1105    
1106 amb 236 FreeQueueList(queue);
1107    
1108 amb 112 /* Check it worked */
1109    
1110     if(results->number==1)
1111     {
1112     FreeResultsList(results);
1113     return(NULL);
1114     }
1115    
1116 amb 605 /* Create a results structure with the node at the end of the segment opposite the start */
1117    
1118 amb 855 results2=NewResultsList(64);
1119 amb 605
1120     results2->finish_node=results->finish_node;
1121    
1122     result3=FirstResult(results);
1123    
1124     while(result3)
1125     {
1126     if(result3->next)
1127     {
1128     result2=InsertResult(results2,result3->next->node,result3->segment);
1129    
1130 amb 616 result2->score=result3->next->score;
1131 amb 605 }
1132    
1133     result3=NextResult(results,result3);
1134     }
1135    
1136     /* Fix up the result->next pointers */
1137    
1138     result3=FirstResult(results);
1139    
1140     while(result3)
1141     {
1142     if(result3->next && result3->next->next)
1143     {
1144     result1=FindResult(results2,result3->next->node,result3->segment);
1145     result2=FindResult(results2,result3->next->next->node,result3->next->segment);
1146    
1147     result1->next=result2;
1148     }
1149    
1150     result3=NextResult(results,result3);
1151     }
1152    
1153     FreeResultsList(results);
1154    
1155     return(results2);
1156 amb 34 }
1157    
1158    
1159     /*++++++++++++++++++++++++++++++++++++++
1160 amb 95 Create an optimum route given the set of super-nodes to follow.
1161 amb 31
1162 amb 58 Results *CombineRoutes Returns the results from joining the super-nodes.
1163 amb 55
1164 amb 680 Nodes *nodes The set of nodes to use.
1165 amb 31
1166     Segments *segments The set of segments to use.
1167    
1168 amb 680 Ways *ways The set of ways to use.
1169 amb 31
1170 amb 542 Relations *relations The set of relations to use.
1171    
1172 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
1173    
1174 amb 722 Results *begin The set of results for the start of the route.
1175    
1176 amb 686 Results *middle The set of results from the super-node route.
1177 amb 31 ++++++++++++++++++++++++++++++++++++++*/
1178    
1179 amb 722 Results *CombineRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Results *begin,Results *middle)
1180 amb 31 {
1181 amb 686 Result *midres,*comres1;
1182 amb 31 Results *combined;
1183    
1184 amb 855 combined=NewResultsList(256);
1185 amb 31
1186 amb 735 combined->start_node=begin->start_node;
1187     combined->prev_segment=begin->prev_segment;
1188 amb 165
1189 amb 722 /* Insert the start point */
1190 amb 31
1191 amb 686 midres=FindResult(middle,middle->start_node,middle->prev_segment);
1192 amb 31
1193 amb 735 comres1=InsertResult(combined,combined->start_node,combined->prev_segment);
1194 amb 31
1195 amb 722 /* Insert the start of the route */
1196    
1197     if(begin->number>1 && midres->next)
1198     {
1199     Result *begres;
1200    
1201     midres=FindResult(middle,midres->next->node,midres->next->segment);
1202    
1203     begres=FindResult(begin,midres->node,midres->segment);
1204    
1205     FixForwardRoute(begin,begres);
1206    
1207     if(midres->next && midres->next->node==midres->node)
1208     midres=midres->next;
1209    
1210     begres=FindResult(begin,begin->start_node,begin->prev_segment);
1211    
1212     begres=begres->next;
1213    
1214     do
1215     {
1216     Result *comres2;
1217    
1218     comres2=InsertResult(combined,begres->node,begres->segment);
1219    
1220     comres2->score=begres->score+comres1->score;
1221     comres2->prev=comres1;
1222    
1223     begres=begres->next;
1224    
1225     comres1=comres2;
1226     }
1227     while(begres);
1228     }
1229    
1230     /* Sort out the combined route */
1231    
1232 amb 58 do
1233     {
1234 amb 686 Result *result;
1235 amb 594
1236 amb 686 if(midres->next)
1237 amb 31 {
1238 amb 723 Results *results=FindNormalRoute(nodes,segments,ways,relations,profile,comres1->node,comres1->segment,midres->next->node);
1239 amb 31
1240 amb 686 if(!results)
1241 amb 677 return(NULL);
1242    
1243 amb 686 result=FindResult(results,midres->node,comres1->segment);
1244 amb 31
1245 amb 686 result=result->next;
1246 amb 36
1247 amb 605 /*
1248 amb 686 * midres midres->next
1249 amb 605 * = =
1250 amb 686 * ---*----------------------------------* = middle
1251 amb 605 *
1252 amb 686 * ---*----.----.----.----.----.----.----* = results
1253 amb 605 * =
1254 amb 686 * result
1255 amb 605 *
1256     * ---*----.----.----.----.----.----.----* = combined
1257     * = =
1258 amb 686 * comres1 comres2
1259 amb 605 */
1260    
1261 amb 31 do
1262     {
1263 amb 686 Result *comres2;
1264 amb 31
1265 amb 686 comres2=InsertResult(combined,result->node,result->segment);
1266 amb 605
1267 amb 686 comres2->score=result->score+comres1->score;
1268     comres2->prev=comres1;
1269 amb 605
1270 amb 686 result=result->next;
1271    
1272     comres1=comres2;
1273 amb 31 }
1274 amb 686 while(result);
1275 amb 31
1276 amb 686 FreeResultsList(results);
1277 amb 605 }
1278 amb 31
1279 amb 686 midres=midres->next;
1280 amb 31 }
1281 amb 686 while(midres);
1282 amb 31
1283 amb 686 FixForwardRoute(combined,comres1);
1284 amb 605
1285 amb 55 return(combined);
1286 amb 31 }
1287 amb 290
1288    
1289     /*++++++++++++++++++++++++++++++++++++++
1290 amb 605 Fix the forward route (i.e. setup next pointers for forward path from prev nodes on reverse path).
1291 amb 290
1292     Results *results The set of results to update.
1293    
1294 amb 680 Result *finish_result The result for the finish point.
1295 amb 290 ++++++++++++++++++++++++++++++++++++++*/
1296    
1297 amb 605 void FixForwardRoute(Results *results,Result *finish_result)
1298 amb 290 {
1299 amb 605 Result *result2=finish_result;
1300 amb 290
1301 amb 828 /* Erase the old route if there is one */
1302    
1303     if(results->finish_node!=NO_NODE)
1304     {
1305     Result *result1=FirstResult(results);
1306    
1307     while(result1)
1308     {
1309     result1->next=NULL;
1310    
1311     result1=NextResult(results,result1);
1312     }
1313     }
1314    
1315 amb 290 /* Create the forward links for the optimum path */
1316    
1317     do
1318     {
1319 amb 594 Result *result1;
1320    
1321 amb 605 if(result2->prev)
1322 amb 290 {
1323 amb 605 index_t node1=result2->prev->node;
1324     index_t seg1=result2->prev->segment;
1325 amb 290
1326 amb 605 result1=FindResult(results,node1,seg1);
1327 amb 290
1328 amb 712 assert(!result1->next); /* Bugs elsewhere can lead to infinite loop here. */
1329    
1330 amb 605 result1->next=result2;
1331 amb 290
1332     result2=result1;
1333     }
1334     else
1335     result2=NULL;
1336     }
1337     while(result2);
1338    
1339 amb 605 results->finish_node=finish_result->node;
1340     results->last_segment=finish_result->segment;
1341 amb 290 }

Properties

Name Value
cvs:description Route optimiser.