Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/router.c
Parent Directory
|
Revision Log
Revision 324 -
(hide annotations)
(download)
(as text)
Thu Mar 18 18:59:20 2010 UTC (15 years ago) by amb
File MIME type: text/x-csrc
File size: 18809 byte(s)
Thu Mar 18 18:59:20 2010 UTC (15 years ago) by amb
File MIME type: text/x-csrc
File size: 18809 byte(s)
Allow selection of which outputs are to be created.
1 | amb | 2 | /*************************************** |
2 | amb | 324 | $Header: /home/amb/CVS/routino/src/router.c,v 1.69 2010-03-18 18:59:20 amb Exp $ |
3 | amb | 2 | |
4 | OSM router. | ||
5 | amb | 151 | |
6 | Part of the Routino routing software. | ||
7 | amb | 2 | ******************/ /****************** |
8 | amb | 324 | This file Copyright 2008-2010 Andrew M. Bishop |
9 | amb | 2 | |
10 | amb | 151 | 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 | amb | 2 | ***************************************/ |
23 | |||
24 | |||
25 | #include <stdio.h> | ||
26 | amb | 31 | #include <string.h> |
27 | amb | 2 | #include <stdlib.h> |
28 | amb | 130 | #include <ctype.h> |
29 | amb | 2 | |
30 | amb | 96 | #include "types.h" |
31 | amb | 2 | #include "functions.h" |
32 | amb | 82 | #include "profiles.h" |
33 | amb | 115 | #include "nodes.h" |
34 | #include "segments.h" | ||
35 | amb | 109 | #include "ways.h" |
36 | amb | 2 | |
37 | |||
38 | amb | 242 | /*+ The number of waypoints allowed to be specified. +*/ |
39 | #define NWAYPOINTS 99 | ||
40 | |||
41 | amb | 303 | /*+ The maximum distance from the specified point to search for a node or segment (in km). +*/ |
42 | amb | 321 | #define MAXSEARCH 1 |
43 | amb | 242 | |
44 | amb | 303 | /*+ 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 | amb | 113 | /*+ The option not to print any progress information. +*/ |
55 | amb | 107 | int option_quiet=0; |
56 | |||
57 | amb | 324 | /*+ 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 | amb | 113 | /*+ The option to calculate the quickest route insted of the shortest. +*/ |
61 | int option_quickest=0; | ||
62 | amb | 107 | |
63 | amb | 113 | |
64 | amb | 2 | int main(int argc,char** argv) |
65 | { | ||
66 | amb | 95 | Nodes *OSMNodes; |
67 | Segments *OSMSegments; | ||
68 | Ways *OSMWays; | ||
69 | amb | 242 | Results *results[NWAYPOINTS+1]={NULL}; |
70 | int point_used[NWAYPOINTS+1]={0}; | ||
71 | amb | 165 | int help_profile=0,help_profile_js=0,help_profile_pl=0; |
72 | amb | 95 | char *dirname=NULL,*prefix=NULL,*filename; |
73 | amb | 315 | int exactnodes=0; |
74 | amb | 82 | Transport transport=Transport_None; |
75 | Profile profile; | ||
76 | amb | 176 | index_t start=NO_NODE,finish=NO_NODE; |
77 | amb | 303 | int arg,point; |
78 | amb | 2 | |
79 | amb | 44 | /* Parse the command line arguments */ |
80 | amb | 2 | |
81 | amb | 145 | if(argc<2) |
82 | amb | 2 | { |
83 | amb | 44 | usage: |
84 | amb | 75 | |
85 | amb | 324 | fprintf(stderr,"Usage: router [--help | --help-profile | --help-profile-js | --help-profile-pl]\n" |
86 | amb | 101 | " [--dir=<name>] [--prefix=<name>]\n" |
87 | amb | 315 | " [--exact-nodes-only]\n" |
88 | amb | 239 | " [--quiet]\n" |
89 | amb | 324 | " [--output-html]\n" |
90 | " [--output-gpx-track | --output-gpx-route]\n" | ||
91 | " [--output-text | --output-text-all]\n" | ||
92 | " --lon1=<longitude> --lat1=<latitude>\n" | ||
93 | " --lon2=<longitude> --lon2=<latitude>\n" | ||
94 | " [ ... --lon99=<longitude> --lon99=<latitude>]\n" | ||
95 | amb | 101 | " [--transport=<transport>]\n" |
96 | amb | 166 | " [--highway-<highway>=<preference> ...]\n" |
97 | amb | 101 | " [--speed-<highway>=<speed> ...]\n" |
98 | amb | 298 | " [--property-<property>=<preference> ...]\n" |
99 | amb | 130 | " [--oneway=[0|1]]\n" |
100 | amb | 135 | " [--weight=<weight>]\n" |
101 | " [--height=<height>] [--width=<width>] [--length=<length>]\n" | ||
102 | amb | 324 | " [--shortest | --quickest]\n" |
103 | amb | 75 | "\n" |
104 | amb | 82 | "<transport> defaults to motorcar but can be set to:\n" |
105 | amb | 75 | "%s" |
106 | "\n" | ||
107 | amb | 82 | "<highway> can be selected from:\n" |
108 | "%s" | ||
109 | amb | 103 | "\n" |
110 | amb | 298 | "<property> can be selected from:\n" |
111 | "%s" | ||
112 | "\n" | ||
113 | amb | 166 | "<preference> is a preference expressed as a percentage\n" |
114 | amb | 82 | "<speed> is a speed in km/hour\n" |
115 | amb | 135 | "<weight> is a weight in tonnes\n" |
116 | "<height>, <width>, <length> are dimensions in metres\n" | ||
117 | amb | 82 | "\n", |
118 | amb | 298 | TransportList(),HighwayList(),PropertyList()); |
119 | amb | 75 | |
120 | amb | 2 | return(1); |
121 | } | ||
122 | |||
123 | amb | 130 | /* Get the transport type if specified and fill in the default profile */ |
124 | amb | 75 | |
125 | amb | 165 | for(arg=1;arg<argc;arg++) |
126 | if(!strncmp(argv[arg],"--transport=",12)) | ||
127 | amb | 82 | { |
128 | amb | 165 | transport=TransportType(&argv[arg][12]); |
129 | amb | 75 | |
130 | amb | 82 | if(transport==Transport_None) |
131 | goto usage; | ||
132 | } | ||
133 | |||
134 | if(transport==Transport_None) | ||
135 | transport=Transport_Motorcar; | ||
136 | |||
137 | profile=*GetProfile(transport); | ||
138 | |||
139 | /* Parse the other command line arguments */ | ||
140 | |||
141 | amb | 165 | for(arg=1;arg<argc;arg++) |
142 | amb | 44 | { |
143 | amb | 324 | if(!strcmp(argv[arg],"--help")) |
144 | goto usage; | ||
145 | else if(!strcmp(argv[arg],"--help-profile")) | ||
146 | help_profile=1; | ||
147 | else if(!strcmp(argv[arg],"--help-profile-js")) | ||
148 | help_profile_js=1; | ||
149 | else if(!strcmp(argv[arg],"--help-profile-pl")) | ||
150 | help_profile_pl=1; | ||
151 | else if(!strncmp(argv[arg],"--dir=",6)) | ||
152 | dirname=&argv[arg][6]; | ||
153 | else if(!strncmp(argv[arg],"--prefix=",9)) | ||
154 | prefix=&argv[arg][9]; | ||
155 | else if(!strcmp(argv[arg],"--exact-nodes-only")) | ||
156 | exactnodes=1; | ||
157 | else if(!strcmp(argv[arg],"--quiet")) | ||
158 | option_quiet=1; | ||
159 | else if(!strcmp(argv[arg],"--output-html")) | ||
160 | option_html=1; | ||
161 | else if(!strcmp(argv[arg],"--output-gpx-track")) | ||
162 | option_gpx_track=1; | ||
163 | else if(!strcmp(argv[arg],"--output-gpx-route")) | ||
164 | option_gpx_route=1; | ||
165 | else if(!strcmp(argv[arg],"--output-text")) | ||
166 | option_text=1; | ||
167 | else if(!strcmp(argv[arg],"--output-text-all")) | ||
168 | option_text_all=1; | ||
169 | else if(isdigit(argv[arg][0]) || | ||
170 | amb | 165 | ((argv[arg][0]=='-' || argv[arg][0]=='+') && isdigit(argv[arg][1]))) |
171 | amb | 130 | { |
172 | amb | 303 | for(point=1;point<=NWAYPOINTS;point++) |
173 | if(point_used[point]!=3) | ||
174 | amb | 165 | { |
175 | amb | 303 | if(point_used[point]==0) |
176 | amb | 165 | { |
177 | amb | 303 | point_lon[point]=degrees_to_radians(atof(argv[arg])); |
178 | point_used[point]=1; | ||
179 | amb | 165 | } |
180 | amb | 303 | else /* if(point_used[point]==1) */ |
181 | amb | 165 | { |
182 | amb | 303 | point_lat[point]=degrees_to_radians(atof(argv[arg])); |
183 | point_used[point]=3; | ||
184 | amb | 165 | } |
185 | break; | ||
186 | } | ||
187 | } | ||
188 | amb | 242 | else if(!strncmp(argv[arg],"--lon",5) && isdigit(argv[arg][5])) |
189 | { | ||
190 | char *p=&argv[arg][6]; | ||
191 | while(isdigit(*p)) p++; | ||
192 | if(*p++!='=') | ||
193 | goto usage; | ||
194 | |||
195 | amb | 303 | point=atoi(&argv[arg][5]); |
196 | if(point>NWAYPOINTS || point_used[point]&1) | ||
197 | amb | 242 | goto usage; |
198 | |||
199 | amb | 303 | point_lon[point]=degrees_to_radians(atof(p)); |
200 | point_used[point]+=1; | ||
201 | amb | 130 | } |
202 | amb | 242 | else if(!strncmp(argv[arg],"--lat",5) && isdigit(argv[arg][5])) |
203 | { | ||
204 | char *p=&argv[arg][6]; | ||
205 | while(isdigit(*p)) p++; | ||
206 | if(*p++!='=') | ||
207 | goto usage; | ||
208 | |||
209 | amb | 303 | point=atoi(&argv[arg][5]); |
210 | if(point>NWAYPOINTS || point_used[point]&2) | ||
211 | amb | 242 | goto usage; |
212 | |||
213 | amb | 303 | point_lat[point]=degrees_to_radians(atof(p)); |
214 | point_used[point]+=2; | ||
215 | amb | 165 | } |
216 | else if(!strncmp(argv[arg],"--transport=",12)) | ||
217 | amb | 324 | ; /* Done this already */ |
218 | amb | 165 | else if(!strncmp(argv[arg],"--highway-",10)) |
219 | amb | 75 | { |
220 | amb | 130 | Highway highway; |
221 | amb | 165 | char *equal=strchr(argv[arg],'='); |
222 | amb | 130 | char *string; |
223 | amb | 82 | |
224 | amb | 130 | if(!equal) |
225 | goto usage; | ||
226 | |||
227 | amb | 165 | string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+10); |
228 | string[equal-argv[arg]-10]=0; | ||
229 | amb | 130 | |
230 | highway=HighwayType(string); | ||
231 | |||
232 | amb | 300 | if(highway==Way_Count) |
233 | amb | 82 | goto usage; |
234 | |||
235 | amb | 166 | profile.highway[highway]=atof(equal+1); |
236 | amb | 298 | |
237 | free(string); | ||
238 | amb | 75 | } |
239 | amb | 165 | else if(!strncmp(argv[arg],"--speed-",8)) |
240 | amb | 82 | { |
241 | Highway highway; | ||
242 | amb | 165 | char *equal=strchr(argv[arg],'='); |
243 | amb | 82 | char *string; |
244 | |||
245 | if(!equal) | ||
246 | goto usage; | ||
247 | |||
248 | amb | 165 | string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+8); |
249 | string[equal-argv[arg]-8]=0; | ||
250 | amb | 82 | |
251 | highway=HighwayType(string); | ||
252 | |||
253 | amb | 300 | if(highway==Way_Count) |
254 | amb | 82 | goto usage; |
255 | |||
256 | amb | 166 | profile.speed[highway]=kph_to_speed(atof(equal+1)); |
257 | amb | 298 | |
258 | free(string); | ||
259 | amb | 82 | } |
260 | amb | 298 | else if(!strncmp(argv[arg],"--property-",11)) |
261 | { | ||
262 | Property property; | ||
263 | char *equal=strchr(argv[arg],'='); | ||
264 | char *string; | ||
265 | |||
266 | if(!equal) | ||
267 | goto usage; | ||
268 | |||
269 | string=strcpy((char*)malloc(strlen(argv[arg])),argv[arg]+11); | ||
270 | string[equal-argv[arg]-11]=0; | ||
271 | |||
272 | property=PropertyType(string); | ||
273 | |||
274 | amb | 300 | if(property==Way_Count) |
275 | amb | 298 | goto usage; |
276 | |||
277 | profile.props_yes[property]=atof(equal+1); | ||
278 | |||
279 | free(string); | ||
280 | } | ||
281 | amb | 165 | else if(!strncmp(argv[arg],"--oneway=",9)) |
282 | amb | 166 | profile.oneway=!!atoi(&argv[arg][9]); |
283 | amb | 165 | else if(!strncmp(argv[arg],"--weight=",9)) |
284 | profile.weight=tonnes_to_weight(atof(&argv[arg][9])); | ||
285 | else if(!strncmp(argv[arg],"--height=",9)) | ||
286 | profile.height=metres_to_height(atof(&argv[arg][9])); | ||
287 | else if(!strncmp(argv[arg],"--width=",8)) | ||
288 | profile.width=metres_to_width(atof(&argv[arg][8])); | ||
289 | else if(!strncmp(argv[arg],"--length=",9)) | ||
290 | profile.length=metres_to_length(atof(&argv[arg][9])); | ||
291 | amb | 324 | else if(!strcmp(argv[arg],"--shortest")) |
292 | option_quickest=0; | ||
293 | else if(!strcmp(argv[arg],"--quickest")) | ||
294 | option_quickest=1; | ||
295 | amb | 44 | else |
296 | goto usage; | ||
297 | } | ||
298 | |||
299 | amb | 303 | for(point=1;point<=NWAYPOINTS;point++) |
300 | if(point_used[point]==1 || point_used[point]==2) | ||
301 | amb | 165 | goto usage; |
302 | |||
303 | amb | 82 | if(help_profile) |
304 | { | ||
305 | PrintProfile(&profile); | ||
306 | |||
307 | return(0); | ||
308 | } | ||
309 | amb | 129 | else if(help_profile_js) |
310 | { | ||
311 | PrintProfilesJS(); | ||
312 | amb | 82 | |
313 | amb | 129 | return(0); |
314 | } | ||
315 | amb | 145 | else if(help_profile_pl) |
316 | { | ||
317 | PrintProfilesPerl(); | ||
318 | amb | 129 | |
319 | amb | 145 | return(0); |
320 | } | ||
321 | |||
322 | amb | 166 | UpdateProfile(&profile); |
323 | |||
324 | amb | 2 | /* Load in the data */ |
325 | |||
326 | amb | 162 | OSMNodes=LoadNodeList(filename=FileName(dirname,prefix,"nodes.mem")); |
327 | amb | 95 | |
328 | amb | 100 | if(!OSMNodes) |
329 | { | ||
330 | amb | 227 | fprintf(stderr,"Error: Cannot open nodes file '%s'.\n",filename); |
331 | amb | 100 | return(1); |
332 | } | ||
333 | |||
334 | amb | 162 | OSMSegments=LoadSegmentList(filename=FileName(dirname,prefix,"segments.mem")); |
335 | amb | 66 | |
336 | amb | 100 | if(!OSMSegments) |
337 | { | ||
338 | amb | 227 | fprintf(stderr,"Error: Cannot open segments file '%s'.\n",filename); |
339 | amb | 100 | return(1); |
340 | } | ||
341 | |||
342 | amb | 162 | OSMWays=LoadWayList(filename=FileName(dirname,prefix,"ways.mem")); |
343 | amb | 31 | |
344 | amb | 100 | if(!OSMWays) |
345 | { | ||
346 | amb | 227 | fprintf(stderr,"Error: Cannot open ways file '%s'.\n",filename); |
347 | amb | 100 | return(1); |
348 | } | ||
349 | |||
350 | amb | 307 | if(!(profile.allow & OSMWays->allow)) |
351 | { | ||
352 | fprintf(stderr,"Error: Database was not generated for selected transport.\n"); | ||
353 | return(1); | ||
354 | } | ||
355 | |||
356 | amb | 324 | if(option_html==0 && option_gpx_track==0 && option_gpx_route==0 && option_text==0 && option_text_all==0) |
357 | option_html=option_gpx_track=option_gpx_route=option_text=option_text_all=1; | ||
358 | |||
359 | amb | 303 | /* Loop through all pairs of points */ |
360 | amb | 99 | |
361 | amb | 303 | for(point=1;point<=NWAYPOINTS;point++) |
362 | amb | 107 | { |
363 | amb | 239 | Results *begin,*end; |
364 | amb | 315 | distance_t distmax=km_to_distance(MAXSEARCH); |
365 | distance_t distmin; | ||
366 | Segment *segment=NULL; | ||
367 | amb | 303 | index_t node1,node2; |
368 | amb | 99 | |
369 | amb | 303 | if(point_used[point]!=3) |
370 | amb | 165 | continue; |
371 | amb | 107 | |
372 | amb | 303 | /* Find the closest point */ |
373 | amb | 107 | |
374 | amb | 174 | start=finish; |
375 | amb | 165 | |
376 | amb | 315 | if(exactnodes) |
377 | { | ||
378 | finish=FindClosestNode(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,&profile,&distmin); | ||
379 | } | ||
380 | else | ||
381 | { | ||
382 | distance_t dist1,dist2; | ||
383 | amb | 165 | |
384 | amb | 315 | segment=FindClosestSegment(OSMNodes,OSMSegments,OSMWays,point_lat[point],point_lon[point],distmax,&profile,&distmin,&node1,&node2,&dist1,&dist2); |
385 | amb | 303 | |
386 | amb | 315 | finish=CreateFakes(OSMNodes,point,segment,node1,node2,dist1,dist2); |
387 | } | ||
388 | amb | 303 | |
389 | amb | 176 | if(finish==NO_NODE) |
390 | amb | 107 | { |
391 | amb | 303 | fprintf(stderr,"Error: Cannot find node close to specified point %d.\n",point); |
392 | amb | 107 | return(1); |
393 | } | ||
394 | |||
395 | if(!option_quiet) | ||
396 | { | ||
397 | amb | 219 | double lat,lon; |
398 | amb | 107 | |
399 | amb | 303 | if(IsFakeNode(finish)) |
400 | GetFakeLatLong(finish,&lat,&lon); | ||
401 | else | ||
402 | GetLatLong(OSMNodes,finish,&lat,&lon); | ||
403 | amb | 107 | |
404 | amb | 303 | if(IsFakeNode(finish)) |
405 | printf("Point %d is segment %d (node %d -> %d): %3.6f %4.6f = %2.3f km\n",point,IndexSegment(OSMSegments,segment),node1,node2, | ||
406 | amb | 315 | radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin)); |
407 | amb | 303 | else |
408 | printf("Point %d is node %d: %3.6f %4.6f = %2.3f km\n",point,finish, | ||
409 | amb | 315 | radians_to_degrees(lon),radians_to_degrees(lat),distance_to_km(distmin)); |
410 | amb | 107 | } |
411 | |||
412 | amb | 176 | if(start==NO_NODE) |
413 | amb | 165 | continue; |
414 | |||
415 | amb | 239 | /* Calculate the beginning of the route */ |
416 | amb | 165 | |
417 | amb | 303 | if(!IsFakeNode(start) && IsSuperNode(OSMNodes,start)) |
418 | amb | 126 | { |
419 | amb | 239 | Result *result; |
420 | amb | 107 | |
421 | amb | 239 | begin=NewResultsList(1); |
422 | amb | 97 | |
423 | amb | 239 | begin->start=start; |
424 | |||
425 | result=InsertResult(begin,start); | ||
426 | |||
427 | ZeroResult(result); | ||
428 | } | ||
429 | else | ||
430 | amb | 77 | { |
431 | amb | 239 | begin=FindStartRoutes(OSMNodes,OSMSegments,OSMWays,start,&profile); |
432 | amb | 2 | |
433 | amb | 239 | if(!begin) |
434 | amb | 112 | { |
435 | amb | 239 | fprintf(stderr,"Error: Cannot find initial section of route compatible with profile.\n"); |
436 | amb | 112 | return(1); |
437 | } | ||
438 | } | ||
439 | amb | 239 | |
440 | if(FindResult(begin,finish)) | ||
441 | { | ||
442 | amb | 290 | FixForwardRoute(begin,finish); |
443 | |||
444 | amb | 303 | results[point]=begin; |
445 | amb | 305 | |
446 | if(!option_quiet) | ||
447 | { | ||
448 | printf("\rRouted: Super-Nodes Checked = %d\n",begin->number); | ||
449 | fflush(stdout); | ||
450 | } | ||
451 | amb | 239 | } |
452 | amb | 34 | else |
453 | { | ||
454 | amb | 239 | Results *superresults; |
455 | amb | 48 | |
456 | amb | 239 | /* Calculate the end of the route */ |
457 | amb | 34 | |
458 | amb | 303 | if(!IsFakeNode(finish) && IsSuperNode(OSMNodes,finish)) |
459 | amb | 34 | { |
460 | Result *result; | ||
461 | |||
462 | amb | 239 | end=NewResultsList(1); |
463 | amb | 34 | |
464 | amb | 239 | end->finish=finish; |
465 | amb | 34 | |
466 | amb | 239 | result=InsertResult(end,finish); |
467 | amb | 165 | |
468 | amb | 166 | ZeroResult(result); |
469 | amb | 34 | } |
470 | else | ||
471 | amb | 112 | { |
472 | amb | 239 | end=FindFinishRoutes(OSMNodes,OSMSegments,OSMWays,finish,&profile); |
473 | amb | 34 | |
474 | amb | 239 | if(!end) |
475 | amb | 112 | { |
476 | amb | 239 | fprintf(stderr,"Error: Cannot find final section of route compatible with profile.\n"); |
477 | amb | 112 | return(1); |
478 | } | ||
479 | } | ||
480 | |||
481 | amb | 239 | /* Calculate the middle of the route */ |
482 | |||
483 | superresults=FindMiddleRoute(OSMNodes,OSMSegments,OSMWays,begin,end,&profile); | ||
484 | |||
485 | amb | 317 | FreeResultsList(begin); |
486 | FreeResultsList(end); | ||
487 | |||
488 | amb | 239 | if(!superresults) |
489 | amb | 165 | { |
490 | amb | 239 | fprintf(stderr,"Error: Cannot find route compatible with profile.\n"); |
491 | return(1); | ||
492 | amb | 165 | } |
493 | amb | 34 | |
494 | amb | 303 | results[point]=CombineRoutes(superresults,OSMNodes,OSMSegments,OSMWays,&profile); |
495 | amb | 317 | |
496 | FreeResultsList(superresults); | ||
497 | amb | 34 | } |
498 | amb | 31 | } |
499 | |||
500 | amb | 239 | /* Print out the combined route */ |
501 | amb | 164 | |
502 | amb | 239 | PrintRouteHead(FileName(dirname,prefix,"copyright.txt")); |
503 | amb | 164 | |
504 | amb | 317 | PrintRoute(results,NWAYPOINTS,OSMNodes,OSMSegments,OSMWays,&profile); |
505 | amb | 164 | |
506 | amb | 239 | PrintRouteTail(); |
507 | |||
508 | amb | 2 | return(0); |
509 | } | ||
510 | amb | 303 | |
511 | |||
512 | /*++++++++++++++++++++++++++++++++++++++ | ||
513 | Create a pair of fake segments corresponding to the given segment split in two. | ||
514 | |||
515 | index_t CreateFakes Returns the fake node index (or a real one in special cases). | ||
516 | |||
517 | Nodes *nodes The set of nodes to use. | ||
518 | |||
519 | int point Which of the waypoints is this. | ||
520 | |||
521 | Segment *segment The segment to split. | ||
522 | |||
523 | index_t node1 The first node at the end of this segment. | ||
524 | |||
525 | index_t node2 The second node at the end of this segment. | ||
526 | |||
527 | distance_t dist1 The distance to the first node. | ||
528 | |||
529 | distance_t dist2 The distance to the second node. | ||
530 | ++++++++++++++++++++++++++++++++++++++*/ | ||
531 | |||
532 | index_t CreateFakes(Nodes *nodes,int point,Segment *segment,index_t node1,index_t node2,distance_t dist1,distance_t dist2) | ||
533 | { | ||
534 | index_t fakenode; | ||
535 | double lat1,lon1,lat2,lon2; | ||
536 | |||
537 | /* Check if we are actually close enough to an existing node */ | ||
538 | |||
539 | if(dist1<km_to_distance(MINSEGMENT) && dist2>km_to_distance(MINSEGMENT)) | ||
540 | return(node1); | ||
541 | |||
542 | if(dist2<km_to_distance(MINSEGMENT) && dist1>km_to_distance(MINSEGMENT)) | ||
543 | return(node2); | ||
544 | |||
545 | if(dist1<km_to_distance(MINSEGMENT) && dist2<km_to_distance(MINSEGMENT)) | ||
546 | { | ||
547 | if(dist1<dist2) | ||
548 | return(node1); | ||
549 | else | ||
550 | return(node2); | ||
551 | } | ||
552 | |||
553 | /* Create the fake node */ | ||
554 | |||
555 | fakenode=point|NODE_SUPER; | ||
556 | |||
557 | GetLatLong(nodes,node1,&lat1,&lon1); | ||
558 | GetLatLong(nodes,node2,&lat2,&lon2); | ||
559 | |||
560 | if(lat1>3 && lat2<-3) | ||
561 | lat2+=2*M_PI; | ||
562 | else if(lat1<-3 && lat2>3) | ||
563 | lat1+=2*M_PI; | ||
564 | |||
565 | point_lat[point]=lat1+(lat2-lat1)*(double)dist1/(double)(dist1+dist2); | ||
566 | point_lon[point]=lon1+(lon2-lon1)*(double)dist1/(double)(dist1+dist2); | ||
567 | |||
568 | if(point_lat[point]>M_PI) point_lat[point]-=2*M_PI; | ||
569 | |||
570 | /* Create the first fake segment */ | ||
571 | |||
572 | fake_segments[2*point-2]=*segment; | ||
573 | |||
574 | if(segment->node1==node1) | ||
575 | fake_segments[2*point-2].node1=fakenode; | ||
576 | else | ||
577 | fake_segments[2*point-2].node2=fakenode; | ||
578 | |||
579 | fake_segments[2*point-2].distance=DISTANCE(dist1)|DISTFLAG(segment->distance); | ||
580 | |||
581 | /* Create the second fake segment */ | ||
582 | |||
583 | fake_segments[2*point-1]=*segment; | ||
584 | |||
585 | if(segment->node1==node2) | ||
586 | fake_segments[2*point-1].node1=fakenode; | ||
587 | else | ||
588 | fake_segments[2*point-1].node2=fakenode; | ||
589 | |||
590 | fake_segments[2*point-1].distance=DISTANCE(dist2)|DISTFLAG(segment->distance); | ||
591 | |||
592 | return(fakenode); | ||
593 | } | ||
594 | |||
595 | |||
596 | /*++++++++++++++++++++++++++++++++++++++ | ||
597 | Lookup the latitude and longitude of a fake node. | ||
598 | |||
599 | index_t fakenode The node to lookup. | ||
600 | |||
601 | double *latitude Returns the latitude | ||
602 | |||
603 | double *longitude Returns the longitude. | ||
604 | ++++++++++++++++++++++++++++++++++++++*/ | ||
605 | |||
606 | void GetFakeLatLong(index_t fakenode, double *latitude,double *longitude) | ||
607 | { | ||
608 | index_t realnode=fakenode&(~NODE_SUPER); | ||
609 | |||
610 | *latitude =point_lat[realnode]; | ||
611 | *longitude=point_lon[realnode]; | ||
612 | } | ||
613 | |||
614 | |||
615 | /*++++++++++++++++++++++++++++++++++++++ | ||
616 | Finds the first fake segment associated to a fake node. | ||
617 | |||
618 | Segment *FirstFakeSegment Returns the first fake segment. | ||
619 | |||
620 | index_t fakenode The node to lookup. | ||
621 | ++++++++++++++++++++++++++++++++++++++*/ | ||
622 | |||
623 | Segment *FirstFakeSegment(index_t fakenode) | ||
624 | { | ||
625 | index_t realnode=fakenode&(~NODE_SUPER); | ||
626 | |||
627 | return(&fake_segments[2*realnode-2]); | ||
628 | } | ||
629 | |||
630 | |||
631 | /*++++++++++++++++++++++++++++++++++++++ | ||
632 | Finds the next (there can only be two) fake segment associated to a fake node. | ||
633 | |||
634 | Segment *NextFakeSegment Returns the second fake segment. | ||
635 | |||
636 | Segment *segment The first fake segment. | ||
637 | |||
638 | index_t fakenode The node to lookup. | ||
639 | ++++++++++++++++++++++++++++++++++++++*/ | ||
640 | |||
641 | Segment *NextFakeSegment(Segment *segment,index_t fakenode) | ||
642 | { | ||
643 | index_t realnode=fakenode&(~NODE_SUPER); | ||
644 | |||
645 | if(segment==&fake_segments[2*realnode-2]) | ||
646 | return(&fake_segments[2*realnode-1]); | ||
647 | else | ||
648 | return(NULL); | ||
649 | } | ||
650 | |||
651 | |||
652 | /*++++++++++++++++++++++++++++++++++++++ | ||
653 | Finds the next (there can only be two) fake segment associated to a fake node. | ||
654 | |||
655 | Segment *ExtraFakeSegment Returns a segment between the two specified nodes if it exists. | ||
656 | |||
657 | index_t node The real node. | ||
658 | |||
659 | index_t fakenode The fake node to lookup. | ||
660 | ++++++++++++++++++++++++++++++++++++++*/ | ||
661 | |||
662 | Segment *ExtraFakeSegment(index_t node,index_t fakenode) | ||
663 | { | ||
664 | index_t realnode=fakenode&(~NODE_SUPER); | ||
665 | |||
666 | if(fake_segments[2*realnode-2].node1==node || fake_segments[2*realnode-2].node2==node) | ||
667 | amb | 304 | return(&fake_segments[2*realnode-2]); |
668 | amb | 303 | |
669 | if(fake_segments[2*realnode-1].node1==node || fake_segments[2*realnode-1].node2==node) | ||
670 | return(&fake_segments[2*realnode-1]); | ||
671 | |||
672 | return(NULL); | ||
673 | } |
Properties
Name | Value |
---|---|
cvs:description | Router. |