Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/optimiser.c
Parent Directory
|
Revision Log
Revision 412 -
(show annotations)
(download)
(as text)
Sun May 30 12:50:40 2010 UTC (14 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 23510 byte(s)
Sun May 30 12:50:40 2010 UTC (14 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 23510 byte(s)
Fix printing the number of super-segments tried.
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.84 2010-05-30 12:50:40 amb Exp $ |
3 | |
4 | Routing optimiser. |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2008-2010 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <stdio.h> |
26 | |
27 | #include "types.h" |
28 | #include "functions.h" |
29 | #include "nodes.h" |
30 | #include "segments.h" |
31 | #include "ways.h" |
32 | #include "results.h" |
33 | |
34 | |
35 | /*+ The option not to print any progress information. +*/ |
36 | extern int option_quiet; |
37 | |
38 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
39 | extern int option_quickest; |
40 | |
41 | |
42 | /*++++++++++++++++++++++++++++++++++++++ |
43 | Find the optimum route between two nodes not passing through a super-node. |
44 | |
45 | Results *FindNormalRoute Returns a set of results. |
46 | |
47 | Nodes *nodes The set of nodes to use. |
48 | |
49 | Segments *segments The set of segments to use. |
50 | |
51 | Ways *ways The set of ways to use. |
52 | |
53 | index_t start The start node. |
54 | |
55 | index_t finish The finish node. |
56 | |
57 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
58 | ++++++++++++++++++++++++++++++++++++++*/ |
59 | |
60 | Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile) |
61 | { |
62 | Results *results; |
63 | Queue *queue; |
64 | index_t node1,node2; |
65 | score_t finish_score; |
66 | double finish_lat,finish_lon; |
67 | Result *result1,*result2; |
68 | Segment *segment; |
69 | Way *way; |
70 | |
71 | /* Set up the finish conditions */ |
72 | |
73 | finish_score=INF_SCORE; |
74 | |
75 | if(IsFakeNode(finish)) |
76 | GetFakeLatLong(finish,&finish_lat,&finish_lon); |
77 | else |
78 | GetLatLong(nodes,finish,&finish_lat,&finish_lon); |
79 | |
80 | /* Create the list of results and insert the first node into the queue */ |
81 | |
82 | results=NewResultsList(8); |
83 | |
84 | results->start=start; |
85 | results->finish=finish; |
86 | |
87 | result1=InsertResult(results,start); |
88 | |
89 | ZeroResult(result1); |
90 | |
91 | queue=NewQueueList(); |
92 | |
93 | InsertInQueue(queue,result1); |
94 | |
95 | /* Loop across all nodes in the queue */ |
96 | |
97 | while((result1=PopFromQueue(queue))) |
98 | { |
99 | if(result1->score>finish_score) |
100 | continue; |
101 | |
102 | node1=result1->node; |
103 | |
104 | if(IsFakeNode(node1)) |
105 | segment=FirstFakeSegment(node1); |
106 | else |
107 | segment=FirstSegment(segments,nodes,node1); |
108 | |
109 | while(segment) |
110 | { |
111 | score_t segment_pref,segment_score,cumulative_score; |
112 | int i; |
113 | |
114 | node2=OtherNode(segment,node1); /* need this here because we use node2 later */ |
115 | |
116 | if(!IsNormalSegment(segment)) |
117 | goto endloop; |
118 | |
119 | if(profile->oneway && IsOnewayTo(segment,node1)) |
120 | goto endloop; |
121 | |
122 | if(result1->prev==node2) |
123 | goto endloop; |
124 | |
125 | if(node2!=finish && !IsFakeNode(node2) && IsSuperNode(nodes,node2)) |
126 | goto endloop; |
127 | |
128 | way=LookupWay(ways,segment->way); |
129 | |
130 | if(!(way->allow&profile->allow)) |
131 | goto endloop; |
132 | |
133 | if(!profile->highway[HIGHWAY(way->type)]) |
134 | goto endloop; |
135 | |
136 | if(way->weight && way->weight<profile->weight) |
137 | goto endloop; |
138 | |
139 | if((way->height && way->height<profile->height) || |
140 | (way->width && way->width <profile->width ) || |
141 | (way->length && way->length<profile->length)) |
142 | goto endloop; |
143 | |
144 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
145 | |
146 | for(i=1;i<Property_Count;i++) |
147 | if(ways->props & PROPERTIES(i)) |
148 | { |
149 | if(way->props & PROPERTIES(i)) |
150 | segment_pref*=profile->props_yes[i]; |
151 | else |
152 | segment_pref*=profile->props_no[i]; |
153 | } |
154 | |
155 | if(segment_pref==0) |
156 | goto endloop; |
157 | |
158 | if(option_quickest==0) |
159 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
160 | else |
161 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
162 | |
163 | cumulative_score=result1->score+segment_score; |
164 | |
165 | if(cumulative_score>finish_score) |
166 | goto endloop; |
167 | |
168 | result2=FindResult(results,node2); |
169 | |
170 | if(!result2) /* New end node */ |
171 | { |
172 | result2=InsertResult(results,node2); |
173 | result2->prev=node1; |
174 | result2->next=NO_NODE; |
175 | result2->score=cumulative_score; |
176 | result2->segment=segment; |
177 | |
178 | if(node2==finish) |
179 | { |
180 | finish_score=cumulative_score; |
181 | } |
182 | else |
183 | { |
184 | result2->sortby=result2->score; |
185 | |
186 | InsertInQueue(queue,result2); |
187 | } |
188 | } |
189 | else if(cumulative_score<result2->score) /* New end node is better */ |
190 | { |
191 | result2->prev=node1; |
192 | result2->score=cumulative_score; |
193 | result2->segment=segment; |
194 | |
195 | if(node2==finish) |
196 | { |
197 | finish_score=cumulative_score; |
198 | } |
199 | else |
200 | { |
201 | result2->sortby=result2->score; |
202 | |
203 | if(result2->score<finish_score) |
204 | InsertInQueue(queue,result2); |
205 | } |
206 | } |
207 | |
208 | endloop: |
209 | |
210 | if(IsFakeNode(node1)) |
211 | segment=NextFakeSegment(segment,node1); |
212 | else if(IsFakeNode(node2)) |
213 | segment=NULL; /* cannot call NextSegment() with a fake segment */ |
214 | else |
215 | { |
216 | segment=NextSegment(segments,segment,node1); |
217 | |
218 | if(!segment && IsFakeNode(finish)) |
219 | segment=ExtraFakeSegment(node1,finish); |
220 | } |
221 | } |
222 | } |
223 | |
224 | FreeQueueList(queue); |
225 | |
226 | /* Check it worked */ |
227 | |
228 | if(!FindResult(results,finish)) |
229 | { |
230 | FreeResultsList(results); |
231 | return(NULL); |
232 | } |
233 | |
234 | FixForwardRoute(results,finish); |
235 | |
236 | return(results); |
237 | } |
238 | |
239 | |
240 | /*++++++++++++++++++++++++++++++++++++++ |
241 | Find the optimum route between two nodes where the start and end are a set of pre-routed super-nodes. |
242 | |
243 | Results *FindMiddleRoute Returns a set of results. |
244 | |
245 | Nodes *nodes The set of nodes to use. |
246 | |
247 | Segments *segments The set of segments to use. |
248 | |
249 | Ways *ways The set of ways to use. |
250 | |
251 | Results *begin The initial portion of the route. |
252 | |
253 | Results *end The final portion of the route. |
254 | |
255 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
256 | ++++++++++++++++++++++++++++++++++++++*/ |
257 | |
258 | Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *begin,Results *end,Profile *profile) |
259 | { |
260 | Results *results; |
261 | Queue *queue; |
262 | index_t node1,node2; |
263 | score_t finish_score; |
264 | double finish_lat,finish_lon; |
265 | Result *result1,*result2,*result3; |
266 | Segment *segment; |
267 | Way *way; |
268 | |
269 | if(!option_quiet) |
270 | { |
271 | printf("Routing: Super-Nodes checked = 0"); |
272 | fflush(stdout); |
273 | } |
274 | |
275 | /* Set up the finish conditions */ |
276 | |
277 | finish_score=INF_DISTANCE; |
278 | |
279 | if(IsFakeNode(end->finish)) |
280 | GetFakeLatLong(end->finish,&finish_lat,&finish_lon); |
281 | else |
282 | GetLatLong(nodes,end->finish,&finish_lat,&finish_lon); |
283 | |
284 | /* Create the list of results and insert the first node into the queue */ |
285 | |
286 | results=NewResultsList(65536); |
287 | |
288 | results->start=begin->start; |
289 | results->finish=end->finish; |
290 | |
291 | result1=InsertResult(results,begin->start); |
292 | result3=FindResult(begin,begin->start); |
293 | |
294 | *result1=*result3; |
295 | |
296 | queue=NewQueueList(); |
297 | |
298 | /* Insert the finish points of the beginning part of the path into the queue */ |
299 | |
300 | result3=FirstResult(begin); |
301 | |
302 | while(result3) |
303 | { |
304 | if(result3->node!=begin->start && !IsFakeNode(result3->node) && IsSuperNode(nodes,result3->node)) |
305 | { |
306 | result2=InsertResult(results,result3->node); |
307 | |
308 | *result2=*result3; |
309 | |
310 | result2->prev=begin->start; |
311 | |
312 | result2->sortby=result2->score; |
313 | |
314 | InsertInQueue(queue,result2); |
315 | } |
316 | |
317 | result3=NextResult(begin,result3); |
318 | } |
319 | |
320 | if(begin->number==1) |
321 | InsertInQueue(queue,result1); |
322 | |
323 | /* Loop across all nodes in the queue */ |
324 | |
325 | while((result1=PopFromQueue(queue))) |
326 | { |
327 | if(result1->score>finish_score) |
328 | continue; |
329 | |
330 | node1=result1->node; |
331 | |
332 | if(IsFakeNode(node1)) |
333 | segment=FirstFakeSegment(node1); |
334 | else |
335 | segment=FirstSegment(segments,nodes,node1); |
336 | |
337 | while(segment) |
338 | { |
339 | score_t segment_pref,segment_score,cumulative_score; |
340 | int i; |
341 | |
342 | if(!IsSuperSegment(segment)) |
343 | goto endloop; |
344 | |
345 | if(profile->oneway && IsOnewayTo(segment,node1)) |
346 | goto endloop; |
347 | |
348 | node2=OtherNode(segment,node1); |
349 | |
350 | if(result1->prev==node2) |
351 | goto endloop; |
352 | |
353 | way=LookupWay(ways,segment->way); |
354 | |
355 | if(!(way->allow&profile->allow)) |
356 | goto endloop; |
357 | |
358 | if(!profile->highway[HIGHWAY(way->type)]) |
359 | goto endloop; |
360 | |
361 | if(way->weight && way->weight<profile->weight) |
362 | goto endloop; |
363 | |
364 | if((way->height && way->height<profile->height) || |
365 | (way->width && way->width <profile->width ) || |
366 | (way->length && way->length<profile->length)) |
367 | goto endloop; |
368 | |
369 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
370 | |
371 | for(i=1;i<Property_Count;i++) |
372 | if(ways->props & PROPERTIES(i)) |
373 | { |
374 | if(way->props & PROPERTIES(i)) |
375 | segment_pref*=profile->props_yes[i]; |
376 | else |
377 | segment_pref*=profile->props_no[i]; |
378 | } |
379 | |
380 | if(segment_pref==0) |
381 | goto endloop; |
382 | |
383 | if(option_quickest==0) |
384 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
385 | else |
386 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
387 | |
388 | cumulative_score=result1->score+segment_score; |
389 | |
390 | if(cumulative_score>finish_score) |
391 | goto endloop; |
392 | |
393 | result2=FindResult(results,node2); |
394 | |
395 | if(!result2) /* New end node */ |
396 | { |
397 | result2=InsertResult(results,node2); |
398 | result2->prev=node1; |
399 | result2->next=NO_NODE; |
400 | result2->score=cumulative_score; |
401 | result2->segment=segment; |
402 | |
403 | if((result3=FindResult(end,node2))) |
404 | { |
405 | finish_score=result2->score+result3->score; |
406 | } |
407 | else |
408 | { |
409 | double lat,lon; |
410 | distance_t direct; |
411 | |
412 | if(IsFakeNode(node2)) |
413 | GetFakeLatLong(node2,&lat,&lon); |
414 | else |
415 | GetLatLong(nodes,node2,&lat,&lon); |
416 | direct=Distance(lat,lon,finish_lat,finish_lon); |
417 | |
418 | if(option_quickest==0) |
419 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
420 | else |
421 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
422 | |
423 | InsertInQueue(queue,result2); |
424 | } |
425 | } |
426 | else if(cumulative_score<result2->score) /* New end node is better */ |
427 | { |
428 | result2->prev=node1; |
429 | result2->score=cumulative_score; |
430 | result2->segment=segment; |
431 | |
432 | if((result3=FindResult(end,node2))) |
433 | { |
434 | if((result2->score+result3->score)<finish_score) |
435 | { |
436 | finish_score=result2->score+result3->score; |
437 | } |
438 | } |
439 | else if(result2->score<finish_score) |
440 | { |
441 | double lat,lon; |
442 | distance_t direct; |
443 | |
444 | if(IsFakeNode(node2)) |
445 | GetFakeLatLong(node2,&lat,&lon); |
446 | else |
447 | GetLatLong(nodes,node2,&lat,&lon); |
448 | direct=Distance(lat,lon,finish_lat,finish_lon); |
449 | |
450 | if(option_quickest==0) |
451 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
452 | else |
453 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
454 | |
455 | InsertInQueue(queue,result2); |
456 | } |
457 | } |
458 | |
459 | endloop: |
460 | |
461 | if(!option_quiet && !(results->number%10000)) |
462 | { |
463 | printf("\rRouting: Super-Nodes checked = %d",results->number); |
464 | fflush(stdout); |
465 | } |
466 | |
467 | if(IsFakeNode(node1)) |
468 | segment=NextFakeSegment(segment,node1); |
469 | else |
470 | segment=NextSegment(segments,segment,node1); |
471 | } |
472 | } |
473 | |
474 | if(!option_quiet) |
475 | { |
476 | printf("\rRouted: Super-Nodes checked = %d \n",results->number); |
477 | fflush(stdout); |
478 | } |
479 | |
480 | /* Finish off the end part of the route. */ |
481 | |
482 | if(!FindResult(results,end->finish)) |
483 | { |
484 | result2=InsertResult(results,end->finish); |
485 | result3=FindResult(end,end->finish); |
486 | |
487 | *result2=*result3; |
488 | |
489 | result2->score=INF_DISTANCE; |
490 | |
491 | result3=FirstResult(end); |
492 | |
493 | while(result3) |
494 | { |
495 | if(!IsFakeNode(result3->node) && IsSuperNode(nodes,result3->node)) |
496 | if((result1=FindResult(results,result3->node))) |
497 | if((result1->score+result3->score)<result2->score) |
498 | { |
499 | result2->score=result1->score+result3->score; |
500 | result2->prev=result1->node; |
501 | } |
502 | |
503 | result3=NextResult(end,result3); |
504 | } |
505 | } |
506 | |
507 | FreeQueueList(queue); |
508 | |
509 | /* Check it worked */ |
510 | |
511 | if(!FindResult(results,end->finish)) |
512 | { |
513 | FreeResultsList(results); |
514 | return(NULL); |
515 | } |
516 | |
517 | FixForwardRoute(results,end->finish); |
518 | |
519 | return(results); |
520 | } |
521 | |
522 | |
523 | /*++++++++++++++++++++++++++++++++++++++ |
524 | Find all routes from a specified node to any super-node. |
525 | |
526 | Results *FindStartRoutes Returns a set of results. |
527 | |
528 | Nodes *nodes The set of nodes to use. |
529 | |
530 | Segments *segments The set of segments to use. |
531 | |
532 | Ways *ways The set of ways to use. |
533 | |
534 | index_t start The start node. |
535 | |
536 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
537 | ++++++++++++++++++++++++++++++++++++++*/ |
538 | |
539 | Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile) |
540 | { |
541 | Results *results; |
542 | Queue *queue; |
543 | index_t node1,node2; |
544 | Result *result1,*result2; |
545 | Segment *segment; |
546 | Way *way; |
547 | |
548 | /* Insert the first node into the queue */ |
549 | |
550 | results=NewResultsList(8); |
551 | |
552 | results->start=start; |
553 | |
554 | result1=InsertResult(results,start); |
555 | |
556 | ZeroResult(result1); |
557 | |
558 | queue=NewQueueList(); |
559 | |
560 | InsertInQueue(queue,result1); |
561 | |
562 | /* Loop across all nodes in the queue */ |
563 | |
564 | while((result1=PopFromQueue(queue))) |
565 | { |
566 | node1=result1->node; |
567 | |
568 | if(IsFakeNode(node1)) |
569 | segment=FirstFakeSegment(node1); |
570 | else |
571 | segment=FirstSegment(segments,nodes,node1); |
572 | |
573 | while(segment) |
574 | { |
575 | score_t segment_pref,segment_score,cumulative_score; |
576 | int i; |
577 | |
578 | if(!IsNormalSegment(segment)) |
579 | goto endloop; |
580 | |
581 | if(profile->oneway && IsOnewayTo(segment,node1)) |
582 | goto endloop; |
583 | |
584 | node2=OtherNode(segment,node1); |
585 | |
586 | if(result1->prev==node2) |
587 | goto endloop; |
588 | |
589 | way=LookupWay(ways,segment->way); |
590 | |
591 | if(!(way->allow&profile->allow)) |
592 | goto endloop; |
593 | |
594 | if(!profile->highway[HIGHWAY(way->type)]) |
595 | goto endloop; |
596 | |
597 | if(way->weight && way->weight<profile->weight) |
598 | goto endloop; |
599 | |
600 | if((way->height && way->height<profile->height) || |
601 | (way->width && way->width <profile->width ) || |
602 | (way->length && way->length<profile->length)) |
603 | goto endloop; |
604 | |
605 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
606 | |
607 | for(i=1;i<Property_Count;i++) |
608 | if(ways->props & PROPERTIES(i)) |
609 | { |
610 | if(way->props & PROPERTIES(i)) |
611 | segment_pref*=profile->props_yes[i]; |
612 | else |
613 | segment_pref*=profile->props_no[i]; |
614 | } |
615 | |
616 | if(segment_pref==0) |
617 | goto endloop; |
618 | |
619 | if(option_quickest==0) |
620 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
621 | else |
622 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
623 | |
624 | cumulative_score=result1->score+segment_score; |
625 | |
626 | result2=FindResult(results,node2); |
627 | |
628 | if(!result2) /* New end node */ |
629 | { |
630 | result2=InsertResult(results,node2); |
631 | result2->prev=node1; |
632 | result2->next=NO_NODE; |
633 | result2->score=cumulative_score; |
634 | result2->segment=segment; |
635 | |
636 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
637 | { |
638 | result2->sortby=result2->score; |
639 | InsertInQueue(queue,result2); |
640 | } |
641 | } |
642 | else if(cumulative_score<result2->score) /* New end node is better */ |
643 | { |
644 | result2->prev=node1; |
645 | result2->score=cumulative_score; |
646 | result2->segment=segment; |
647 | |
648 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
649 | { |
650 | result2->sortby=result2->score; |
651 | InsertInQueue(queue,result2); |
652 | } |
653 | } |
654 | |
655 | endloop: |
656 | |
657 | if(IsFakeNode(node1)) |
658 | segment=NextFakeSegment(segment,node1); |
659 | else |
660 | segment=NextSegment(segments,segment,node1); |
661 | } |
662 | } |
663 | |
664 | FreeQueueList(queue); |
665 | |
666 | /* Check it worked */ |
667 | |
668 | if(results->number==1) |
669 | { |
670 | FreeResultsList(results); |
671 | return(NULL); |
672 | } |
673 | |
674 | return(results); |
675 | } |
676 | |
677 | |
678 | /*++++++++++++++++++++++++++++++++++++++ |
679 | Find all routes from any super-node to a specific node. |
680 | |
681 | Results *FindFinishRoutes Returns a set of results. |
682 | |
683 | Nodes *nodes The set of nodes to use. |
684 | |
685 | Segments *segments The set of segments to use. |
686 | |
687 | Ways *ways The set of ways to use. |
688 | |
689 | index_t finish The finishing node. |
690 | |
691 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
692 | ++++++++++++++++++++++++++++++++++++++*/ |
693 | |
694 | Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t finish,Profile *profile) |
695 | { |
696 | Results *results; |
697 | Queue *queue; |
698 | index_t node1,node2; |
699 | Result *result1,*result2; |
700 | Segment *segment; |
701 | Way *way; |
702 | |
703 | /* Insert the first node into the queue */ |
704 | |
705 | results=NewResultsList(8); |
706 | |
707 | results->finish=finish; |
708 | |
709 | result1=InsertResult(results,finish); |
710 | |
711 | ZeroResult(result1); |
712 | |
713 | queue=NewQueueList(); |
714 | |
715 | InsertInQueue(queue,result1); |
716 | |
717 | /* Loop across all nodes in the queue */ |
718 | |
719 | while((result1=PopFromQueue(queue))) |
720 | { |
721 | node1=result1->node; |
722 | |
723 | if(IsFakeNode(node1)) |
724 | segment=FirstFakeSegment(node1); |
725 | else |
726 | segment=FirstSegment(segments,nodes,node1); |
727 | |
728 | while(segment) |
729 | { |
730 | score_t segment_pref,segment_score,cumulative_score; |
731 | int i; |
732 | |
733 | if(!IsNormalSegment(segment)) |
734 | goto endloop; |
735 | |
736 | if(profile->oneway && IsOnewayFrom(segment,node1)) |
737 | goto endloop; |
738 | |
739 | node2=OtherNode(segment,node1); |
740 | |
741 | if(result1->next==node2) |
742 | goto endloop; |
743 | |
744 | way=LookupWay(ways,segment->way); |
745 | |
746 | if(!(way->allow&profile->allow)) |
747 | goto endloop; |
748 | |
749 | if(!profile->highway[HIGHWAY(way->type)]) |
750 | goto endloop; |
751 | |
752 | if(way->weight && way->weight<profile->weight) |
753 | goto endloop; |
754 | |
755 | if((way->height && way->height<profile->height) || |
756 | (way->width && way->width <profile->width ) || |
757 | (way->length && way->length<profile->length)) |
758 | goto endloop; |
759 | |
760 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
761 | |
762 | for(i=1;i<Property_Count;i++) |
763 | if(ways->props & PROPERTIES(i)) |
764 | { |
765 | if(way->props & PROPERTIES(i)) |
766 | segment_pref*=profile->props_yes[i]; |
767 | else |
768 | segment_pref*=profile->props_no[i]; |
769 | } |
770 | |
771 | if(segment_pref==0) |
772 | goto endloop; |
773 | |
774 | if(option_quickest==0) |
775 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
776 | else |
777 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
778 | |
779 | cumulative_score=result1->score+segment_score; |
780 | |
781 | result2=FindResult(results,node2); |
782 | |
783 | if(!result2) /* New end node */ |
784 | { |
785 | result2=InsertResult(results,node2); |
786 | result2->prev=NO_NODE; |
787 | result2->next=node1; |
788 | result2->score=cumulative_score; |
789 | result2->segment=segment; |
790 | |
791 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
792 | { |
793 | result2->sortby=result2->score; |
794 | InsertInQueue(queue,result2); |
795 | } |
796 | } |
797 | else if(cumulative_score<result2->score) /* New end node is better */ |
798 | { |
799 | result2->next=node1; |
800 | result2->score=cumulative_score; |
801 | result2->segment=segment; |
802 | |
803 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
804 | { |
805 | result2->sortby=result2->score; |
806 | InsertInQueue(queue,result2); |
807 | } |
808 | } |
809 | |
810 | endloop: |
811 | |
812 | if(IsFakeNode(node1)) |
813 | segment=NextFakeSegment(segment,node1); |
814 | else |
815 | segment=NextSegment(segments,segment,node1); |
816 | } |
817 | } |
818 | |
819 | FreeQueueList(queue); |
820 | |
821 | /* Check it worked */ |
822 | |
823 | if(results->number==1) |
824 | { |
825 | FreeResultsList(results); |
826 | return(NULL); |
827 | } |
828 | |
829 | return(results); |
830 | } |
831 | |
832 | |
833 | /*++++++++++++++++++++++++++++++++++++++ |
834 | Create an optimum route given the set of super-nodes to follow. |
835 | |
836 | Results *CombineRoutes Returns the results from joining the super-nodes. |
837 | |
838 | Results *results The set of results from the super-nodes. |
839 | |
840 | Nodes *nodes The list of nodes. |
841 | |
842 | Segments *segments The set of segments to use. |
843 | |
844 | Ways *ways The list of ways. |
845 | |
846 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
847 | ++++++++++++++++++++++++++++++++++++++*/ |
848 | |
849 | Results *CombineRoutes(Results *results,Nodes *nodes,Segments *segments,Ways *ways,Profile *profile) |
850 | { |
851 | Result *result1,*result2,*result3,*result4; |
852 | Results *combined; |
853 | |
854 | combined=NewResultsList(64); |
855 | |
856 | combined->start=results->start; |
857 | combined->finish=results->finish; |
858 | |
859 | /* Sort out the combined route */ |
860 | |
861 | result1=FindResult(results,results->start); |
862 | |
863 | result3=InsertResult(combined,results->start); |
864 | |
865 | ZeroResult(result3); |
866 | |
867 | do |
868 | { |
869 | if(result1->next!=NO_NODE) |
870 | { |
871 | Results *results2=FindNormalRoute(nodes,segments,ways,result1->node,result1->next,profile); |
872 | |
873 | result2=FindResult(results2,result1->node); |
874 | |
875 | result3->next=result2->next; |
876 | |
877 | result2=FindResult(results2,result2->next); |
878 | |
879 | do |
880 | { |
881 | result4=InsertResult(combined,result2->node); |
882 | |
883 | *result4=*result2; |
884 | result4->score+=result3->score; |
885 | |
886 | if(result2->next!=NO_NODE) |
887 | result2=FindResult(results2,result2->next); |
888 | else |
889 | result2=NULL; |
890 | } |
891 | while(result2); |
892 | |
893 | FreeResultsList(results2); |
894 | |
895 | result1=FindResult(results,result1->next); |
896 | |
897 | result3=result4; |
898 | } |
899 | else |
900 | result1=NULL; |
901 | } |
902 | while(result1); |
903 | |
904 | return(combined); |
905 | } |
906 | |
907 | |
908 | /*++++++++++++++++++++++++++++++++++++++ |
909 | Fx the forward route (i.e. setup next nodes for forward path from prev nodes on reverse path). |
910 | |
911 | Results *results The set of results to update. |
912 | |
913 | index_t finish The finish point. |
914 | ++++++++++++++++++++++++++++++++++++++*/ |
915 | |
916 | void FixForwardRoute(Results *results,index_t finish) |
917 | { |
918 | Result *result2=FindResult(results,finish); |
919 | Result *result1; |
920 | |
921 | /* Create the forward links for the optimum path */ |
922 | |
923 | do |
924 | { |
925 | if(result2->prev!=NO_NODE) |
926 | { |
927 | index_t node1=result2->prev; |
928 | |
929 | result1=FindResult(results,node1); |
930 | |
931 | result1->next=result2->node; |
932 | |
933 | result2=result1; |
934 | } |
935 | else |
936 | result2=NULL; |
937 | } |
938 | while(result2); |
939 | |
940 | results->finish=finish; |
941 | } |
Properties
Name | Value |
---|---|
cvs:description | Route optimiser. |