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 610 - (show annotations) (download) (as text)
Sat Jan 29 17:50:15 2011 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 29511 byte(s)
Add some comments, shuffle a few lines of code.

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

Properties

Name Value
cvs:description Route optimiser.