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