]> git.street.me.uk Git - andy/viking.git/blob - src/degrees_converters.c
Fix a bug that causes segfault on trackpoint properties dialog.
[andy/viking.git] / src / degrees_converters.c
1 #include <math.h>
2 #include <glib.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 /**
7  * @param pos_c char for positive value
8  * @param neg_c char for negative value
9  */
10 static gchar *convert_dec_to_ddd(gdouble dec, gchar pos_c, gchar neg_c)
11 {
12   gchar sign_c = ' ';
13   gdouble val_d;
14   gchar *result = NULL;
15
16   if ( dec > 0 )
17     sign_c = pos_c;
18   else if ( dec < 0 )
19     sign_c = neg_c;
20   else /* Nul value */
21     sign_c = ' ';
22
23   /* Degree */
24   val_d = fabs(dec);
25
26   /* Format */
27   /* TODO : replace "°" as UTF-8 */
28   result = g_strdup_printf ( "%c%f°", sign_c, val_d );
29   return result;
30 }
31
32 gchar *convert_lat_dec_to_ddd(gdouble lat)
33 {
34   return convert_dec_to_ddd(lat, 'N', 'S');
35 }
36
37 gchar *convert_lon_dec_to_ddd(gdouble lon)
38 {
39   return convert_dec_to_ddd(lon, 'E', 'W');
40 }
41
42 /**
43  * @param pos_c char for positive value
44  * @param neg_c char for negative value
45  */
46 static gchar *convert_dec_to_dmm(gdouble dec, gchar pos_c, gchar neg_c)
47 {
48   gdouble tmp;
49   gchar sign_c = ' ';
50   gint val_d;
51   gdouble val_m;
52   gchar *result = NULL;
53
54   if ( dec > 0 )
55     sign_c = pos_c;
56   else if ( dec < 0 )
57     sign_c = neg_c;
58   else /* Nul value */
59     sign_c = ' ';
60
61   /* Degree */
62   tmp = fabs(dec);
63   val_d = (gint)tmp;
64
65   /* Minutes */
66   val_m = (tmp - val_d) * 60;
67
68   /* Format */
69   /* TODO : replace "°" as UTF-8 */
70   result = g_strdup_printf ( "%c%d°%f'",
71                              sign_c, val_d, val_m );
72   return result;
73 }
74
75 gchar *convert_lat_dec_to_dmm(gdouble lat)
76 {
77   return convert_dec_to_dmm(lat, 'N', 'S');
78 }
79
80 gchar *convert_lon_dec_to_dmm(gdouble lon)
81 {
82   return convert_dec_to_dmm(lon, 'E', 'W');
83 }
84
85 /**
86  * @param pos_c char for positive value
87  * @param neg_c char for negative value
88  */
89 static gchar *convert_dec_to_dms(gdouble dec, gchar pos_c, gchar neg_c)
90 {
91   gdouble tmp;
92   gchar sign_c = ' ';
93   gint val_d, val_m;
94   gdouble val_s;
95   gchar *result = NULL;
96
97   if ( dec > 0 )
98     sign_c = pos_c;
99   else if ( dec < 0 )
100     sign_c = neg_c;
101   else /* Nul value */
102     sign_c = ' ';
103
104   /* Degree */
105   tmp = fabs(dec);
106   val_d = (gint)tmp;
107
108   /* Minutes */
109   tmp = (tmp - val_d) * 60;
110   val_m = (gint)tmp;
111
112   /* Minutes */
113   val_s = (tmp - val_m) * 60;
114
115   /* Format */
116   /* TODO : replace "°" as UTF-8 */
117   result = g_strdup_printf ( "%c%d°%d'%f\"",
118                              sign_c, val_d, val_m, val_s );
119   return result;
120 }
121
122 gchar *convert_lat_dec_to_dms(gdouble lat)
123 {
124   return convert_dec_to_dms(lat, 'N', 'S');
125 }
126
127 gchar *convert_lon_dec_to_dms(gdouble lon)
128 {
129   return convert_dec_to_dms(lon, 'E', 'W');
130 }
131
132 gdouble convert_dms_to_dec(const gchar *dms)
133 {
134         gdouble d = 0.0; /* Degree */
135         gdouble m = 0.0; /* Minutes */
136         gdouble s = 0.0; /* Seconds */
137         gint neg = FALSE;
138         gdouble result;
139         
140         if (dms != NULL) {
141                 int nbFloat = 0;
142                 const gchar *ptr, *endptr;
143
144                 // Compute the sign
145                 // It is negative if:
146                 // - the '-' sign occurs
147                 // - it is a west longitude or south latitude
148                 if (strpbrk (dms, "-wWsS") != NULL)
149                     neg = TRUE;
150
151                 // Peek the différent components
152                 endptr = dms;
153                 do {
154                         gdouble value;
155                         ptr = strpbrk (endptr, "0123456789,.");
156                         if (ptr != NULL) {
157                                 value = g_strtod(ptr, &endptr);
158                         nbFloat++;
159                 switch(nbFloat) {
160                         case 1:
161                                 d = value;
162                                 break;
163                         case 2:
164                                 m = value;
165                                 break;
166                         case 3:
167                                 s = value;
168                                 break;
169                 }
170                         }
171                 } while (ptr != NULL && endptr != NULL);
172         }
173         
174         // Compute the result
175         result = d + m/60 + s/3600;
176         
177         if (neg) result = - result;
178         
179         return result;
180 }