Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino
Annotation of /trunk/src/nodes.c
Parent Directory
|
Revision Log
Revision 706 -
(hide annotations)
(download)
(as text)
Sun May 8 16:39:44 2011 UTC (13 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 17372 byte(s)
Sun May 8 16:39:44 2011 UTC (13 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 17372 byte(s)
Ensure that the correct number of cached nodes, segments, ways or relations are initialised.
1 | amb | 2 | /*************************************** |
2 | Node data type functions. | ||
3 | amb | 151 | |
4 | Part of the Routino routing software. | ||
5 | amb | 2 | ******************/ /****************** |
6 | amb | 607 | This file Copyright 2008-2011 Andrew M. Bishop |
7 | amb | 2 | |
8 | amb | 151 | This program is free software: you can redistribute it and/or modify |
9 | it under the terms of the GNU Affero General Public License as published by | ||
10 | the Free Software Foundation, either version 3 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU Affero General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU Affero General Public License | ||
19 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | amb | 2 | ***************************************/ |
21 | |||
22 | |||
23 | amb | 214 | #include <sys/types.h> |
24 | amb | 2 | #include <stdlib.h> |
25 | amb | 118 | #include <math.h> |
26 | amb | 2 | |
27 | amb | 109 | #include "nodes.h" |
28 | amb | 114 | #include "segments.h" |
29 | amb | 179 | #include "ways.h" |
30 | amb | 2 | |
31 | amb | 449 | #include "files.h" |
32 | #include "profiles.h" | ||
33 | amb | 2 | |
34 | amb | 449 | |
35 | amb | 17 | /*++++++++++++++++++++++++++++++++++++++ |
36 | amb | 2 | Load in a node list from a file. |
37 | |||
38 | amb | 681 | Nodes *LoadNodeList Returns the node list. |
39 | amb | 17 | |
40 | amb | 2 | const char *filename The name of the file to load. |
41 | ++++++++++++++++++++++++++++++++++++++*/ | ||
42 | |||
43 | amb | 19 | Nodes *LoadNodeList(const char *filename) |
44 | amb | 2 | { |
45 | amb | 88 | Nodes *nodes; |
46 | amb | 706 | #if SLIM |
47 | int i; | ||
48 | #endif | ||
49 | amb | 88 | |
50 | nodes=(Nodes*)malloc(sizeof(Nodes)); | ||
51 | |||
52 | amb | 453 | #if !SLIM |
53 | amb | 88 | |
54 | amb | 453 | nodes->data=MapFile(filename); |
55 | amb | 88 | |
56 | amb | 453 | /* Copy the NodesFile header structure from the loaded data */ |
57 | amb | 88 | |
58 | amb | 453 | nodes->file=*((NodesFile*)nodes->data); |
59 | amb | 88 | |
60 | amb | 453 | /* Set the pointers in the Nodes structure. */ |
61 | amb | 88 | |
62 | amb | 453 | nodes->offsets=(index_t*)(nodes->data+sizeof(NodesFile)); |
63 | amb | 460 | nodes->nodes =(Node* )(nodes->data+sizeof(NodesFile)+(nodes->file.latbins*nodes->file.lonbins+1)*sizeof(index_t)); |
64 | amb | 453 | |
65 | #else | ||
66 | |||
67 | nodes->fd=ReOpenFile(filename); | ||
68 | |||
69 | /* Copy the NodesFile header structure from the loaded data */ | ||
70 | |||
71 | ReadFile(nodes->fd,&nodes->file,sizeof(NodesFile)); | ||
72 | |||
73 | nodes->nodesoffset=sizeof(NodesFile)+(nodes->file.latbins*nodes->file.lonbins+1)*sizeof(index_t); | ||
74 | |||
75 | amb | 706 | for(i=0;i<sizeof(nodes->cached)/sizeof(nodes->cached[0]);i++) |
76 | nodes->incache[i]=NO_NODE; | ||
77 | amb | 453 | |
78 | #endif | ||
79 | |||
80 | amb | 88 | return(nodes); |
81 | amb | 2 | } |
82 | |||
83 | |||
84 | /*++++++++++++++++++++++++++++++++++++++ | ||
85 | amb | 680 | Find the closest node given its latitude, longitude and optionally the profile |
86 | of the mode of transport that must be able to move to/from this node. | ||
87 | amb | 99 | |
88 | amb | 303 | index_t FindClosestNode Returns the closest node. |
89 | amb | 99 | |
90 | amb | 681 | Nodes *nodes The set of nodes to search. |
91 | amb | 99 | |
92 | amb | 179 | Segments *segments The set of segments to use. |
93 | |||
94 | Ways *ways The set of ways to use. | ||
95 | |||
96 | amb | 219 | double latitude The latitude to look for. |
97 | amb | 99 | |
98 | amb | 219 | double longitude The longitude to look for. |
99 | amb | 124 | |
100 | amb | 680 | distance_t distance The maximum distance to look from the specified coordinates. |
101 | amb | 179 | |
102 | amb | 303 | Profile *profile The profile of the mode of transport (or NULL). |
103 | |||
104 | distance_t *bestdist Returns the distance to the best node. | ||
105 | amb | 99 | ++++++++++++++++++++++++++++++++++++++*/ |
106 | |||
107 | amb | 681 | index_t FindClosestNode(Nodes *nodes,Segments *segments,Ways *ways,double latitude,double longitude, |
108 | amb | 303 | distance_t distance,Profile *profile,distance_t *bestdist) |
109 | amb | 99 | { |
110 | amb | 453 | ll_bin_t latbin=latlong_to_bin(radians_to_latlong(latitude ))-nodes->file.latzero; |
111 | ll_bin_t lonbin=latlong_to_bin(radians_to_latlong(longitude))-nodes->file.lonzero; | ||
112 | amb | 303 | int delta=0,count; |
113 | amb | 462 | index_t i,index1,index2; |
114 | index_t bestn=NO_NODE; | ||
115 | amb | 303 | distance_t bestd=INF_DISTANCE; |
116 | amb | 99 | |
117 | amb | 124 | /* Start with the bin containing the location, then spiral outwards. */ |
118 | amb | 118 | |
119 | amb | 124 | do |
120 | amb | 99 | { |
121 | amb | 124 | int latb,lonb,llbin; |
122 | amb | 99 | |
123 | amb | 124 | count=0; |
124 | amb | 453 | |
125 | amb | 124 | for(latb=latbin-delta;latb<=latbin+delta;latb++) |
126 | amb | 303 | { |
127 | amb | 453 | if(latb<0 || latb>=nodes->file.latbins) |
128 | amb | 303 | continue; |
129 | |||
130 | amb | 124 | for(lonb=lonbin-delta;lonb<=lonbin+delta;lonb++) |
131 | { | ||
132 | amb | 453 | if(lonb<0 || lonb>=nodes->file.lonbins) |
133 | amb | 303 | continue; |
134 | |||
135 | amb | 124 | if(abs(latb-latbin)<delta && abs(lonb-lonbin)<delta) |
136 | continue; | ||
137 | amb | 99 | |
138 | amb | 453 | llbin=lonb*nodes->file.latbins+latb; |
139 | amb | 124 | |
140 | amb | 303 | /* Check if this grid square has any hope of being close enough */ |
141 | amb | 124 | |
142 | if(delta>0) | ||
143 | { | ||
144 | amb | 453 | double lat1=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)); |
145 | double lon1=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)); | ||
146 | double lat2=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb+1)); | ||
147 | double lon2=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb+1)); | ||
148 | amb | 124 | |
149 | if(latb==latbin) | ||
150 | { | ||
151 | distance_t dist1=Distance(latitude,lon1,latitude,longitude); | ||
152 | distance_t dist2=Distance(latitude,lon2,latitude,longitude); | ||
153 | |||
154 | amb | 303 | if(dist1>distance && dist2>distance) |
155 | amb | 124 | continue; |
156 | } | ||
157 | else if(lonb==lonbin) | ||
158 | { | ||
159 | distance_t dist1=Distance(lat1,longitude,latitude,longitude); | ||
160 | distance_t dist2=Distance(lat2,longitude,latitude,longitude); | ||
161 | |||
162 | amb | 303 | if(dist1>distance && dist2>distance) |
163 | amb | 124 | continue; |
164 | } | ||
165 | else | ||
166 | { | ||
167 | distance_t dist1=Distance(lat1,lon1,latitude,longitude); | ||
168 | distance_t dist2=Distance(lat2,lon1,latitude,longitude); | ||
169 | distance_t dist3=Distance(lat2,lon2,latitude,longitude); | ||
170 | distance_t dist4=Distance(lat1,lon2,latitude,longitude); | ||
171 | |||
172 | amb | 303 | if(dist1>distance && dist2>distance && dist3>distance && dist4>distance) |
173 | amb | 124 | continue; |
174 | } | ||
175 | } | ||
176 | |||
177 | amb | 303 | /* Check every node in this grid square. */ |
178 | |||
179 | amb | 462 | index1=LookupNodeOffset(nodes,llbin); |
180 | index2=LookupNodeOffset(nodes,llbin+1); | ||
181 | |||
182 | for(i=index1;i<index2;i++) | ||
183 | amb | 124 | { |
184 | amb | 453 | Node *node=LookupNode(nodes,i,1); |
185 | double lat=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)+off_to_latlong(node->latoffset)); | ||
186 | double lon=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)+off_to_latlong(node->lonoffset)); | ||
187 | amb | 124 | |
188 | distance_t dist=Distance(lat,lon,latitude,longitude); | ||
189 | |||
190 | amb | 303 | if(dist<distance) |
191 | amb | 179 | { |
192 | if(profile) | ||
193 | { | ||
194 | Segment *segment; | ||
195 | |||
196 | /* Decide if this is node is valid for the profile */ | ||
197 | |||
198 | segment=FirstSegment(segments,nodes,i); | ||
199 | |||
200 | do | ||
201 | { | ||
202 | amb | 460 | Way *way=LookupWay(ways,segment->way,1); |
203 | amb | 179 | |
204 | if(way->allow&profile->allow) | ||
205 | break; | ||
206 | |||
207 | segment=NextSegment(segments,segment,i); | ||
208 | } | ||
209 | while(segment); | ||
210 | |||
211 | if(!segment) | ||
212 | continue; | ||
213 | } | ||
214 | |||
215 | amb | 303 | bestn=i; bestd=distance=dist; |
216 | amb | 179 | } |
217 | amb | 124 | } |
218 | |||
219 | count++; | ||
220 | } | ||
221 | amb | 303 | } |
222 | amb | 124 | |
223 | delta++; | ||
224 | amb | 99 | } |
225 | amb | 124 | while(count); |
226 | amb | 99 | |
227 | amb | 303 | *bestdist=bestd; |
228 | |||
229 | return(bestn); | ||
230 | amb | 99 | } |
231 | |||
232 | |||
233 | /*++++++++++++++++++++++++++++++++++++++ | ||
234 | amb | 680 | Find the closest point on the closest segment given its latitude, longitude |
235 | and optionally the profile of the mode of transport that must be able to move | ||
236 | along this segment. | ||
237 | amb | 303 | |
238 | amb | 459 | index_t FindClosestSegment Returns the closest segment index. |
239 | amb | 303 | |
240 | amb | 681 | Nodes *nodes The set of nodes to use. |
241 | amb | 303 | |
242 | amb | 680 | Segments *segments The set of segments to search. |
243 | amb | 303 | |
244 | Ways *ways The set of ways to use. | ||
245 | |||
246 | double latitude The latitude to look for. | ||
247 | |||
248 | double longitude The longitude to look for. | ||
249 | |||
250 | amb | 680 | distance_t distance The maximum distance to look from the specified coordinates. |
251 | amb | 303 | |
252 | Profile *profile The profile of the mode of transport (or NULL). | ||
253 | |||
254 | amb | 680 | distance_t *bestdist Returns the distance to the closest point on the best segment. |
255 | amb | 303 | |
256 | amb | 680 | index_t *bestnode1 Returns the index of the node at one end of the closest segment. |
257 | amb | 303 | |
258 | amb | 680 | index_t *bestnode2 Returns the index of the node at the other end of the closest segment. |
259 | amb | 303 | |
260 | amb | 680 | distance_t *bestdist1 Returns the distance along the segment to the node at one end. |
261 | amb | 303 | |
262 | amb | 680 | distance_t *bestdist2 Returns the distance along the segment to the node at the other end. |
263 | amb | 303 | ++++++++++++++++++++++++++++++++++++++*/ |
264 | |||
265 | amb | 681 | index_t FindClosestSegment(Nodes *nodes,Segments *segments,Ways *ways,double latitude,double longitude, |
266 | amb | 459 | distance_t distance,Profile *profile, distance_t *bestdist, |
267 | index_t *bestnode1,index_t *bestnode2,distance_t *bestdist1,distance_t *bestdist2) | ||
268 | amb | 303 | { |
269 | amb | 453 | ll_bin_t latbin=latlong_to_bin(radians_to_latlong(latitude ))-nodes->file.latzero; |
270 | ll_bin_t lonbin=latlong_to_bin(radians_to_latlong(longitude))-nodes->file.lonzero; | ||
271 | amb | 303 | int delta=0,count; |
272 | amb | 462 | index_t i,index1,index2; |
273 | index_t bestn1=NO_NODE,bestn2=NO_NODE; | ||
274 | amb | 303 | distance_t bestd=INF_DISTANCE,bestd1=INF_DISTANCE,bestd2=INF_DISTANCE; |
275 | amb | 459 | index_t bests=NO_SEGMENT; |
276 | amb | 303 | |
277 | /* Start with the bin containing the location, then spiral outwards. */ | ||
278 | |||
279 | do | ||
280 | { | ||
281 | int latb,lonb,llbin; | ||
282 | |||
283 | count=0; | ||
284 | amb | 453 | |
285 | amb | 303 | for(latb=latbin-delta;latb<=latbin+delta;latb++) |
286 | { | ||
287 | amb | 453 | if(latb<0 || latb>=nodes->file.latbins) |
288 | amb | 303 | continue; |
289 | |||
290 | for(lonb=lonbin-delta;lonb<=lonbin+delta;lonb++) | ||
291 | { | ||
292 | amb | 453 | if(lonb<0 || lonb>=nodes->file.lonbins) |
293 | amb | 303 | continue; |
294 | |||
295 | if(abs(latb-latbin)<delta && abs(lonb-lonbin)<delta) | ||
296 | continue; | ||
297 | |||
298 | amb | 453 | llbin=lonb*nodes->file.latbins+latb; |
299 | amb | 303 | |
300 | /* Check if this grid square has any hope of being close enough */ | ||
301 | |||
302 | if(delta>0) | ||
303 | { | ||
304 | amb | 453 | double lat1=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)); |
305 | double lon1=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)); | ||
306 | double lat2=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb+1)); | ||
307 | double lon2=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb+1)); | ||
308 | amb | 303 | |
309 | if(latb==latbin) | ||
310 | { | ||
311 | distance_t dist1=Distance(latitude,lon1,latitude,longitude); | ||
312 | distance_t dist2=Distance(latitude,lon2,latitude,longitude); | ||
313 | |||
314 | if(dist1>distance && dist2>distance) | ||
315 | continue; | ||
316 | } | ||
317 | else if(lonb==lonbin) | ||
318 | { | ||
319 | distance_t dist1=Distance(lat1,longitude,latitude,longitude); | ||
320 | distance_t dist2=Distance(lat2,longitude,latitude,longitude); | ||
321 | |||
322 | if(dist1>distance && dist2>distance) | ||
323 | continue; | ||
324 | } | ||
325 | else | ||
326 | { | ||
327 | distance_t dist1=Distance(lat1,lon1,latitude,longitude); | ||
328 | distance_t dist2=Distance(lat2,lon1,latitude,longitude); | ||
329 | distance_t dist3=Distance(lat2,lon2,latitude,longitude); | ||
330 | distance_t dist4=Distance(lat1,lon2,latitude,longitude); | ||
331 | |||
332 | if(dist1>distance && dist2>distance && dist3>distance && dist4>distance) | ||
333 | continue; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | /* Check every node in this grid square. */ | ||
338 | |||
339 | amb | 462 | index1=LookupNodeOffset(nodes,llbin); |
340 | index2=LookupNodeOffset(nodes,llbin+1); | ||
341 | |||
342 | for(i=index1;i<index2;i++) | ||
343 | amb | 303 | { |
344 | amb | 453 | Node *node=LookupNode(nodes,i,1); |
345 | double lat1=latlong_to_radians(bin_to_latlong(nodes->file.latzero+latb)+off_to_latlong(node->latoffset)); | ||
346 | double lon1=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonb)+off_to_latlong(node->lonoffset)); | ||
347 | amb | 408 | distance_t dist1; |
348 | amb | 303 | |
349 | dist1=Distance(lat1,lon1,latitude,longitude); | ||
350 | |||
351 | amb | 321 | if(dist1<distance) |
352 | { | ||
353 | Segment *segment; | ||
354 | amb | 303 | |
355 | amb | 321 | /* Check each segment for closeness and if valid for the profile */ |
356 | amb | 303 | |
357 | amb | 321 | segment=FirstSegment(segments,nodes,i); |
358 | |||
359 | do | ||
360 | amb | 303 | { |
361 | amb | 321 | if(IsNormalSegment(segment)) |
362 | { | ||
363 | Way *way=NULL; | ||
364 | amb | 303 | |
365 | amb | 321 | if(profile) |
366 | amb | 460 | way=LookupWay(ways,segment->way,1); |
367 | amb | 303 | |
368 | amb | 321 | if(!profile || way->allow&profile->allow) |
369 | { | ||
370 | amb | 408 | distance_t dist2,dist3; |
371 | double lat2,lon2,dist3a,dist3b,distp; | ||
372 | amb | 303 | |
373 | amb | 321 | GetLatLong(nodes,OtherNode(segment,i),&lat2,&lon2); |
374 | amb | 303 | |
375 | amb | 321 | dist2=Distance(lat2,lon2,latitude,longitude); |
376 | amb | 303 | |
377 | amb | 408 | dist3=Distance(lat1,lon1,lat2,lon2); |
378 | amb | 303 | |
379 | amb | 408 | /* Use law of cosines (assume flat Earth) */ |
380 | amb | 303 | |
381 | amb | 408 | dist3a=((double)dist1*(double)dist1-(double)dist2*(double)dist2+(double)dist3*(double)dist3)/(2.0*(double)dist3); |
382 | dist3b=(double)dist3-dist3a; | ||
383 | amb | 303 | |
384 | amb | 607 | if((dist1+dist2)<dist3) |
385 | { | ||
386 | distp=0; | ||
387 | } | ||
388 | else if(dist3a>=0 && dist3b>=0) | ||
389 | amb | 443 | distp=sqrt((double)dist1*(double)dist1-dist3a*dist3a); |
390 | else if(dist3a>0) | ||
391 | amb | 408 | { |
392 | amb | 443 | distp=dist2; |
393 | dist3a=dist3; | ||
394 | dist3b=0; | ||
395 | } | ||
396 | else /* if(dist3b>0) */ | ||
397 | { | ||
398 | distp=dist1; | ||
399 | dist3a=0; | ||
400 | dist3b=dist3; | ||
401 | } | ||
402 | amb | 321 | |
403 | amb | 443 | if(distp<(double)bestd) |
404 | { | ||
405 | amb | 459 | bests=IndexSegment(segments,segment); |
406 | amb | 534 | |
407 | if(segment->node1==i) | ||
408 | { | ||
409 | bestn1=i; | ||
410 | bestn2=OtherNode(segment,i); | ||
411 | bestd1=(distance_t)dist3a; | ||
412 | bestd2=(distance_t)dist3b; | ||
413 | } | ||
414 | else | ||
415 | { | ||
416 | bestn1=OtherNode(segment,i); | ||
417 | bestn2=i; | ||
418 | bestd1=(distance_t)dist3b; | ||
419 | bestd2=(distance_t)dist3a; | ||
420 | } | ||
421 | |||
422 | amb | 443 | bestd=(distance_t)distp; |
423 | amb | 408 | } |
424 | amb | 303 | } |
425 | } | ||
426 | amb | 321 | |
427 | segment=NextSegment(segments,segment,i); | ||
428 | amb | 303 | } |
429 | amb | 321 | while(segment); |
430 | amb | 303 | } |
431 | |||
432 | amb | 321 | } /* dist1 < distance */ |
433 | |||
434 | amb | 303 | count++; |
435 | } | ||
436 | } | ||
437 | |||
438 | delta++; | ||
439 | } | ||
440 | while(count); | ||
441 | |||
442 | *bestdist=bestd; | ||
443 | |||
444 | *bestnode1=bestn1; | ||
445 | *bestnode2=bestn2; | ||
446 | *bestdist1=bestd1; | ||
447 | *bestdist2=bestd2; | ||
448 | |||
449 | return(bests); | ||
450 | } | ||
451 | |||
452 | |||
453 | /*++++++++++++++++++++++++++++++++++++++ | ||
454 | amb | 99 | Get the latitude and longitude associated with a node. |
455 | |||
456 | amb | 680 | Nodes *nodes The set of nodes to use. |
457 | amb | 99 | |
458 | amb | 174 | index_t index The node index. |
459 | amb | 99 | |
460 | amb | 219 | double *latitude Returns the latitude. |
461 | amb | 99 | |
462 | amb | 219 | double *longitude Returns the logitude. |
463 | amb | 99 | ++++++++++++++++++++++++++++++++++++++*/ |
464 | |||
465 | amb | 219 | void GetLatLong(Nodes *nodes,index_t index,double *latitude,double *longitude) |
466 | amb | 99 | { |
467 | amb | 453 | Node *node=LookupNode(nodes,index,2); |
468 | amb | 99 | int latbin=-1,lonbin=-1; |
469 | int start,end,mid; | ||
470 | amb | 462 | index_t offset; |
471 | amb | 99 | |
472 | amb | 680 | /* Binary search - search key exact match only is required. |
473 | amb | 99 | * |
474 | * # <- start | Check mid and move start or end if it doesn't match | ||
475 | * # | | ||
476 | amb | 680 | * # | Since an exact match is wanted we can set end=mid-1 |
477 | * # <- mid | or start=mid+1 because we know that mid doesn't match. | ||
478 | amb | 99 | * # | |
479 | * # | Eventually either end=start or end=start+1 and one of | ||
480 | * # <- end | start or end is the wanted one. | ||
481 | */ | ||
482 | |||
483 | /* Search for longitude */ | ||
484 | |||
485 | start=0; | ||
486 | amb | 453 | end=nodes->file.lonbins-1; |
487 | amb | 99 | |
488 | do | ||
489 | { | ||
490 | amb | 462 | mid=(start+end)/2; /* Choose mid point */ |
491 | amb | 99 | |
492 | amb | 462 | offset=LookupNodeOffset(nodes,nodes->file.latbins*mid); |
493 | |||
494 | if(offset<index) /* Mid point is too low */ | ||
495 | amb | 99 | start=mid; |
496 | amb | 462 | else if(offset>index) /* Mid point is too high */ |
497 | amb | 99 | end=mid-1; |
498 | amb | 462 | else /* Mid point is correct */ |
499 | amb | 99 | {lonbin=mid;break;} |
500 | } | ||
501 | while((end-start)>1); | ||
502 | |||
503 | if(lonbin==-1) | ||
504 | { | ||
505 | amb | 462 | offset=LookupNodeOffset(nodes,nodes->file.latbins*end); |
506 | |||
507 | if(offset>index) | ||
508 | amb | 99 | lonbin=start; |
509 | else | ||
510 | lonbin=end; | ||
511 | } | ||
512 | |||
513 | amb | 462 | while(lonbin<nodes->file.lonbins && |
514 | LookupNodeOffset(nodes,lonbin*nodes->file.latbins)==LookupNodeOffset(nodes,(lonbin+1)*nodes->file.latbins)) | ||
515 | amb | 99 | lonbin++; |
516 | |||
517 | /* Search for latitude */ | ||
518 | |||
519 | start=0; | ||
520 | amb | 453 | end=nodes->file.latbins-1; |
521 | amb | 99 | |
522 | do | ||
523 | { | ||
524 | amb | 462 | mid=(start+end)/2; /* Choose mid point */ |
525 | amb | 99 | |
526 | amb | 462 | offset=LookupNodeOffset(nodes,lonbin*nodes->file.latbins+mid); |
527 | |||
528 | if(offset<index) /* Mid point is too low */ | ||
529 | amb | 99 | start=mid; |
530 | amb | 462 | else if(offset>index) /* Mid point is too high */ |
531 | amb | 99 | end=mid-1; |
532 | amb | 462 | else /* Mid point is correct */ |
533 | amb | 99 | {latbin=mid;break;} |
534 | } | ||
535 | while((end-start)>1); | ||
536 | |||
537 | if(latbin==-1) | ||
538 | { | ||
539 | amb | 462 | offset=LookupNodeOffset(nodes,lonbin*nodes->file.latbins+end); |
540 | |||
541 | if(offset>index) | ||
542 | amb | 99 | latbin=start; |
543 | else | ||
544 | latbin=end; | ||
545 | } | ||
546 | |||
547 | amb | 462 | while(latbin<nodes->file.latbins && |
548 | LookupNodeOffset(nodes,lonbin*nodes->file.latbins+latbin)==LookupNodeOffset(nodes,lonbin*nodes->file.latbins+latbin+1)) | ||
549 | amb | 99 | latbin++; |
550 | |||
551 | /* Return the values */ | ||
552 | |||
553 | amb | 453 | *latitude =latlong_to_radians(bin_to_latlong(nodes->file.latzero+latbin)+off_to_latlong(node->latoffset)); |
554 | *longitude=latlong_to_radians(bin_to_latlong(nodes->file.lonzero+lonbin)+off_to_latlong(node->lonoffset)); | ||
555 | amb | 99 | } |
Properties
Name | Value |
---|---|
cvs:description | Node data type. |