]> git.street.me.uk Git - andy/viking.git/blob - src/vikcoord.c
vikcoord does not depend on GTK
[andy/viking.git] / src / vikcoord.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "coords.h"
23 #include "vikcoord.h"
24
25 /* all coord operations MUST BE ABSTRACTED!!! */
26
27 void vik_coord_convert(VikCoord *coord, VikCoordMode dest_mode)
28 {
29   VikCoord tmp;
30   if ( coord->mode != dest_mode )
31   {
32     if ( dest_mode == VIK_COORD_LATLON ) {
33       a_coords_utm_to_latlon ( (struct UTM *)coord, (struct LatLon *)&tmp );
34       *((struct LatLon *)coord) = *((struct LatLon *)&tmp);
35     } else {
36       a_coords_latlon_to_utm ( (struct LatLon *)coord, (struct UTM *)&tmp );
37       *((struct UTM *)coord) = *((struct UTM *)&tmp);
38     }
39     coord->mode = dest_mode;
40   }
41 }
42
43 void vik_coord_copy_convert(const VikCoord *coord, VikCoordMode dest_mode, VikCoord *dest)
44 {
45   if ( coord->mode == dest_mode ) {
46     *dest = *coord;
47   } else {
48     if ( dest_mode == VIK_COORD_LATLON )
49       a_coords_utm_to_latlon ( (struct UTM *)coord, (struct LatLon *)dest );
50     else
51       a_coords_latlon_to_utm ( (struct LatLon *)coord, (struct UTM *)dest );
52     dest->mode = dest_mode;
53   }
54 }
55
56 static gdouble vik_coord_diff_safe(const VikCoord *c1, const VikCoord *c2)
57 {
58   struct LatLon a, b;
59   vik_coord_to_latlon ( c1, &a );
60   vik_coord_to_latlon ( c2, &b );
61   return a_coords_latlon_diff ( &a, &b );
62 }
63
64 gdouble vik_coord_diff(const VikCoord *c1, const VikCoord *c2)
65 {
66   if ( c1->mode == c2->mode )
67     return vik_coord_diff_safe ( c1, c2 );
68   if ( c1->mode == VIK_COORD_UTM )
69     return a_coords_utm_diff ( (const struct UTM *) c1, (const struct UTM *) c2 );
70   else
71     return a_coords_latlon_diff ( (const struct LatLon *) c1, (const struct LatLon *) c2 );
72 }
73
74 void vik_coord_load_from_latlon ( VikCoord *coord, VikCoordMode mode, const struct LatLon *ll )
75 {
76   if ( mode == VIK_COORD_LATLON )
77     *((struct LatLon *)coord) = *ll;
78   else
79     a_coords_latlon_to_utm ( ll, (struct UTM *) coord );
80   coord->mode = mode;
81 }
82
83 void vik_coord_load_from_utm ( VikCoord *coord, VikCoordMode mode, const struct UTM *utm )
84 {
85   if ( mode == VIK_COORD_UTM )
86     *((struct UTM *)coord) = *utm;
87   else
88     a_coords_utm_to_latlon ( utm, (struct LatLon *) coord );
89   coord->mode = mode;
90 }
91
92 void vik_coord_to_latlon ( const VikCoord *coord, struct LatLon *dest )
93 {
94   if ( coord->mode == VIK_COORD_LATLON )
95     *dest = *((const struct LatLon *)coord);
96   else
97     a_coords_utm_to_latlon ( (const struct UTM *) coord, dest );
98 }
99
100 void vik_coord_to_utm ( const VikCoord *coord, struct UTM *dest )
101 {
102   if ( coord->mode == VIK_COORD_UTM )
103     *dest = *((const struct UTM *)coord);
104   else
105     a_coords_latlon_to_utm ( (const struct LatLon *) coord, dest );
106 }
107
108 gboolean vik_coord_equals ( const VikCoord *coord1, const VikCoord *coord2 )
109 {
110   if ( coord1->mode != coord2->mode )
111     return FALSE;
112   if ( coord1->mode == VIK_COORD_LATLON )
113     return coord1->north_south == coord2->north_south && coord1->east_west == coord2->east_west;
114   else /* VIK_COORD_UTM */
115     return coord1->utm_zone == coord2->utm_zone && coord1->north_south == coord2->north_south && coord1->east_west == coord2->east_west;
116 }
117
118 static void get_north_west(struct LatLon *center, struct LatLon *dist, struct LatLon *nw) 
119 {
120   nw->lat = center->lat + dist->lat;
121   nw->lon = center->lon - dist->lon;
122   if (nw->lon < -180)
123     nw->lon += 360.0;
124   if (nw->lat > 90.0) {  /* over north pole */
125     nw->lat = 180 - nw->lat;
126     nw->lon = nw->lon - 180;
127   }
128 }
129
130 static void get_south_east(struct LatLon *center, struct LatLon *dist, struct LatLon *se) 
131 {
132   se->lat = center->lat - dist->lat;
133   se->lon = center->lon + dist->lon;
134   if (se->lon > 180.0)
135     se->lon -= 360.0;
136   if (se->lat < -90.0) {  /* over south pole */
137     se->lat += 180;
138     se->lon = se->lon - 180;
139   }
140 }
141
142 void vik_coord_set_area(const VikCoord *coord, const struct LatLon *wh, VikCoord *tl, VikCoord *br)
143 {
144   struct LatLon center, nw, se;
145   struct LatLon dist;
146
147   dist.lat = wh->lat/2;
148   dist.lon = wh->lon/2;
149
150   vik_coord_to_latlon(coord, &center);
151   get_north_west(&center, &dist, &nw);
152   get_south_east(&center, &dist, &se);
153
154   *((struct LatLon *)tl) = nw;
155   *((struct LatLon *)br) = se;
156   tl->mode = br->mode = VIK_COORD_LATLON;
157 }
158
159 gboolean vik_coord_inside(const VikCoord *coord, const VikCoord *tl, const VikCoord *br)
160 {
161   struct LatLon ll, tl_ll, br_ll;
162
163   vik_coord_to_latlon(coord, &ll);
164   vik_coord_to_latlon(tl, &tl_ll);
165   vik_coord_to_latlon(br, &br_ll);
166
167   if ((ll.lat > tl_ll.lat) || (ll.lon < tl_ll.lon))
168     return FALSE;
169   if ((ll.lat  < br_ll.lat) || (ll.lon > br_ll.lon))
170     return FALSE;
171   return TRUE;
172 }