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