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 608 - (show annotations) (download) (as text)
Sat Jan 29 16:00:10 2011 UTC (14 years, 2 months ago) by amb
File MIME type: text/x-csrc
File size: 29072 byte(s)
When finding a normal route check for turn relations (considering previous segment).
When finding turn relations convert fake segments into real ones.

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 segment=FirstSegment(segments,nodes,node1);
374
375 while(segment)
376 {
377 index_t node2,seg2;
378 Node *node;
379 Way *way;
380 score_t segment_pref,segment_score,cumulative_score;
381 int i;
382
383 if(!IsSuperSegment(segment))
384 goto endloop;
385
386 if(profile->oneway && IsOnewayTo(segment,node1))
387 goto endloop;
388
389 node2=OtherNode(segment,node1);
390
391 if(result1->prev && result1->prev->node==node2)
392 goto endloop;
393
394 seg2=IndexSegment(segments,segment);
395
396 if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1,seg2,profile->allow))
397 goto endloop;
398
399 way=LookupWay(ways,segment->way,1);
400
401 if(!(way->allow&profile->allow))
402 goto endloop;
403
404 if(!profile->highway[HIGHWAY(way->type)])
405 goto endloop;
406
407 if(way->weight && way->weight<profile->weight)
408 goto endloop;
409
410 if((way->height && way->height<profile->height) ||
411 (way->width && way->width <profile->width ) ||
412 (way->length && way->length<profile->length))
413 goto endloop;
414
415 segment_pref=profile->highway[HIGHWAY(way->type)];
416
417 for(i=1;i<Property_Count;i++)
418 if(ways->file.props & PROPERTIES(i))
419 {
420 if(way->props & PROPERTIES(i))
421 segment_pref*=profile->props_yes[i];
422 else
423 segment_pref*=profile->props_no[i];
424 }
425
426 if(segment_pref==0)
427 goto endloop;
428
429 node=LookupNode(nodes,node2,2);
430
431 if(!(node->allow&profile->allow))
432 goto endloop;
433
434 if(option_quickest==0)
435 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
436 else
437 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
438
439 cumulative_score=result1->score+segment_score;
440
441 if(cumulative_score>finish_score)
442 goto endloop;
443
444 result2=FindResult(results,node2,seg2);
445
446 if(!result2) /* New end node/segment pair */
447 {
448 result2=InsertResult(results,node2,seg2);
449 result2->prev=result1;
450 result2->score=cumulative_score;
451
452 if((result3=FindResult(end,node2,seg2)))
453 {
454 if((result2->score+result3->score)<finish_score)
455 {
456 finish_score=result2->score+result3->score;
457 finish_result=result2;
458 }
459 }
460 else
461 {
462 double lat,lon;
463 distance_t direct;
464
465 GetLatLong(nodes,node2,&lat,&lon);
466 direct=Distance(lat,lon,finish_lat,finish_lon);
467
468 if(option_quickest==0)
469 result2->sortby=result2->score+(score_t)direct/profile->max_pref;
470 else
471 result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
472
473 InsertInQueue(queue,result2);
474 }
475 }
476 else if(cumulative_score<result2->score) /* New end node/segment pair is better */
477 {
478 result2->prev=result1;
479 result2->score=cumulative_score;
480
481 if((result3=FindResult(end,node2,seg2)))
482 {
483 if((result2->score+result3->score)<finish_score)
484 {
485 finish_score=result2->score+result3->score;
486 finish_result=result2;
487 }
488 }
489 else if(result2->score<finish_score)
490 {
491 double lat,lon;
492 distance_t direct;
493
494 GetLatLong(nodes,node2,&lat,&lon);
495 direct=Distance(lat,lon,finish_lat,finish_lon);
496
497 if(option_quickest==0)
498 result2->sortby=result2->score+(score_t)direct/profile->max_pref;
499 else
500 result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
501
502 InsertInQueue(queue,result2);
503 }
504 }
505
506 endloop:
507
508 if(!option_quiet && !(results->number%10000))
509 printf_middle("Routing: Super-Nodes checked = %d",results->number);
510
511 segment=NextSegment(segments,segment,node1);
512 }
513 }
514
515 if(!option_quiet)
516 printf_last("Routing: Super-Nodes checked = %d",results->number);
517
518 FreeQueueList(queue);
519
520 /* Check it worked */
521
522 if(!finish_result)
523 {
524 FreeResultsList(results);
525 return(NULL);
526 }
527
528 /* Finish off the end part of the route. */
529
530 result3=InsertResult(results,end->finish_node,NO_SEGMENT);
531
532 result3->prev=finish_result;
533 result3->score=finish_score;
534
535 FixForwardRoute(results,result3);
536
537 return(results);
538 }
539
540
541 /*++++++++++++++++++++++++++++++++++++++
542 Find all routes from a specified node to any super-node.
543
544 Results *FindStartRoutes Returns a set of results.
545
546 Nodes *nodes The set of nodes to use.
547
548 Segments *segments The set of segments to use.
549
550 Ways *ways The set of ways to use.
551
552 Relations *relations The set of relations to use.
553
554 index_t start_node The start node.
555
556 index_t prev_segment The previous segment before the start node.
557
558 Profile *profile The profile containing the transport type, speeds and allowed highways.
559 ++++++++++++++++++++++++++++++++++++++*/
560
561 Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,index_t start_node,index_t prev_segment,Profile *profile)
562 {
563 Results *results;
564 Queue *queue;
565 Result *result1,*result2;
566
567 /* Create the results and insert the start node */
568
569 results=NewResultsList(8);
570
571 results->start_node=start_node;
572 results->prev_segment=prev_segment;
573
574 result1=InsertResult(results,start_node,prev_segment);
575
576 /* Take a shortcut if the first node is a super-node. */
577
578 if(!IsFakeNode(start_node) && IsSuperNode(LookupNode(nodes,start_node,1)))
579 return(results);
580
581 /* Insert the first node into the queue */
582
583 queue=NewQueueList();
584
585 InsertInQueue(queue,result1);
586
587 /* Loop across all nodes in the queue */
588
589 while((result1=PopFromQueue(queue)))
590 {
591 index_t node1,seg1;
592 Segment *segment;
593 // index_t turnrelation=NO_RELATION;
594
595 node1=result1->node;
596 seg1=result1->segment;
597
598 // if(IsTurnRestrictedNode(LookupNode(nodes,node1,1)))
599 // turnrelation=FindFirstTurnRelation2(relations,node1,seg1);
600
601 if(IsFakeNode(node1))
602 segment=FirstFakeSegment(node1);
603 else
604 segment=FirstSegment(segments,nodes,node1);
605
606 while(segment)
607 {
608 index_t node2,seg2;
609 Way *way;
610 score_t segment_pref,segment_score,cumulative_score;
611 int i;
612
613 if(!IsNormalSegment(segment))
614 goto endloop;
615
616 if(profile->oneway && IsOnewayTo(segment,node1))
617 goto endloop;
618
619 node2=OtherNode(segment,node1);
620
621 if(result1->prev && result1->prev->node==node2)
622 goto endloop;
623
624 if(IsFakeNode(node1) || IsFakeNode(node2))
625 seg2=IndexFakeSegment(segment);
626 else
627 seg2=IndexSegment(segments,segment);
628
629 // if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1,seg2,profile->allow))
630 // goto endloop;
631
632 way=LookupWay(ways,segment->way,1);
633
634 if(!(way->allow&profile->allow))
635 goto endloop;
636
637 if(!profile->highway[HIGHWAY(way->type)])
638 goto endloop;
639
640 if(way->weight && way->weight<profile->weight)
641 goto endloop;
642
643 if((way->height && way->height<profile->height) ||
644 (way->width && way->width <profile->width ) ||
645 (way->length && way->length<profile->length))
646 goto endloop;
647
648 segment_pref=profile->highway[HIGHWAY(way->type)];
649
650 for(i=1;i<Property_Count;i++)
651 if(ways->file.props & PROPERTIES(i))
652 {
653 if(way->props & PROPERTIES(i))
654 segment_pref*=profile->props_yes[i];
655 else
656 segment_pref*=profile->props_no[i];
657 }
658
659 if(segment_pref==0)
660 goto endloop;
661
662 if(!IsFakeNode(node2))
663 {
664 Node *node=LookupNode(nodes,node2,2);
665
666 if(!(node->allow&profile->allow))
667 goto endloop;
668 }
669
670 if(option_quickest==0)
671 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
672 else
673 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
674
675 cumulative_score=result1->score+segment_score;
676
677 result2=FindResult(results,node2,seg2);
678
679 if(!result2) /* New end node/segment combination */
680 {
681 result2=InsertResult(results,node2,seg2);
682 result2->prev=result1;
683 result2->score=cumulative_score;
684
685 if(!IsFakeNode(node2) && !IsSuperNode(LookupNode(nodes,node2,2)))
686 {
687 result2->sortby=result2->score;
688 InsertInQueue(queue,result2);
689 }
690 }
691 else if(cumulative_score<result2->score) /* New end node/segment combination is better */
692 {
693 result2->prev=result1;
694 result2->score=cumulative_score;
695
696 if(!IsFakeNode(node2) && !IsSuperNode(LookupNode(nodes,node2,2)))
697 {
698 result2->sortby=result2->score;
699 InsertInQueue(queue,result2);
700 }
701 }
702
703 endloop:
704
705 if(IsFakeNode(node1))
706 segment=NextFakeSegment(segment,node1);
707 else
708 segment=NextSegment(segments,segment,node1);
709 }
710 }
711
712 FreeQueueList(queue);
713
714 /* Check it worked */
715
716 if(results->number==1)
717 {
718 FreeResultsList(results);
719 return(NULL);
720 }
721
722 return(results);
723 }
724
725
726 /*++++++++++++++++++++++++++++++++++++++
727 Find all routes from any super-node to a specific node.
728
729 Results *FindFinishRoutes Returns a set of results.
730
731 Nodes *nodes The set of nodes to use.
732
733 Segments *segments The set of segments to use.
734
735 Ways *ways The set of ways to use.
736
737 Relations *relations The set of relations to use.
738
739 index_t finish_node The finishing node.
740
741 Profile *profile The profile containing the transport type, speeds and allowed highways.
742 ++++++++++++++++++++++++++++++++++++++*/
743
744 Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,index_t finish_node,Profile *profile)
745 {
746 Results *results,*results2;
747 Queue *queue;
748 Result *result1,*result2,*result3;
749
750 /* Create the results and insert the finish node */
751
752 results=NewResultsList(8);
753
754 results->finish_node=finish_node;
755
756 result1=InsertResult(results,finish_node,NO_SEGMENT);
757
758 /* Take a shortcut if the first node is a super-node. */
759
760 if(!IsFakeNode(finish_node) && IsSuperNode(LookupNode(nodes,finish_node,1)))
761 return(results);
762
763 /* Insert the first node into the queue */
764
765 queue=NewQueueList();
766
767 InsertInQueue(queue,result1);
768
769 /* Loop across all nodes in the queue */
770
771 while((result1=PopFromQueue(queue)))
772 {
773 index_t node1,seg1;
774 Segment *segment;
775 index_t turnrelation=NO_RELATION;
776
777 node1=result1->node;
778 seg1=result1->segment;
779
780 if(IsTurnRestrictedNode(LookupNode(nodes,node1,1)))
781 turnrelation=FindFirstTurnRelation1(relations,node1); /* working backwards => turn relation sort order doesn't help */
782
783 if(IsFakeNode(node1))
784 segment=FirstFakeSegment(node1);
785 else
786 segment=FirstSegment(segments,nodes,node1);
787
788 while(segment)
789 {
790 index_t node2,seg2;
791 Way *way;
792 score_t segment_pref,segment_score,cumulative_score;
793 int i;
794
795 if(!IsNormalSegment(segment))
796 goto endloop;
797
798 if(profile->oneway && IsOnewayFrom(segment,node1)) /* Disallow oneway from node2 *to* node1 */
799 goto endloop;
800
801 node2=OtherNode(segment,node1);
802
803 if(result1->next && result1->next->node==node2)
804 goto endloop;
805
806 if(IsFakeNode(node1) || IsFakeNode(node2))
807 seg2=IndexFakeSegment(segment);
808 else
809 seg2=IndexSegment(segments,segment);
810
811 if(turnrelation!=NO_RELATION)
812 {
813 index_t turnrelation2=FindFirstTurnRelation2(relations,node1,node2); /* node2 -> node1 -> result1->next->node */
814
815 if(turnrelation2!=NO_RELATION && !IsTurnAllowed(relations,turnrelation2,node1,seg2,seg1,profile->allow))
816 goto endloop;
817 }
818
819 way=LookupWay(ways,segment->way,1);
820
821 if(!(way->allow&profile->allow))
822 goto endloop;
823
824 if(!profile->highway[HIGHWAY(way->type)])
825 goto endloop;
826
827 if(way->weight && way->weight<profile->weight)
828 goto endloop;
829
830 if((way->height && way->height<profile->height) ||
831 (way->width && way->width <profile->width ) ||
832 (way->length && way->length<profile->length))
833 goto endloop;
834
835 segment_pref=profile->highway[HIGHWAY(way->type)];
836
837 for(i=1;i<Property_Count;i++)
838 if(ways->file.props & PROPERTIES(i))
839 {
840 if(way->props & PROPERTIES(i))
841 segment_pref*=profile->props_yes[i];
842 else
843 segment_pref*=profile->props_no[i];
844 }
845
846 if(segment_pref==0)
847 goto endloop;
848
849 if(!IsFakeNode(node2))
850 {
851 Node *node=LookupNode(nodes,node2,2);
852
853 if(!(node->allow&profile->allow))
854 goto endloop;
855 }
856
857 if(option_quickest==0)
858 segment_score=(score_t)DISTANCE(segment->distance)/segment_pref;
859 else
860 segment_score=(score_t)Duration(segment,way,profile)/segment_pref;
861
862 cumulative_score=result1->score+segment_score;
863
864 result2=FindResult(results,node2,seg2);
865
866 if(!result2) /* New end node */
867 {
868 result2=InsertResult(results,node2,seg2);
869 result2->next=result1; /* working backwards */
870 result2->score=cumulative_score;
871
872 if(!IsFakeNode(node1) && !IsSuperNode(LookupNode(nodes,node1,1))) /* Overshoot by one segment */
873 {
874 result2->sortby=result2->score;
875 InsertInQueue(queue,result2);
876 }
877 }
878 else if(cumulative_score<result2->score) /* New end node is better */
879 {
880 result2->next=result1; /* working backwards */
881 result2->score=cumulative_score;
882
883 if(!IsFakeNode(node1) && !IsSuperNode(LookupNode(nodes,node1,1))) /* Overshoot by one segment */
884 {
885 result2->sortby=result2->score;
886 InsertInQueue(queue,result2);
887 }
888 }
889
890 endloop:
891
892 if(IsFakeNode(node1))
893 segment=NextFakeSegment(segment,node1);
894 else
895 segment=NextSegment(segments,segment,node1);
896 }
897 }
898
899 FreeQueueList(queue);
900
901 /* Check it worked */
902
903 if(results->number==1)
904 {
905 FreeResultsList(results);
906 return(NULL);
907 }
908
909 /* Create a results structure with the node at the end of the segment opposite the start */
910
911 results2=NewResultsList(8);
912
913 results2->finish_node=results->finish_node;
914
915 result3=FirstResult(results);
916
917 while(result3)
918 {
919 if(result3->next)
920 {
921 result2=InsertResult(results2,result3->next->node,result3->segment);
922
923 result2->score=result3->score;
924 }
925
926 result3=NextResult(results,result3);
927 }
928
929 /* Fix up the result->next pointers */
930
931 result3=FirstResult(results);
932
933 while(result3)
934 {
935 if(result3->next && result3->next->next)
936 {
937 result1=FindResult(results2,result3->next->node,result3->segment);
938 result2=FindResult(results2,result3->next->next->node,result3->next->segment);
939
940 result1->next=result2;
941 }
942
943 result3=NextResult(results,result3);
944 }
945
946 FreeResultsList(results);
947
948 return(results2);
949 }
950
951
952 /*++++++++++++++++++++++++++++++++++++++
953 Create an optimum route given the set of super-nodes to follow.
954
955 Results *CombineRoutes Returns the results from joining the super-nodes.
956
957 Nodes *nodes The list of nodes.
958
959 Segments *segments The set of segments to use.
960
961 Ways *ways The list of ways.
962
963 Relations *relations The set of relations to use.
964
965 Results *results The set of results from the super-nodes.
966
967 index_t prev_segment The previous segment before the start node.
968
969 Profile *profile The profile containing the transport type, speeds and allowed highways.
970 ++++++++++++++++++++++++++++++++++++++*/
971
972 Results *CombineRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Results *results,index_t prev_segment,Profile *profile)
973 {
974 Result *result1,*result3;
975 Results *combined;
976
977 combined=NewResultsList(64);
978
979 combined->start_node=results->start_node;
980 combined->finish_node=results->finish_node;
981
982 combined->last_segment=results->last_segment;
983
984 /* Sort out the combined route */
985
986 result1=FindResult(results,results->start_node,prev_segment);
987
988 result3=InsertResult(combined,results->start_node,prev_segment);
989
990 do
991 {
992 Result *result2,*result4;
993
994 if(result1->next)
995 {
996 Results *results2=FindNormalRoute(nodes,segments,ways,relations,result1->node,result3->segment,result1->next->node,profile);
997
998 result2=FindResult(results2,result1->node,result3->segment);
999
1000 // printf("CombineRoutes(result2->node=%ld result2->segment=%ld)\n",result2->node,result2->segment);
1001
1002 result2=result2->next;
1003
1004 /*
1005 * result1 result1->next
1006 * = =
1007 * ---*----------------------------------* = results
1008 *
1009 * ---*----.----.----.----.----.----.----* = results2
1010 * =
1011 * result2
1012 *
1013 * ---*----.----.----.----.----.----.----* = combined
1014 * = =
1015 * result3 result4
1016 */
1017
1018 do
1019 {
1020 // printf("CombineRoutes(result2->node=%ld result2->segment=%ld)\n",result2->node,result2->segment);
1021
1022 result4=InsertResult(combined,result2->node,result2->segment);
1023
1024 result4->score=result2->score+result3->score;
1025 result4->prev=result3;
1026
1027 result2=result2->next;
1028
1029 result3=result4;
1030 }
1031 while(result2);
1032
1033 FreeResultsList(results2);
1034 }
1035
1036 result1=result1->next;
1037 }
1038 while(result1);
1039
1040 FixForwardRoute(combined,result3);
1041
1042 return(combined);
1043 }
1044
1045
1046 /*++++++++++++++++++++++++++++++++++++++
1047 Fix the forward route (i.e. setup next pointers for forward path from prev nodes on reverse path).
1048
1049 Results *results The set of results to update.
1050
1051 Result *finish_result The finish result.
1052 ++++++++++++++++++++++++++++++++++++++*/
1053
1054 void FixForwardRoute(Results *results,Result *finish_result)
1055 {
1056 Result *result2=finish_result;
1057
1058 /* Create the forward links for the optimum path */
1059
1060 do
1061 {
1062 Result *result1;
1063
1064 if(result2->prev)
1065 {
1066 index_t node1=result2->prev->node;
1067 index_t seg1=result2->prev->segment;
1068
1069 result1=FindResult(results,node1,seg1);
1070
1071 result1->next=result2;
1072
1073 result2=result1;
1074 }
1075 else
1076 result2=NULL;
1077 }
1078 while(result2);
1079
1080 results->finish_node=finish_result->node;
1081 results->last_segment=finish_result->segment;
1082 }

Properties

Name Value
cvs:description Route optimiser.