Routino SVN Repository Browser

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

ViewVC logotype

Annotation of /trunk/src/router+lib.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1749 - (hide annotations) (download) (as text)
Thu Jul 16 18:46:22 2015 UTC (9 years, 8 months ago) by amb
Original Path: branches/libroutino/src/router+lib.c
File MIME type: text/x-csrc
File size: 14298 byte(s)
Allow choosing a named translation, the first in the file or the
built-in English one.  Make the routers use the first in the file if
no language is specified rather than the built-in one.

1 amb 1738 /***************************************
2     OSM router using libroutino library.
3    
4     Part of the Routino routing software.
5     ******************/ /******************
6     This file Copyright 2008-2015 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 <unistd.h>
24     #include <stdio.h>
25     #include <string.h>
26     #include <stdlib.h>
27     #include <ctype.h>
28    
29     #include "routino.h"
30    
31    
32     /*+ The maximum distance from the specified point to search for a node or segment (in km). +*/
33     #define MAXSEARCH 1
34    
35     /*+ The maximum number of waypoints +*/
36     #define NWAYPOINTS 99
37    
38    
39     /* Local functions */
40    
41     static char *FileName(const char *dirname,const char *prefix, const char *name);
42     static void print_usage(int detail,const char *argerr,const char *err);
43    
44    
45     /*++++++++++++++++++++++++++++++++++++++
46     The main program for the router.
47     ++++++++++++++++++++++++++++++++++++++*/
48    
49     int main(int argc,char** argv)
50     {
51     Routino_Database *database;
52     Routino_Profile *profile;
53     Routino_Translation *translation;
54     Routino_Waypoint **waypoints;
55     int point_used[NWAYPOINTS+1]={0};
56     double point_lon[NWAYPOINTS+1],point_lat[NWAYPOINTS+1];
57     char *dirname=NULL,*prefix=NULL;
58     char *profiles=NULL,*profilename="motorcar";
59     char *translations=NULL,*language="en";
60     int reverse=0,loop=0;
61     int quickest=0;
62     int html=0,gpx_track=0,gpx_route=0,text=0,text_all=0,none=0,stdout=0;
63     int arg;
64     int first_waypoint=NWAYPOINTS,last_waypoint=1,inc_dec_waypoint,waypoint,nwaypoints=0;
65    
66     /* Parse the command line arguments */
67    
68     if(argc<2)
69     print_usage(0,NULL,NULL);
70    
71     /* Get the non-routing, general program options */
72    
73     for(arg=1;arg<argc;arg++)
74     {
75     if(!strcmp(argv[arg],"--help"))
76     print_usage(1,NULL,NULL);
77     else if(!strncmp(argv[arg],"--dir=",6))
78     dirname=&argv[arg][6];
79     else if(!strncmp(argv[arg],"--prefix=",9))
80     prefix=&argv[arg][9];
81     else if(!strncmp(argv[arg],"--profiles=",11))
82     profiles=&argv[arg][11];
83     else if(!strncmp(argv[arg],"--translations=",15))
84     translations=&argv[arg][15];
85     else if(!strcmp(argv[arg],"--reverse"))
86     reverse=1;
87     else if(!strcmp(argv[arg],"--loop"))
88     loop=1;
89     else if(!strcmp(argv[arg],"--output-html"))
90     html=1;
91     else if(!strcmp(argv[arg],"--output-gpx-track"))
92     gpx_track=1;
93     else if(!strcmp(argv[arg],"--output-gpx-route"))
94     gpx_route=1;
95     else if(!strcmp(argv[arg],"--output-text"))
96     text=1;
97     else if(!strcmp(argv[arg],"--output-text-all"))
98     text_all=1;
99     else if(!strcmp(argv[arg],"--output-none"))
100     none=1;
101     else if(!strcmp(argv[arg],"--output-stdout"))
102     { stdout=1; }
103     else if(!strncmp(argv[arg],"--profile=",10))
104     profilename=&argv[arg][10];
105     else if(!strncmp(argv[arg],"--language=",11))
106     language=&argv[arg][11];
107     else if(!strcmp(argv[arg],"--shortest"))
108     quickest=0;
109     else if(!strcmp(argv[arg],"--quickest"))
110     quickest=1;
111     else if(!strncmp(argv[arg],"--lon",5) && isdigit(argv[arg][5]))
112     {
113     int point;
114     char *p=&argv[arg][6];
115    
116     while(isdigit(*p)) p++;
117     if(*p++!='=')
118     print_usage(0,argv[arg],NULL);
119    
120     point=atoi(&argv[arg][5]);
121     if(point>NWAYPOINTS || point_used[point]&1)
122     print_usage(0,argv[arg],NULL);
123    
124     point_lon[point]=atof(p);
125     point_used[point]+=1;
126    
127     if(point<first_waypoint)
128     first_waypoint=point;
129     if(point>last_waypoint)
130     last_waypoint=point;
131     }
132     else if(!strncmp(argv[arg],"--lat",5) && isdigit(argv[arg][5]))
133     {
134     int point;
135     char *p=&argv[arg][6];
136    
137     while(isdigit(*p)) p++;
138     if(*p++!='=')
139     print_usage(0,argv[arg],NULL);
140    
141     point=atoi(&argv[arg][5]);
142     if(point>NWAYPOINTS || point_used[point]&2)
143     print_usage(0,argv[arg],NULL);
144    
145     point_lat[point]=atof(p);
146     point_used[point]+=2;
147    
148     if(point<first_waypoint)
149     first_waypoint=point;
150     if(point>last_waypoint)
151     last_waypoint=point;
152     }
153     else
154     print_usage(0,argv[arg],NULL);
155    
156     argv[arg]=NULL;
157     }
158    
159     /* Check the specified command line options */
160    
161     if(stdout && (html+gpx_track+gpx_route+text+text_all)!=1)
162     {
163     fprintf(stderr,"Error: The '--output-stdout' option requires exactly one other output option (but not '--output-none').\n");
164     exit(EXIT_FAILURE);
165     }
166    
167     /* Load in the selected profiles */
168    
169     if(profiles)
170     {
171     if(access(profiles,F_OK))
172     {
173     fprintf(stderr,"Error: The '--profiles' option specifies a file that does not exist.\n");
174     exit(EXIT_FAILURE);
175     }
176     }
177     else
178     {
179     profiles=FileName(dirname,prefix,"profiles.xml");
180    
181     if(access(profiles,F_OK))
182     {
183     free(profiles);
184    
185     profiles=FileName(ROUTINO_DATADIR,NULL,"profiles.xml");
186    
187     if(access(profiles,F_OK))
188     {
189     fprintf(stderr,"Error: The '--profiles' option was not used and the default 'profiles.xml' does not exist.\n");
190     exit(EXIT_FAILURE);
191     }
192     }
193     }
194    
195     if(!profilename)
196     {
197     fprintf(stderr,"Error: A profile name must be specified.\n");
198     exit(EXIT_FAILURE);
199     }
200    
201     if(Routino_ParseXMLProfiles(profiles))
202     {
203     fprintf(stderr,"Error: Cannot read the profiles in the file '%s'.\n",profiles);
204     exit(EXIT_FAILURE);
205     }
206    
207     profile=Routino_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     /* Load in the selected translation */
216    
217     if(translations)
218     {
219     if(access(translations,F_OK))
220     {
221     fprintf(stderr,"Error: The '--translations' option specifies a file that does not exist.\n");
222     exit(EXIT_FAILURE);
223     }
224     }
225     else
226     {
227     translations=FileName(dirname,prefix,"translations.xml");
228    
229     if(access(translations,F_OK))
230     {
231     free(translations);
232    
233     translations=FileName(ROUTINO_DATADIR,NULL,"translations.xml");
234    
235     if(access(translations,F_OK))
236     {
237     fprintf(stderr,"Error: The '--translations' option was not used and the default 'translations.xml' does not exist.\n");
238     exit(EXIT_FAILURE);
239     }
240     }
241     }
242    
243     if(Routino_ParseXMLTranslations(translations))
244     {
245     fprintf(stderr,"Error: Cannot read the translations in the file '%s'.\n",translations);
246     exit(EXIT_FAILURE);
247     }
248    
249 amb 1749 if(language)
250     {
251     translation=GetTranslation(language);
252 amb 1738
253 amb 1749 if(!translation)
254     {
255     fprintf(stderr,"Warning: Cannot find a translation called '%s' in '%s'.\n",language,translations);
256     exit(EXIT_FAILURE);
257     }
258     }
259     else
260 amb 1738 {
261 amb 1749 translation=GetTranslation(""); /* first in file */
262 amb 1738
263 amb 1749 if(!translation)
264     {
265     fprintf(stderr,"Warning: No translations in '%s'.\n",translations);
266     exit(EXIT_FAILURE);
267     }
268     }
269    
270 amb 1738 /* Check the waypoints are valid */
271    
272     for(waypoint=first_waypoint;waypoint<=last_waypoint;waypoint++)
273     if(point_used[waypoint]==1 || point_used[waypoint]==2)
274     print_usage(0,NULL,"All waypoints must have latitude and longitude.");
275     else if(point_used[waypoint]==3)
276     nwaypoints++;
277    
278     if(first_waypoint>=last_waypoint)
279     {
280     fprintf(stderr,"Error: At least two waypoints must be specified.\n");
281     exit(EXIT_FAILURE);
282     }
283    
284     waypoints=calloc(sizeof(Routino_Waypoint*),nwaypoints+2);
285    
286 amb 1748 /* Load in the routing database */
287    
288     database=Routino_LoadDatabase(dirname,prefix);
289    
290     /* Check the profile is valid for use with this database */
291    
292     Routino_ValidateProfile(database,profile);
293    
294 amb 1738 /* Check for reverse direction */
295    
296     if(reverse)
297     {
298     int temp;
299    
300     temp=first_waypoint;
301     first_waypoint=last_waypoint;
302     last_waypoint=temp;
303    
304     last_waypoint--;
305    
306     inc_dec_waypoint=-1;
307     }
308     else
309     {
310     last_waypoint++;
311    
312     inc_dec_waypoint=1;
313     }
314    
315     /* Loop through all waypoints */
316    
317     nwaypoints=0;
318    
319     for(waypoint=first_waypoint;waypoint!=last_waypoint;waypoint+=inc_dec_waypoint)
320     if(point_used[waypoint]==3)
321     {
322     waypoints[nwaypoints]=Routino_FindWaypoint(database,profile,point_lat[waypoint],point_lon[waypoint]);
323    
324     if(!waypoints[nwaypoints])
325     {
326     fprintf(stderr,"Error: Cannot find node close to specified point %d.\n",waypoint);
327     exit(EXIT_FAILURE);
328     }
329    
330     nwaypoints++;
331     }
332    
333     if(loop)
334     waypoints[nwaypoints++]=waypoints[0];
335    
336     /* Create the route */
337    
338     if(quickest)
339     Routino_Quickest();
340     else
341     Routino_Shortest();
342    
343     if(Routino_CalculateRoute(database,profile,translation,waypoints,nwaypoints))
344     {
345     fprintf(stderr,"Error: Cannot find a route between specified waypoints.\n");
346     exit(EXIT_FAILURE);
347     }
348    
349     /* Tidy up and exit */
350    
351     Routino_UnloadDatabase(database);
352    
353     Routino_FreeXMLProfiles();
354    
355     Routino_FreeXMLTranslations();
356    
357     for(waypoint=0;waypoint<nwaypoints;waypoint++)
358     free(waypoints[waypoint]);
359    
360     free(waypoints);
361    
362     exit(EXIT_SUCCESS);
363     }
364    
365    
366     /*++++++++++++++++++++++++++++++++++++++
367     Return a filename composed of the dirname, prefix and name.
368    
369     char *FileName Returns a pointer to memory allocated to the filename.
370    
371     const char *dirname The directory name.
372    
373     const char *prefix The file prefix.
374    
375     const char *name The main part of the name.
376     ++++++++++++++++++++++++++++++++++++++*/
377    
378     static char *FileName(const char *dirname,const char *prefix, const char *name)
379     {
380     char *filename=(char*)malloc((dirname?strlen(dirname):0)+1+(prefix?strlen(prefix):0)+1+strlen(name)+1);
381    
382     sprintf(filename,"%s%s%s%s%s",dirname?dirname:"",dirname?"/":"",prefix?prefix:"",prefix?"-":"",name);
383    
384     return(filename);
385     }
386    
387    
388     /*++++++++++++++++++++++++++++++++++++++
389     Print out the usage information.
390    
391     int detail The level of detail to use - 0 = low, 1 = high.
392    
393     const char *argerr The argument that gave the error (if there is one).
394    
395     const char *err Other error message (if there is one).
396     ++++++++++++++++++++++++++++++++++++++*/
397    
398     static void print_usage(int detail,const char *argerr,const char *err)
399     {
400     fprintf(stderr,
401     "Usage: router [--help ]\n"
402     " [--dir=<dirname>] [--prefix=<name>]\n"
403     " [--profiles=<filename>] [--translations=<filename>]\n"
404     " [--language=<lang>]\n"
405     " [--output-html]\n"
406     " [--output-gpx-track] [--output-gpx-route]\n"
407     " [--output-text] [--output-text-all]\n"
408     " [--output-none] [--output-stdout]\n"
409     " [--profile=<name>]\n"
410     " [--shortest | --quickest]\n"
411     " --lon1=<longitude> --lat1=<latitude>\n"
412     " --lon2=<longitude> --lon2=<latitude>\n"
413     " [ ... --lon99=<longitude> --lon99=<latitude>]\n"
414     " [--reverse] [--loop]\n");
415    
416     if(argerr)
417     fprintf(stderr,
418     "\n"
419     "Error with command line parameter: %s\n",argerr);
420    
421     if(err)
422     fprintf(stderr,
423     "\n"
424     "Error: %s\n",err);
425    
426     if(detail)
427     fprintf(stderr,
428     "\n"
429     "--help Prints this information.\n"
430     "\n"
431     "--dir=<dirname> The directory containing the routing database.\n"
432     "--prefix=<name> The filename prefix for the routing database.\n"
433     "--profiles=<filename> The name of the XML file containing the profiles\n"
434     " (defaults to 'profiles.xml' with '--dir' and\n"
435     " '--prefix' options or the file installed in\n"
436     " '" ROUTINO_DATADIR "').\n"
437     "--translations=<fname> The name of the XML file containing the translations\n"
438     " (defaults to 'translations.xml' with '--dir' and\n"
439     " '--prefix' options or the file installed in\n"
440     " '" ROUTINO_DATADIR "').\n"
441     "\n"
442     "--language=<lang> Use the translations for specified language.\n"
443     "--output-html Write an HTML description of the route.\n"
444     "--output-gpx-track Write a GPX track file with all route points.\n"
445     "--output-gpx-route Write a GPX route file with interesting junctions.\n"
446     "--output-text Write a plain text file with interesting junctions.\n"
447     "--output-text-all Write a plain test file with all route points.\n"
448     "--output-none Don't write any output files or read any translations.\n"
449     " (If no output option is given then all are written.)\n"
450     "--output-stdout Write to stdout instead of a file (requires exactly\n"
451     " one output format option, implies '--quiet').\n"
452     "\n"
453     "--profile=<name> Select the loaded profile with this name.\n"
454     "\n"
455     "--shortest Find the shortest route between the waypoints.\n"
456     "--quickest Find the quickest route between the waypoints.\n"
457     "\n"
458     "--lon<n>=<longitude> Specify the longitude of the n'th waypoint.\n"
459     "--lat<n>=<latitude> Specify the latitude of the n'th waypoint.\n"
460     "\n"
461     "--reverse Find a route between the waypoints in reverse order.\n"
462     "--loop Find a route that returns to the first waypoint.\n"
463     "\n");
464    
465     exit(!detail);
466     }