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 124 - (show annotations) (download) (as text)
Sun Feb 15 16:19:28 2009 UTC (16 years, 1 month ago) by amb
File MIME type: text/x-csrc
File size: 7059 byte(s)
The search to find a node given the lat/long now searches harder.

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

Properties

Name Value
cvs:description Node data type.