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