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 176 - (show annotations) (download) (as text)
Thu May 14 18:02:30 2009 UTC (15 years, 11 months ago) by amb
File MIME type: text/x-csrc
File size: 7499 byte(s)
Replace ~0 or 0 with NO_NODE value for "no node" condition.

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

Properties

Name Value
cvs:description Node data type.