/[zanavi_public1]/navit/navit/coord.c
ZANavi

Contents of /navit/navit/coord.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 9976 byte(s)
import files
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include <stdlib.h>
21 #include <glib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25 #include "debug.h"
26 #include "item.h"
27 #include "coord.h"
28 #include "transform.h"
29 #include "projection.h"
30 /**
31 * @defgroup coord Coordinate handling functions
32 * @{
33 */
34
35 /**
36 * Get a coordinate
37 *
38 * @param p Pointer to the coordinate
39 * @returns the coordinate
40 */
41
42 struct coord *
43 coord_get(unsigned char **p)
44 {
45 struct coord *ret=(struct coord *)(*p);
46 *p += sizeof(*ret);
47 return ret;
48 }
49
50 struct coord *
51 coord_new(int x, int y)
52 {
53 struct coord *c=g_new(struct coord, 1);
54
55 c->x=x;
56 c->y=y;
57
58 return c;
59 }
60
61 struct coord *
62 coord_new_from_attrs(struct attr *parent, struct attr **attrs)
63 {
64 struct attr *x,*y;
65 x=attr_search(attrs, NULL, attr_x);
66 y=attr_search(attrs, NULL, attr_y);
67 if (!x || !y)
68 return NULL;
69 return coord_new(x->u.num, y->u.num);
70 }
71
72
73 void
74 coord_destroy(struct coord *c)
75 {
76 g_free(c);
77 }
78
79 struct coord_rect *
80 coord_rect_new(struct coord *lu, struct coord *rl)
81 {
82 struct coord_rect *r=g_new(struct coord_rect, 1);
83
84 dbg_assert(lu->x <= rl->x);
85 dbg_assert(lu->y >= rl->y);
86
87 r->lu=*lu;
88 r->rl=*rl;
89
90 return r;
91
92 }
93
94 void
95 coord_rect_destroy(struct coord_rect *r)
96 {
97 g_free(r);
98 }
99
100 int
101 coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2)
102 {
103 dbg(1,"0x%x,0x%x - 0x%x,0x%x vs 0x%x,0x%x - 0x%x,0x%x\n", r1->lu.x, r1->lu.y, r1->rl.x, r1->rl.y, r2->lu.x, r2->lu.y, r2->rl.x, r2->rl.y);
104
105 // ****** this sometimes causes a crash at startup!! ********
106 // ****** this sometimes causes a crash at startup!! ********
107 // dbg_assert(r1->lu.x <= r1->rl.x);
108 // dbg_assert(r1->lu.y >= r1->rl.y);
109 // dbg_assert(r2->lu.x <= r2->rl.x);
110 // dbg_assert(r2->lu.y >= r2->rl.y);
111 // ****** this sometimes causes a crash at startup!! ********
112 // ****** this sometimes causes a crash at startup!! ********
113 if (r1->lu.x > r2->rl.x)
114 return 0;
115 if (r1->rl.x < r2->lu.x)
116 return 0;
117 if (r1->lu.y < r2->rl.y)
118 return 0;
119 if (r1->rl.y > r2->lu.y)
120 return 0;
121 return 1;
122 }
123
124 int
125 coord_rect_contains(struct coord_rect *r, struct coord *c)
126 {
127 dbg_assert(r->lu.x <= r->rl.x);
128 dbg_assert(r->lu.y >= r->rl.y);
129 if (c->x < r->lu.x)
130 return 0;
131 if (c->x > r->rl.x)
132 return 0;
133 if (c->y < r->rl.y)
134 return 0;
135 if (c->y > r->lu.y)
136 return 0;
137 return 1;
138 }
139
140 void
141 coord_rect_extend(struct coord_rect *r, struct coord *c)
142 {
143 if (c->x < r->lu.x)
144 r->lu.x=c->x;
145 if (c->x > r->rl.x)
146 r->rl.x=c->x;
147 if (c->y < r->rl.y)
148 r->rl.y=c->y;
149 if (c->y > r->lu.y)
150 r->lu.y=c->y;
151 }
152
153 /**
154 * Parses \c char \a *c_str and writes back the coordinates to \c coord \a *c_ret. Uses \c projection \a pro if no projection is given in \c char \a *c_str.
155 * The format for \a *c_str can be:
156 * \li [Proj:]-0xX [-]0xX
157 * - where Proj can be mg/garmin, defaults to mg
158 * \li [Proj:][D][D]Dmm.ss[S][S] N/S [D][D]DMM.ss[S][S]... E/W
159 * \li [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]
160 * - where Proj can be geo
161 *
162 * @param *c_str String to be parsed
163 * @param pro Projection of the string
164 * @param *pc_ret Where the \a pcoord should get stored
165 * @returns The lenght of the parsed string
166 */
167
168 int
169 coord_parse(const char *c_str, enum projection pro, struct coord *c_ret)
170 {
171 int debug=0;
172 char *proj=NULL,*s,*co;
173 const char *str=c_str;
174 int args,ret = 0;
175 struct coord_geo g;
176 struct coord c;
177 enum projection str_pro=projection_none;
178
179 dbg(1,"enter('%s',%d,%p)\n", c_str, pro, c_ret);
180 s=strchr(str,' ');
181 co=strchr(str,':');
182 if (co && co < s) {
183 proj=malloc(co-str+1);
184 strncpy(proj, str, co-str);
185 proj[co-str]='\0';
186 dbg(1,"projection=%s\n", proj);
187 str=co+1;
188 s=strchr(str,' ');
189 if (!strcmp(proj, "mg"))
190 str_pro = projection_mg;
191 else if (!strcmp(proj, "garmin"))
192 str_pro = projection_garmin;
193 else if (!strcmp(proj, "geo"))
194 str_pro = projection_none;
195 else {
196 dbg(0, "Unknown projection: %s\n", proj);
197 goto out;
198 }
199 }
200 if (! s) {
201 ret=0;
202 goto out;
203 }
204 while (*s == ' ') {
205 s++;
206 }
207 if (!strncmp(s, "0x", 2) || !strncmp(s, "-0x", 3)) {
208 args=sscanf(str, "%i %i%n",&c.x, &c.y, &ret);
209 if (args < 2)
210 goto out;
211 dbg(1,"str='%s' x=0x%x y=0x%x c=%d\n", str, c.x, c.y, ret);
212 dbg(1,"rest='%s'\n", str+ret);
213
214 if (str_pro == projection_none)
215 str_pro=projection_mg;
216 if (str_pro != pro) {
217 transform_to_geo(str_pro, &c, &g);
218 transform_from_geo(pro, &g, &c);
219 }
220 *c_ret=c;
221 } else if (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's') {
222 double lng, lat;
223 char ns, ew;
224 dbg(1,"str='%s'\n", str);
225 args=sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret);
226 dbg(1,"args=%d\n", args);
227 dbg(1,"lat=%f %c lon=%f %c\n", lat, ns, lng, ew);
228 if (args < 4)
229 goto out;
230 dbg(1,"projection=%d str_pro=%d projection_none=%d\n", pro, str_pro, projection_none);
231 if (str_pro == projection_none) {
232 g.lat=floor(lat/100);
233 lat-=g.lat*100;
234 g.lat+=lat/60;
235 g.lng=floor(lng/100);
236 lng-=g.lng*100;
237 g.lng+=lng/60;
238 if (ns == 's' || ns == 'S')
239 g.lat=-g.lat;
240 if (ew == 'w' || ew == 'W')
241 g.lng=-g.lng;
242 dbg(1,"transform_from_geo(%f,%f)",g.lat,g.lng);
243 transform_from_geo(pro, &g, c_ret);
244 dbg(1,"result 0x%x,0x%x\n", c_ret->x,c_ret->y);
245 }
246 dbg(3,"str='%s' x=%f ns=%c y=%f ew=%c c=%d\n", str, lng, ns, lat, ew, ret);
247 dbg(3,"rest='%s'\n", str+ret);
248 } else {
249 double lng, lat;
250 args=sscanf(str, "%lf %lf%n", &lng, &lat, &ret);
251 if (args < 2)
252 goto out;
253 dbg(1,"str='%s' x=%f y=%f c=%d\n", str, lng, lat, ret);
254 dbg(1,"rest='%s'\n", str+ret);
255 g.lng=lng;
256 g.lat=lat;
257 transform_from_geo(pro, &g, c_ret);
258 }
259 if (debug)
260 printf("rest='%s'\n", str+ret);
261 ret+=str-c_str;
262 if (debug) {
263 printf("args=%d\n", args);
264 printf("ret=%d delta=%d ret_str='%s'\n", ret, GPOINTER_TO_INT(str-c_str), c_str+ret);
265 }
266 out:
267 free(proj);
268 return ret;
269 }
270
271 /**
272 * A wrapper for pcoord_parse that also return the projection
273 * @param *c_str String to be parsed
274 * @param pro Projection of the string
275 * @param *pc_ret Where the \a pcoord should get stored
276 * @returns The lenght of the parsed string
277 */
278
279 int
280 pcoord_parse(const char *c_str, enum projection pro, struct pcoord *pc_ret)
281 {
282 struct coord c;
283 int ret;
284 ret = coord_parse(c_str, pro, &c);
285 pc_ret->x = c.x;
286 pc_ret->y = c.y;
287 pc_ret->pro = pro;
288 return ret;
289 }
290
291 void
292 coord_print(enum projection pro, struct coord *c, FILE *out) {
293 unsigned int x;
294 unsigned int y;
295 char *sign_x = "";
296 char *sign_y = "";
297
298 if ( c->x < 0 ) {
299 x = -c->x;
300 sign_x = "-";
301 } else {
302 x = c->x;
303 }
304 if ( c->y < 0 ) {
305 y = -c->y;
306 sign_y = "-";
307 } else {
308 y = c->y;
309 }
310 fprintf( out, "%s: %s0x%x %s0x%x\n",
311 projection_to_name( pro , NULL),
312 sign_x, x,
313 sign_y, y );
314 return;
315 }
316
317 /**
318 * @brief Converts a lat/lon into a text formatted text string.
319 * @param lat The latitude (if lat is 360 or greater, the latitude will be omitted)
320 * @param lng The longitude (if lng is 360 or greater, the longitude will be omitted)
321 * @param fmt The format to use.
322 * @li DEGREES_DECIMAL=>Degrees with decimal places, i.e. 20.5000°N 110.5000°E
323 * @li DEGREES_MINUTES=>Degrees and minutes, i.e. 20°30.00'N 110°30.00'E
324 * @li DEGREES_MINUTES_SECONDS=>Degrees, minutes and seconds, i.e. 20°30'30.00"N 110°30'30"E
325 *
326 *
327 * @param buffer A buffer large enough to hold the output + a terminating NULL (up to 31 bytes)
328 * @param size The size of the buffer
329 *
330 */
331 void coord_format(float lat,float lng, enum coord_format fmt, char * buffer, int size)
332 {
333
334 char lat_c='N';
335 char lng_c='E';
336 float lat_deg,lat_min,lat_sec;
337 float lng_deg,lng_min,lng_sec;
338 int size_used=0;
339
340 if (lng < 0) {
341 lng=-lng;
342 lng_c='W';
343 }
344 if (lat < 0) {
345 lat=-lat;
346 lat_c='S';
347 }
348 lat_deg=lat;
349 lat_min=(lat-floor(lat_deg))*60;
350 lat_sec=fmod(lat*3600,60);
351 lng_deg=lng;
352 lng_min=(lng-floor(lng_deg))*60;
353 lng_sec=fmod(lng*3600,60);
354 switch(fmt)
355 {
356
357 case DEGREES_DECIMAL:
358 if (lat<360)
359 size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.6f°%c",lat,lat_c);
360 if ((lat<360)&&(lng<360))
361 size_used+=g_snprintf(buffer+size_used,size-size_used," ");
362 if (lng<360)
363 size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.7f°%c",lng,lng_c);
364 break;
365 case DEGREES_MINUTES:
366 if (lat<360)
367 size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.0f°%07.4f' %c",floor(lat_deg),lat_min,lat_c);
368 if ((lat<360)&&(lng<360))
369 size_used+=g_snprintf(buffer+size_used,size-size_used," ");
370 if (lng<360)
371 size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.0f°%07.4f' %c",floor(lng_deg),lng_min,lng_c);
372 break;
373 case DEGREES_MINUTES_SECONDS:
374 if (lat<360)
375 size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.0f°%02.0f'%05.2f\" %c",floor(lat_deg),floor(lat_min),lat_sec,lat_c);
376 if ((lat<360)&&(lng<360))
377 size_used+=g_snprintf(buffer+size_used,size-size_used," ");
378 if (lng<360)
379 size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.0f°%02.0f'%05.2f\" %c",floor(lng_deg),floor(lng_min),lng_sec,lng_c);
380 break;
381
382
383 }
384
385 }
386
387 unsigned int
388 coord_hash(const void *key)
389 {
390 const struct coord *c=key;
391 return c->x^c->y;
392 }
393
394 int
395 coord_equal(const void *a, const void *b)
396 {
397 const struct coord *c_a=a;
398 const struct coord *c_b=b;
399 if (c_a->x == c_b->x && c_a->y == c_b->y)
400 return TRUE;
401 return FALSE;
402 }
403 /** @} */

   
Visit the ZANavi Wiki