Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Contents of /trunk/src/router.c
Parent Directory
|
Revision Log
Revision 165 -
(show annotations)
(download)
(as text)
Mon Apr 27 18:56:39 2009 UTC (15 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 12274 byte(s)
Mon Apr 27 18:56:39 2009 UTC (15 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 12274 byte(s)
Allow generating a route with intermediate waypoints.
1 | /*************************************** |
2 | $Header: /home/amb/CVS/routino/src/router.c,v 1.47 2009-04-27 18:56:39 amb Exp $ |
3 | |
4 | OSM router. |
5 | |
6 | Part of the Routino routing software. |
7 | ******************/ /****************** |
8 | This file Copyright 2008,2009 Andrew M. Bishop |
9 | |
10 | This program is free software: you can redistribute it and/or modify |
11 | it under the terms of the GNU Affero General Public License as published by |
12 | the Free Software Foundation, either version 3 of the License, or |
13 | (at your option) any later version. |
14 | |
15 | This program is distributed in the hope that it will be useful, |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public License |
21 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | ***************************************/ |
23 | |
24 | |
25 | #include <stdio.h> |
26 | #include <string.h> |
27 | #include <stdlib.h> |
28 | #include <math.h> |
29 | #include <ctype.h> |
30 | |
31 | #include "types.h" |
32 | #include "functions.h" |
33 | #include "profiles.h" |
34 | #include "nodes.h" |
35 | #include "segments.h" |
36 | #include "ways.h" |
37 | |
38 | |
39 | /*+ The option not to print any progress information. +*/ |
40 | int option_quiet=0; |
41 | |
42 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
43 | int option_quickest=0; |
44 | |
45 | |
46 | int main(int argc,char** argv) |
47 | { |
48 | Nodes *OSMNodes; |
49 | Segments *OSMSegments; |
50 | Ways *OSMWays; |
51 | Results *results[9]={NULL}; |
52 | int point_used[9]={0}; |
53 | float point_lon[9],point_lat[9]; |
54 | int help_profile=0,help_profile_js=0,help_profile_pl=0; |
55 | int option_all=0,option_super=0,option_no_output=0; |
56 | char *dirname=NULL,*prefix=NULL,*filename; |
57 | Transport transport=Transport_None; |
58 | Profile profile; |
59 | Node *start_node=NULL,*finish_node=NULL; |
60 | int arg,node; |
61 | |
62 | /* Parse the command line arguments */ |
63 | |
64 | if(argc<2) |
65 | { |
66 | usage: |
67 | |
68 | fprintf(stderr,"Usage: router [--lon1=]<longitude> [--lat1=]<latitude>\n" |
69 | " [--lon2=]<longitude> [--lon2=]<latitude>\n" |
70 | " [ ... [--lon9=]<longitude> [--lon9=]<latitude> ]\n" |
71 | " [--help | --help-profile | --help-profile-js | --help-profile-pl]\n" |
72 | " [--dir=<name>] [--prefix=<name>]\n" |
73 | " [--shortest | --quickest]\n" |
74 | " [--all | --super]\n" |
75 | " [--no-output] [--quiet]\n" |
76 | " [--transport=<transport>]\n" |
77 | " [--highway-<highway>=[0|1] ...]\n" |
78 | " [--speed-<highway>=<speed> ...]\n" |
79 | " [--oneway=[0|1]]\n" |
80 | " [--weight=<weight>]\n" |
81 | " [--height=<height>] [--width=<width>] [--length=<length>]\n" |
82 | "\n" |
83 | "<transport> defaults to motorcar but can be set to:\n" |
84 | "%s" |
85 | "\n" |
86 | "<highway> can be selected from:\n" |
87 | "%s" |
88 | "\n" |
89 | "<speed> is a speed in km/hour\n" |
90 | "<weight> is a weight in tonnes\n" |
91 | "<height>, <width>, <length> are dimensions in metres\n" |
92 | "\n", |
93 | TransportList(),HighwayList()); |
94 | |
95 | return(1); |
96 | } |
97 | |
98 | /* Get the transport type if specified and fill in the default profile */ |
99 | |
100 | for(arg=1;arg<argc;arg++) |
101 | if(!strncmp(argv[arg],"--transport=",12)) |
102 | { |
103 | transport=TransportType(&argv[arg][12]); |
104 | |
105 | if(transport==Transport_None) |
106 | goto usage; |
107 | } |
108 | |
109 | if(transport==Transport_None) |
110 | transport=Transport_Motorcar; |
111 | |
112 | profile=*GetProfile(transport); |
113 | |
114 | /* Parse the other command line arguments */ |
115 | |
116 | for(arg=1;arg<argc;arg++) |
117 | { |
118 | if(isdigit(argv[arg][0]) || |
119 | ((argv[arg][0]=='-' || argv[arg][0]=='+') && isdigit(argv[arg][1]))) |
120 | { |
121 | for(node=0;node<sizeof(point_used)/sizeof(point_used[0]);node++) |
122 | if(point_used[node]!=3) |
123 | { |
124 | if(point_used[node]==0) |
125 | { |
126 | point_lon[node]=(M_PI/180)*atof(argv[arg]); |
127 | point_used[node]=1; |
128 | } |
129 | else /* if(point_used[node]==1) */ |
130 | { |
131 | point_lat[node]=(M_PI/180)*atof(argv[arg]); |
132 | point_used[node]=3; |
133 | } |
134 | break; |
135 | } |
136 | } |
137 | else if(!strncmp(argv[arg],"--lon",5) && isdigit(argv[arg][5]) && argv[arg][6]=='=') |
138 | { |
139 | node=atoi(&argv[arg][5]); |
140 | if(point_used[node]&1) |
141 | goto usage; |
142 | point_lon[node]=(M_PI/180)*atof(&argv[arg][7]); |
143 | point_used[node]+=1; |
144 | } |
145 | else if(!strncmp(argv[arg],"--lat",5) && isdigit(argv[arg][5]) && argv[arg][6]=='=') |
146 | { |
147 | node=atoi(&argv[arg][5]); |
148 | if(point_used[node]&2) |
149 | goto usage; |
150 | point_lat[node]=(M_PI/180)*atof(&argv[arg][7]); |
151 | point_used[node]+=2; |
152 | } |
153 | else if(!strcmp(argv[arg],"--help")) |
154 | goto usage; |
155 | else if(!strcmp(argv[arg],"--help-profile")) |
156 | help_profile=1; |
157 | else if(!strcmp(argv[arg],"--help-profile-js")) |
158 | help_profile_js=1; |
159 | else if(!strcmp(argv[arg],"--help-profile-pl")) |
160 | help_profile_pl=1; |
161 | else if(!strncmp(argv[arg],"--dir=",6)) |
162 | dirname=&argv[arg][6]; |
163 | else if(!strncmp(argv[arg],"--prefix=",9)) |
164 | prefix=&argv[arg][9]; |
165 | else if(!strcmp(argv[arg],"--shortest")) |
166 | option_quickest=0; |
167 | else if(!strcmp(argv[arg],"--quickest")) |
168 | option_quickest=1; |
169 | else if(!strcmp(argv[arg],"--all")) |
170 | option_all=1; |
171 | else if(!strcmp(argv[arg],"--super")) |
172 | option_super=1; |
173 | else if(!strcmp(argv[arg],"--no-output")) |
174 | option_no_output=1; |
175 | else if(!strcmp(argv[arg],"--quiet")) |
176 | option_quiet=1; |
177 | else if(!strncmp(argv[arg],"--transport=",12)) |
178 | ; /* Done this already*/ |
179 | else if(!strncmp(argv[arg],"--highway-",10)) |
180 | { |
181 | Highway highway; |
182 | char *equal=strchr(argv[arg],'='); |
183 | char *string; |
184 | |
185 | if(!equal) |
186 | goto usage; |
187 | |
188 | string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10); |
189 | string[equal-argv[arg]-10]=0; |
190 | |
191 | highway=HighwayType(string); |
192 | |
193 | free(string); |
194 | |
195 | if(highway==Way_Unknown) |
196 | goto usage; |
197 | |
198 | profile.highways[highway]=atoi(equal+1); |
199 | } |
200 | else if(!strncmp(argv[arg],"--speed-",8)) |
201 | { |
202 | Highway highway; |
203 | char *equal=strchr(argv[arg],'='); |
204 | char *string; |
205 | |
206 | if(!equal) |
207 | goto usage; |
208 | |
209 | string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8); |
210 | string[equal-argv[arg]-8]=0; |
211 | |
212 | highway=HighwayType(string); |
213 | |
214 | free(string); |
215 | |
216 | if(highway==Way_Unknown) |
217 | goto usage; |
218 | |
219 | profile.speed[highway]=atoi(equal+1); |
220 | } |
221 | else if(!strncmp(argv[arg],"--oneway=",9)) |
222 | profile.oneway=atoi(&argv[arg][9]); |
223 | else if(!strncmp(argv[arg],"--weight=",9)) |
224 | profile.weight=tonnes_to_weight(atof(&argv[arg][9])); |
225 | else if(!strncmp(argv[arg],"--height=",9)) |
226 | profile.height=metres_to_height(atof(&argv[arg][9])); |
227 | else if(!strncmp(argv[arg],"--width=",8)) |
228 | profile.width=metres_to_width(atof(&argv[arg][8])); |
229 | else if(!strncmp(argv[arg],"--length=",9)) |
230 | profile.length=metres_to_length(atof(&argv[arg][9])); |
231 | else |
232 | goto usage; |
233 | } |
234 | |
235 | for(node=0;node<sizeof(point_used)/sizeof(point_used[0]);node++) |
236 | if(point_used[node]==1 || point_used[node]==2) |
237 | goto usage; |
238 | |
239 | if(help_profile) |
240 | { |
241 | PrintProfile(&profile); |
242 | |
243 | return(0); |
244 | } |
245 | else if(help_profile_js) |
246 | { |
247 | PrintProfilesJS(); |
248 | |
249 | return(0); |
250 | } |
251 | else if(help_profile_pl) |
252 | { |
253 | PrintProfilesPerl(); |
254 | |
255 | return(0); |
256 | } |
257 | |
258 | /* Load in the data */ |
259 | |
260 | OSMNodes=LoadNodeList(filename=FileName(dirname,prefix,"nodes.mem")); |
261 | |
262 | if(!OSMNodes) |
263 | { |
264 | fprintf(stderr,"Cannot open nodes file '%s'.\n",filename); |
265 | return(1); |
266 | } |
267 | |
268 | OSMSegments=LoadSegmentList(filename=FileName(dirname,prefix,"segments.mem")); |
269 | |
270 | if(!OSMSegments) |
271 | { |
272 | fprintf(stderr,"Cannot open segments file '%s'.\n",filename); |
273 | return(1); |
274 | } |
275 | |
276 | OSMWays=LoadWayList(filename=FileName(dirname,prefix,"ways.mem")); |
277 | |
278 | if(!OSMWays) |
279 | { |
280 | fprintf(stderr,"Cannot open ways file '%s'.\n",filename); |
281 | return(1); |
282 | } |
283 | |
284 | /* Loop through all pairs of nodes */ |
285 | |
286 | for(node=0;node<sizeof(point_used)/sizeof(point_used[0]);node++) |
287 | { |
288 | distance_t dist=km_to_distance(10); |
289 | index_t start,finish; |
290 | |
291 | if(point_used[node]!=3) |
292 | continue; |
293 | |
294 | /* Find the node */ |
295 | |
296 | start_node=finish_node; |
297 | |
298 | finish_node=FindNode(OSMNodes,point_lat[node],point_lon[node],&dist); |
299 | |
300 | if(!finish_node) |
301 | { |
302 | fprintf(stderr,"Cannot find node close to specified point %d.\n",node); |
303 | return(1); |
304 | } |
305 | |
306 | if(!option_quiet) |
307 | { |
308 | float lat,lon; |
309 | |
310 | GetLatLong(OSMNodes,finish_node,&lat,&lon); |
311 | |
312 | printf("Node %d: %3.6f %4.6f = %2.3f km\n",node,(180.0/M_PI)*lat,(180.0/M_PI)*lon,distance_to_km(dist)); |
313 | } |
314 | |
315 | if(!start_node || !finish_node) |
316 | continue; |
317 | |
318 | /* Find the route segment */ |
319 | |
320 | start =IndexNode(OSMNodes,start_node ); |
321 | finish=IndexNode(OSMNodes,finish_node); |
322 | |
323 | if(option_super && !IsSuperNode(start_node) && !IsSuperNode(finish_node)) |
324 | { |
325 | fprintf(stderr,"Start and/or finish nodes are not super-nodes.\n"); |
326 | return(1); |
327 | } |
328 | |
329 | /* Calculate the route. */ |
330 | |
331 | if(option_all) |
332 | { |
333 | /* Calculate the route */ |
334 | |
335 | results[node]=FindRoute(OSMNodes,OSMSegments,OSMWays,start,finish,&profile,option_all); |
336 | |
337 | if(!results[node]) |
338 | { |
339 | fprintf(stderr,"Cannot find route compatible with profile.\n"); |
340 | return(1); |
341 | } |
342 | } |
343 | else |
344 | { |
345 | Results *begin,*end; |
346 | |
347 | /* Calculate the beginning of the route */ |
348 | |
349 | if(IsSuperNode(LookupNode(OSMNodes,start))) |
350 | { |
351 | Result *result; |
352 | |
353 | begin=NewResultsList(1); |
354 | |
355 | begin->start=start; |
356 | |
357 | result=InsertResult(begin,start); |
358 | |
359 | result->node=start; |
360 | result->prev=0; |
361 | result->next=0; |
362 | result->distance=0; |
363 | result->duration=0; |
364 | } |
365 | else |
366 | { |
367 | begin=FindStartRoutes(OSMNodes,OSMSegments,OSMWays,start,&profile); |
368 | |
369 | if(!begin) |
370 | { |
371 | fprintf(stderr,"Cannot find initial section of route compatible with profile.\n"); |
372 | return(1); |
373 | } |
374 | } |
375 | |
376 | if(FindResult(begin,finish)) |
377 | { |
378 | results[node]=begin; |
379 | |
380 | results[node]->finish=finish; |
381 | } |
382 | else |
383 | { |
384 | Results *superresults; |
385 | |
386 | /* Calculate the end of the route */ |
387 | |
388 | if(IsSuperNode(LookupNode(OSMNodes,finish))) |
389 | { |
390 | Result *result; |
391 | |
392 | end=NewResultsList(1); |
393 | |
394 | end->finish=finish; |
395 | |
396 | result=InsertResult(end,finish); |
397 | |
398 | result->node=finish; |
399 | result->prev=0; |
400 | result->next=0; |
401 | result->distance=0; |
402 | result->duration=0; |
403 | } |
404 | else |
405 | { |
406 | end=FindFinishRoutes(OSMNodes,OSMSegments,OSMWays,finish,&profile); |
407 | |
408 | if(!end) |
409 | { |
410 | fprintf(stderr,"Cannot find final section of route compatible with profile.\n"); |
411 | return(1); |
412 | } |
413 | } |
414 | |
415 | /* Calculate the middle of the route */ |
416 | |
417 | superresults=FindRoute3(OSMNodes,OSMSegments,OSMWays,begin,end,&profile); |
418 | |
419 | if(!superresults) |
420 | { |
421 | fprintf(stderr,"Cannot find route compatible with profile.\n"); |
422 | return(1); |
423 | } |
424 | |
425 | if(option_super) |
426 | results[node]=superresults; |
427 | else |
428 | results[node]=CombineRoutes(superresults,OSMNodes,OSMSegments,OSMWays,&profile); |
429 | } |
430 | } |
431 | } |
432 | |
433 | if(!option_no_output) |
434 | { |
435 | PrintRouteHead(FileName(dirname,prefix,"copyright.txt")); |
436 | |
437 | for(node=1;node<sizeof(point_used)/sizeof(point_used[0]);node++) |
438 | if(results[node]) |
439 | PrintRoute(results[node],OSMNodes,OSMSegments,OSMWays,&profile); |
440 | |
441 | PrintRouteTail(); |
442 | } |
443 | |
444 | return(0); |
445 | } |
Properties
Name | Value |
---|---|
cvs:description | Router. |