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 460 -
(show annotations)
(download)
(as text)
Sat Jul 24 10:09:07 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 23898 byte(s)
Sat Jul 24 10:09:07 2010 UTC (14 years, 8 months ago) by amb
File MIME type: text/x-csrc
File size: 23898 byte(s)
Finished slim mode for the router by adding ways.
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/optimiser.c,v 1.90 2010-07-24 10:09:06 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 "nodes.h" |
29 | #include "segments.h" |
30 | #include "ways.h" |
31 | |
32 | #include "functions.h" |
33 | #include "results.h" |
34 | |
35 | |
36 | /*+ The option not to print any progress information. +*/ |
37 | extern int option_quiet; |
38 | |
39 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
40 | extern int option_quickest; |
41 | |
42 | |
43 | /*++++++++++++++++++++++++++++++++++++++ |
44 | Find the optimum route between two nodes not passing through a super-node. |
45 | |
46 | Results *FindNormalRoute Returns a set of results. |
47 | |
48 | Nodes *nodes The set of nodes to use. |
49 | |
50 | Segments *segments The set of segments to use. |
51 | |
52 | Ways *ways The set of ways to use. |
53 | |
54 | index_t start The start node. |
55 | |
56 | index_t finish The finish node. |
57 | |
58 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
59 | ++++++++++++++++++++++++++++++++++++++*/ |
60 | |
61 | Results *FindNormalRoute(Nodes *nodes,Segments *segments,Ways *ways,index_t start,index_t finish,Profile *profile) |
62 | { |
63 | Results *results; |
64 | Queue *queue; |
65 | index_t node1,node2; |
66 | score_t finish_score; |
67 | double finish_lat,finish_lon; |
68 | Result *result1,*result2; |
69 | Segment *segment; |
70 | Way *way; |
71 | |
72 | /* Set up the finish conditions */ |
73 | |
74 | finish_score=INF_SCORE; |
75 | |
76 | if(IsFakeNode(finish)) |
77 | GetFakeLatLong(finish,&finish_lat,&finish_lon); |
78 | else |
79 | GetLatLong(nodes,finish,&finish_lat,&finish_lon); |
80 | |
81 | /* Create the list of results and insert the first node into the queue */ |
82 | |
83 | results=NewResultsList(8); |
84 | |
85 | results->start=start; |
86 | results->finish=finish; |
87 | |
88 | result1=InsertResult(results,start); |
89 | |
90 | ZeroResult(result1); |
91 | |
92 | queue=NewQueueList(); |
93 | |
94 | InsertInQueue(queue,result1); |
95 | |
96 | /* Loop across all nodes in the queue */ |
97 | |
98 | while((result1=PopFromQueue(queue))) |
99 | { |
100 | if(result1->score>finish_score) |
101 | continue; |
102 | |
103 | node1=result1->node; |
104 | |
105 | if(IsFakeNode(node1)) |
106 | segment=FirstFakeSegment(node1); |
107 | else |
108 | segment=FirstSegment(segments,nodes,node1); |
109 | |
110 | while(segment) |
111 | { |
112 | score_t segment_pref,segment_score,cumulative_score; |
113 | int i; |
114 | |
115 | node2=OtherNode(segment,node1); /* need this here because we use node2 later */ |
116 | |
117 | if(!IsNormalSegment(segment)) |
118 | goto endloop; |
119 | |
120 | if(profile->oneway && IsOnewayTo(segment,node1)) |
121 | goto endloop; |
122 | |
123 | if(result1->prev==node2) |
124 | goto endloop; |
125 | |
126 | if(node2!=finish && !IsFakeNode(node2) && IsSuperNode(nodes,node2)) |
127 | goto endloop; |
128 | |
129 | way=LookupWay(ways,segment->way,1); |
130 | |
131 | if(!(way->allow&profile->allow)) |
132 | goto endloop; |
133 | |
134 | if(!profile->highway[HIGHWAY(way->type)]) |
135 | goto endloop; |
136 | |
137 | if(way->weight && way->weight<profile->weight) |
138 | goto endloop; |
139 | |
140 | if((way->height && way->height<profile->height) || |
141 | (way->width && way->width <profile->width ) || |
142 | (way->length && way->length<profile->length)) |
143 | goto endloop; |
144 | |
145 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
146 | |
147 | for(i=1;i<Property_Count;i++) |
148 | if(ways->file.props & PROPERTIES(i)) |
149 | { |
150 | if(way->props & PROPERTIES(i)) |
151 | segment_pref*=profile->props_yes[i]; |
152 | else |
153 | segment_pref*=profile->props_no[i]; |
154 | } |
155 | |
156 | if(segment_pref==0) |
157 | goto endloop; |
158 | |
159 | if(option_quickest==0) |
160 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
161 | else |
162 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
163 | |
164 | cumulative_score=result1->score+segment_score; |
165 | |
166 | if(cumulative_score>finish_score) |
167 | goto endloop; |
168 | |
169 | result2=FindResult(results,node2); |
170 | |
171 | if(!result2) /* New end node */ |
172 | { |
173 | result2=InsertResult(results,node2); |
174 | result2->prev=node1; |
175 | result2->next=NO_NODE; |
176 | result2->score=cumulative_score; |
177 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
178 | result2->segment=IndexFakeSegment(segment); |
179 | else |
180 | result2->segment=IndexSegment(segments,segment); |
181 | |
182 | if(node2==finish) |
183 | { |
184 | finish_score=cumulative_score; |
185 | } |
186 | else |
187 | { |
188 | result2->sortby=result2->score; |
189 | |
190 | InsertInQueue(queue,result2); |
191 | } |
192 | } |
193 | else if(cumulative_score<result2->score) /* New end node is better */ |
194 | { |
195 | result2->prev=node1; |
196 | result2->score=cumulative_score; |
197 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
198 | result2->segment=IndexFakeSegment(segment); |
199 | else |
200 | result2->segment=IndexSegment(segments,segment); |
201 | |
202 | if(node2==finish) |
203 | { |
204 | finish_score=cumulative_score; |
205 | } |
206 | else |
207 | { |
208 | result2->sortby=result2->score; |
209 | |
210 | if(result2->score<finish_score) |
211 | InsertInQueue(queue,result2); |
212 | } |
213 | } |
214 | |
215 | endloop: |
216 | |
217 | if(IsFakeNode(node1)) |
218 | segment=NextFakeSegment(segment,node1); |
219 | else if(IsFakeNode(node2)) |
220 | segment=NULL; /* cannot call NextSegment() with a fake segment */ |
221 | else |
222 | { |
223 | segment=NextSegment(segments,segment,node1); |
224 | |
225 | if(!segment && IsFakeNode(finish)) |
226 | segment=ExtraFakeSegment(node1,finish); |
227 | } |
228 | } |
229 | } |
230 | |
231 | FreeQueueList(queue); |
232 | |
233 | /* Check it worked */ |
234 | |
235 | if(!FindResult(results,finish)) |
236 | { |
237 | FreeResultsList(results); |
238 | return(NULL); |
239 | } |
240 | |
241 | FixForwardRoute(results,finish); |
242 | |
243 | return(results); |
244 | } |
245 | |
246 | |
247 | /*++++++++++++++++++++++++++++++++++++++ |
248 | Find the optimum route between two nodes where the start and end are a set of pre-routed super-nodes. |
249 | |
250 | Results *FindMiddleRoute Returns a set of results. |
251 | |
252 | Nodes *nodes The set of nodes to use. |
253 | |
254 | Segments *segments The set of segments to use. |
255 | |
256 | Ways *ways The set of ways to use. |
257 | |
258 | Results *begin The initial portion of the route. |
259 | |
260 | Results *end The final portion of the route. |
261 | |
262 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
263 | ++++++++++++++++++++++++++++++++++++++*/ |
264 | |
265 | Results *FindMiddleRoute(Nodes *nodes,Segments *segments,Ways *ways,Results *begin,Results *end,Profile *profile) |
266 | { |
267 | Results *results; |
268 | Queue *queue; |
269 | index_t node1,node2; |
270 | index_t end_prev; |
271 | score_t finish_score; |
272 | double finish_lat,finish_lon; |
273 | Result *result1,*result2,*result3; |
274 | Segment *segment; |
275 | Way *way; |
276 | |
277 | if(!option_quiet) |
278 | { |
279 | printf("Routing: Super-Nodes checked = 0"); |
280 | fflush(stdout); |
281 | } |
282 | |
283 | /* Set up the finish conditions */ |
284 | |
285 | finish_score=INF_DISTANCE; |
286 | end_prev=NO_NODE; |
287 | |
288 | if(IsFakeNode(end->finish)) |
289 | GetFakeLatLong(end->finish,&finish_lat,&finish_lon); |
290 | else |
291 | GetLatLong(nodes,end->finish,&finish_lat,&finish_lon); |
292 | |
293 | /* Create the list of results and insert the first node into the queue */ |
294 | |
295 | results=NewResultsList(2048); |
296 | |
297 | results->start=begin->start; |
298 | results->finish=end->finish; |
299 | |
300 | result1=InsertResult(results,begin->start); |
301 | result3=FindResult(begin,begin->start); |
302 | |
303 | *result1=*result3; |
304 | |
305 | queue=NewQueueList(); |
306 | |
307 | /* Insert the finish points of the beginning part of the path into the queue */ |
308 | |
309 | result3=FirstResult(begin); |
310 | |
311 | while(result3) |
312 | { |
313 | if(result3->node!=begin->start && !IsFakeNode(result3->node) && IsSuperNode(nodes,result3->node)) |
314 | { |
315 | result2=InsertResult(results,result3->node); |
316 | |
317 | *result2=*result3; |
318 | |
319 | result2->prev=begin->start; |
320 | |
321 | result2->sortby=result2->score; |
322 | |
323 | InsertInQueue(queue,result2); |
324 | } |
325 | |
326 | result3=NextResult(begin,result3); |
327 | } |
328 | |
329 | if(begin->number==1) |
330 | InsertInQueue(queue,result1); |
331 | |
332 | /* Loop across all nodes in the queue */ |
333 | |
334 | while((result1=PopFromQueue(queue))) |
335 | { |
336 | if(result1->score>finish_score) |
337 | continue; |
338 | |
339 | node1=result1->node; |
340 | |
341 | segment=FirstSegment(segments,nodes,node1); |
342 | |
343 | while(segment) |
344 | { |
345 | score_t segment_pref,segment_score,cumulative_score; |
346 | int i; |
347 | |
348 | if(!IsSuperSegment(segment)) |
349 | goto endloop; |
350 | |
351 | if(profile->oneway && IsOnewayTo(segment,node1)) |
352 | goto endloop; |
353 | |
354 | node2=OtherNode(segment,node1); |
355 | |
356 | if(result1->prev==node2) |
357 | goto endloop; |
358 | |
359 | way=LookupWay(ways,segment->way,1); |
360 | |
361 | if(!(way->allow&profile->allow)) |
362 | goto endloop; |
363 | |
364 | if(!profile->highway[HIGHWAY(way->type)]) |
365 | goto endloop; |
366 | |
367 | if(way->weight && way->weight<profile->weight) |
368 | goto endloop; |
369 | |
370 | if((way->height && way->height<profile->height) || |
371 | (way->width && way->width <profile->width ) || |
372 | (way->length && way->length<profile->length)) |
373 | goto endloop; |
374 | |
375 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
376 | |
377 | for(i=1;i<Property_Count;i++) |
378 | if(ways->file.props & PROPERTIES(i)) |
379 | { |
380 | if(way->props & PROPERTIES(i)) |
381 | segment_pref*=profile->props_yes[i]; |
382 | else |
383 | segment_pref*=profile->props_no[i]; |
384 | } |
385 | |
386 | if(segment_pref==0) |
387 | goto endloop; |
388 | |
389 | if(option_quickest==0) |
390 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
391 | else |
392 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
393 | |
394 | cumulative_score=result1->score+segment_score; |
395 | |
396 | if(cumulative_score>finish_score) |
397 | goto endloop; |
398 | |
399 | result2=FindResult(results,node2); |
400 | |
401 | if(!result2) /* New end node */ |
402 | { |
403 | result2=InsertResult(results,node2); |
404 | result2->prev=node1; |
405 | result2->next=NO_NODE; |
406 | result2->score=cumulative_score; |
407 | result2->segment=IndexSegment(segments,segment); |
408 | |
409 | if((result3=FindResult(end,node2))) |
410 | { |
411 | if((result2->score+result3->score)<finish_score) |
412 | { |
413 | finish_score=result2->score+result3->score; |
414 | end_prev=node2; |
415 | } |
416 | } |
417 | else |
418 | { |
419 | double lat,lon; |
420 | distance_t direct; |
421 | |
422 | GetLatLong(nodes,node2,&lat,&lon); |
423 | direct=Distance(lat,lon,finish_lat,finish_lon); |
424 | |
425 | if(option_quickest==0) |
426 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
427 | else |
428 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
429 | |
430 | InsertInQueue(queue,result2); |
431 | } |
432 | } |
433 | else if(cumulative_score<result2->score) /* New end node is better */ |
434 | { |
435 | result2->prev=node1; |
436 | result2->score=cumulative_score; |
437 | result2->segment=IndexSegment(segments,segment); |
438 | |
439 | if((result3=FindResult(end,node2))) |
440 | { |
441 | if((result2->score+result3->score)<finish_score) |
442 | { |
443 | finish_score=result2->score+result3->score; |
444 | end_prev=node2; |
445 | } |
446 | } |
447 | else if(result2->score<finish_score) |
448 | { |
449 | double lat,lon; |
450 | distance_t direct; |
451 | |
452 | GetLatLong(nodes,node2,&lat,&lon); |
453 | direct=Distance(lat,lon,finish_lat,finish_lon); |
454 | |
455 | if(option_quickest==0) |
456 | result2->sortby=result2->score+(score_t)direct/profile->max_pref; |
457 | else |
458 | result2->sortby=result2->score+(score_t)distance_speed_to_duration(direct,profile->max_speed)/profile->max_pref; |
459 | |
460 | InsertInQueue(queue,result2); |
461 | } |
462 | } |
463 | |
464 | endloop: |
465 | |
466 | if(!option_quiet && !(results->number%10000)) |
467 | { |
468 | printf("\rRouting: Super-Nodes checked = %d",results->number); |
469 | fflush(stdout); |
470 | } |
471 | |
472 | segment=NextSegment(segments,segment,node1); |
473 | } |
474 | } |
475 | |
476 | if(!option_quiet) |
477 | { |
478 | printf("\rRouting: Super-Nodes checked = %d\n",results->number); |
479 | fflush(stdout); |
480 | } |
481 | |
482 | /* Finish off the end part of the route. */ |
483 | |
484 | if(!FindResult(results,end->finish) && end_prev!=NO_NODE) |
485 | { |
486 | result2=InsertResult(results,end->finish); |
487 | result3=FindResult(end,end->finish); |
488 | |
489 | *result2=*result3; |
490 | |
491 | result2->prev=end_prev; |
492 | result2->score=finish_score; |
493 | } |
494 | |
495 | FreeQueueList(queue); |
496 | |
497 | /* Check it worked */ |
498 | |
499 | if(end_prev==NO_NODE) |
500 | { |
501 | FreeResultsList(results); |
502 | return(NULL); |
503 | } |
504 | |
505 | FixForwardRoute(results,end->finish); |
506 | |
507 | return(results); |
508 | } |
509 | |
510 | |
511 | /*++++++++++++++++++++++++++++++++++++++ |
512 | Find all routes from a specified node to any super-node. |
513 | |
514 | Results *FindStartRoutes Returns a set of results. |
515 | |
516 | Nodes *nodes The set of nodes to use. |
517 | |
518 | Segments *segments The set of segments to use. |
519 | |
520 | Ways *ways The set of ways to use. |
521 | |
522 | index_t start The start node. |
523 | |
524 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
525 | ++++++++++++++++++++++++++++++++++++++*/ |
526 | |
527 | Results *FindStartRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t start,Profile *profile) |
528 | { |
529 | Results *results; |
530 | Queue *queue; |
531 | index_t node1,node2; |
532 | Result *result1,*result2; |
533 | Segment *segment; |
534 | Way *way; |
535 | |
536 | /* Insert the first node into the queue */ |
537 | |
538 | results=NewResultsList(8); |
539 | |
540 | results->start=start; |
541 | |
542 | result1=InsertResult(results,start); |
543 | |
544 | ZeroResult(result1); |
545 | |
546 | queue=NewQueueList(); |
547 | |
548 | InsertInQueue(queue,result1); |
549 | |
550 | /* Loop across all nodes in the queue */ |
551 | |
552 | while((result1=PopFromQueue(queue))) |
553 | { |
554 | node1=result1->node; |
555 | |
556 | if(IsFakeNode(node1)) |
557 | segment=FirstFakeSegment(node1); |
558 | else |
559 | segment=FirstSegment(segments,nodes,node1); |
560 | |
561 | while(segment) |
562 | { |
563 | score_t segment_pref,segment_score,cumulative_score; |
564 | int i; |
565 | |
566 | if(!IsNormalSegment(segment)) |
567 | goto endloop; |
568 | |
569 | if(profile->oneway && IsOnewayTo(segment,node1)) |
570 | goto endloop; |
571 | |
572 | node2=OtherNode(segment,node1); |
573 | |
574 | if(result1->prev==node2) |
575 | goto endloop; |
576 | |
577 | way=LookupWay(ways,segment->way,1); |
578 | |
579 | if(!(way->allow&profile->allow)) |
580 | goto endloop; |
581 | |
582 | if(!profile->highway[HIGHWAY(way->type)]) |
583 | goto endloop; |
584 | |
585 | if(way->weight && way->weight<profile->weight) |
586 | goto endloop; |
587 | |
588 | if((way->height && way->height<profile->height) || |
589 | (way->width && way->width <profile->width ) || |
590 | (way->length && way->length<profile->length)) |
591 | goto endloop; |
592 | |
593 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
594 | |
595 | for(i=1;i<Property_Count;i++) |
596 | if(ways->file.props & PROPERTIES(i)) |
597 | { |
598 | if(way->props & PROPERTIES(i)) |
599 | segment_pref*=profile->props_yes[i]; |
600 | else |
601 | segment_pref*=profile->props_no[i]; |
602 | } |
603 | |
604 | if(segment_pref==0) |
605 | goto endloop; |
606 | |
607 | if(option_quickest==0) |
608 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
609 | else |
610 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
611 | |
612 | cumulative_score=result1->score+segment_score; |
613 | |
614 | result2=FindResult(results,node2); |
615 | |
616 | if(!result2) /* New end node */ |
617 | { |
618 | result2=InsertResult(results,node2); |
619 | result2->prev=node1; |
620 | result2->next=NO_NODE; |
621 | result2->score=cumulative_score; |
622 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
623 | result2->segment=IndexFakeSegment(segment); |
624 | else |
625 | result2->segment=IndexSegment(segments,segment); |
626 | |
627 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
628 | { |
629 | result2->sortby=result2->score; |
630 | InsertInQueue(queue,result2); |
631 | } |
632 | } |
633 | else if(cumulative_score<result2->score) /* New end node is better */ |
634 | { |
635 | result2->prev=node1; |
636 | result2->score=cumulative_score; |
637 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
638 | result2->segment=IndexFakeSegment(segment); |
639 | else |
640 | result2->segment=IndexSegment(segments,segment); |
641 | |
642 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
643 | { |
644 | result2->sortby=result2->score; |
645 | InsertInQueue(queue,result2); |
646 | } |
647 | } |
648 | |
649 | endloop: |
650 | |
651 | if(IsFakeNode(node1)) |
652 | segment=NextFakeSegment(segment,node1); |
653 | else |
654 | segment=NextSegment(segments,segment,node1); |
655 | } |
656 | } |
657 | |
658 | FreeQueueList(queue); |
659 | |
660 | /* Check it worked */ |
661 | |
662 | if(results->number==1) |
663 | { |
664 | FreeResultsList(results); |
665 | return(NULL); |
666 | } |
667 | |
668 | return(results); |
669 | } |
670 | |
671 | |
672 | /*++++++++++++++++++++++++++++++++++++++ |
673 | Find all routes from any super-node to a specific node. |
674 | |
675 | Results *FindFinishRoutes Returns a set of results. |
676 | |
677 | Nodes *nodes The set of nodes to use. |
678 | |
679 | Segments *segments The set of segments to use. |
680 | |
681 | Ways *ways The set of ways to use. |
682 | |
683 | index_t finish The finishing node. |
684 | |
685 | Profile *profile The profile containing the transport type, speeds and allowed highways. |
686 | ++++++++++++++++++++++++++++++++++++++*/ |
687 | |
688 | Results *FindFinishRoutes(Nodes *nodes,Segments *segments,Ways *ways,index_t finish,Profile *profile) |
689 | { |
690 | Results *results; |
691 | Queue *queue; |
692 | index_t node1,node2; |
693 | Result *result1,*result2; |
694 | Segment *segment; |
695 | Way *way; |
696 | |
697 | /* Insert the first node into the queue */ |
698 | |
699 | results=NewResultsList(8); |
700 | |
701 | results->finish=finish; |
702 | |
703 | result1=InsertResult(results,finish); |
704 | |
705 | ZeroResult(result1); |
706 | |
707 | queue=NewQueueList(); |
708 | |
709 | InsertInQueue(queue,result1); |
710 | |
711 | /* Loop across all nodes in the queue */ |
712 | |
713 | while((result1=PopFromQueue(queue))) |
714 | { |
715 | node1=result1->node; |
716 | |
717 | if(IsFakeNode(node1)) |
718 | segment=FirstFakeSegment(node1); |
719 | else |
720 | segment=FirstSegment(segments,nodes,node1); |
721 | |
722 | while(segment) |
723 | { |
724 | score_t segment_pref,segment_score,cumulative_score; |
725 | int i; |
726 | |
727 | if(!IsNormalSegment(segment)) |
728 | goto endloop; |
729 | |
730 | if(profile->oneway && IsOnewayFrom(segment,node1)) |
731 | goto endloop; |
732 | |
733 | node2=OtherNode(segment,node1); |
734 | |
735 | if(result1->next==node2) |
736 | goto endloop; |
737 | |
738 | way=LookupWay(ways,segment->way,1); |
739 | |
740 | if(!(way->allow&profile->allow)) |
741 | goto endloop; |
742 | |
743 | if(!profile->highway[HIGHWAY(way->type)]) |
744 | goto endloop; |
745 | |
746 | if(way->weight && way->weight<profile->weight) |
747 | goto endloop; |
748 | |
749 | if((way->height && way->height<profile->height) || |
750 | (way->width && way->width <profile->width ) || |
751 | (way->length && way->length<profile->length)) |
752 | goto endloop; |
753 | |
754 | segment_pref=profile->highway[HIGHWAY(way->type)]; |
755 | |
756 | for(i=1;i<Property_Count;i++) |
757 | if(ways->file.props & PROPERTIES(i)) |
758 | { |
759 | if(way->props & PROPERTIES(i)) |
760 | segment_pref*=profile->props_yes[i]; |
761 | else |
762 | segment_pref*=profile->props_no[i]; |
763 | } |
764 | |
765 | if(segment_pref==0) |
766 | goto endloop; |
767 | |
768 | if(option_quickest==0) |
769 | segment_score=(score_t)DISTANCE(segment->distance)/segment_pref; |
770 | else |
771 | segment_score=(score_t)Duration(segment,way,profile)/segment_pref; |
772 | |
773 | cumulative_score=result1->score+segment_score; |
774 | |
775 | result2=FindResult(results,node2); |
776 | |
777 | if(!result2) /* New end node */ |
778 | { |
779 | result2=InsertResult(results,node2); |
780 | result2->prev=NO_NODE; |
781 | result2->next=node1; |
782 | result2->score=cumulative_score; |
783 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
784 | result2->segment=IndexFakeSegment(segment); |
785 | else |
786 | result2->segment=IndexSegment(segments,segment); |
787 | |
788 | if(!IsFakeNode(node2) && !IsSuperNode(nodes,node2)) |
789 | { |
790 | result2->sortby=result2->score; |
791 | InsertInQueue(queue,result2); |
792 | } |
793 | } |
794 | else if(cumulative_score<result2->score) /* New end node is better */ |
795 | { |
796 | result2->next=node1; |
797 | result2->score=cumulative_score; |
798 | if(IsFakeNode(node1) || IsFakeNode(node2)) |
799 | result2->segment=IndexFakeSegment(segment); |
800 | else |
801 | result2->segment=IndexSegment(segments,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. |