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