2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
28 #include "transform.h"
29 #include "projection.h"
31 * @defgroup coord Coordinate handling functions
38 * @param p Pointer to the coordinate
39 * @returns the coordinate
43 coord_get(unsigned char **p)
45 struct coord *ret=(struct coord *)(*p);
51 coord_new(int x, int y)
53 struct coord *c=g_new(struct coord, 1);
62 coord_new_from_attrs(struct attr *parent, struct attr **attrs)
65 x=attr_search(attrs, NULL, attr_x);
66 y=attr_search(attrs, NULL, attr_y);
69 return coord_new(x->u.num, y->u.num);
74 coord_destroy(struct coord *c)
80 coord_rect_new(struct coord *lu, struct coord *rl)
82 struct coord_rect *r=g_new(struct coord_rect, 1);
84 dbg_assert(lu->x <= rl->x);
85 dbg_assert(lu->y >= rl->y);
95 coord_rect_destroy(struct coord_rect *r)
101 coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2)
103 dbg_assert(r1->lu.x <= r1->rl.x);
104 dbg_assert(r1->lu.y >= r1->rl.y);
105 dbg_assert(r2->lu.x <= r2->rl.x);
106 dbg_assert(r2->lu.y >= r2->rl.y);
107 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);
108 if (r1->lu.x > r2->rl.x)
110 if (r1->rl.x < r2->lu.x)
112 if (r1->lu.y < r2->rl.y)
114 if (r1->rl.y > r2->lu.y)
120 coord_rect_contains(struct coord_rect *r, struct coord *c)
122 dbg_assert(r->lu.x <= r->rl.x);
123 dbg_assert(r->lu.y >= r->rl.y);
136 coord_rect_extend(struct coord_rect *r, struct coord *c)
149 * 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.
150 * The format for \a *c_str can be:
151 * \li [Proj:]-0xX [-]0xX
152 * - where Proj can be mg/garmin, defaults to mg
153 * \li [Proj:][D][D]Dmm.ss[S][S] N/S [D][D]DMM.ss[S][S]... E/W
154 * \li [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]
155 * - where Proj can be geo
157 * @param *c_str String to be parsed
158 * @param pro Projection of the string
159 * @param *pc_ret Where the \a pcoord should get stored
160 * @returns The lenght of the parsed string
164 coord_parse(const char *c_str, enum projection pro, struct coord *c_ret)
167 char *proj=NULL,*s,*co;
168 const char *str=c_str;
172 enum projection str_pro=projection_none;
174 dbg(1,"enter('%s',%d,%p)\n", c_str, pro, c_ret);
178 proj=malloc(co-str+1);
179 strncpy(proj, str, co-str);
181 dbg(1,"projection=%s\n", proj);
184 if (!strcmp(proj, "mg"))
185 str_pro = projection_mg;
186 else if (!strcmp(proj, "garmin"))
187 str_pro = projection_garmin;
188 else if (!strcmp(proj, "geo"))
189 str_pro = projection_none;
191 dbg(0, "Unknown projection: %s\n", proj);
202 if (!strncmp(s, "0x", 2) || !strncmp(s, "-0x", 3)) {
203 args=sscanf(str, "%i %i%n",&c.x, &c.y, &ret);
206 dbg(1,"str='%s' x=0x%x y=0x%x c=%d\n", str, c.x, c.y, ret);
207 dbg(1,"rest='%s'\n", str+ret);
209 if (str_pro == projection_none)
210 str_pro=projection_mg;
211 if (str_pro != pro) {
212 transform_to_geo(str_pro, &c, &g);
213 transform_from_geo(pro, &g, &c);
216 } else if (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's') {
219 dbg(1,"str='%s'\n", str);
220 args=sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret);
221 dbg(1,"args=%d\n", args);
222 dbg(1,"lat=%f %c lon=%f %c\n", lat, ns, lng, ew);
225 dbg(1,"projection=%d str_pro=%d projection_none=%d\n", pro, str_pro, projection_none);
226 if (str_pro == projection_none) {
227 g.lat=floor(lat/100);
230 g.lng=floor(lng/100);
233 if (ns == 's' || ns == 'S')
235 if (ew == 'w' || ew == 'W')
237 dbg(1,"transform_from_geo(%f,%f)",g.lat,g.lng);
238 transform_from_geo(pro, &g, c_ret);
239 dbg(1,"result 0x%x,0x%x\n", c_ret->x,c_ret->y);
241 dbg(3,"str='%s' x=%f ns=%c y=%f ew=%c c=%d\n", str, lng, ns, lat, ew, ret);
242 dbg(3,"rest='%s'\n", str+ret);
245 args=sscanf(str, "%lf %lf%n", &lng, &lat, &ret);
248 dbg(1,"str='%s' x=%f y=%f c=%d\n", str, lng, lat, ret);
249 dbg(1,"rest='%s'\n", str+ret);
252 transform_from_geo(pro, &g, c_ret);
255 printf("rest='%s'\n", str+ret);
258 printf("args=%d\n", args);
259 printf("ret=%d delta=%d ret_str='%s'\n", ret, GPOINTER_TO_INT(str-c_str), c_str+ret);
267 * A wrapper for pcoord_parse that also return the projection
268 * @param *c_str String to be parsed
269 * @param pro Projection of the string
270 * @param *pc_ret Where the \a pcoord should get stored
271 * @returns The lenght of the parsed string
275 pcoord_parse(const char *c_str, enum projection pro, struct pcoord *pc_ret)
279 ret = coord_parse(c_str, pro, &c);
287 coord_print(enum projection pro, struct coord *c, FILE *out) {
305 fprintf( out, "%s: %s0x%x %s0x%x\n",
306 projection_to_name( pro ),
313 * @brief Converts a lat/lon into a text formatted text string.
314 * @param lat The latitude (if lat is 360 or greater, the latitude will be omitted)
315 * @param lng The longitude (if lng is 360 or greater, the longitude will be omitted)
316 * @param fmt The format to use.
317 * @li DEGREES_DECIMAL=>Degrees with decimal places, i.e. 20.5000°N 110.5000°E
318 * @li DEGREES_MINUTES=>Degrees and minutes, i.e. 20°30.00'N 110°30.00'E
319 * @li DEGREES_MINUTES_SECONDS=>Degrees, minutes and seconds, i.e. 20°30'30.00"N 110°30'30"E
322 * @param buffer A buffer large enough to hold the output + a terminating NULL (up to 31 bytes)
323 * @param size The size of the buffer
326 void coord_format(float lat,float lng, enum coord_format fmt, char * buffer, int size)
331 float lat_deg,lat_min,lat_sec;
332 float lng_deg,lng_min,lng_sec;
344 lat_min=(lat-floor(lat_deg))*60;
345 lat_sec=fmod(lat*3600,60);
347 lng_min=(lng-floor(lng_deg))*60;
348 lng_sec=fmod(lng*3600,60);
352 case DEGREES_DECIMAL:
354 size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.6f°%c",lat,lat_c);
355 if ((lat<360)&&(lng<360))
356 size_used+=g_snprintf(buffer+size_used,size-size_used," ");
358 size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.7f°%c",lng,lng_c);
360 case DEGREES_MINUTES:
362 size_used+=g_snprintf(buffer+size_used,size-size_used,"%02.0f°%07.4f' %c",floor(lat_deg),lat_min,lat_c);
363 if ((lat<360)&&(lng<360))
364 size_used+=g_snprintf(buffer+size_used,size-size_used," ");
366 size_used+=g_snprintf(buffer+size_used,size-size_used,"%03.0f°%07.4f' %c",floor(lng_deg),lng_min,lng_c);
368 case DEGREES_MINUTES_SECONDS:
370 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);
371 if ((lat<360)&&(lng<360))
372 size_used+=g_snprintf(buffer+size_used,size-size_used," ");
374 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);
383 coord_hash(const void *key)
385 const struct coord *c=key;
390 coord_equal(const void *a, const void *b)
392 const struct coord *c_a=a;
393 const struct coord *c_b=b;
394 if (c_a->x == c_b->x && c_a->y == c_b->y)