Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /trunk/src/nodes.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 214 - (show annotations) (download) (as text)
Thu Jul 2 17:49:16 2009 UTC (15 years, 9 months ago) by amb
File MIME type: text/x-csrc
File size: 8440 byte(s)
Fix some gcc pedantic warnings.

1 /***************************************
2 $Header: /home/amb/CVS/routino/src/nodes.c,v 1.31 2009-07-02 17:49:16 amb Exp $
3
4 Node data type functions.
5
6 Part of the Routino routing software.
7 ******************/ /******************
8 This file Copyright 2008,2009 Andrew M. Bishop
9
10 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 ***************************************/
23
24
25 #include <sys/types.h>
26 #include <stdlib.h>
27 #include <math.h>
28
29 #include "profiles.h"
30 #include "nodes.h"
31 #include "segments.h"
32 #include "ways.h"
33 #include "functions.h"
34
35
36 /*++++++++++++++++++++++++++++++++++++++
37 Load in a node list from a file.
38
39 Nodes* LoadNodeList Returns the node list.
40
41 const char *filename The name of the file to load.
42 ++++++++++++++++++++++++++++++++++++++*/
43
44 Nodes *LoadNodeList(const char *filename)
45 {
46 void *data;
47 Nodes *nodes;
48
49 nodes=(Nodes*)malloc(sizeof(Nodes));
50
51 data=MapFile(filename);
52
53 if(!data)
54 return(NULL);
55
56 /* Copy the Nodes structure from the loaded data */
57
58 *nodes=*((Nodes*)data);
59
60 /* Adjust the pointers in the Nodes structure. */
61
62 nodes->data=data;
63 nodes->offsets=(index_t*)(data+(off_t)nodes->offsets);
64 nodes->nodes=(Node*)(data+(off_t)nodes->nodes);
65
66 return(nodes);
67 }
68
69
70 /*++++++++++++++++++++++++++++++++++++++
71 Find the closest node given its latitude and longitude and optionally profile.
72
73 index_t FindNode Returns the node index.
74
75 Nodes* nodes The set of nodes to search.
76
77 Segments *segments The set of segments to use.
78
79 Ways *ways The set of ways to use.
80
81 float latitude The latitude to look for.
82
83 float longitude The longitude to look for.
84
85 distance_t distance The maximum distance to look, returns the final distance.
86
87 Profile *profile The profile of the mode of transport.
88 ++++++++++++++++++++++++++++++++++++++*/
89
90 index_t FindNode(Nodes* nodes,Segments *segments,Ways *ways,float latitude,float longitude,distance_t *distance,Profile *profile)
91 {
92 int32_t latbin=lat_long_to_bin(latitude )-nodes->latzero;
93 int32_t lonbin=lat_long_to_bin(longitude)-nodes->lonzero;
94 int delta=0,count;
95 index_t i,best=NO_NODE;
96
97 /* Start with the bin containing the location, then spiral outwards. */
98
99 do
100 {
101 int latb,lonb,llbin;
102
103 count=0;
104
105 for(latb=latbin-delta;latb<=latbin+delta;latb++)
106 for(lonb=lonbin-delta;lonb<=lonbin+delta;lonb++)
107 {
108 if(abs(latb-latbin)<delta && abs(lonb-lonbin)<delta)
109 continue;
110
111 llbin=lonb*nodes->latbins+latb;
112
113 if(llbin<0 || llbin>(nodes->latbins*nodes->lonbins))
114 continue;
115
116 if(delta>0)
117 {
118 float lat1=(float)((nodes->latzero+latb)*LAT_LONG_BIN)/LAT_LONG_SCALE;
119 float lon1=(float)((nodes->lonzero+lonb)*LAT_LONG_BIN)/LAT_LONG_SCALE;
120 float lat2=(float)((nodes->latzero+latb+1)*LAT_LONG_BIN)/LAT_LONG_SCALE;
121 float lon2=(float)((nodes->lonzero+lonb+1)*LAT_LONG_BIN)/LAT_LONG_SCALE;
122
123 if(latb==latbin)
124 {
125 distance_t dist1=Distance(latitude,lon1,latitude,longitude);
126 distance_t dist2=Distance(latitude,lon2,latitude,longitude);
127
128 if(dist1>*distance && dist2>*distance)
129 continue;
130 }
131 else if(lonb==lonbin)
132 {
133 distance_t dist1=Distance(lat1,longitude,latitude,longitude);
134 distance_t dist2=Distance(lat2,longitude,latitude,longitude);
135
136 if(dist1>*distance && dist2>*distance)
137 continue;
138 }
139 else
140 {
141 distance_t dist1=Distance(lat1,lon1,latitude,longitude);
142 distance_t dist2=Distance(lat2,lon1,latitude,longitude);
143 distance_t dist3=Distance(lat2,lon2,latitude,longitude);
144 distance_t dist4=Distance(lat1,lon2,latitude,longitude);
145
146 if(dist1>*distance && dist2>*distance && dist3>*distance && dist4>*distance)
147 continue;
148 }
149 }
150
151 for(i=nodes->offsets[llbin];i<nodes->offsets[llbin+1];i++)
152 {
153 float lat=(float)((nodes->latzero+latb)*LAT_LONG_BIN+nodes->nodes[i].latoffset)/LAT_LONG_SCALE;
154 float lon=(float)((nodes->lonzero+lonb)*LAT_LONG_BIN+nodes->nodes[i].lonoffset)/LAT_LONG_SCALE;
155
156 distance_t dist=Distance(lat,lon,latitude,longitude);
157
158 if(dist<*distance)
159 {
160 if(profile)
161 {
162 Segment *segment;
163
164 /* Decide if this is node is valid for the profile */
165
166 segment=FirstSegment(segments,nodes,i);
167
168 do
169 {
170 Way *way=LookupWay(ways,segment->way);
171
172 if(way->allow&profile->allow)
173 break;
174
175 segment=NextSegment(segments,segment,i);
176 }
177 while(segment);
178
179 if(!segment)
180 continue;
181 }
182
183 best=i; *distance=dist;
184 }
185 }
186
187 count++;
188 }
189
190 delta++;
191 }
192 while(count);
193
194 return(best);
195 }
196
197
198 /*++++++++++++++++++++++++++++++++++++++
199 Get the latitude and longitude associated with a node.
200
201 Nodes *nodes The set of nodes.
202
203 index_t index The node index.
204
205 float *latitude Returns the latitude.
206
207 float *longitude Returns the logitude.
208 ++++++++++++++++++++++++++++++++++++++*/
209
210 void GetLatLong(Nodes *nodes,index_t index,float *latitude,float *longitude)
211 {
212 Node *node=&nodes->nodes[index];
213 int latbin=-1,lonbin=-1;
214 int start,end,mid;
215
216 /* Binary search - search key closest below is required.
217 *
218 * # <- start | Check mid and move start or end if it doesn't match
219 * # |
220 * # | Since an inexact match is wanted we must set end=mid-1
221 * # <- mid | or start=mid because we know that mid doesn't match.
222 * # |
223 * # | Eventually either end=start or end=start+1 and one of
224 * # <- end | start or end is the wanted one.
225 */
226
227 /* Search for longitude */
228
229 start=0;
230 end=nodes->lonbins-1;
231
232 do
233 {
234 mid=(start+end)/2; /* Choose mid point */
235
236 if(nodes->offsets[nodes->latbins*mid]<index) /* Mid point is too low */
237 start=mid;
238 else if(nodes->offsets[nodes->latbins*mid]>index) /* Mid point is too high */
239 end=mid-1;
240 else /* Mid point is correct */
241 {lonbin=mid;break;}
242 }
243 while((end-start)>1);
244
245 if(lonbin==-1)
246 {
247 if(nodes->offsets[nodes->latbins*end]>index)
248 lonbin=start;
249 else
250 lonbin=end;
251 }
252
253 while(lonbin<nodes->lonbins && nodes->offsets[lonbin*nodes->latbins]==nodes->offsets[(lonbin+1)*nodes->latbins])
254 lonbin++;
255
256 /* Search for latitude */
257
258 start=0;
259 end=nodes->latbins-1;
260
261 do
262 {
263 mid=(start+end)/2; /* Choose mid point */
264
265 if(nodes->offsets[lonbin*nodes->latbins+mid]<index) /* Mid point is too low */
266 start=mid;
267 else if(nodes->offsets[lonbin*nodes->latbins+mid]>index) /* Mid point is too high */
268 end=mid-1;
269 else /* Mid point is correct */
270 {latbin=mid;break;}
271 }
272 while((end-start)>1);
273
274 if(latbin==-1)
275 {
276 if(nodes->offsets[lonbin*nodes->latbins+end]>index)
277 latbin=start;
278 else
279 latbin=end;
280 }
281
282 while(latbin<nodes->latbins && nodes->offsets[lonbin*nodes->latbins+latbin]==nodes->offsets[lonbin*nodes->latbins+latbin+1])
283 latbin++;
284
285 /* Return the values */
286
287 *latitude =(float)((nodes->latzero+latbin)*LAT_LONG_BIN+node->latoffset)/LAT_LONG_SCALE;
288 *longitude=(float)((nodes->lonzero+lonbin)*LAT_LONG_BIN+node->lonoffset)/LAT_LONG_SCALE;
289 }

Properties

Name Value
cvs:description Node data type.