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 1634 - (hide annotations) (download) (as text)
Sat Mar 28 14:23:23 2015 UTC (9 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 49666 byte(s)
The new FindStartRoutes() function does not need to be so complicated.

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

Properties

Name Value
cvs:description Route optimiser.