74b6a104172c8e814408d8c05b973b41a580f9bd
[navit-package] / navit / coord.c
1 #include <glib.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 #include "debug.h"
7 #include "coord.h"
8 #include "transform.h"
9 #include "projection.h"
10 /**
11  * @defgroup coord Coordinate handling functions
12  * @{
13  */
14
15 /**
16  * Get a coordinate
17  *
18  * @param p Pointer to the coordinate
19  * @returns the coordinate
20  */
21
22 struct coord *
23 coord_get(unsigned char **p)
24 {
25         struct coord *ret=(struct coord *)(*p);
26         *p += sizeof(*ret);
27         return ret;
28 }
29
30 struct coord *
31 coord_new(int x, int y)
32 {
33         struct coord *c=g_new(struct coord, 1);
34
35         c->x=x;
36         c->y=y;
37
38         return c;
39 }
40
41 void
42 coord_destroy(struct coord *c)
43 {
44         g_free(c);
45 }
46
47 struct coord_rect *
48 coord_rect_new(struct coord *lu, struct coord *rl)
49 {
50         struct coord_rect *r=g_new(struct coord_rect, 1);
51
52         g_assert(lu->x <= rl->x);
53         g_assert(lu->y >= rl->y);
54
55         r->lu=*lu;
56         r->rl=*rl;
57
58         return r;
59         
60 }
61
62 void
63 coord_rect_destroy(struct coord_rect *r)
64 {
65         g_free(r);
66 }
67
68 int 
69 coord_rect_overlap(struct coord_rect *r1, struct coord_rect *r2)
70 {
71         g_assert(r1->lu.x <= r1->rl.x);
72         g_assert(r1->lu.y >= r1->rl.y);
73         g_assert(r2->lu.x <= r2->rl.x);
74         g_assert(r2->lu.y >= r2->rl.y);
75         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);
76         if (r1->lu.x > r2->rl.x)
77                 return 0;
78         if (r1->rl.x < r2->lu.x)
79                 return 0;
80         if (r1->lu.y < r2->rl.y)
81                 return 0;
82         if (r1->rl.y > r2->lu.y)
83                 return 0;
84         return 1;
85 }
86
87 int
88 coord_rect_contains(struct coord_rect *r, struct coord *c)
89 {
90         g_assert(r->lu.x <= r->rl.x);
91         g_assert(r->lu.y >= r->rl.y);
92         if (c->x < r->lu.x)
93                 return 0;
94         if (c->x > r->rl.x)
95                 return 0;
96         if (c->y < r->rl.y)
97                 return 0;
98         if (c->y > r->lu.y)
99                 return 0;
100         return 1;
101 }
102
103 void
104 coord_rect_extend(struct coord_rect *r, struct coord *c)
105 {
106         if (c->x < r->lu.x)
107                 r->lu.x=c->x;
108         if (c->x > r->rl.x)
109                 r->rl.x=c->x;
110         if (c->y < r->rl.y)
111                 r->rl.y=c->y;
112         if (c->y > r->lu.y)
113                 r->lu.y=c->y;
114 }
115
116         /* [Proj:][Ð]DMM.ss[S][S]... N/S [D][D]DMM.ss[S][S]... E/W */
117         /* [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]... */
118         /* [Proj:][-]0xX [-]0xX */
119 /*
120  * Currently supported:
121  *      [Proj:]-0xX [-]0xX 
122  *      - where Proj can be mg/garmin, defaults to mg
123  *      [Proj:][D][D]Dmm.ss[S][S] N/S [D][D]DMM.ss[S][S]... E/W
124  *      [Proj:][-][D]D.d[d]... [-][D][D]D.d[d]
125  *      - where Proj can be geo
126  */
127
128 int
129 coord_parse(const char *c_str, enum projection pro, struct coord *c_ret)
130 {
131         int debug=0;
132         char *proj=NULL,*s,*co;
133         const char *str=c_str;
134         int args,ret = 0;
135         struct coord_geo g;
136         struct coord c;
137         enum projection str_pro=projection_none;
138
139         dbg(1,"enter('%s',%d,%p)\n", c_str, pro, c_ret);
140         s=strchr(str,' ');
141         co=strchr(str,':');
142         if (co && co < s) {
143                 proj=malloc(co-str+1);
144                 strncpy(proj, str, co-str);
145                 proj[co-str]='\0';
146                 dbg(1,"projection=%s\n", proj);
147                 str=co+1;
148                 s=strchr(str,' ');
149                 if (!strcmp(proj, "mg"))
150                         str_pro = projection_mg;
151                 else if (!strcmp(proj, "garmin"))
152                         str_pro = projection_garmin;
153                 else if (!strcmp(proj, "geo"))
154                         str_pro = projection_none;
155                 else {
156                         dbg(0, "Unknown projection: %s\n", proj);
157                         goto out;
158                 }
159         }
160         if (! s)
161                 return 0;
162         while (*s == ' ') {
163                 s++;
164         }
165         if (!strncmp(str, "0x", 2) || !strncmp(str,"-0x", 3)) {
166                 args=sscanf(str, "%x %x%n",&c.x, &c.y, &ret);
167                 if (args < 2)
168                         goto out;
169                 dbg(1,"str='%s' x=0x%x y=0x%x c=%d\n", str, c.x, c.y, ret);
170                 dbg(1,"rest='%s'\n", str+ret);
171
172                 if (str_pro == projection_none) 
173                         str_pro=projection_mg;
174                 if (str_pro != pro) {
175                         transform_to_geo(str_pro, &c, &g);
176                         transform_from_geo(pro, &g, &c);
177                 }
178                 *c_ret=c;
179         } else if (*s == 'N' || *s == 'n' || *s == 'S' || *s == 's') {
180                 double lng, lat;
181                 char ns, ew;
182                 dbg(1,"str='%s'\n", str);
183                 args=sscanf(str, "%lf %c %lf %c%n", &lat, &ns, &lng, &ew, &ret);
184                 if (args < 4)
185                         goto out;
186                 if (str_pro == projection_none) {
187                         g.lat=floor(lat/100);
188                         lat-=g.lat*100;
189                         g.lat+=lat/60;
190                         g.lng=floor(lng/100);
191                         lng-=g.lng*100;
192                         g.lng+=lng/60;
193                         if (ns == 's' || ns == 'S')
194                                 g.lat=-g.lat;
195                         if (ew == 'w' || ew == 'W')
196                                 g.lng=-g.lng;
197                         transform_from_geo(pro, &g, c_ret);
198                 }
199                 dbg(3,"str='%s' x=%f ns=%c y=%f ew=%c c=%d\n", str, lng, ns, lat, ew, ret);
200                 dbg(3,"rest='%s'\n", str+ret);
201         } else {
202                 double lng, lat;
203                 args=sscanf(str, "%lf %lf%n", &lng, &lat, &ret);
204                 if (args < 2)
205                         goto out;
206                 dbg(1,"str='%s' x=%f y=%f  c=%d\n", str, lng, lat, ret);
207                 dbg(1,"rest='%s'\n", str+ret);
208                 g.lng=lng;
209                 g.lat=lat;
210                 transform_from_geo(pro, &g, c_ret);
211         }
212         if (debug)
213                 printf("rest='%s'\n", str+ret);
214         ret+=str-c_str;
215         if (debug) {
216                 printf("args=%d\n", args);
217                 printf("ret=%d delta=%d ret_str='%s'\n", ret, str-c_str, c_str+ret);
218         }
219 out:
220         if (proj)
221                 free(proj);
222         return ret;
223 }
224
225 /** @} */