Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/optimiser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 302 - (show annotations) (download) (as text)
Fri Nov 13 19:26:18 2009 UTC (15 years, 4 months ago) by amb
File MIME type: text/x-csrc
File size: 21627 byte(s)
Added in some more constants with the value ~0.

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

Properties

Name Value
cvs:description Route optimiser.