Contents of /trunk/src/pos.c

Parent Directory Parent Directory | Revision Log Revision Log


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