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/router.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1565 - (show annotations) (download) (as text)
Sat May 10 10:22:15 2014 UTC (10 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 28367 byte(s)
Don't crash if the specified route contains two consecutive coincident
waypoints (route instructions at those points may not be perfect).

1 /***************************************
2 OSM router.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2008-2014 Andrew M. Bishop
7
8 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 ***************************************/
21
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27
28 #include "types.h"
29 #include "nodes.h"
30 #include "segments.h"
31 #include "ways.h"
32 #include "relations.h"
33
34 #include "files.h"
35 #include "logging.h"
36 #include "functions.h"
37 #include "fakes.h"
38 #include "translations.h"
39 #include "profiles.h"
40
41
42 /*+ To help when debugging +*/
43 #define DEBUG 0
44
45 /*+ The maximum distance from the specified point to search for a node or segment (in km). +*/
46 #define MAXSEARCH 1
47
48
49 /* Global variables */
50
51 /*+ The option not to print any progress information. +*/
52 int option_quiet=0;
53
54 /*+ The options to select the format of the output. +*/
55 int option_html=0,option_gpx_track=0,option_gpx_route=0,option_text=0,option_text_all=0,option_none=0,option_stdout=0;
56
57 /*+ The option to calculate the quickest route insted of the shortest. +*/
58 int option_quickest=0;
59
60
61 /* Local functions */
62
63 static void print_usage(int detail,const char *argerr,const char *err);
64
65 static Results *CalculateRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,
66 index_t start_node,index_t prev_segment,index_t finish_node,
67 int start_waypoint,int finish_waypoint);
68
69
70 /*++++++++++++++++++++++++++++++++++++++
71 The main program for the router.
72 ++++++++++++++++++++++++++++++++++++++*/
73
74 int main(int argc,char** argv)
75 {
76 Nodes *OSMNodes;
77 Segments *OSMSegments;
78 Ways *OSMWays;
79 Relations *OSMRelations;
80 Results *results[NWAYPOINTS+1]={NULL};
81 int point_used[NWAYPOINTS+1]={0};
82 double point_lon[NWAYPOINTS+1],point_lat[NWAYPOINTS+1];
83 double heading=-999;
84 int help_profile=0,help_profile_xml=0,help_profile_json=0,help_profile_pl=0;
85 char *dirname=NULL,*prefix=NULL;
86 char *profiles=NULL,*profilename=NULL;
87 char *translations=NULL,*language=NULL;
88 int exactnodes=0,reverse=0,loop=0;
89 Transport transport=Transport_None;
90 Profile *profile=NULL;
91 index_t start_node,finish_node=NO_NODE,first_node=NO_NODE;
92 index_t join_segment=NO_SEGMENT;
93 int arg,nresults=0;
94 waypoint_t start_waypoint,finish_waypoint=NO_WAYPOINT;
95 waypoint_t first_waypoint=NWAYPOINTS,last_waypoint=1,inc_dec_waypoint,waypoint;
96
97 /* Parse the command line arguments */
98
99 if(argc<2)
100 print_usage(0,NULL,NULL);
101
102 /* Get the non-routing, general program options */
103
104 for(arg=1;arg<argc;arg++)
105 {
106 if(!strcmp(argv[arg],"--help"))
107 print_usage(1,NULL,NULL);
108 else if(!strcmp(argv[arg],"--help-profile"))
109 help_profile=1;
110 else if(!strcmp(argv[arg],"--help-profile-xml"))
111 help_profile_xml=1;
112 else if(!strcmp(argv[arg],"--help-profile-json"))
113 help_profile_json=1;
114 else if(!strcmp(argv[arg],"--help-profile-perl"))
115 help_profile_pl=1;
116 else if(!strncmp(argv[arg],"--dir=",6))
117 dirname=&argv[arg][6];
118 else if(!strncmp(argv[arg],"--prefix=",9))
119 prefix=&argv[arg][9];
120 else if(!strncmp(argv[arg],"--profiles=",11))
121 profiles=&argv[arg][11];
122 else if(!strncmp(argv[arg],"--translations=",15))
123 translations=&argv[arg][15];
124 else if(!strcmp(argv[arg],"--exact-nodes-only"))
125 exactnodes=1;
126 else if(!strcmp(argv[arg],"--reverse"))
127 reverse=1;
128 else if(!strcmp(argv[arg],"--loop"))
129 loop=1;
130 else if(!strcmp(argv[arg],"--quiet"))
131 option_quiet=1;
132 else if(!strcmp(argv[arg],"--loggable"))
133 option_loggable=1;
134 else if(!strcmp(argv[arg],"--output-html"))
135 option_html=1;
136 else if(!strcmp(argv[arg],"--output-gpx-track"))
137 option_gpx_track=1;
138 else if(!strcmp(argv[arg],"--output-gpx-route"))
139 option_gpx_route=1;
140 else if(!strcmp(argv[arg],"--output-text"))
141 option_text=1;
142 else if(!strcmp(argv[arg],"--output-text-all"))
143 option_text_all=1;
144 else if(!strcmp(argv[arg],"--output-none"))
145 option_none=1;
146 else if(!strcmp(argv[arg],"--output-stdout"))
147 { option_stdout=1; option_quiet=1; }
148 else if(!strncmp(argv[arg],"--profile=",10))
149 profilename=&argv[arg][10];
150 else if(!strncmp(argv[arg],"--language=",11))
151 language=&argv[arg][11];
152 else if(!strncmp(argv[arg],"--transport=",12))
153 {
154 transport=TransportType(&argv[arg][12]);
155
156 if(transport==Transport_None)
157 print_usage(0,argv[arg],NULL);
158 }
159 else
160 continue;
161
162 argv[arg]=NULL;
163 }
164
165 if(option_stdout && (option_html+option_gpx_track+option_gpx_route+option_text+option_text_all)!=1)
166 {
167 fprintf(stderr,"Error: The '--output-stdout' option requires exactly one other output option (but not '--output-none').\n");
168 exit(EXIT_FAILURE);
169 }
170
171 /* Load in the profiles */
172
173 if(transport==Transport_None)
174 transport=Transport_Motorcar;
175
176 if(profiles)
177 {
178 if(!ExistsFile(profiles))
179 {
180 fprintf(stderr,"Error: The '--profiles' option specifies a file that does not exist.\n");
181 exit(EXIT_FAILURE);
182 }
183 }
184 else
185 {
186 if(ExistsFile(FileName(dirname,prefix,"profiles.xml")))
187 profiles=FileName(dirname,prefix,"profiles.xml");
188 else if(ExistsFile(FileName(DATADIR,NULL,"profiles.xml")))
189 profiles=FileName(DATADIR,NULL,"profiles.xml");
190 else
191 {
192 fprintf(stderr,"Error: The '--profiles' option was not used and the default 'profiles.xml' does not exist.\n");
193 exit(EXIT_FAILURE);
194 }
195 }
196
197 if(ParseXMLProfiles(profiles))
198 {
199 fprintf(stderr,"Error: Cannot read the profiles in the file '%s'.\n",profiles);
200 exit(EXIT_FAILURE);
201 }
202
203 /* Choose the selected profile. */
204
205 if(profilename)
206 {
207 profile=GetProfile(profilename);
208
209 if(!profile)
210 {
211 fprintf(stderr,"Error: Cannot find a profile called '%s' in '%s'.\n",profilename,profiles);
212 exit(EXIT_FAILURE);
213 }
214 }
215 else
216 profile=GetProfile(TransportName(transport));
217
218 if(!profile)
219 {
220 profile=(Profile*)calloc(1,sizeof(Profile));
221 profile->transport=transport;
222 }
223
224 /* Parse the other command line arguments */
225
226 for(arg=1;arg<argc;arg++)
227 {
228 if(!argv[arg])
229 continue;
230 else if(!strcmp(argv[arg],"--shortest"))
231 option_quickest=0;
232 else if(!strcmp(argv[arg],"--quickest"))
233 option_quickest=1;
234 else if(!strncmp(argv[arg],"--lon",5) && isdigit(argv[arg][5]))
235 {
236 int point;
237 char *p=&argv[arg][6];
238
239 while(isdigit(*p)) p++;
240 if(*p++!='=')
241 print_usage(0,argv[arg],NULL);
242
243 point=atoi(&argv[arg][5]);
244 if(point>NWAYPOINTS || point_used[point]&1)
245 print_usage(0,argv[arg],NULL);
246
247 point_lon[point]=degrees_to_radians(atof(p));
248 point_used[point]+=1;
249
250 if(point<first_waypoint)
251 first_waypoint=point;
252 if(point>last_waypoint)
253 last_waypoint=point;
254 }
255 else if(!strncmp(argv[arg],"--lat",5) && isdigit(argv[arg][5]))
256 {
257 int point;
258 char *p=&argv[arg][6];
259
260 while(isdigit(*p)) p++;
261 if(*p++!='=')
262 print_usage(0,argv[arg],NULL);
263
264 point=atoi(&argv[arg][5]);
265 if(point>NWAYPOINTS || point_used[point]&2)
266 print_usage(0,argv[arg],NULL);
267
268 point_lat[point]=degrees_to_radians(atof(p));
269 point_used[point]+=2;
270
271 if(point<first_waypoint)
272 first_waypoint=point;
273 if(point>last_waypoint)
274 last_waypoint=point;
275 }
276 else if(!strncmp(argv[arg],"--heading=",10))
277 {
278 double h=atof(&argv[arg][10]);
279
280 if(h>=-360 && h<=360)
281 {
282 heading=h;
283
284 if(heading<0) heading+=360;
285 }
286 }
287 else if(!strncmp(argv[arg],"--transport=",12))
288 ; /* Done this already */
289 else if(!strncmp(argv[arg],"--highway-",10))
290 {
291 Highway highway;
292 char *equal=strchr(argv[arg],'=');
293 char *string;
294
295 if(!equal)
296 print_usage(0,argv[arg],NULL);
297
298 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10);
299 string[equal-argv[arg]-10]=0;
300
301 highway=HighwayType(string);
302
303 if(highway==Highway_None)
304 print_usage(0,argv[arg],NULL);
305
306 profile->highway[highway]=atof(equal+1);
307
308 free(string);
309 }
310 else if(!strncmp(argv[arg],"--speed-",8))
311 {
312 Highway highway;
313 char *equal=strchr(argv[arg],'=');
314 char *string;
315
316 if(!equal)
317 print_usage(0,argv[arg],NULL);
318
319 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8);
320 string[equal-argv[arg]-8]=0;
321
322 highway=HighwayType(string);
323
324 if(highway==Highway_None)
325 print_usage(0,argv[arg],NULL);
326
327 profile->speed[highway]=kph_to_speed(atof(equal+1));
328
329 free(string);
330 }
331 else if(!strncmp(argv[arg],"--property-",11))
332 {
333 Property property;
334 char *equal=strchr(argv[arg],'=');
335 char *string;
336
337 if(!equal)
338 print_usage(0,argv[arg],NULL);
339
340 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+11);
341 string[equal-argv[arg]-11]=0;
342
343 property=PropertyType(string);
344
345 if(property==Property_None)
346 print_usage(0,argv[arg],NULL);
347
348 profile->props_yes[property]=atof(equal+1);
349
350 free(string);
351 }
352 else if(!strncmp(argv[arg],"--oneway=",9))
353 profile->oneway=!!atoi(&argv[arg][9]);
354 else if(!strncmp(argv[arg],"--turns=",8))
355 profile->turns=!!atoi(&argv[arg][8]);
356 else if(!strncmp(argv[arg],"--weight=",9))
357 profile->weight=tonnes_to_weight(atof(&argv[arg][9]));
358 else if(!strncmp(argv[arg],"--height=",9))
359 profile->height=metres_to_height(atof(&argv[arg][9]));
360 else if(!strncmp(argv[arg],"--width=",8))
361 profile->width=metres_to_width(atof(&argv[arg][8]));
362 else if(!strncmp(argv[arg],"--length=",9))
363 profile->length=metres_to_length(atof(&argv[arg][9]));
364 else
365 print_usage(0,argv[arg],NULL);
366 }
367
368 /* Print one of the profiles if requested */
369
370 if(help_profile)
371 {
372 PrintProfile(profile);
373
374 return(0);
375 }
376 else if(help_profile_xml)
377 {
378 PrintProfilesXML();
379
380 return(0);
381 }
382 else if(help_profile_json)
383 {
384 PrintProfilesJSON();
385
386 return(0);
387 }
388 else if(help_profile_pl)
389 {
390 PrintProfilesPerl();
391
392 return(0);
393 }
394
395 /* Check the waypoints are valid */
396
397 for(waypoint=1;waypoint<=NWAYPOINTS;waypoint++)
398 if(point_used[waypoint]==1 || point_used[waypoint]==2)
399 print_usage(0,NULL,"All waypoints must have latitude and longitude.");
400
401 if(first_waypoint>=last_waypoint)
402 print_usage(0,NULL,"At least two waypoints must be specified.");
403
404 /* Load in the translations */
405
406 if(option_html==0 && option_gpx_track==0 && option_gpx_route==0 && option_text==0 && option_text_all==0 && option_none==0)
407 option_html=option_gpx_track=option_gpx_route=option_text=option_text_all=1;
408
409 if(option_html || option_gpx_route || option_gpx_track)
410 {
411 if(translations)
412 {
413 if(!ExistsFile(translations))
414 {
415 fprintf(stderr,"Error: The '--translations' option specifies a file that does not exist.\n");
416 exit(EXIT_FAILURE);
417 }
418 }
419 else
420 {
421 if(ExistsFile(FileName(dirname,prefix,"translations.xml")))
422 translations=FileName(dirname,prefix,"translations.xml");
423 else if(ExistsFile(FileName(DATADIR,NULL,"translations.xml")))
424 translations=FileName(DATADIR,NULL,"translations.xml");
425 else
426 {
427 fprintf(stderr,"Error: The '--translations' option was not used and the default 'translations.xml' does not exist.\n");
428 exit(EXIT_FAILURE);
429 }
430 }
431
432 if(ParseXMLTranslations(translations,language))
433 {
434 fprintf(stderr,"Error: Cannot read the translations in the file '%s'.\n",translations);
435 exit(EXIT_FAILURE);
436 }
437 }
438
439 /* Load in the data - Note: No error checking because Load*List() will call exit() in case of an error. */
440
441 OSMNodes=LoadNodeList(FileName(dirname,prefix,"nodes.mem"));
442
443 OSMSegments=LoadSegmentList(FileName(dirname,prefix,"segments.mem"));
444
445 OSMWays=LoadWayList(FileName(dirname,prefix,"ways.mem"));
446
447 OSMRelations=LoadRelationList(FileName(dirname,prefix,"relations.mem"));
448
449 if(UpdateProfile(profile,OSMWays))
450 {
451 fprintf(stderr,"Error: Profile is invalid or not compatible with database.\n");
452 exit(EXIT_FAILURE);
453 }
454
455 /* Check for reverse direction */
456
457 if(reverse)
458 {
459 waypoint_t temp;
460
461 temp=first_waypoint;
462 first_waypoint=last_waypoint;
463 last_waypoint=temp;
464
465 last_waypoint--;
466
467 inc_dec_waypoint=-1;
468 }
469 else
470 {
471 last_waypoint++;
472
473 inc_dec_waypoint=1;
474 }
475
476 /* Loop through all pairs of waypoints */
477
478 for(waypoint=first_waypoint;waypoint!=last_waypoint;waypoint+=inc_dec_waypoint)
479 {
480 distance_t distmax=km_to_distance(MAXSEARCH);
481 distance_t distmin;
482 index_t segment=NO_SEGMENT;
483 index_t node1,node2;
484
485 if(point_used[waypoint]!=3)
486 continue;
487
488 /* Find the closest point */
489
490 start_node=finish_node;
491 start_waypoint=finish_waypoint;
492
493 if(exactnodes)
494 {
495 finish_node=FindClosestNode(OSMNodes,OSMSegments,OSMWays,point_lat[waypoint],point_lon[waypoint],distmax,profile,&distmin);
496 }
497 else
498 {
499 distance_t dist1,dist2;
500
501 segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[waypoint],point_lon[waypoint],distmax,profile,&distmin,&node1,&node2,&dist1,&dist2);
502
503 if(segment!=NO_SEGMENT)
504 finish_node=CreateFakes(OSMNodes,OSMSegments,waypoint,LookupSegment(OSMSegments,segment,1),node1,node2,dist1,dist2);
505 else
506 finish_node=NO_NODE;
507 }
508
509 if(finish_node==NO_NODE)
510 {
511 fprintf(stderr,"Error: Cannot find node close to specified point %d.\n",waypoint);
512 exit(EXIT_FAILURE);
513 }
514
515 finish_waypoint=waypoint;
516
517 if(!option_quiet)
518 {
519 double lat,lon;
520
521 if(IsFakeNode(finish_node))
522 GetFakeLatLong(finish_node,&lat,&lon);
523 else
524 GetLatLong(OSMNodes,finish_node,NULL,&lat,&lon);
525
526 if(IsFakeNode(finish_node))
527 printf("Waypoint %d is segment %"Pindex_t" (node %"Pindex_t" -> %"Pindex_t"): %3.6f %4.6f = %2.3f km\n",waypoint,segment,node1,node2,
528 radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
529 else
530 printf("Waypoint %d is node %"Pindex_t": %3.6f %4.6f = %2.3f km\n",waypoint,finish_node,
531 radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
532 }
533
534 /* Check the nodes */
535
536 if(start_node==NO_NODE)
537 continue;
538
539 if(first_node==NO_NODE)
540 first_node=start_node;
541
542 if(heading!=-999 && join_segment==NO_SEGMENT)
543 join_segment=FindClosestSegmentHeading(OSMNodes,OSMSegments,OSMWays,start_node,heading,profile);
544
545 /* Calculate the route */
546
547 results[nresults]=CalculateRoute(OSMNodes,OSMSegments,OSMWays,OSMRelations,profile,start_node,join_segment,finish_node,start_waypoint,finish_waypoint);
548
549 join_segment=results[nresults]->last_segment;
550
551 nresults++;
552 }
553
554 /* Finish the loop */
555
556 if(loop && finish_node!=NO_NODE)
557 {
558 results[nresults]=CalculateRoute(OSMNodes,OSMSegments,OSMWays,OSMRelations,profile,finish_node,join_segment,first_node,last_waypoint,first_waypoint);
559
560 nresults++;
561 }
562
563 if(!option_quiet)
564 {
565 printf("Routed OK\n");
566 fflush(stdout);
567 }
568
569 /* Print out the combined route */
570
571 if(!option_none)
572 PrintRoute(results,nresults,OSMNodes,OSMSegments,OSMWays,profile);
573
574 /* Destroy the remaining results lists and data structures */
575
576 #if 0
577
578 for(waypoint=0;waypoint<=nresults;waypoint++)
579 FreeResultsList(results[waypoint]);
580
581 DestroyNodeList(OSMNodes);
582 DestroySegmentList(OSMSegments);
583 DestroyWayList(OSMWays);
584 DestroyRelationList(OSMRelations);
585
586 #endif
587
588 return(0);
589 }
590
591
592 /*++++++++++++++++++++++++++++++++++++++
593 Find a complete route from a specified node to another node.
594
595 Results *CalculateRoute Returns a set of results.
596
597 Nodes *nodes The set of nodes to use.
598
599 Segments *segments The set of segments to use.
600
601 Ways *ways The set of ways to use.
602
603 Relations *relations The set of relations to use.
604
605 Profile *profile The profile containing the transport type, speeds and allowed highways.
606
607 index_t start_node The start node.
608
609 index_t prev_segment The previous segment before the start node.
610
611 index_t finish_node The finish node.
612
613 int start_waypoint The starting waypoint.
614
615 int finish_waypoint The finish waypoint.
616 ++++++++++++++++++++++++++++++++++++++*/
617
618 static Results *CalculateRoute(Nodes *nodes,Segments *segments,Ways *ways,Relations *relations,Profile *profile,
619 index_t start_node,index_t prev_segment,index_t finish_node,
620 int start_waypoint,int finish_waypoint)
621 {
622 Results *complete=NULL;
623
624 /* A special case if the first and last nodes are the same */
625
626 if(start_node==finish_node)
627 {
628 index_t fake_segment;
629 Result *result1,*result2;
630
631 complete=NewResultsList(8);
632
633 if(prev_segment==NO_SEGMENT)
634 {
635 double lat,lon;
636 distance_t distmin,dist1,dist2;
637 index_t node1,node2;
638
639 GetLatLong(nodes,start_node,NULL,&lat,&lon);
640
641 prev_segment=FindClosestSegment(nodes,segments,ways,lat,lon,1,profile,&distmin,&node1,&node2,&dist1,&dist2);
642 }
643
644 fake_segment=CreateFakeNullSegment(segments,start_node,prev_segment,finish_waypoint);
645
646 result1=InsertResult(complete,start_node,prev_segment);
647 result2=InsertResult(complete,finish_node,fake_segment);
648
649 result1->next=result2;
650
651 complete->start_node=start_node;
652 complete->prev_segment=prev_segment;
653
654 complete->finish_node=finish_node;
655 complete->last_segment=prev_segment;
656
657 complete->last_segment=result2->segment;
658 }
659 else
660 {
661 Results *begin,*end;
662
663 /* Calculate the beginning of the route */
664
665 begin=FindStartRoutes(nodes,segments,ways,relations,profile,start_node,prev_segment,finish_node);
666
667 if(begin)
668 {
669 /* Check if the end of the route was reached */
670
671 if(begin->finish_node!=NO_NODE)
672 complete=ExtendStartRoutes(nodes,segments,ways,relations,profile,begin,finish_node);
673 }
674 else
675 {
676 if(prev_segment!=NO_SEGMENT)
677 {
678 /* Try again but allow a U-turn at the start waypoint -
679 this solves the problem of facing a dead-end that contains no super-nodes. */
680
681 prev_segment=NO_SEGMENT;
682
683 begin=FindStartRoutes(nodes,segments,ways,relations,profile,start_node,prev_segment,finish_node);
684 }
685
686 if(begin)
687 {
688 /* Check if the end of the route was reached */
689
690 if(begin->finish_node!=NO_NODE)
691 complete=ExtendStartRoutes(nodes,segments,ways,relations,profile,begin,finish_node);
692 }
693 else
694 {
695 fprintf(stderr,"Error: Cannot find initial section of route compatible with profile.\n");
696 exit(EXIT_FAILURE);
697 }
698 }
699
700 /* Calculate the rest of the route */
701
702 if(!complete)
703 {
704 Results *middle;
705
706 /* Calculate the end of the route */
707
708 end=FindFinishRoutes(nodes,segments,ways,relations,profile,finish_node);
709
710 if(!end)
711 {
712 fprintf(stderr,"Error: Cannot find final section of route compatible with profile.\n");
713 exit(EXIT_FAILURE);
714 }
715
716 /* Calculate the middle of the route */
717
718 middle=FindMiddleRoute(nodes,segments,ways,relations,profile,begin,end);
719
720 if(!middle && prev_segment!=NO_SEGMENT)
721 {
722 /* Try again but allow a U-turn at the start waypoint -
723 this solves the problem of facing a dead-end that contains some super-nodes. */
724
725 FreeResultsList(begin);
726
727 begin=FindStartRoutes(nodes,segments,ways,relations,profile,start_node,NO_SEGMENT,finish_node);
728
729 if(begin)
730 middle=FindMiddleRoute(nodes,segments,ways,relations,profile,begin,end);
731 }
732
733 FreeResultsList(end);
734
735 if(!middle)
736 {
737 fprintf(stderr,"Error: Cannot find super-route compatible with profile.\n");
738 exit(EXIT_FAILURE);
739 }
740
741 complete=CombineRoutes(nodes,segments,ways,relations,profile,begin,middle);
742
743 if(!complete)
744 {
745 fprintf(stderr,"Error: Cannot create combined route following super-route.\n");
746 exit(EXIT_FAILURE);
747 }
748
749 FreeResultsList(begin);
750
751 FreeResultsList(middle);
752 }
753 }
754
755 complete->start_waypoint=start_waypoint;
756 complete->finish_waypoint=finish_waypoint;
757
758 #if DEBUG
759 Result *r=FindResult(complete,complete->start_node,complete->prev_segment);
760
761 printf("The final route is:\n");
762
763 while(r)
764 {
765 printf(" node=%"Pindex_t" segment=%"Pindex_t" score=%f\n",r->node,r->segment,r->score);
766
767 r=r->next;
768 }
769 #endif
770
771 return(complete);
772 }
773
774
775 /*++++++++++++++++++++++++++++++++++++++
776 Print out the usage information.
777
778 int detail The level of detail to use - 0 = low, 1 = high.
779
780 const char *argerr The argument that gave the error (if there is one).
781
782 const char *err Other error message (if there is one).
783 ++++++++++++++++++++++++++++++++++++++*/
784
785 static void print_usage(int detail,const char *argerr,const char *err)
786 {
787 fprintf(stderr,
788 "Usage: router [--help | --help-profile | --help-profile-xml |\n"
789 " --help-profile-json | --help-profile-perl ]\n"
790 " [--dir=<dirname>] [--prefix=<name>]\n"
791 " [--profiles=<filename>] [--translations=<filename>]\n"
792 " [--exact-nodes-only]\n"
793 " [--loggable | --quiet]\n"
794 " [--language=<lang>]\n"
795 " [--output-html]\n"
796 " [--output-gpx-track] [--output-gpx-route]\n"
797 " [--output-text] [--output-text-all]\n"
798 " [--output-none] [--output-stdout]\n"
799 " [--profile=<name>]\n"
800 " [--transport=<transport>]\n"
801 " [--shortest | --quickest]\n"
802 " --lon1=<longitude> --lat1=<latitude>\n"
803 " --lon2=<longitude> --lon2=<latitude>\n"
804 " [ ... --lon99=<longitude> --lon99=<latitude>]\n"
805 " [--reverse] [--loop]\n"
806 " [--highway-<highway>=<preference> ...]\n"
807 " [--speed-<highway>=<speed> ...]\n"
808 " [--property-<property>=<preference> ...]\n"
809 " [--oneway=(0|1)] [--turns=(0|1)]\n"
810 " [--weight=<weight>]\n"
811 " [--height=<height>] [--width=<width>] [--length=<length>]\n");
812
813 if(argerr)
814 fprintf(stderr,
815 "\n"
816 "Error with command line parameter: %s\n",argerr);
817
818 if(err)
819 fprintf(stderr,
820 "\n"
821 "Error: %s\n",err);
822
823 if(detail)
824 fprintf(stderr,
825 "\n"
826 "--help Prints this information.\n"
827 "--help-profile Prints the information about the selected profile.\n"
828 "--help-profile-xml Prints all loaded profiles in XML format.\n"
829 "--help-profile-json Prints all loaded profiles in JSON format.\n"
830 "--help-profile-perl Prints all loaded profiles in Perl format.\n"
831 "\n"
832 "--dir=<dirname> The directory containing the routing database.\n"
833 "--prefix=<name> The filename prefix for the routing database.\n"
834 "--profiles=<filename> The name of the XML file containing the profiles\n"
835 " (defaults to 'profiles.xml' with '--dir' and\n"
836 " '--prefix' options or the file installed in\n"
837 " '" DATADIR "').\n"
838 "--translations=<fname> The name of the XML file containing the translations\n"
839 " (defaults to 'translations.xml' with '--dir' and\n"
840 " '--prefix' options or the file installed in\n"
841 " '" DATADIR "').\n"
842 "\n"
843 "--exact-nodes-only Only route between nodes (don't find closest segment).\n"
844 "\n"
845 "--loggable Print progress messages suitable for logging to file.\n"
846 "--quiet Don't print any screen output when running.\n"
847 "\n"
848 "--language=<lang> Use the translations for specified language.\n"
849 "--output-html Write an HTML description of the route.\n"
850 "--output-gpx-track Write a GPX track file with all route points.\n"
851 "--output-gpx-route Write a GPX route file with interesting junctions.\n"
852 "--output-text Write a plain text file with interesting junctions.\n"
853 "--output-text-all Write a plain test file with all route points.\n"
854 "--output-none Don't write any output files or read any translations.\n"
855 " (If no output option is given then all are written.)\n"
856 "--output-stdout Write to stdout instead of a file (requires exactly\n"
857 " one output format option, implies '--quiet').\n"
858 "\n"
859 "--profile=<name> Select the loaded profile with this name.\n"
860 "--transport=<transport> Select the transport to use (selects the profile\n"
861 " named after the transport if '--profile' is not used.)\n"
862 "\n"
863 "--shortest Find the shortest route between the waypoints.\n"
864 "--quickest Find the quickest route between the waypoints.\n"
865 "\n"
866 "--lon<n>=<longitude> Specify the longitude of the n'th waypoint.\n"
867 "--lat<n>=<latitude> Specify the latitude of the n'th waypoint.\n"
868 "\n"
869 "--reverse Find a route between the waypoints in reverse order.\n"
870 "--loop Find a route that returns to the first waypoint.\n"
871 "\n"
872 "--heading=<bearing> Initial compass bearing at lowest numbered waypoint.\n"
873 "\n"
874 " Routing preference options\n"
875 "--highway-<highway>=<preference> * preference for highway type (%%).\n"
876 "--speed-<highway>=<speed> * speed for highway type (km/h).\n"
877 "--property-<property>=<preference> * preference for proprty type (%%).\n"
878 "--oneway=(0|1) * oneway restrictions are to be obeyed.\n"
879 "--turns=(0|1) * turn restrictions are to be obeyed.\n"
880 "--weight=<weight> * maximum weight limit (tonnes).\n"
881 "--height=<height> * maximum height limit (metres).\n"
882 "--width=<width> * maximum width limit (metres).\n"
883 "--length=<length> * maximum length limit (metres).\n"
884 "\n"
885 "<transport> defaults to motorcar but can be set to:\n"
886 "%s"
887 "\n"
888 "<highway> can be selected from:\n"
889 "%s"
890 "\n"
891 "<property> can be selected from:\n"
892 "%s",
893 TransportList(),HighwayList(),PropertyList());
894
895 exit(!detail);
896 }

Properties

Name Value
cvs:description Router.