Routino SVN Repository Browser

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

ViewVC logotype

Annotation of /branches/libroutino/src/router.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1706 - (hide annotations) (download) (as text)
Fri Jun 12 17:42:25 2015 UTC (9 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 29511 byte(s)
Create a Translation structure to hold the translated strings and have
one global variable instead of 30.  Add a function to free the memory
in the Translation structure.

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

Properties

Name Value
cvs:description Router.