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 622 - (hide annotations) (download) (as text)
Sat Feb 5 15:41:48 2011 UTC (14 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 28869 byte(s)
Include the option to obey turn restrictions in the profile for each transport
type.

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

Properties

Name Value
cvs:description Route optimiser.