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 1281 - (hide annotations) (download) (as text)
Sat Apr 27 07:37:29 2013 UTC (11 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 51978 byte(s)
Remove the FindResult1 function which allows hashing to be performed on a
combination of node and segment rather than just node.

1 amb 2 /***************************************
2     Routing optimiser.
3 amb 151
4     Part of the Routino routing software.
5 amb 2 ******************/ /******************
6 amb 1278 This file Copyright 2008-2013 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 96 #include "types.h"
24 amb 109 #include "nodes.h"
25     #include "segments.h"
26     #include "ways.h"
27 amb 596 #include "relations.h"
28 amb 449
29 amb 519 #include "logging.h"
30 amb 449 #include "functions.h"
31 amb 532 #include "fakes.h"
32 amb 28 #include "results.h"
33 amb 2
34 amb 26
35 amb 1278 /*+ To help when debugging +*/
36     #define DEBUG 0
37    
38    
39 amb 685 /* Global variables */
40    
41 amb 113 /*+ The option not to print any progress information. +*/
42 amb 107 extern int option_quiet;
43 amb 2
44 amb 113 /*+ The option to calculate the quickest route insted of the shortest. +*/
45     extern int option_quickest;
46 amb 31
47 amb 113
48 amb 685 /* Local functions */
49    
50 amb 1063 static index_t FindSuperSegment(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,index_t finish_node,index_t finish_segment);
51     static Results *FindSuperRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,index_t start_node,index_t finish_node);
52 amb 685
53    
54 amb 2 /*++++++++++++++++++++++++++++++++++++++
55 amb 727 Find the optimum route between two nodes not passing through a super-node.
56 amb 2
57 amb 238 Results *FindNormalRoute Returns a set of results.
58 amb 26
59     Nodes *nodes The set of nodes to use.
60    
61     Segments *segments The set of segments to use.
62    
63 amb 54 Ways *ways The set of ways to use.
64    
65 amb 542 Relations *relations The set of relations to use.
66    
67 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
68    
69 amb 605 index_t start_node The start node.
70 amb 2
71 amb 605 index_t prev_segment The previous segment before the start node.
72 amb 54
73 amb 605 index_t finish_node The finish node.
74 amb 2 ++++++++++++++++++++++++++++++++++++++*/
75    
76 amb 723 Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t start_node,index_t prev_segment,index_t finish_node)
77 amb 2 {
78 amb 31 Results *results;
79 amb 469 Queue *queue;
80 amb 166 score_t finish_score;
81 amb 219 double finish_lat,finish_lon;
82 amb 605 Result *finish_result;
83 amb 469 Result *result1,*result2;
84 amb 1068 int force_uturn=0;
85 amb 2
86 amb 1278 #if DEBUG
87     printf(" FindNormalRoute(...,start_node=%"Pindex_t" prev_segment=%"Pindex_t" finish_node=%"Pindex_t")\n",start_node,prev_segment,finish_node);
88     #endif
89    
90 amb 10 /* Set up the finish conditions */
91    
92 amb 176 finish_score=INF_SCORE;
93 amb 605 finish_result=NULL;
94 amb 10
95 amb 605 if(IsFakeNode(finish_node))
96     GetFakeLatLong(finish_node,&finish_lat,&finish_lon);
97 amb 303 else
98 amb 605 GetLatLong(nodes,finish_node,&finish_lat,&finish_lon);
99 amb 119
100 amb 165 /* Create the list of results and insert the first node into the queue */
101 amb 2
102 amb 855 results=NewResultsList(64);
103 amb 1068 queue=NewQueueList();
104 amb 2
105 amb 605 results->start_node=start_node;
106 amb 617 results->prev_segment=prev_segment;
107 amb 165
108 amb 735 result1=InsertResult(results,results->start_node,results->prev_segment);
109 amb 28
110 amb 236 InsertInQueue(queue,result1);
111    
112 amb 1068 /* Check for barrier at start waypoint - must perform U-turn */
113    
114     if(prev_segment!=NO_SEGMENT && !IsFakeNode(start_node))
115     {
116 amb 1078 Node *startp=LookupNode(nodes,start_node,1);
117 amb 1068
118 amb 1078 if(!(startp->allow&profile->allow))
119 amb 1068 force_uturn=1;
120     }
121    
122 amb 2 /* Loop across all nodes in the queue */
123    
124 amb 236 while((result1=PopFromQueue(queue)))
125 amb 2 {
126 amb 885 Node *node1p=NULL;
127 amb 1078 Segment *segmentp;
128 amb 637 index_t node1,seg1,seg1r;
129 amb 608 index_t turnrelation=NO_RELATION;
130 amb 594
131 amb 680 /* score must be better than current best score */
132 amb 1066 if(result1->score>=finish_score)
133 amb 119 continue;
134    
135 amb 43 node1=result1->node;
136 amb 605 seg1=result1->segment;
137 amb 2
138 amb 637 if(IsFakeSegment(seg1))
139     seg1r=IndexRealSegment(seg1);
140     else
141     seg1r=seg1;
142    
143 amb 885 if(!IsFakeNode(node1))
144     node1p=LookupNode(nodes,node1,1);
145    
146 amb 680 /* lookup if a turn restriction applies */
147 amb 885 if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
148 amb 637 turnrelation=FindFirstTurnRelation2(relations,node1,seg1r);
149 amb 596
150 amb 680 /* Loop across all segments */
151    
152 amb 303 if(IsFakeNode(node1))
153 amb 1078 segmentp=FirstFakeSegment(node1);
154 amb 303 else
155 amb 1078 segmentp=FirstSegment(segments,node1p,1);
156 amb 2
157 amb 1078 while(segmentp)
158 amb 2 {
159 amb 885 Node *node2p=NULL;
160 amb 1078 Way *wayp;
161 amb 637 index_t node2,seg2,seg2r;
162 amb 298 score_t segment_pref,segment_score,cumulative_score;
163     int i;
164 amb 59
165 amb 1078 node2=OtherNode(segmentp,node1); /* need this here because we use node2 at the end of the loop */
166 amb 303
167 amb 680 /* must be a normal segment */
168 amb 1078 if(!IsNormalSegment(segmentp))
169 amb 90 goto endloop;
170    
171 amb 680 /* must obey one-way restrictions (unless profile allows) */
172 amb 1078 if(profile->oneway && IsOnewayTo(segmentp,node1))
173 amb 64 goto endloop;
174    
175 amb 605 if(IsFakeNode(node1) || IsFakeNode(node2))
176 amb 637 {
177 amb 1078 seg2 =IndexFakeSegment(segmentp);
178 amb 637 seg2r=IndexRealSegment(seg2);
179     }
180 amb 605 else
181 amb 637 {
182 amb 1078 seg2 =IndexSegment(segments,segmentp);
183 amb 637 seg2r=seg2;
184     }
185 amb 603
186 amb 1068 /* must perform U-turn in special cases */
187     if(force_uturn && node1==results->start_node)
188     {
189     if(seg2r!=result1->segment)
190     goto endloop;
191     }
192     else
193     /* must not perform U-turn (unless profile allows) */
194     if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
195     goto endloop;
196 amb 636
197 amb 680 /* must obey turn relations */
198 amb 637 if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1r,seg2r,profile->allow))
199 amb 608 goto endloop;
200 amb 596
201 amb 885 if(!IsFakeNode(node2))
202     node2p=LookupNode(nodes,node2,2);
203    
204 amb 723 /* must not pass over super-node */
205 amb 885 if(node2!=finish_node && node2p && IsSuperNode(node2p))
206 amb 238 goto endloop;
207    
208 amb 1078 wayp=LookupWay(ways,segmentp->way,1);
209 amb 54
210 amb 680 /* mode of transport must be allowed on the highway */
211 amb 1078 if(!(wayp->allow&profile->allow))
212 amb 54 goto endloop;
213    
214 amb 680 /* must obey weight restriction (if exists) */
215 amb 1078 if(wayp->weight && wayp->weight<profile->weight)
216 amb 135 goto endloop;
217    
218 amb 1066 /* must obey height/width/length restriction (if exist) */
219 amb 1078 if((wayp->height && wayp->height<profile->height) ||
220     (wayp->width && wayp->width <profile->width ) ||
221     (wayp->length && wayp->length<profile->length))
222 amb 135 goto endloop;
223    
224 amb 1078 segment_pref=profile->highway[HIGHWAY(wayp->type)];
225 amb 298
226 amb 1066 /* highway preferences must allow this highway */
227     if(segment_pref==0)
228     goto endloop;
229    
230 amb 298 for(i=1;i<Property_Count;i++)
231 amb 460 if(ways->file.props & PROPERTIES(i))
232 amb 307 {
233 amb 1078 if(wayp->props & PROPERTIES(i))
234 amb 307 segment_pref*=profile->props_yes[i];
235     else
236     segment_pref*=profile->props_no[i];
237     }
238 amb 298
239 amb 680 /* profile preferences must allow this highway */
240 amb 298 if(segment_pref==0)
241     goto endloop;
242    
243 amb 1068 /* mode of transport must be allowed through node2 unless it is the final node */
244     if(node2p && node2!=finish_node && !(node2p->allow&profile->allow))
245 amb 885 goto endloop;
246 amb 469
247 amb 166 if(option_quickest==0)
248 amb 1168 segment_score=(score_t)DISTANCE(segmentp->distance)/segment_pref;
249 amb 166 else
250 amb 1078 segment_score=(score_t)Duration(segmentp,wayp,profile)/segment_pref;
251 amb 59
252 amb 170 cumulative_score=result1->score+segment_score;
253 amb 166
254 amb 680 /* score must be better than current best score */
255 amb 1066 if(cumulative_score>=finish_score)
256 amb 2 goto endloop;
257    
258 amb 605 result2=FindResult(results,node2,seg2);
259 amb 42
260 amb 680 if(!result2) /* New end node/segment combination */
261 amb 2 {
262 amb 605 result2=InsertResult(results,node2,seg2);
263     result2->prev=result1;
264 amb 170 result2->score=cumulative_score;
265 amb 2 }
266 amb 605 else if(cumulative_score<result2->score) /* New score for end node/segment combination is better */
267 amb 2 {
268 amb 605 result2->prev=result1;
269 amb 170 result2->score=cumulative_score;
270 amb 605 result2->segment=seg2;
271 amb 1217 }
272     else
273     goto endloop;
274 amb 166
275 amb 1217 if(node2==finish_node)
276     {
277     finish_score=cumulative_score;
278     finish_result=result2;
279 amb 2 }
280 amb 1217 else
281     {
282     result2->sortby=result2->score;
283     InsertInQueue(queue,result2);
284     }
285 amb 2
286     endloop:
287    
288 amb 303 if(IsFakeNode(node1))
289 amb 1078 segmentp=NextFakeSegment(segmentp,node1);
290 amb 303 else if(IsFakeNode(node2))
291 amb 1078 segmentp=NULL; /* cannot call NextSegment() with a fake segment */
292 amb 303 else
293     {
294 amb 1078 segmentp=NextSegment(segments,segmentp,node1);
295 amb 303
296 amb 1078 if(!segmentp && IsFakeNode(finish_node))
297     segmentp=ExtraFakeSegment(node1,finish_node);
298 amb 303 }
299 amb 2 }
300     }
301    
302 amb 236 FreeQueueList(queue);
303    
304 amb 77 /* Check it worked */
305    
306 amb 605 if(!finish_result)
307 amb 77 {
308 amb 1278 #if DEBUG
309     printf(" Failed\n");
310     #endif
311    
312 amb 77 FreeResultsList(results);
313     return(NULL);
314     }
315    
316 amb 605 FixForwardRoute(results,finish_result);
317 amb 31
318 amb 1278 #if DEBUG
319     Result *r=FindResult(results,results->start_node,results->prev_segment);
320    
321     while(r)
322     {
323     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
324    
325     r=r->next;
326     }
327     #endif
328    
329 amb 31 return(results);
330 amb 2 }
331    
332    
333     /*++++++++++++++++++++++++++++++++++++++
334 amb 680 Find the optimum route between two nodes where the start and end are a set of pre/post-routed super-nodes.
335 amb 34
336 amb 238 Results *FindMiddleRoute Returns a set of results.
337 amb 34
338 amb 95 Nodes *nodes The set of nodes to use.
339 amb 34
340 amb 95 Segments *segments The set of segments to use.
341 amb 34
342 amb 95 Ways *ways The set of ways to use.
343 amb 54
344 amb 542 Relations *relations The set of relations to use.
345    
346 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
347    
348 amb 34 Results *begin The initial portion of the route.
349    
350     Results *end The final portion of the route.
351     ++++++++++++++++++++++++++++++++++++++*/
352    
353 amb 721 Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Results *begin,Results *end)
354 amb 34 {
355     Results *results;
356 amb 469 Queue *queue;
357 amb 605 Result *finish_result;
358 amb 166 score_t finish_score;
359 amb 219 double finish_lat,finish_lon;
360 amb 632 Result *result1,*result2,*result3,*result4;
361 amb 1068 int force_uturn=0;
362 amb 34
363 amb 1278 #if DEBUG
364     printf(" FindMiddleRoute(...,[begin has %d nodes],[end has %d nodes])\n",begin->number,end->number);
365     #endif
366    
367     #if !DEBUG
368 amb 227 if(!option_quiet)
369 amb 519 printf_first("Routing: Super-Nodes checked = 0");
370 amb 1278 #endif
371 amb 227
372 amb 34 /* Set up the finish conditions */
373    
374 amb 1210 finish_score=INF_SCORE;
375 amb 605 finish_result=NULL;
376 amb 34
377 amb 605 if(IsFakeNode(end->finish_node))
378     GetFakeLatLong(end->finish_node,&finish_lat,&finish_lon);
379 amb 303 else
380 amb 605 GetLatLong(nodes,end->finish_node,&finish_lat,&finish_lon);
381 amb 119
382 amb 165 /* Create the list of results and insert the first node into the queue */
383 amb 34
384 amb 860 results=NewResultsList(65536);
385 amb 1068 queue=NewQueueList();
386 amb 34
387 amb 605 results->start_node=begin->start_node;
388     results->prev_segment=begin->prev_segment;
389 amb 34
390 amb 688 if(begin->number==1)
391     {
392 amb 828 if(begin->prev_segment==NO_SEGMENT)
393     results->prev_segment=NO_SEGMENT;
394     else
395     {
396 amb 1063 index_t superseg=FindSuperSegment(nodes,segments,ways,relations,begin->start_node,begin->prev_segment);
397 amb 34
398 amb 828 results->prev_segment=superseg;
399     }
400 amb 688 }
401    
402     result1=InsertResult(results,results->start_node,results->prev_segment);
403    
404 amb 685 /* Insert the finish points of the beginning part of the path into the queue,
405     translating the segments into super-segments. */
406 amb 34
407 amb 79 result3=FirstResult(begin);
408    
409     while(result3)
410     {
411 amb 735 if((results->start_node!=result3->node || results->prev_segment!=result3->segment) &&
412 amb 885 !IsFakeNode(result3->node) && IsSuperNode(LookupNode(nodes,result3->node,5)))
413 amb 45 {
414 amb 722 Result *result5=result1;
415 amb 1063 index_t superseg=FindSuperSegment(nodes,segments,ways,relations,result3->node,result3->segment);
416 amb 34
417 amb 722 if(superseg!=result3->segment)
418     {
419     result5=InsertResult(results,result3->node,result3->segment);
420    
421     result5->prev=result1;
422     }
423    
424 amb 703 if(!FindResult(results,result3->node,superseg))
425     {
426     result2=InsertResult(results,result3->node,superseg);
427 amb 722 result2->prev=result5;
428 amb 685
429 amb 703 result2->score=result3->score;
430     result2->sortby=result3->score;
431 amb 119
432 amb 703 InsertInQueue(queue,result2);
433 amb 632
434 amb 703 if((result4=FindResult(end,result2->node,result2->segment)))
435 amb 632 {
436 amb 703 if((result2->score+result4->score)<finish_score)
437     {
438     finish_score=result2->score+result4->score;
439     finish_result=result2;
440     }
441 amb 632 }
442     }
443 amb 45 }
444 amb 34
445 amb 79 result3=NextResult(begin,result3);
446     }
447    
448 amb 238 if(begin->number==1)
449     InsertInQueue(queue,result1);
450    
451 amb 1068 /* Check for barrier at start waypoint - must perform U-turn */
452    
453     if(begin->number==1 && results->prev_segment!=NO_SEGMENT)
454     {
455 amb 1078 Node *startp=LookupNode(nodes,result1->node,1);
456 amb 1068
457 amb 1078 if(!(startp->allow&profile->allow))
458 amb 1068 force_uturn=1;
459     }
460    
461 amb 95 /* Loop across all nodes in the queue */
462 amb 34
463 amb 236 while((result1=PopFromQueue(queue)))
464 amb 34 {
465 amb 885 Node *node1p;
466 amb 1078 Segment *segmentp;
467 amb 605 index_t node1,seg1;
468 amb 596 index_t turnrelation=NO_RELATION;
469 amb 594
470 amb 680 /* score must be better than current best score */
471 amb 1066 if(result1->score>=finish_score)
472 amb 119 continue;
473    
474 amb 43 node1=result1->node;
475 amb 605 seg1=result1->segment;
476 amb 34
477 amb 885 node1p=LookupNode(nodes,node1,1); /* node1 cannot be a fake node (must be a super-node) */
478    
479 amb 680 /* lookup if a turn restriction applies */
480 amb 885 if(profile->turns && IsTurnRestrictedNode(node1p)) /* node1 cannot be a fake node (must be a super-node) */
481 amb 605 turnrelation=FindFirstTurnRelation2(relations,node1,seg1);
482 amb 596
483 amb 680 /* Loop across all segments */
484 amb 34
485 amb 1078 segmentp=FirstSegment(segments,node1p,1); /* node1 cannot be a fake node (must be a super-node) */
486 amb 680
487 amb 1078 while(segmentp)
488 amb 34 {
489 amb 885 Node *node2p;
490 amb 1078 Way *wayp;
491 amb 603 index_t node2,seg2;
492 amb 298 score_t segment_pref,segment_score,cumulative_score;
493     int i;
494 amb 59
495 amb 680 /* must be a super segment */
496 amb 1078 if(!IsSuperSegment(segmentp))
497 amb 95 goto endloop;
498    
499 amb 680 /* must obey one-way restrictions (unless profile allows) */
500 amb 1078 if(profile->oneway && IsOnewayTo(segmentp,node1))
501 amb 64 goto endloop;
502    
503 amb 1078 seg2=IndexSegment(segments,segmentp); /* segment cannot be a fake segment (must be a super-segment) */
504 amb 34
505 amb 1068 /* must perform U-turn in special cases */
506     if(force_uturn && node1==results->start_node)
507     {
508     if(seg2!=result1->segment)
509     goto endloop;
510     }
511     else
512     /* must not perform U-turn */
513     if(seg1==seg2) /* No fake segments, applies to all profiles */
514     goto endloop;
515 amb 636
516 amb 680 /* must obey turn relations */
517 amb 605 if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1,seg2,profile->allow))
518 amb 596 goto endloop;
519    
520 amb 1078 wayp=LookupWay(ways,segmentp->way,1);
521 amb 54
522 amb 1066 /* mode of transport must be allowed on the highway */
523 amb 1078 if(!(wayp->allow&profile->allow))
524 amb 54 goto endloop;
525    
526 amb 680 /* must obey weight restriction (if exists) */
527 amb 1078 if(wayp->weight && wayp->weight<profile->weight)
528 amb 135 goto endloop;
529    
530 amb 1066 /* must obey height/width/length restriction (if exist) */
531 amb 1078 if((wayp->height && wayp->height<profile->height) ||
532     (wayp->width && wayp->width <profile->width ) ||
533     (wayp->length && wayp->length<profile->length))
534 amb 135 goto endloop;
535    
536 amb 1078 segment_pref=profile->highway[HIGHWAY(wayp->type)];
537 amb 298
538 amb 1066 /* highway preferences must allow this highway */
539     if(segment_pref==0)
540     goto endloop;
541    
542 amb 298 for(i=1;i<Property_Count;i++)
543 amb 460 if(ways->file.props & PROPERTIES(i))
544 amb 307 {
545 amb 1078 if(wayp->props & PROPERTIES(i))
546 amb 307 segment_pref*=profile->props_yes[i];
547     else
548     segment_pref*=profile->props_no[i];
549     }
550 amb 298
551 amb 680 /* profile preferences must allow this highway */
552 amb 298 if(segment_pref==0)
553     goto endloop;
554    
555 amb 1078 node2=OtherNode(segmentp,node1);
556 amb 1066
557 amb 885 node2p=LookupNode(nodes,node2,2); /* node2 cannot be a fake node (must be a super-node) */
558 amb 469
559 amb 1068 /* mode of transport must be allowed through node2 unless it is the final node */
560     if(node2!=end->finish_node && !(node2p->allow&profile->allow))
561 amb 469 goto endloop;
562    
563 amb 166 if(option_quickest==0)
564 amb 1168 segment_score=(score_t)DISTANCE(segmentp->distance)/segment_pref;
565 amb 166 else
566 amb 1078 segment_score=(score_t)Duration(segmentp,wayp,profile)/segment_pref;
567 amb 34
568 amb 170 cumulative_score=result1->score+segment_score;
569 amb 166
570 amb 680 /* score must be better than current best score */
571 amb 1066 if(cumulative_score>=finish_score)
572 amb 34 goto endloop;
573    
574 amb 605 result2=FindResult(results,node2,seg2);
575 amb 42
576 amb 680 if(!result2) /* New end node/segment pair */
577 amb 34 {
578 amb 605 result2=InsertResult(results,node2,seg2);
579     result2->prev=result1;
580 amb 170 result2->score=cumulative_score;
581 amb 34 }
582 amb 605 else if(cumulative_score<result2->score) /* New end node/segment pair is better */
583 amb 34 {
584 amb 605 result2->prev=result1;
585 amb 170 result2->score=cumulative_score;
586 amb 1217 }
587     else
588     goto endloop;
589 amb 166
590 amb 1217 if((result3=FindResult(end,node2,seg2)))
591     {
592     if((result2->score+result3->score)<finish_score)
593 amb 34 {
594 amb 1217 finish_score=result2->score+result3->score;
595     finish_result=result2;
596 amb 34 }
597 amb 1217 }
598     else
599     {
600     double lat,lon;
601     distance_t direct;
602 amb 34
603 amb 1217 GetLatLong(nodes,node2,&lat,&lon); /* node2 cannot be a fake node (must be a super-node) */
604 amb 680
605 amb 1217 direct=Distance(lat,lon,finish_lat,finish_lon);
606 amb 166
607 amb 1217 if(option_quickest==0)
608     result2->sortby=result2->score+(score_t)direct/profile->max_pref;
609     else
610     result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref;
611 amb 119
612 amb 1217 if(result2->sortby<finish_score)
613     InsertInQueue(queue,result2);
614 amb 34 }
615    
616 amb 1278 #if !DEBUG
617 amb 757 if(!option_quiet && !(results->number%1000))
618 amb 519 printf_middle("Routing: Super-Nodes checked = %d",results->number);
619 amb 1278 #endif
620 amb 34
621 amb 627 endloop:
622    
623 amb 1078 segmentp=NextSegment(segments,segmentp,node1); /* node1 cannot be a fake node (must be a super-node) */
624 amb 34 }
625     }
626    
627 amb 1278 #if !DEBUG
628 amb 107 if(!option_quiet)
629 amb 519 printf_last("Routing: Super-Nodes checked = %d",results->number);
630 amb 1278 #endif
631 amb 34
632 amb 236 FreeQueueList(queue);
633    
634 amb 77 /* Check it worked */
635    
636 amb 605 if(!finish_result)
637 amb 77 {
638 amb 1278 #if DEBUG
639     printf(" Failed\n");
640     #endif
641    
642 amb 77 FreeResultsList(results);
643     return(NULL);
644     }
645    
646 amb 680 /* Finish off the end part of the route */
647 amb 34
648 amb 616 if(finish_result->node!=end->finish_node)
649     {
650     result3=InsertResult(results,end->finish_node,NO_SEGMENT);
651 amb 605
652 amb 616 result3->prev=finish_result;
653     result3->score=finish_score;
654 amb 605
655 amb 616 finish_result=result3;
656     }
657 amb 605
658 amb 616 FixForwardRoute(results,finish_result);
659    
660 amb 1278 #if DEBUG
661     Result *r=FindResult(results,results->start_node,results->prev_segment);
662    
663     while(r)
664     {
665     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
666    
667     r=r->next;
668     }
669     #endif
670    
671 amb 34 return(results);
672     }
673    
674    
675     /*++++++++++++++++++++++++++++++++++++++
676 amb 685 Find the super-segment that represents the route that contains a particular segment.
677    
678     index_t FindSuperSegment Returns the index of the super-segment.
679    
680     Nodes *nodes The set of nodes to use.
681    
682     Segments *segments The set of segments to use.
683    
684     Ways *ways The set of ways to use.
685    
686     Relations *relations The set of relations to use.
687    
688 amb 1061 index_t finish_node The super-node that the route ends at.
689 amb 685
690 amb 1061 index_t finish_segment The segment that the route ends with.
691 amb 685 ++++++++++++++++++++++++++++++++++++++*/
692    
693 amb 1063 static index_t FindSuperSegment(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,index_t finish_node,index_t finish_segment)
694 amb 685 {
695 amb 1078 Node *supernodep;
696     Segment *supersegmentp;
697 amb 685
698 amb 1061 if(IsFakeSegment(finish_segment))
699     finish_segment=IndexRealSegment(finish_segment);
700 amb 699
701 amb 1078 supernodep=LookupNode(nodes,finish_node,5); /* finish_node cannot be a fake node (must be a super-node) */
702     supersegmentp=LookupSegment(segments,finish_segment,2); /* finish_segment cannot be a fake segment. */
703 amb 687
704 amb 1078 if(IsSuperSegment(supersegmentp))
705 amb 1061 return(finish_segment);
706 amb 687
707 amb 685 /* Loop across all segments */
708    
709 amb 1078 supersegmentp=FirstSegment(segments,supernodep,3); /* supernode cannot be a fake node (must be a super-node) */
710 amb 685
711 amb 1078 while(supersegmentp)
712 amb 685 {
713 amb 1078 if(IsSuperSegment(supersegmentp))
714 amb 685 {
715     Results *results;
716 amb 1063 Result *result;
717     index_t start_node;
718 amb 685
719 amb 1078 start_node=OtherNode(supersegmentp,finish_node);
720 amb 685
721 amb 1063 results=FindSuperRoute(nodes,segments,ways,relations,start_node,finish_node);
722 amb 685
723 amb 1063 if(!results)
724     continue;
725 amb 1061
726 amb 1063 result=FindResult(results,finish_node,finish_segment);
727 amb 1061
728 amb 1168 if(result && (distance_t)result->score==DISTANCE(supersegmentp->distance))
729 amb 1063 {
730     FreeResultsList(results);
731 amb 1078 return(IndexSegment(segments,supersegmentp));
732 amb 1063 }
733 amb 1061
734 amb 1063 if(results)
735     FreeResultsList(results);
736     }
737 amb 1061
738 amb 1078 supersegmentp=NextSegment(segments,supersegmentp,finish_node); /* finish_node cannot be a fake node (must be a super-node) */
739 amb 1063 }
740 amb 1061
741 amb 1063 return(finish_segment);
742     }
743 amb 1061
744    
745 amb 1063 /*++++++++++++++++++++++++++++++++++++++
746     Find the shortest route between two super-nodes using only normal nodes.
747     This is effectively the same function as is used in superx.c when finding super-segments initially.
748 amb 1061
749 amb 1063 Results *FindSuperRoute Returns a set of results.
750 amb 1061
751 amb 1063 Nodes *nodes The set of nodes to use.
752 amb 1061
753 amb 1063 Segments *segments The set of segments to use.
754 amb 1061
755 amb 1063 Ways *ways The set of ways to use.
756 amb 1061
757 amb 1063 Relations *relations The set of relations to use.
758 amb 1061
759 amb 1063 index_t start_node The start node.
760 amb 1061
761 amb 1063 index_t finish_node The finish node.
762     ++++++++++++++++++++++++++++++++++++++*/
763 amb 1061
764 amb 1063 static Results *FindSuperRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,index_t start_node,index_t finish_node)
765     {
766     Results *results;
767     Queue *queue;
768     Result *result1,*result2;
769 amb 1061
770 amb 1278 #if DEBUG
771     printf(" FindSuperRoute(...,start_node=%"Pindex_t" finish_node=%"Pindex_t")\n",start_node,finish_node);
772     #endif
773    
774 amb 1063 /* Create the list of results and insert the first node into the queue */
775 amb 1061
776 amb 1066 results=NewResultsList(64);
777 amb 1068 queue=NewQueueList();
778 amb 1061
779 amb 1063 results->start_node=start_node;
780     results->prev_segment=NO_SEGMENT;
781 amb 1061
782 amb 1063 result1=InsertResult(results,results->start_node,results->prev_segment);
783 amb 1061
784 amb 1063 InsertInQueue(queue,result1);
785 amb 1061
786 amb 1063 /* Loop across all nodes in the queue */
787 amb 1061
788 amb 1063 while((result1=PopFromQueue(queue)))
789     {
790     Node *node1p=NULL;
791 amb 1078 Segment *segmentp;
792 amb 1063 index_t node1,seg1;
793 amb 1061
794 amb 1063 node1=result1->node;
795     seg1=result1->segment;
796 amb 1061
797 amb 1066 node1p=LookupNode(nodes,node1,1); /* node1 cannot be a fake node */
798 amb 1061
799 amb 1063 /* Loop across all segments */
800 amb 1061
801 amb 1078 segmentp=FirstSegment(segments,node1p,1); /* node1 cannot be a fake node */
802 amb 1061
803 amb 1078 while(segmentp)
804 amb 1063 {
805     Node *node2p=NULL;
806     index_t node2,seg2;
807     score_t cumulative_score;
808 amb 1061
809 amb 1063 /* must be a normal segment */
810 amb 1078 if(!IsNormalSegment(segmentp))
811 amb 1063 goto endloop;
812 amb 1061
813 amb 1063 /* must obey one-way restrictions */
814 amb 1078 if(IsOnewayTo(segmentp,node1))
815 amb 1063 goto endloop;
816 amb 1061
817 amb 1078 seg2=IndexSegment(segments,segmentp);
818 amb 1061
819 amb 1063 /* must not perform U-turn */
820     if(seg1==seg2)
821     goto endloop;
822 amb 1061
823 amb 1078 node2=OtherNode(segmentp,node1);
824 amb 1061
825 amb 1066 node2p=LookupNode(nodes,node2,2); /* node2 cannot be a fake node */
826 amb 1061
827 amb 1063 /* must not pass over super-node */
828     if(node2!=finish_node && IsSuperNode(node2p))
829     goto endloop;
830 amb 1061
831 amb 1066 /* Specifically looking for the shortest route to emulate superx.c */
832 amb 1168 cumulative_score=result1->score+(score_t)DISTANCE(segmentp->distance);
833 amb 1061
834 amb 1063 result2=FindResult(results,node2,seg2);
835    
836     if(!result2) /* New end node/segment combination */
837 amb 1061 {
838 amb 1063 result2=InsertResult(results,node2,seg2);
839     result2->prev=result1;
840     result2->score=cumulative_score;
841     result2->sortby=result2->score;
842 amb 798 }
843 amb 1063 else if(cumulative_score<result2->score) /* New score for end node/segment combination is better */
844     {
845     result2->prev=result1;
846     result2->segment=seg2;
847     result2->score=cumulative_score;
848     result2->sortby=result2->score;
849     }
850 amb 1217 else goto endloop;
851 amb 1063
852 amb 1217 /* don't route beyond a super-node. */
853     if(!IsSuperNode(node2p))
854     InsertInQueue(queue,result2);
855    
856 amb 1063 endloop:
857    
858 amb 1078 segmentp=NextSegment(segments,segmentp,node1);
859 amb 685 }
860     }
861    
862 amb 1063 FreeQueueList(queue);
863    
864 amb 1278 #if DEBUG
865     Result *r=FindResult(results,results->start_node,results->prev_segment);
866    
867     while(r)
868     {
869     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
870    
871     r=r->next;
872     }
873     #endif
874    
875 amb 1063 return(results);
876 amb 685 }
877    
878    
879     /*++++++++++++++++++++++++++++++++++++++
880 amb 95 Find all routes from a specified node to any super-node.
881 amb 3
882 amb 126 Results *FindStartRoutes Returns a set of results.
883 amb 31
884     Nodes *nodes The set of nodes to use.
885    
886     Segments *segments The set of segments to use.
887    
888 amb 54 Ways *ways The set of ways to use.
889    
890 amb 542 Relations *relations The set of relations to use.
891    
892 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
893    
894 amb 605 index_t start_node The start node.
895 amb 31
896 amb 605 index_t prev_segment The previous segment before the start node.
897    
898 amb 729 index_t finish_node The finish node.
899 amb 31 ++++++++++++++++++++++++++++++++++++++*/
900    
901 amb 1278 Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t start_node,index_t prev_segment,index_t finish_node)
902 amb 31 {
903     Results *results;
904 amb 469 Queue *queue;
905     Result *result1,*result2;
906 amb 1278 int nsuper=0,force_uturn=0;
907 amb 31
908 amb 1278 #if DEBUG
909     printf(" FindStartRoutes(...,start_node=%"Pindex_t" prev_segment=%"Pindex_t" finish_node=%"Pindex_t")\n",start_node,prev_segment,finish_node);
910     #endif
911    
912 amb 1068 /* Create the list of results and insert the first node into the queue */
913 amb 31
914 amb 855 results=NewResultsList(64);
915 amb 1068 queue=NewQueueList();
916 amb 31
917 amb 605 results->start_node=start_node;
918     results->prev_segment=prev_segment;
919 amb 165
920 amb 735 result1=InsertResult(results,results->start_node,results->prev_segment);
921 amb 31
922 amb 1068 InsertInQueue(queue,result1);
923 amb 531
924 amb 1068 /* Check for barrier at start waypoint - must perform U-turn */
925 amb 31
926 amb 1068 if(prev_segment!=NO_SEGMENT && !IsFakeNode(start_node))
927     {
928 amb 1078 Node *startp=LookupNode(nodes,start_node,1);
929 amb 236
930 amb 1078 if(!(startp->allow&profile->allow))
931 amb 1068 force_uturn=1;
932     }
933    
934 amb 31 /* Loop across all nodes in the queue */
935    
936 amb 236 while((result1=PopFromQueue(queue)))
937 amb 31 {
938 amb 885 Node *node1p=NULL;
939 amb 1078 Segment *segmentp;
940 amb 637 index_t node1,seg1,seg1r;
941 amb 719 index_t turnrelation=NO_RELATION;
942 amb 594
943 amb 43 node1=result1->node;
944 amb 605 seg1=result1->segment;
945 amb 31
946 amb 637 if(IsFakeSegment(seg1))
947     seg1r=IndexRealSegment(seg1);
948     else
949     seg1r=seg1;
950    
951 amb 885 if(!IsFakeNode(node1))
952     node1p=LookupNode(nodes,node1,1);
953    
954 amb 719 /* lookup if a turn restriction applies */
955 amb 885 if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
956 amb 719 turnrelation=FindFirstTurnRelation2(relations,node1,seg1r);
957 amb 680
958     /* Loop across all segments */
959    
960 amb 303 if(IsFakeNode(node1))
961 amb 1078 segmentp=FirstFakeSegment(node1);
962 amb 303 else
963 amb 1078 segmentp=FirstSegment(segments,node1p,1);
964 amb 31
965 amb 1078 while(segmentp)
966 amb 31 {
967 amb 885 Node *node2p=NULL;
968 amb 1078 Way *wayp;
969 amb 637 index_t node2,seg2,seg2r;
970 amb 298 score_t segment_pref,segment_score,cumulative_score;
971     int i;
972 amb 59
973 amb 1078 node2=OtherNode(segmentp,node1); /* need this here because we use node2 at the end of the loop */
974 amb 734
975 amb 680 /* must be a normal segment */
976 amb 1078 if(!IsNormalSegment(segmentp))
977 amb 95 goto endloop;
978    
979 amb 680 /* must obey one-way restrictions (unless profile allows) */
980 amb 1078 if(profile->oneway && IsOnewayTo(segmentp,node1))
981 amb 64 goto endloop;
982    
983 amb 605 if(IsFakeNode(node1) || IsFakeNode(node2))
984 amb 637 {
985 amb 1078 seg2 =IndexFakeSegment(segmentp);
986 amb 637 seg2r=IndexRealSegment(seg2);
987     }
988 amb 605 else
989 amb 637 {
990 amb 1078 seg2 =IndexSegment(segments,segmentp);
991 amb 637 seg2r=seg2;
992     }
993 amb 603
994 amb 1068 /* must perform U-turn in special cases */
995     if(node1==start_node && force_uturn)
996     {
997     if(seg2r!=result1->segment)
998     goto endloop;
999     }
1000     else
1001     /* must not perform U-turn (unless profile allows) */
1002     if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
1003     goto endloop;
1004 amb 636
1005 amb 719 /* must obey turn relations */
1006     if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1r,seg2r,profile->allow))
1007     goto endloop;
1008 amb 596
1009 amb 1078 wayp=LookupWay(ways,segmentp->way,1);
1010 amb 54
1011 amb 680 /* mode of transport must be allowed on the highway */
1012 amb 1078 if(!(wayp->allow&profile->allow))
1013 amb 54 goto endloop;
1014    
1015 amb 680 /* must obey weight restriction (if exists) */
1016 amb 1078 if(wayp->weight && wayp->weight<profile->weight)
1017 amb 135 goto endloop;
1018    
1019 amb 680 /* must obey height/width/length restriction (if exists) */
1020 amb 1078 if((wayp->height && wayp->height<profile->height) ||
1021     (wayp->width && wayp->width <profile->width ) ||
1022     (wayp->length && wayp->length<profile->length))
1023 amb 135 goto endloop;
1024    
1025 amb 1078 segment_pref=profile->highway[HIGHWAY(wayp->type)];
1026 amb 298
1027 amb 1066 /* highway preferences must allow this highway */
1028     if(segment_pref==0)
1029     goto endloop;
1030    
1031 amb 298 for(i=1;i<Property_Count;i++)
1032 amb 460 if(ways->file.props & PROPERTIES(i))
1033 amb 307 {
1034 amb 1078 if(wayp->props & PROPERTIES(i))
1035 amb 307 segment_pref*=profile->props_yes[i];
1036     else
1037     segment_pref*=profile->props_no[i];
1038     }
1039 amb 298
1040 amb 680 /* profile preferences must allow this highway */
1041 amb 298 if(segment_pref==0)
1042     goto endloop;
1043    
1044 amb 471 if(!IsFakeNode(node2))
1045 amb 885 node2p=LookupNode(nodes,node2,2);
1046 amb 469
1047 amb 1068 /* mode of transport must be allowed through node2 unless it is the final node */
1048     if(node2p && node2!=finish_node && !(node2p->allow&profile->allow))
1049 amb 885 goto endloop;
1050 amb 469
1051 amb 166 if(option_quickest==0)
1052 amb 1168 segment_score=(score_t)DISTANCE(segmentp->distance)/segment_pref;
1053 amb 166 else
1054 amb 1078 segment_score=(score_t)Duration(segmentp,wayp,profile)/segment_pref;
1055 amb 59
1056 amb 170 cumulative_score=result1->score+segment_score;
1057 amb 166
1058 amb 605 result2=FindResult(results,node2,seg2);
1059 amb 31
1060 amb 680 if(!result2) /* New end node/segment combination */
1061 amb 31 {
1062 amb 605 result2=InsertResult(results,node2,seg2);
1063     result2->prev=result1;
1064 amb 170 result2->score=cumulative_score;
1065 amb 31
1066 amb 885 if(node2p && IsSuperNode(node2p))
1067 amb 1278 nsuper++;
1068 amb 729
1069 amb 734 if(node2==finish_node)
1070 amb 1278 nsuper++;
1071 amb 1281
1072     if(node2==finish_node)
1073     {
1074     results->finish_node=finish_node;
1075     results->last_segment=seg2;
1076     }
1077 amb 31 }
1078 amb 1066 else if(cumulative_score<result2->score) /* New score for end node/segment combination is better */
1079 amb 31 {
1080 amb 605 result2->prev=result1;
1081 amb 170 result2->score=cumulative_score;
1082 amb 1281
1083     if(node2==finish_node)
1084     {
1085     results->finish_node=finish_node;
1086     results->last_segment=seg2;
1087     }
1088 amb 1217 }
1089     else
1090     goto endloop;
1091 amb 31
1092 amb 1217 if(node2p && !IsSuperNode(node2p))
1093     {
1094     result2->sortby=result2->score;
1095     InsertInQueue(queue,result2);
1096 amb 31 }
1097    
1098     endloop:
1099    
1100 amb 303 if(IsFakeNode(node1))
1101 amb 1078 segmentp=NextFakeSegment(segmentp,node1);
1102 amb 729 else if(IsFakeNode(node2))
1103 amb 1078 segmentp=NULL; /* cannot call NextSegment() with a fake segment */
1104 amb 303 else
1105 amb 729 {
1106 amb 1078 segmentp=NextSegment(segments,segmentp,node1);
1107 amb 678
1108 amb 1078 if(!segmentp && IsFakeNode(finish_node))
1109     segmentp=ExtraFakeSegment(node1,finish_node);
1110 amb 729 }
1111 amb 31 }
1112     }
1113    
1114 amb 236 FreeQueueList(queue);
1115    
1116 amb 112 /* Check it worked */
1117    
1118 amb 1278 if(results->number==1 || nsuper==0)
1119 amb 112 {
1120 amb 1278 #if DEBUG
1121     printf(" Failed (%d results, %d super)\n",results->number,nsuper);
1122     #endif
1123    
1124 amb 112 FreeResultsList(results);
1125     return(NULL);
1126     }
1127    
1128 amb 1278 #if DEBUG
1129     Result *s=FirstResult(results);
1130    
1131     while(s)
1132     {
1133     if(s->node==finish_node)
1134     {
1135     Result *r=FindResult(results,s->node,s->segment);
1136    
1137     printf(" -------- route to finish node\n");
1138    
1139     while(r)
1140     {
1141     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
1142    
1143     r=r->prev;
1144     }
1145     }
1146    
1147     if(!IsFakeNode(s->node))
1148     {
1149     Node *n=LookupNode(nodes,s->node,1);
1150    
1151     if(IsSuperNode(n))
1152     {
1153     Result *r=FindResult(results,s->node,s->segment);
1154    
1155     printf(" -------- route to super node\n");
1156    
1157     while(r)
1158     {
1159     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
1160    
1161     r=r->prev;
1162     }
1163     }
1164     }
1165    
1166     s=NextResult(results,s);
1167     }
1168     #endif
1169    
1170 amb 31 return(results);
1171 amb 2 }
1172    
1173    
1174     /*++++++++++++++++++++++++++++++++++++++
1175 amb 1278 Continue finding routes from a set of super-nodes to a finish point.
1176    
1177     Results *ExtendStartRoutes Returns the set of results that were passed in.
1178    
1179     Nodes *nodes The set of nodes to use.
1180    
1181     Segments *segments The set of segments to use.
1182    
1183     Ways *ways The set of ways to use.
1184    
1185     Relations *relations The set of relations to use.
1186    
1187     Profile *profile The profile containing the transport type, speeds and allowed highways.
1188    
1189     Results *being The partial set of routes already computed.
1190    
1191     index_t finish_node The finish node.
1192     ++++++++++++++++++++++++++++++++++++++*/
1193    
1194     Results *ExtendStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Results *begin,index_t finish_node)
1195     {
1196     Results *results=begin;
1197     Queue *queue;
1198     Result *result1,*result2,*result3;
1199     Result *finish_result=NULL;
1200     score_t finish_score=INF_SCORE;
1201    
1202     #if DEBUG
1203     printf(" ExtendStartRoutes(...,[begin has %d nodes],finish_node=%"Pindex_t")\n",begin->number,finish_node);
1204     #endif
1205    
1206     /* Check the list of results and insert the super nodes into the queue */
1207    
1208     queue=NewQueueList();
1209    
1210     result3=FirstResult(begin);
1211    
1212     while(result3)
1213     {
1214     if(result3->node==finish_node)
1215     if(result3->score<finish_score)
1216     {
1217     finish_score=result3->score;
1218     finish_result=result3;
1219     }
1220    
1221     if(!IsFakeNode(result3->node))
1222     if(IsSuperNode(LookupNode(nodes,result3->node,5)))
1223     InsertInQueue(queue,result3);
1224    
1225     result3=NextResult(results,result3);
1226     }
1227    
1228     /* Loop across all nodes in the queue */
1229    
1230     while((result1=PopFromQueue(queue)))
1231     {
1232     Node *node1p=NULL;
1233     Segment *segmentp;
1234     index_t node1,seg1,seg1r;
1235     index_t turnrelation=NO_RELATION;
1236    
1237     /* score must be better than current best score */
1238     if(result1->score>=finish_score)
1239     continue;
1240    
1241     node1=result1->node;
1242     seg1=result1->segment;
1243    
1244     if(IsFakeSegment(seg1))
1245     seg1r=IndexRealSegment(seg1);
1246     else
1247     seg1r=seg1;
1248    
1249     if(!IsFakeNode(node1))
1250     node1p=LookupNode(nodes,node1,1);
1251    
1252     /* lookup if a turn restriction applies */
1253     if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
1254     turnrelation=FindFirstTurnRelation2(relations,node1,seg1r);
1255    
1256     /* Loop across all segments */
1257    
1258     if(IsFakeNode(node1))
1259     segmentp=FirstFakeSegment(node1);
1260     else
1261     segmentp=FirstSegment(segments,node1p,1);
1262    
1263     while(segmentp)
1264     {
1265     Node *node2p=NULL;
1266     Way *wayp;
1267     index_t node2,seg2,seg2r;
1268     score_t segment_pref,segment_score,cumulative_score;
1269     int i;
1270    
1271     node2=OtherNode(segmentp,node1); /* need this here because we use node2 at the end of the loop */
1272    
1273     /* must be a normal segment */
1274     if(!IsNormalSegment(segmentp))
1275     goto endloop;
1276    
1277     /* must obey one-way restrictions (unless profile allows) */
1278     if(profile->oneway && IsOnewayTo(segmentp,node1))
1279     goto endloop;
1280    
1281     if(IsFakeNode(node1) || IsFakeNode(node2))
1282     {
1283     seg2 =IndexFakeSegment(segmentp);
1284     seg2r=IndexRealSegment(seg2);
1285     }
1286     else
1287     {
1288     seg2 =IndexSegment(segments,segmentp);
1289     seg2r=seg2;
1290     }
1291    
1292     /* must not perform U-turn (unless profile allows) */
1293     if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
1294     goto endloop;
1295    
1296     /* must obey turn relations */
1297     if(turnrelation!=NO_RELATION && !IsTurnAllowed(relations,turnrelation,node1,seg1r,seg2r,profile->allow))
1298     goto endloop;
1299    
1300     wayp=LookupWay(ways,segmentp->way,1);
1301    
1302     /* mode of transport must be allowed on the highway */
1303     if(!(wayp->allow&profile->allow))
1304     goto endloop;
1305    
1306     /* must obey weight restriction (if exists) */
1307     if(wayp->weight && wayp->weight<profile->weight)
1308     goto endloop;
1309    
1310     /* must obey height/width/length restriction (if exists) */
1311     if((wayp->height && wayp->height<profile->height) ||
1312     (wayp->width && wayp->width <profile->width ) ||
1313     (wayp->length && wayp->length<profile->length))
1314     goto endloop;
1315    
1316     segment_pref=profile->highway[HIGHWAY(wayp->type)];
1317    
1318     /* highway preferences must allow this highway */
1319     if(segment_pref==0)
1320     goto endloop;
1321    
1322     for(i=1;i<Property_Count;i++)
1323     if(ways->file.props & PROPERTIES(i))
1324     {
1325     if(wayp->props & PROPERTIES(i))
1326     segment_pref*=profile->props_yes[i];
1327     else
1328     segment_pref*=profile->props_no[i];
1329     }
1330    
1331     /* profile preferences must allow this highway */
1332     if(segment_pref==0)
1333     goto endloop;
1334    
1335     if(!IsFakeNode(node2))
1336     node2p=LookupNode(nodes,node2,2);
1337    
1338     /* mode of transport must be allowed through node2 unless it is the final node */
1339     if(node2p && node2!=finish_node && !(node2p->allow&profile->allow))
1340     goto endloop;
1341    
1342     if(option_quickest==0)
1343     segment_score=(score_t)DISTANCE(segmentp->distance)/segment_pref;
1344     else
1345     segment_score=(score_t)Duration(segmentp,wayp,profile)/segment_pref;
1346    
1347     cumulative_score=result1->score+segment_score;
1348    
1349     /* score must be better than current best score */
1350     if(cumulative_score>=finish_score)
1351     goto endloop;
1352    
1353     result2=FindResult(results,node2,seg2);
1354    
1355     if(!result2) /* New end node/segment combination */
1356     {
1357     result2=InsertResult(results,node2,seg2);
1358     result2->prev=result1;
1359     result2->score=cumulative_score;
1360     }
1361     else if(cumulative_score<result2->score) /* New score for end node/segment combination is better */
1362     {
1363     result2->prev=result1;
1364     result2->score=cumulative_score;
1365     }
1366     else
1367     goto endloop;
1368    
1369     if(node2==finish_node)
1370     {
1371     if(cumulative_score<finish_score)
1372     {
1373     finish_score=cumulative_score;
1374     finish_result=result2;
1375     }
1376     }
1377     else
1378     {
1379     result2->sortby=result2->score;
1380     InsertInQueue(queue,result2);
1381     }
1382    
1383     endloop:
1384    
1385     if(IsFakeNode(node1))
1386     segmentp=NextFakeSegment(segmentp,node1);
1387     else if(IsFakeNode(node2))
1388     segmentp=NULL; /* cannot call NextSegment() with a fake segment */
1389     else
1390     {
1391     segmentp=NextSegment(segments,segmentp,node1);
1392    
1393     if(!segmentp && IsFakeNode(finish_node))
1394     segmentp=ExtraFakeSegment(node1,finish_node);
1395     }
1396     }
1397     }
1398    
1399     FreeQueueList(queue);
1400    
1401     FixForwardRoute(results,finish_result);
1402    
1403     #if DEBUG
1404     Result *r=FindResult(results,results->start_node,results->prev_segment);
1405    
1406     while(r)
1407     {
1408     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
1409    
1410     r=r->next;
1411     }
1412     #endif
1413    
1414     return(results);
1415     }
1416    
1417    
1418     /*++++++++++++++++++++++++++++++++++++++
1419 amb 680 Find all routes from any super-node to a specific node (by working backwards from the specific node to all super-nodes).
1420 amb 34
1421 amb 126 Results *FindFinishRoutes Returns a set of results.
1422 amb 34
1423     Nodes *nodes The set of nodes to use.
1424    
1425     Segments *segments The set of segments to use.
1426    
1427 amb 54 Ways *ways The set of ways to use.
1428    
1429 amb 542 Relations *relations The set of relations to use.
1430    
1431 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
1432    
1433 amb 605 index_t finish_node The finishing node.
1434 amb 34 ++++++++++++++++++++++++++++++++++++++*/
1435    
1436 amb 721 Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,index_t finish_node)
1437 amb 34 {
1438 amb 605 Results *results,*results2;
1439 amb 469 Queue *queue;
1440 amb 605 Result *result1,*result2,*result3;
1441 amb 34
1442 amb 1278 #if DEBUG
1443     printf(" FindFinishRoutes(...,finish_node=%"Pindex_t")\n",finish_node);
1444     #endif
1445    
1446 amb 1068 /* Create the results and insert the finish node into the queue */
1447 amb 34
1448 amb 855 results=NewResultsList(64);
1449 amb 1068 queue=NewQueueList();
1450 amb 34
1451 amb 605 results->finish_node=finish_node;
1452 amb 165
1453 amb 605 result1=InsertResult(results,finish_node,NO_SEGMENT);
1454 amb 34
1455 amb 236 InsertInQueue(queue,result1);
1456    
1457 amb 34 /* Loop across all nodes in the queue */
1458    
1459 amb 236 while((result1=PopFromQueue(queue)))
1460 amb 34 {
1461 amb 885 Node *node1p=NULL;
1462 amb 1078 Segment *segmentp;
1463 amb 637 index_t node1,seg1,seg1r;
1464 amb 596 index_t turnrelation=NO_RELATION;
1465 amb 594
1466 amb 43 node1=result1->node;
1467 amb 605 seg1=result1->segment;
1468 amb 34
1469 amb 637 if(IsFakeSegment(seg1))
1470     seg1r=IndexRealSegment(seg1);
1471     else
1472     seg1r=seg1;
1473    
1474 amb 885 if(!IsFakeNode(node1))
1475     node1p=LookupNode(nodes,node1,1);
1476    
1477 amb 680 /* lookup if a turn restriction applies */
1478 amb 885 if(profile->turns && node1p && IsTurnRestrictedNode(node1p))
1479 amb 596 turnrelation=FindFirstTurnRelation1(relations,node1); /* working backwards => turn relation sort order doesn't help */
1480    
1481 amb 680 /* Loop across all segments */
1482    
1483 amb 303 if(IsFakeNode(node1))
1484 amb 1078 segmentp=FirstFakeSegment(node1);
1485 amb 303 else
1486 amb 1078 segmentp=FirstSegment(segments,node1p,1);
1487 amb 34
1488 amb 1078 while(segmentp)
1489 amb 34 {
1490 amb 885 Node *node2p=NULL;
1491 amb 1078 Way *wayp;
1492 amb 637 index_t node2,seg2,seg2r;
1493 amb 298 score_t segment_pref,segment_score,cumulative_score;
1494     int i;
1495 amb 59
1496 amb 1066 /* must be a normal segment unless node1 is a super-node (see below). */
1497 amb 1078 if((IsFakeNode(node1) || !IsSuperNode(node1p)) && !IsNormalSegment(segmentp))
1498 amb 34 goto endloop;
1499    
1500 amb 1066 /* must be a super segment if node1 is a super-node to give starting super-segment for finding middle route. */
1501 amb 1078 if((!IsFakeNode(node1) && IsSuperNode(node1p)) && !IsSuperSegment(segmentp))
1502 amb 1066 goto endloop;
1503    
1504 amb 680 /* must obey one-way restrictions (unless profile allows) */
1505 amb 1078 if(profile->oneway && IsOnewayFrom(segmentp,node1)) /* working backwards => disallow oneway *from* node1 */
1506 amb 95 goto endloop;
1507    
1508 amb 1078 node2=OtherNode(segmentp,node1);
1509 amb 64
1510 amb 605 if(IsFakeNode(node1) || IsFakeNode(node2))
1511 amb 637 {
1512 amb 1078 seg2 =IndexFakeSegment(segmentp);
1513 amb 637 seg2r=IndexRealSegment(seg2);
1514     }
1515 amb 605 else
1516 amb 637 {
1517 amb 1078 seg2 =IndexSegment(segments,segmentp);
1518 amb 637 seg2r=seg2;
1519     }
1520 amb 605
1521 amb 699 /* must not perform U-turn (unless profile allows) */
1522 amb 727 if(profile->turns && (seg1==seg2 || seg1==seg2r || seg1r==seg2 || (seg1r==seg2r && IsFakeUTurn(seg1,seg2))))
1523 amb 636 goto endloop;
1524    
1525 amb 680 /* must obey turn relations */
1526 amb 596 if(turnrelation!=NO_RELATION)
1527     {
1528 amb 637 index_t turnrelation2=FindFirstTurnRelation2(relations,node1,seg2r); /* node2 -> node1 -> result1->next->node */
1529 amb 596
1530 amb 637 if(turnrelation2!=NO_RELATION && !IsTurnAllowed(relations,turnrelation2,node1,seg2r,seg1r,profile->allow))
1531 amb 596 goto endloop;
1532     }
1533    
1534 amb 1078 wayp=LookupWay(ways,segmentp->way,1);
1535 amb 54
1536 amb 680 /* mode of transport must be allowed on the highway */
1537 amb 1078 if(!(wayp->allow&profile->allow))
1538 amb 54 goto endloop;
1539    
1540 amb 680 /* must obey weight restriction (if exists) */
1541 amb 1078 if(wayp->weight && wayp->weight<profile->weight)
1542 amb 135 goto endloop;
1543    
1544 amb 1066 /* must obey height/width/length restriction (if exist) */
1545 amb 1078 if((wayp->height && wayp->height<profile->height) ||
1546     (wayp->width && wayp->width <profile->width ) ||
1547     (wayp->length && wayp->length<profile->length))
1548 amb 135 goto endloop;
1549    
1550 amb 1078 segment_pref=profile->highway[HIGHWAY(wayp->type)];
1551 amb 298
1552 amb 1066 /* highway preferences must allow this highway */
1553     if(segment_pref==0)
1554     goto endloop;
1555    
1556 amb 298 for(i=1;i<Property_Count;i++)
1557 amb 460 if(ways->file.props & PROPERTIES(i))
1558 amb 307 {
1559 amb 1078 if(wayp->props & PROPERTIES(i))
1560 amb 307 segment_pref*=profile->props_yes[i];
1561     else
1562     segment_pref*=profile->props_no[i];
1563     }
1564 amb 298
1565 amb 680 /* profile preferences must allow this highway */
1566 amb 298 if(segment_pref==0)
1567     goto endloop;
1568    
1569 amb 471 if(!IsFakeNode(node2))
1570 amb 885 node2p=LookupNode(nodes,node2,2);
1571 amb 469
1572 amb 885 /* mode of transport must be allowed through node2 */
1573     if(node2p && !(node2p->allow&profile->allow))
1574     goto endloop;
1575 amb 469
1576 amb 166 if(option_quickest==0)
1577 amb 1168 segment_score=(score_t)DISTANCE(segmentp->distance)/segment_pref;
1578 amb 166 else
1579 amb 1078 segment_score=(score_t)Duration(segmentp,wayp,profile)/segment_pref;
1580 amb 59
1581 amb 170 cumulative_score=result1->score+segment_score;
1582 amb 166
1583 amb 605 result2=FindResult(results,node2,seg2);
1584 amb 34
1585 amb 680 if(!result2) /* New end node */
1586 amb 34 {
1587 amb 605 result2=InsertResult(results,node2,seg2);
1588     result2->next=result1; /* working backwards */
1589 amb 170 result2->score=cumulative_score;
1590 amb 34 }
1591 amb 166 else if(cumulative_score<result2->score) /* New end node is better */
1592 amb 34 {
1593 amb 605 result2->next=result1; /* working backwards */
1594 amb 170 result2->score=cumulative_score;
1595 amb 1217 }
1596     else
1597     goto endloop;
1598 amb 34
1599 amb 1217 if(IsFakeNode(node1) || !IsSuperNode(node1p))
1600     {
1601     result2->sortby=result2->score;
1602     InsertInQueue(queue,result2);
1603 amb 34 }
1604    
1605     endloop:
1606    
1607 amb 303 if(IsFakeNode(node1))
1608 amb 1078 segmentp=NextFakeSegment(segmentp,node1);
1609 amb 303 else
1610 amb 1078 segmentp=NextSegment(segments,segmentp,node1);
1611 amb 34 }
1612     }
1613    
1614 amb 236 FreeQueueList(queue);
1615    
1616 amb 112 /* Check it worked */
1617    
1618     if(results->number==1)
1619     {
1620 amb 1278 #if DEBUG
1621     printf(" Failed\n");
1622     #endif
1623    
1624 amb 112 FreeResultsList(results);
1625     return(NULL);
1626     }
1627    
1628 amb 605 /* Create a results structure with the node at the end of the segment opposite the start */
1629    
1630 amb 855 results2=NewResultsList(64);
1631 amb 605
1632     results2->finish_node=results->finish_node;
1633    
1634     result3=FirstResult(results);
1635    
1636     while(result3)
1637     {
1638     if(result3->next)
1639     {
1640     result2=InsertResult(results2,result3->next->node,result3->segment);
1641    
1642 amb 616 result2->score=result3->next->score;
1643 amb 605 }
1644    
1645     result3=NextResult(results,result3);
1646     }
1647    
1648     /* Fix up the result->next pointers */
1649    
1650     result3=FirstResult(results);
1651    
1652     while(result3)
1653     {
1654     if(result3->next && result3->next->next)
1655     {
1656     result1=FindResult(results2,result3->next->node,result3->segment);
1657     result2=FindResult(results2,result3->next->next->node,result3->next->segment);
1658    
1659     result1->next=result2;
1660     }
1661    
1662     result3=NextResult(results,result3);
1663     }
1664    
1665     FreeResultsList(results);
1666    
1667 amb 1278 #if DEBUG
1668     Result *s=FirstResult(results2);
1669    
1670     while(s)
1671     {
1672     if(!IsFakeNode(s->node))
1673     {
1674     Node *n=LookupNode(nodes,s->node,1);
1675    
1676     if(IsSuperNode(n))
1677     {
1678     Result *r=FindResult(results2,s->node,s->segment);
1679    
1680     printf(" --------\n");
1681    
1682     while(r)
1683     {
1684     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
1685    
1686     r=r->next;
1687     }
1688     }
1689     }
1690    
1691     s=NextResult(results2,s);
1692     }
1693     #endif
1694    
1695 amb 605 return(results2);
1696 amb 34 }
1697    
1698    
1699     /*++++++++++++++++++++++++++++++++++++++
1700 amb 95 Create an optimum route given the set of super-nodes to follow.
1701 amb 31
1702 amb 58 Results *CombineRoutes Returns the results from joining the super-nodes.
1703 amb 55
1704 amb 680 Nodes *nodes The set of nodes to use.
1705 amb 31
1706     Segments *segments The set of segments to use.
1707    
1708 amb 680 Ways *ways The set of ways to use.
1709 amb 31
1710 amb 542 Relations *relations The set of relations to use.
1711    
1712 amb 721 Profile *profile The profile containing the transport type, speeds and allowed highways.
1713    
1714 amb 722 Results *begin The set of results for the start of the route.
1715    
1716 amb 686 Results *middle The set of results from the super-node route.
1717 amb 31 ++++++++++++++++++++++++++++++++++++++*/
1718    
1719 amb 722 Results *CombineRoutes(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,Results *begin,Results *middle)
1720 amb 31 {
1721 amb 686 Result *midres,*comres1;
1722 amb 31 Results *combined;
1723    
1724 amb 1278 #if DEBUG
1725     printf(" CombineRoutes(...,[begin has %d nodes],[middle has %d nodes])\n",begin->number,middle->number);
1726     #endif
1727    
1728 amb 855 combined=NewResultsList(256);
1729 amb 31
1730 amb 735 combined->start_node=begin->start_node;
1731     combined->prev_segment=begin->prev_segment;
1732 amb 165
1733 amb 722 /* Insert the start point */
1734 amb 31
1735 amb 686 midres=FindResult(middle,middle->start_node,middle->prev_segment);
1736 amb 31
1737 amb 735 comres1=InsertResult(combined,combined->start_node,combined->prev_segment);
1738 amb 31
1739 amb 722 /* Insert the start of the route */
1740    
1741     if(begin->number>1 && midres->next)
1742     {
1743     Result *begres;
1744    
1745     midres=FindResult(middle,midres->next->node,midres->next->segment);
1746    
1747     begres=FindResult(begin,midres->node,midres->segment);
1748    
1749     FixForwardRoute(begin,begres);
1750    
1751     if(midres->next && midres->next->node==midres->node)
1752     midres=midres->next;
1753    
1754     begres=FindResult(begin,begin->start_node,begin->prev_segment);
1755    
1756     begres=begres->next;
1757    
1758     do
1759     {
1760     Result *comres2;
1761    
1762     comres2=InsertResult(combined,begres->node,begres->segment);
1763    
1764 amb 1276 comres2->score=begres->score;
1765 amb 722 comres2->prev=comres1;
1766    
1767     begres=begres->next;
1768    
1769     comres1=comres2;
1770     }
1771     while(begres);
1772     }
1773    
1774     /* Sort out the combined route */
1775    
1776 amb 58 do
1777     {
1778 amb 686 Result *result;
1779 amb 594
1780 amb 686 if(midres->next)
1781 amb 31 {
1782 amb 723 Results *results=FindNormalRoute(nodes,segments,ways,relations,profile,comres1->node,comres1->segment,midres->next->node);
1783 amb 31
1784 amb 686 if(!results)
1785 amb 677 return(NULL);
1786    
1787 amb 686 result=FindResult(results,midres->node,comres1->segment);
1788 amb 31
1789 amb 686 result=result->next;
1790 amb 36
1791 amb 605 /*
1792 amb 686 * midres midres->next
1793 amb 605 * = =
1794 amb 686 * ---*----------------------------------* = middle
1795 amb 605 *
1796 amb 686 * ---*----.----.----.----.----.----.----* = results
1797 amb 605 * =
1798 amb 686 * result
1799 amb 605 *
1800     * ---*----.----.----.----.----.----.----* = combined
1801     * = =
1802 amb 686 * comres1 comres2
1803 amb 605 */
1804    
1805 amb 31 do
1806     {
1807 amb 686 Result *comres2;
1808 amb 31
1809 amb 686 comres2=InsertResult(combined,result->node,result->segment);
1810 amb 605
1811 amb 1276 comres2->score=midres->score+result->score;
1812 amb 686 comres2->prev=comres1;
1813 amb 605
1814 amb 686 result=result->next;
1815    
1816     comres1=comres2;
1817 amb 31 }
1818 amb 686 while(result);
1819 amb 31
1820 amb 686 FreeResultsList(results);
1821 amb 605 }
1822 amb 31
1823 amb 686 midres=midres->next;
1824 amb 31 }
1825 amb 686 while(midres);
1826 amb 31
1827 amb 686 FixForwardRoute(combined,comres1);
1828 amb 605
1829 amb 1278 #if DEBUG
1830     Result *r=FindResult(combined,combined->start_node,combined->prev_segment);
1831    
1832     while(r)
1833     {
1834     printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
1835    
1836     r=r->next;
1837     }
1838     #endif
1839    
1840 amb 55 return(combined);
1841 amb 31 }
1842 amb 290
1843    
1844     /*++++++++++++++++++++++++++++++++++++++
1845 amb 605 Fix the forward route (i.e. setup next pointers for forward path from prev nodes on reverse path).
1846 amb 290
1847     Results *results The set of results to update.
1848    
1849 amb 680 Result *finish_result The result for the finish point.
1850 amb 290 ++++++++++++++++++++++++++++++++++++++*/
1851    
1852 amb 605 void FixForwardRoute(Results *results,Result *finish_result)
1853 amb 290 {
1854 amb 605 Result *result2=finish_result;
1855 amb 290
1856 amb 828 /* Erase the old route if there is one */
1857    
1858     if(results->finish_node!=NO_NODE)
1859     {
1860     Result *result1=FirstResult(results);
1861    
1862     while(result1)
1863     {
1864     result1->next=NULL;
1865    
1866     result1=NextResult(results,result1);
1867     }
1868     }
1869    
1870 amb 290 /* Create the forward links for the optimum path */
1871    
1872     do
1873     {
1874 amb 594 Result *result1;
1875    
1876 amb 605 if(result2->prev)
1877 amb 290 {
1878 amb 605 index_t node1=result2->prev->node;
1879     index_t seg1=result2->prev->segment;
1880 amb 290
1881 amb 605 result1=FindResult(results,node1,seg1);
1882 amb 290
1883 amb 1166 logassert(!result1->next,"Unable to reverse route through results (report a bug)"); /* Bugs elsewhere can lead to infinite loop here. */
1884 amb 712
1885 amb 605 result1->next=result2;
1886 amb 290
1887     result2=result1;
1888     }
1889     else
1890     result2=NULL;
1891     }
1892     while(result2);
1893    
1894 amb 605 results->finish_node=finish_result->node;
1895     results->last_segment=finish_result->segment;
1896 amb 290 }

Properties

Name Value
cvs:description Route optimiser.