Contents of /trunk/src/pos.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (show annotations)
Sun Jan 18 19:43:20 2009 UTC (15 years, 3 months ago) by harbaum
File MIME type: text/plain
File size: 6540 byte(s)
Option to use float math instead of double
1 /*
2 * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3 *
4 * This file is part of OSM2Go.
5 *
6 * OSM2Go 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 3 of the License, or
9 * (at your option) any later version.
10 *
11 * OSM2Go 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 OSM2Go. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ctype.h>
21
22 #include "appdata.h"
23
24 #define TAG_STATE GTK_STATE_PRELIGHT
25
26 void pos_lat_str(char *str, int len, pos_float_t latitude) {
27 snprintf(str, len-1, "%.5f", latitude);
28 /* eliminate trailing zeros */
29 if((strchr(str, '.') != NULL) || (strchr(str, ',') != NULL)) {
30 char *p = str+strlen(str)-1;
31 while(*p == '0') *p-- = 0;
32 if((*p == '.')||(*p == ','))
33 *p = 0;
34 }
35 strcat(str, "°");
36 }
37
38 void pos_lon_str(char *str, int len, pos_float_t longitude) {
39 snprintf(str, len-1, "%.5f", longitude);
40 /* eliminate trailing zeros */
41 if((strchr(str, '.') != NULL) || (strchr(str, ',') != NULL)) {
42 char *p = str+strlen(str)-1;
43 while(*p == '0') *p-- = 0;
44 if((*p == '.')||(*p == ','))
45 *p = 0;
46 }
47 strcat(str, "°");
48 }
49
50 pos_float_t pos_parse_lat(char *str) {
51 return g_strtod(str, NULL);
52 }
53
54 pos_float_t pos_parse_lon(char *str) {
55 return g_strtod(str, NULL);
56 }
57
58 gboolean pos_lat_valid(pos_float_t lat) {
59 return(!isnan(lat) && (lat >= -90.0) && (lat <= 90.0));
60 }
61
62 gboolean pos_lon_valid(pos_float_t lon) {
63 return(!isnan(lon) && (lon >= -180.0) && (lon <= 180.0));
64 }
65
66 static gboolean mark(GtkWidget *widget, gboolean valid) {
67 gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);
68 return valid;
69 }
70
71 static void callback_modified_lat(GtkWidget *widget, gpointer data ) {
72 pos_float_t i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
73 mark(widget, pos_lat_valid(i));
74 }
75
76 /* a entry that is colored red when being "active" */
77 GtkWidget *pos_lat_entry_new(pos_float_t lat) {
78 GdkColor color;
79 GtkWidget *widget = gtk_entry_new();
80 gdk_color_parse("red", &color);
81 gtk_widget_modify_text(widget, TAG_STATE, &color);
82
83 char str[32];
84 pos_lat_str(str, sizeof(str), lat);
85 gtk_entry_set_text(GTK_ENTRY(widget), str);
86
87 g_signal_connect(G_OBJECT(widget), "changed",
88 G_CALLBACK(callback_modified_lat), NULL);
89
90 return widget;
91 }
92
93 static void callback_modified_lon(GtkWidget *widget, gpointer data ) {
94 pos_float_t i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
95 mark(widget, pos_lon_valid(i));
96 }
97
98 /* a entry that is colored red when filled with invalid coordinate */
99 GtkWidget *pos_lon_entry_new(pos_float_t lon) {
100 GdkColor color;
101 GtkWidget *widget = gtk_entry_new();
102 gdk_color_parse("#ff0000", &color);
103 gtk_widget_modify_text(widget, TAG_STATE, &color);
104
105 char str[32];
106 pos_lon_str(str, sizeof(str), lon);
107 gtk_entry_set_text(GTK_ENTRY(widget), str);
108
109 g_signal_connect(G_OBJECT(widget), "changed",
110 G_CALLBACK(callback_modified_lon), NULL);
111
112 return widget;
113 }
114
115 pos_float_t pos_lat_get(GtkWidget *widget) {
116 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
117 return pos_parse_lat(p);
118 }
119
120 pos_float_t pos_lon_get(GtkWidget *widget) {
121 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
122 return pos_parse_lon(p);
123 }
124
125 void pos_lat_entry_set(GtkWidget *entry, pos_float_t lat) {
126 char str[32];
127 pos_lat_str(str, sizeof(str), lat);
128 gtk_entry_set_text(GTK_ENTRY(entry), str);
129 }
130
131 void pos_lon_entry_set(GtkWidget *entry, pos_float_t lon) {
132 char str[32];
133 pos_lon_str(str, sizeof(str), lon);
134 gtk_entry_set_text(GTK_ENTRY(entry), str);
135 }
136
137 GtkWidget *pos_lat_label_new(pos_float_t lat) {
138 char str[32];
139 pos_lat_str(str, sizeof(str), lat);
140 return gtk_label_new(str);
141 }
142
143 GtkWidget *pos_lon_label_new(pos_float_t lon) {
144 char str[32];
145 pos_lon_str(str, sizeof(str), lon);
146 return gtk_label_new(str);
147 }
148
149 void pos_lat_label_set(GtkWidget *label, pos_float_t lat) {
150 char str[32];
151 pos_lat_str(str, sizeof(str), lat);
152 gtk_label_set_text(GTK_LABEL(label), str);
153 }
154
155 void pos_lon_label_set(GtkWidget *label, pos_float_t lon) {
156 char str[32];
157 pos_lon_str(str, sizeof(str), lon);
158 gtk_label_set_text(GTK_LABEL(label), str);
159 }
160
161 void pos2lpos(bounds_t *bounds, pos_t *pos, lpos_t *lpos) {
162 lpos->x = POS_EQ_RADIUS * DEG2RAD(pos->lon);
163 #ifdef USE_FLOAT
164 lpos->y = POS_EQ_RADIUS * logf(tanf(M_PI/4 + DEG2RAD(pos->lat)/2));
165 #else
166 lpos->y = POS_EQ_RADIUS * log(tan(M_PI/4 + DEG2RAD(pos->lat)/2));
167 #endif
168 lpos->x = ( lpos->x - bounds->center.x) * bounds->scale;
169 lpos->y = (-lpos->y + bounds->center.y) * bounds->scale;
170 }
171
172 /* the maps center is special as it isn't offset (by itself) */
173 void pos2lpos_center(pos_t *pos, lpos_t *lpos) {
174 lpos->x = POS_EQ_RADIUS * DEG2RAD(pos->lon);
175 #ifdef USE_FLOAT
176 lpos->y = POS_EQ_RADIUS * logf(tanf(M_PI/4 + DEG2RAD(pos->lat)/2));
177 #else
178 lpos->y = POS_EQ_RADIUS * log(tan(M_PI/4 + DEG2RAD(pos->lat)/2));
179 #endif
180 }
181
182 void lpos2pos(bounds_t *bounds, lpos_t *lpos, pos_t *pos) {
183 lpos_t tmp = *lpos;
184
185 tmp.x = ( tmp.x/bounds->scale) + bounds->center.x;
186 tmp.y = (-tmp.y/bounds->scale) + bounds->center.y;
187
188 pos->lon = RAD2DEG(tmp.x / POS_EQ_RADIUS);
189 #ifdef USE_FLOAT
190 pos->lat = RAD2DEG(2 * atanf(expf(tmp.y/POS_EQ_RADIUS)) - M_PI/2);
191 #else
192 pos->lat = RAD2DEG(2 * atan(exp(tmp.y/POS_EQ_RADIUS)) - M_PI/2);
193 #endif
194 }
195
196 void pos_dist_str(char *str, int len, pos_float_t dist, gboolean is_mil) {
197 /* is this to be displayed as miles? */
198 if(is_mil) dist /= KMPMIL; // kilometer per mile
199
200 snprintf(str, len, "%.4f", dist);
201 /* eliminate trailing zeros */
202 if((strchr(str, '.') != NULL) || (strchr(str, ',') != NULL)) {
203 char *p = str+strlen(str)-1;
204 while(*p == '0') *p-- = 0;
205 if((*p == '.')||(*p == ','))
206 *p = 0;
207 }
208 }
209
210 void pos_dist_entry_set(GtkWidget *entry, pos_float_t dist, gboolean is_mil) {
211 char str[32];
212 pos_dist_str(str, sizeof(str), dist, is_mil);
213 gtk_entry_set_text(GTK_ENTRY(entry), str);
214 }
215
216 pos_float_t pos_parse_dist(char *str, gboolean is_mil) {
217 return g_strtod(str, NULL) * (is_mil?KMPMIL:1.0);
218 }
219
220 pos_float_t pos_dist_get(GtkWidget *widget, gboolean is_mil) {
221 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
222 return pos_parse_dist(p, is_mil);
223 }