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