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 342 - (show annotations) (download) (as text)
Tue Mar 30 17:58:35 2010 UTC (14 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 22885 byte(s)
Improve the program help messages.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/router.c,v 1.74 2010-03-30 17:58:35 amb Exp $
3
4 OSM router.
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 #include <string.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29
30 #include "types.h"
31 #include "functions.h"
32 #include "profiles.h"
33 #include "nodes.h"
34 #include "segments.h"
35 #include "ways.h"
36
37
38 /*+ The number of waypoints allowed to be specified. +*/
39 #define NWAYPOINTS 99
40
41 /*+ The maximum distance from the specified point to search for a node or segment (in km). +*/
42 #define MAXSEARCH 1
43
44 /*+ The minimum distance along a segment from a node to insert a fake node. (in km). +*/
45 #define MINSEGMENT 0.005
46
47
48 /*+ A set of fake segments to allow start/finish in the middle of a segment. +*/
49 static Segment fake_segments[2*NWAYPOINTS];
50
51 /*+ A set of fake node latitudes and longitudes. +*/
52 static double point_lon[NWAYPOINTS+1],point_lat[NWAYPOINTS+1];
53
54 /*+ The option not to print any progress information. +*/
55 int option_quiet=0;
56
57 /*+ The options to select the format of the output. +*/
58 int option_html=0,option_gpx_track=0,option_gpx_route=0,option_text=0,option_text_all=0;
59
60 /*+ The option to calculate the quickest route insted of the shortest. +*/
61 int option_quickest=0;
62
63
64 /* Local functions */
65
66 static void print_usage(int detail);
67
68
69 /*++++++++++++++++++++++++++++++++++++++
70 The main program for the router.
71 ++++++++++++++++++++++++++++++++++++++*/
72
73 int main(int argc,char** argv)
74 {
75 Nodes *OSMNodes;
76 Segments *OSMSegments;
77 Ways *OSMWays;
78 Results *results[NWAYPOINTS+1]={NULL};
79 int point_used[NWAYPOINTS+1]={0};
80 int help_profile=0,help_profile_xml=0,help_profile_json=0,help_profile_pl=0;
81 char *dirname=NULL,*prefix=NULL,*profiles=NULL,*profilename=NULL;
82 int exactnodes=0;
83 Transport transport=Transport_None;
84 Profile *profile=NULL;
85 index_t start=NO_NODE,finish=NO_NODE;
86 int arg,point;
87
88 /* Parse the command line arguments */
89
90 if(argc<2)
91 print_usage(0);
92
93 /* Get the non-routing, general program options */
94
95 for(arg=1;arg<argc;arg++)
96 {
97 if(!strcmp(argv[arg],"--help"))
98 print_usage(1);
99 else if(!strcmp(argv[arg],"--help-profile"))
100 help_profile=1;
101 else if(!strcmp(argv[arg],"--help-profile-xml"))
102 help_profile_xml=1;
103 else if(!strcmp(argv[arg],"--help-profile-json"))
104 help_profile_json=1;
105 else if(!strcmp(argv[arg],"--help-profile-perl"))
106 help_profile_pl=1;
107 else if(!strncmp(argv[arg],"--dir=",6))
108 dirname=&argv[arg][6];
109 else if(!strncmp(argv[arg],"--prefix=",9))
110 prefix=&argv[arg][9];
111 else if(!strncmp(argv[arg],"--profiles=",11))
112 profiles=&argv[arg][11];
113 else if(!strcmp(argv[arg],"--exact-nodes-only"))
114 exactnodes=1;
115 else if(!strcmp(argv[arg],"--quiet"))
116 option_quiet=1;
117 else if(!strcmp(argv[arg],"--output-html"))
118 option_html=1;
119 else if(!strcmp(argv[arg],"--output-gpx-track"))
120 option_gpx_track=1;
121 else if(!strcmp(argv[arg],"--output-gpx-route"))
122 option_gpx_route=1;
123 else if(!strcmp(argv[arg],"--output-text"))
124 option_text=1;
125 else if(!strcmp(argv[arg],"--output-text-all"))
126 option_text_all=1;
127 else if(!strncmp(argv[arg],"--profile=",10))
128 profilename=&argv[arg][10];
129 else if(!strncmp(argv[arg],"--transport=",12))
130 {
131 transport=TransportType(&argv[arg][12]);
132
133 if(transport==Transport_None)
134 print_usage(0);
135 }
136 else
137 continue;
138
139 argv[arg]=NULL;
140 }
141
142 /* Load in the profiles */
143
144 if(transport==Transport_None)
145 transport=Transport_Motorcar;
146
147 if(profiles && ExistsFile(profiles))
148 ;
149 else if(!profiles && ExistsFile(FileName(dirname,prefix,"profiles.xml")))
150 profiles=FileName(dirname,prefix,"profiles.xml");
151
152 if(profiles && ParseXMLProfiles(profiles))
153 {
154 fprintf(stderr,"Error: Cannot read the profiles in the file '%s'.\n",profiles);
155 return(1);
156 }
157
158 if(!profiles && profile)
159 {
160 fprintf(stderr,"Error: Cannot use '--profile' option without reading some profiles.\n");
161 return(1);
162 }
163
164 if(profilename)
165 {
166 profile=GetProfile(profilename);
167
168 if(!profile)
169 {
170 fprintf(stderr,"Error: Cannot find a profile called '%s' in '%s'.\n",profilename,profiles);
171 return(1);
172 }
173 }
174 else
175 profile=GetProfile(TransportName(transport));
176
177 if(!profile)
178 {
179 profile=(Profile*)calloc(1,sizeof(Profile));
180 profile->transport=transport;
181 }
182
183 /* Parse the other command line arguments */
184
185 for(arg=1;arg<argc;arg++)
186 {
187 if(!argv[arg])
188 continue;
189 else if(!strcmp(argv[arg],"--shortest"))
190 option_quickest=0;
191 else if(!strcmp(argv[arg],"--quickest"))
192 option_quickest=1;
193 else if(isdigit(argv[arg][0]) ||
194 ((argv[arg][0]=='-' || argv[arg][0]=='+') && isdigit(argv[arg][1])))
195 {
196 for(point=1;point<=NWAYPOINTS;point++)
197 if(point_used[point]!=3)
198 {
199 if(point_used[point]==0)
200 {
201 point_lon[point]=degrees_to_radians(atof(argv[arg]));
202 point_used[point]=1;
203 }
204 else /* if(point_used[point]==1) */
205 {
206 point_lat[point]=degrees_to_radians(atof(argv[arg]));
207 point_used[point]=3;
208 }
209 break;
210 }
211 }
212 else if(!strncmp(argv[arg],"--lon",5) && isdigit(argv[arg][5]))
213 {
214 char *p=&argv[arg][6];
215 while(isdigit(*p)) p++;
216 if(*p++!='=')
217 print_usage(0);
218
219 point=atoi(&argv[arg][5]);
220 if(point>NWAYPOINTS || point_used[point]&1)
221 print_usage(0);
222
223 point_lon[point]=degrees_to_radians(atof(p));
224 point_used[point]+=1;
225 }
226 else if(!strncmp(argv[arg],"--lat",5) && isdigit(argv[arg][5]))
227 {
228 char *p=&argv[arg][6];
229 while(isdigit(*p)) p++;
230 if(*p++!='=')
231 print_usage(0);
232
233 point=atoi(&argv[arg][5]);
234 if(point>NWAYPOINTS || point_used[point]&2)
235 print_usage(0);
236
237 point_lat[point]=degrees_to_radians(atof(p));
238 point_used[point]+=2;
239 }
240 else if(!strncmp(argv[arg],"--transport=",12))
241 ; /* Done this already */
242 else if(!strncmp(argv[arg],"--highway-",10))
243 {
244 Highway highway;
245 char *equal=strchr(argv[arg],'=');
246 char *string;
247
248 if(!equal)
249 print_usage(0);
250
251 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10);
252 string[equal-argv[arg]-10]=0;
253
254 highway=HighwayType(string);
255
256 if(highway==Way_Count)
257 print_usage(0);
258
259 profile->highway[highway]=atof(equal+1);
260
261 free(string);
262 }
263 else if(!strncmp(argv[arg],"--speed-",8))
264 {
265 Highway highway;
266 char *equal=strchr(argv[arg],'=');
267 char *string;
268
269 if(!equal)
270 print_usage(0);
271
272 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8);
273 string[equal-argv[arg]-8]=0;
274
275 highway=HighwayType(string);
276
277 if(highway==Way_Count)
278 print_usage(0);
279
280 profile->speed[highway]=kph_to_speed(atof(equal+1));
281
282 free(string);
283 }
284 else if(!strncmp(argv[arg],"--property-",11))
285 {
286 Property property;
287 char *equal=strchr(argv[arg],'=');
288 char *string;
289
290 if(!equal)
291 print_usage(0);
292
293 string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+11);
294 string[equal-argv[arg]-11]=0;
295
296 property=PropertyType(string);
297
298 if(property==Way_Count)
299 print_usage(0);
300
301 profile->props_yes[property]=atof(equal+1);
302
303 free(string);
304 }
305 else if(!strncmp(argv[arg],"--oneway=",9))
306 profile->oneway=!!atoi(&argv[arg][9]);
307 else if(!strncmp(argv[arg],"--weight=",9))
308 profile->weight=tonnes_to_weight(atof(&argv[arg][9]));
309 else if(!strncmp(argv[arg],"--height=",9))
310 profile->height=metres_to_height(atof(&argv[arg][9]));
311 else if(!strncmp(argv[arg],"--width=",8))
312 profile->width=metres_to_width(atof(&argv[arg][8]));
313 else if(!strncmp(argv[arg],"--length=",9))
314 profile->length=metres_to_length(atof(&argv[arg][9]));
315 else
316 print_usage(0);
317 }
318
319 for(point=1;point<=NWAYPOINTS;point++)
320 if(point_used[point]==1 || point_used[point]==2)
321 print_usage(0);
322
323 if(help_profile)
324 {
325 PrintProfile(profile);
326
327 return(0);
328 }
329 else if(help_profile_xml)
330 {
331 PrintProfilesXML();
332
333 return(0);
334 }
335 else if(help_profile_json)
336 {
337 PrintProfilesJSON();
338
339 return(0);
340 }
341 else if(help_profile_pl)
342 {
343 PrintProfilesPerl();
344
345 return(0);
346 }
347
348 UpdateProfile(profile);
349
350 /* Load in the data - Note: No error checking because Load*List() will call exit() in case of an error. */
351
352 OSMNodes=LoadNodeList(FileName(dirname,prefix,"nodes.mem"));
353
354 OSMSegments=LoadSegmentList(FileName(dirname,prefix,"segments.mem"));
355
356 OSMWays=LoadWayList(FileName(dirname,prefix,"ways.mem"));
357
358 if(!(profile->allow & OSMWays->allow))
359 {
360 fprintf(stderr,"Error: Database was not generated for selected transport.\n");
361 return(1);
362 }
363
364 if(option_html==0 && option_gpx_track==0 && option_gpx_route==0 && option_text==0 && option_text_all==0)
365 option_html=option_gpx_track=option_gpx_route=option_text=option_text_all=1;
366
367 /* Loop through all pairs of points */
368
369 for(point=1;point<=NWAYPOINTS;point++)
370 {
371 Results *begin,*end;
372 distance_t distmax=km_to_distance(MAXSEARCH);
373 distance_t distmin;
374 Segment *segment=NULL;
375 index_t node1,node2;
376
377 if(point_used[point]!=3)
378 continue;
379
380 /* Find the closest point */
381
382 start=finish;
383
384 if(exactnodes)
385 {
386 finish=FindClosestNode(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,profile,&distmin);
387 }
388 else
389 {
390 distance_t dist1,dist2;
391
392 segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,profile,&distmin,&node1,&node2,&dist1,&dist2);
393
394 finish=CreateFakes(OSMNodes,point,segment,node1,node2,dist1,dist2);
395 }
396
397 if(finish==NO_NODE)
398 {
399 fprintf(stderr,"Error: Cannot find node close to specified point %d.\n",point);
400 return(1);
401 }
402
403 if(!option_quiet)
404 {
405 double lat,lon;
406
407 if(IsFakeNode(finish))
408 GetFakeLatLong(finish,&lat,&lon);
409 else
410 GetLatLong(OSMNodes,finish,&lat,&lon);
411
412 if(IsFakeNode(finish))
413 printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,IndexSegment(OSMSegments,segment),node1,node2,
414 radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
415 else
416 printf("Point %d is node %d: %3.6f %4.6f = %2.3f km\n",point,finish,
417 radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin));
418 }
419
420 if(start==NO_NODE)
421 continue;
422
423 /* Calculate the beginning of the route */
424
425 if(!IsFakeNode(start) && IsSuperNode(OSMNodes,start))
426 {
427 Result *result;
428
429 begin=NewResultsList(1);
430
431 begin->start=start;
432
433 result=InsertResult(begin,start);
434
435 ZeroResult(result);
436 }
437 else
438 {
439 begin=FindStartRoutes(OSMNodes,OSMSegments,OSMWays,start,profile);
440
441 if(!begin)
442 {
443 fprintf(stderr,"Error: Cannot find initial section of route compatible with profile.\n");
444 return(1);
445 }
446 }
447
448 if(FindResult(begin,finish))
449 {
450 FixForwardRoute(begin,finish);
451
452 results[point]=begin;
453
454 if(!option_quiet)
455 {
456 printf("\rRouted: Super-Nodes Checked = %d\n",begin->number);
457 fflush(stdout);
458 }
459 }
460 else
461 {
462 Results *superresults;
463
464 /* Calculate the end of the route */
465
466 if(!IsFakeNode(finish) && IsSuperNode(OSMNodes,finish))
467 {
468 Result *result;
469
470 end=NewResultsList(1);
471
472 end->finish=finish;
473
474 result=InsertResult(end,finish);
475
476 ZeroResult(result);
477 }
478 else
479 {
480 end=FindFinishRoutes(OSMNodes,OSMSegments,OSMWays,finish,profile);
481
482 if(!end)
483 {
484 fprintf(stderr,"Error: Cannot find final section of route compatible with profile.\n");
485 return(1);
486 }
487 }
488
489 /* Calculate the middle of the route */
490
491 superresults=FindMiddleRoute(OSMNodes,OSMSegments,OSMWays,begin,end,profile);
492
493 FreeResultsList(begin);
494 FreeResultsList(end);
495
496 if(!superresults)
497 {
498 fprintf(stderr,"Error: Cannot find route compatible with profile.\n");
499 return(1);
500 }
501
502 results[point]=CombineRoutes(superresults,OSMNodes,OSMSegments,OSMWays,profile);
503
504 FreeResultsList(superresults);
505 }
506 }
507
508 /* Print out the combined route */
509
510 PrintRouteHead(FileName(dirname,prefix,"copyright.txt"));
511
512 PrintRoute(results,NWAYPOINTS,OSMNodes,OSMSegments,OSMWays,profile);
513
514 PrintRouteTail();
515
516 return(0);
517 }
518
519
520 /*++++++++++++++++++++++++++++++++++++++
521 Create a pair of fake segments corresponding to the given segment split in two.
522
523 index_t CreateFakes Returns the fake node index (or a real one in special cases).
524
525 Nodes *nodes The set of nodes to use.
526
527 int point Which of the waypoints is this.
528
529 Segment *segment The segment to split.
530
531 index_t node1 The first node at the end of this segment.
532
533 index_t node2 The second node at the end of this segment.
534
535 distance_t dist1 The distance to the first node.
536
537 distance_t dist2 The distance to the second node.
538 ++++++++++++++++++++++++++++++++++++++*/
539
540 index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2)
541 {
542 index_t fakenode;
543 double lat1,lon1,lat2,lon2;
544
545 /* Check if we are actually close enough to an existing node */
546
547 if(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT))
548 return(node1);
549
550 if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT))
551 return(node2);
552
553 if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT))
554 {
555 if(dist1<dist2)
556 return(node1);
557 else
558 return(node2);
559 }
560
561 /* Create the fake node */
562
563 fakenode=point|NODE_SUPER;
564
565 GetLatLong(nodes,node1,&lat1,&lon1);
566 GetLatLong(nodes,node2,&lat2,&lon2);
567
568 if(lat1>3 && lat2<-3)
569 lat2+=2*M_PI;
570 else if(lat1<-3 && lat2>3)
571 lat1+=2*M_PI;
572
573 point_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2);
574 point_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2);
575
576 if(point_lat[point]>M_PI) point_lat[point]-=2*M_PI;
577
578 /* Create the first fake segment */
579
580 fake_segments[2*point-2]=*segment;
581
582 if(segment->node1==node1)
583 fake_segments[2*point-2].node1=fakenode;
584 else
585 fake_segments[2*point-2].node2=fakenode;
586
587 fake_segments[2*point-2].distance=DISTANCE(dist1)|DISTFLAG(segment->distance);
588
589 /* Create the second fake segment */
590
591 fake_segments[2*point-1]=*segment;
592
593 if(segment->node1==node2)
594 fake_segments[2*point-1].node1=fakenode;
595 else
596 fake_segments[2*point-1].node2=fakenode;
597
598 fake_segments[2*point-1].distance=DISTANCE(dist2)|DISTFLAG(segment->distance);
599
600 return(fakenode);
601 }
602
603
604 /*++++++++++++++++++++++++++++++++++++++
605 Lookup the latitude and longitude of a fake node.
606
607 index_t fakenode The node to lookup.
608
609 double *latitude Returns the latitude
610
611 double *longitude Returns the longitude.
612 ++++++++++++++++++++++++++++++++++++++*/
613
614 void GetFakeLatLong(index_t fakenode, double *latitude,double *longitude)
615 {
616 index_t realnode=fakenode&(~NODE_SUPER);
617
618 *latitude =point_lat[realnode];
619 *longitude=point_lon[realnode];
620 }
621
622
623 /*++++++++++++++++++++++++++++++++++++++
624 Finds the first fake segment associated to a fake node.
625
626 Segment *FirstFakeSegment Returns the first fake segment.
627
628 index_t fakenode The node to lookup.
629 ++++++++++++++++++++++++++++++++++++++*/
630
631 Segment *FirstFakeSegment(index_t fakenode)
632 {
633 index_t realnode=fakenode&(~NODE_SUPER);
634
635 return(&fake_segments[2*realnode-2]);
636 }
637
638
639 /*++++++++++++++++++++++++++++++++++++++
640 Finds the next (there can only be two) fake segment associated to a fake node.
641
642 Segment *NextFakeSegment Returns the second fake segment.
643
644 Segment *segment The first fake segment.
645
646 index_t fakenode The node to lookup.
647 ++++++++++++++++++++++++++++++++++++++*/
648
649 Segment *NextFakeSegment(Segment *segment,index_t fakenode)
650 {
651 index_t realnode=fakenode&(~NODE_SUPER);
652
653 if(segment==&fake_segments[2*realnode-2])
654 return(&fake_segments[2*realnode-1]);
655 else
656 return(NULL);
657 }
658
659
660 /*++++++++++++++++++++++++++++++++++++++
661 Finds the next (there can only be two) fake segment associated to a fake node.
662
663 Segment *ExtraFakeSegment Returns a segment between the two specified nodes if it exists.
664
665 index_t node The real node.
666
667 index_t fakenode The fake node to lookup.
668 ++++++++++++++++++++++++++++++++++++++*/
669
670 Segment *ExtraFakeSegment(index_t node,index_t fakenode)
671 {
672 index_t realnode=fakenode&(~NODE_SUPER);
673
674 if(fake_segments[2*realnode-2].node1==node || fake_segments[2*realnode-2].node2==node)
675 return(&fake_segments[2*realnode-2]);
676
677 if(fake_segments[2*realnode-1].node1==node || fake_segments[2*realnode-1].node2==node)
678 return(&fake_segments[2*realnode-1]);
679
680 return(NULL);
681 }
682
683
684 /*++++++++++++++++++++++++++++++++++++++
685 Print out the usage information.
686
687 int detail The level of detail to use - 0 = low, 1 = high.
688 ++++++++++++++++++++++++++++++++++++++*/
689
690 static void print_usage(int detail)
691 {
692 fprintf(stderr,
693 "Usage: router [--help | --help-profile | --help-profile-xml |\n"
694 " --help-profile-json | --help-profile-perl ]\n"
695 " [--dir=<dirname>] [--prefix=<name>] [--profiles=<filename>]\n"
696 " [--exact-nodes-only]\n"
697 " [--quiet]\n"
698 " [--output-html]\n"
699 " [--output-gpx-track] [--output-gpx-route]\n"
700 " [--output-text] [--output-text-all]\n"
701 " [--profile=<name>]\n"
702 " [--transport=<transport>]\n"
703 " [--shortest | --quickest]\n"
704 " --lon1=<longitude> --lat1=<latitude>\n"
705 " --lon2=<longitude> --lon2=<latitude>\n"
706 " [ ... --lon99=<longitude> --lon99=<latitude>]\n"
707 " [--highway-<highway>=<preference> ...]\n"
708 " [--speed-<highway>=<speed> ...]\n"
709 " [--property-<property>=<preference> ...]\n"
710 " [--oneway=(0|1)]\n"
711 " [--weight=<weight>]\n"
712 " [--height=<height>] [--width=<width>] [--length=<length>]\n");
713
714 if(detail)
715 fprintf(stderr,
716 "\n"
717 "--help Prints this information.\n"
718 "--help-profile Prints the information about the selected profile.\n"
719 "--help-profile-xml Prints all loaded profiles in XML format.\n"
720 "--help-profile-json Prints all loaded profiles in JSON format.\n"
721 "--help-profile-perl Prints all loaded profiles in Perl format.\n"
722 "\n"
723 "--dir=<dirname> The directory containing the routing database.\n"
724 "--prefix=<name> The filename prefix for the routing database.\n"
725 "--profiles=<filename> The name of the profiles (defaults to 'profiles.xml'\n"
726 " with '--dirname' and '--prefix' options).\n"
727 "\n"
728 "--exact-nodes-only Only route between nodes (don't find closest segment).\n"
729 "\n"
730 "--quiet Don't print any output when running.\n"
731 "--output-html Write an HTML description of the route.\n"
732 "--output-gpx-track Write a GPX track file with all route points.\n"
733 "--output-gpx-route Write a GPX route file with interesting junctions.\n"
734 "--output-text Write a plain text file with interesting junctions.\n"
735 "--output-text-all Write a plain test file with all route points.\n"
736 " (If no output option is given then all are written.)\n"
737 "\n"
738 "--profile=<name> Select the loaded profile with this name.\n"
739 "--transport=<transport> Select the transport to use (selects the profile\n"
740 " named after the transport if '--profile' is not used.)\n"
741 "\n"
742 "--shortest Find the shortest route between the waypoints.\n"
743 "--quickest Find the quickest route between the waypoints.\n"
744 "\n"
745 "--lon<n>=<longitude> Specify the longitude of the n'th waypoint.\n"
746 "--lat<n>=<latitude> Specify the latitude of the n'th waypoint.\n"
747 "\n"
748 " Routing preference options\n"
749 "--highway-<highway>=<preference> * preference for highway type (%%).\n"
750 "--speed-<highway>=<speed> * speed for highway type (km/h).\n"
751 "--property-<property>=<preference> * preference for proprty type (%%).\n"
752 "--oneway=(0|1) * oneway streets are to be obeyed.\n"
753 "--weight=<weight> * maximum weight limit (tonnes).\n"
754 "--height=<height> * maximum height limit (metres).\n"
755 "--width=<width> * maximum width limit (metres).\n"
756 "--length=<length> * maximum length limit (metres).\n"
757 "\n"
758 "<transport> defaults to motorcar but can be set to:\n"
759 "%s"
760 "\n"
761 "<highway> can be selected from:\n"
762 "%s"
763 "\n"
764 "<property> can be selected from:\n"
765 "%s",
766 TransportList(),HighwayList(),PropertyList());
767
768 exit(!detail);
769 }

Properties

Name Value
cvs:description Router.