]> git.street.me.uk Git - andy/viking.git/blob - src/degrees_converters.c
Add Terraserver
[andy/viking.git] / src / degrees_converters.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2006-2007, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
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 <math.h>
23 #include <glib.h>
24 #include <string.h>
25
26 #define DEGREE_SYMBOL "\302\260"
27
28 /**
29  * @param pos_c char for positive value
30  * @param neg_c char for negative value
31  */
32 static gchar *convert_dec_to_ddd(gdouble dec, gchar pos_c, gchar neg_c)
33 {
34   gchar sign_c = ' ';
35   gdouble val_d;
36   gchar *result = NULL;
37
38   if ( dec > 0 )
39     sign_c = pos_c;
40   else if ( dec < 0 )
41     sign_c = neg_c;
42   else /* Nul value */
43     sign_c = ' ';
44
45   /* Degree */
46   val_d = fabs(dec);
47
48   /* Format */
49   result = g_strdup_printf ( "%c%f" DEGREE_SYMBOL, sign_c, val_d );
50   return result;
51 }
52
53 gchar *convert_lat_dec_to_ddd(gdouble lat)
54 {
55   return convert_dec_to_ddd(lat, 'N', 'S');
56 }
57
58 gchar *convert_lon_dec_to_ddd(gdouble lon)
59 {
60   return convert_dec_to_ddd(lon, 'E', 'W');
61 }
62
63 /**
64  * @param pos_c char for positive value
65  * @param neg_c char for negative value
66  */
67 static gchar *convert_dec_to_dmm(gdouble dec, gchar pos_c, gchar neg_c)
68 {
69   gdouble tmp;
70   gchar sign_c = ' ';
71   gint val_d;
72   gdouble val_m;
73   gchar *result = NULL;
74
75   if ( dec > 0 )
76     sign_c = pos_c;
77   else if ( dec < 0 )
78     sign_c = neg_c;
79   else /* Nul value */
80     sign_c = ' ';
81
82   /* Degree */
83   tmp = fabs(dec);
84   val_d = (gint)tmp;
85
86   /* Minutes */
87   val_m = (tmp - val_d) * 60;
88
89   /* Format */
90   result = g_strdup_printf ( "%c%d" DEGREE_SYMBOL "%f'",
91                              sign_c, val_d, val_m );
92   return result;
93 }
94
95 gchar *convert_lat_dec_to_dmm(gdouble lat)
96 {
97   return convert_dec_to_dmm(lat, 'N', 'S');
98 }
99
100 gchar *convert_lon_dec_to_dmm(gdouble lon)
101 {
102   return convert_dec_to_dmm(lon, 'E', 'W');
103 }
104
105 /**
106  * @param pos_c char for positive value
107  * @param neg_c char for negative value
108  */
109 static gchar *convert_dec_to_dms(gdouble dec, gchar pos_c, gchar neg_c)
110 {
111   gdouble tmp;
112   gchar sign_c = ' ';
113   gint val_d, val_m;
114   gdouble val_s;
115   gchar *result = NULL;
116
117   if ( dec > 0 )
118     sign_c = pos_c;
119   else if ( dec < 0 )
120     sign_c = neg_c;
121   else /* Nul value */
122     sign_c = ' ';
123
124   /* Degree */
125   tmp = fabs(dec);
126   val_d = (gint)tmp;
127
128   /* Minutes */
129   tmp = (tmp - val_d) * 60;
130   val_m = (gint)tmp;
131
132   /* Minutes */
133   val_s = (tmp - val_m) * 60;
134
135   /* Format */
136   result = g_strdup_printf ( "%c%d" DEGREE_SYMBOL "%d'%f\"",
137                              sign_c, val_d, val_m, val_s );
138   return result;
139 }
140
141 gchar *convert_lat_dec_to_dms(gdouble lat)
142 {
143   return convert_dec_to_dms(lat, 'N', 'S');
144 }
145
146 gchar *convert_lon_dec_to_dms(gdouble lon)
147 {
148   return convert_dec_to_dms(lon, 'E', 'W');
149 }
150
151 gdouble convert_dms_to_dec(const gchar *dms)
152 {
153         gdouble d = 0.0; /* Degree */
154         gdouble m = 0.0; /* Minutes */
155         gdouble s = 0.0; /* Seconds */
156         gint neg = FALSE;
157         gdouble result;
158         
159         if (dms != NULL) {
160                 int nbFloat = 0;
161                 const gchar *ptr, *endptr;
162
163                 // Compute the sign
164                 // It is negative if:
165                 // - the '-' sign occurs
166                 // - it is a west longitude or south latitude
167                 if (strpbrk (dms, "-wWsS") != NULL)
168                     neg = TRUE;
169
170                 // Peek the diffĂ©rent components
171                 endptr = dms;
172                 do {
173                         gdouble value;
174                         ptr = strpbrk (endptr, "0123456789,.");
175                         if (ptr != NULL) {
176                                 value = g_strtod(ptr, &endptr);
177                         nbFloat++;
178                 switch(nbFloat) {
179                         case 1:
180                                 d = value;
181                                 break;
182                         case 2:
183                                 m = value;
184                                 break;
185                         case 3:
186                                 s = value;
187                                 break;
188                 }
189                         }
190                 } while (ptr != NULL && endptr != NULL);
191         }
192         
193         // Compute the result
194         result = d + m/60 + s/3600;
195         
196         if (neg) result = - result;
197         
198         return result;
199 }