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 611 - (hide annotations) (download) (as text)
Sat Jan 29 17:52:39 2011 UTC (14 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 29366 byte(s)
Don't check for turn relations in FindStartRoutes().

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

Properties

Name Value
cvs:description Route optimiser.