Parent Directory | Revision Log
Initial import
1 | harbaum | 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, double 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, double 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 | double pos_parse_lat(char *str) { | ||
51 | return g_strtod(str, NULL); | ||
52 | } | ||
53 | |||
54 | double pos_parse_lon(char *str) { | ||
55 | return g_strtod(str, NULL); | ||
56 | } | ||
57 | |||
58 | gboolean pos_lat_valid(double lat) { | ||
59 | return(!isnan(lat) && (lat >= -90.0) && (lat <= 90.0)); | ||
60 | } | ||
61 | |||
62 | gboolean pos_lon_valid(double 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 | double 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(double 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 | double 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(double 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 | double 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 | double 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, double 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, double 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(double 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(double 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, double 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, double 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 | lpos->y = POS_EQ_RADIUS * log(tan(M_PI/4 + DEG2RAD(pos->lat)/2)); | ||
164 | |||
165 | lpos->x = ( lpos->x - bounds->center.x) * bounds->scale; | ||
166 | lpos->y = (-lpos->y + bounds->center.y) * bounds->scale; | ||
167 | } | ||
168 | |||
169 | /* the maps center is special as it isn't offset (by itself) */ | ||
170 | void pos2lpos_center(pos_t *pos, lpos_t *lpos) { | ||
171 | lpos->x = POS_EQ_RADIUS * DEG2RAD(pos->lon); | ||
172 | lpos->y = POS_EQ_RADIUS * log(tan(M_PI/4 + DEG2RAD(pos->lat)/2)); | ||
173 | } | ||
174 | |||
175 | void lpos2pos(bounds_t *bounds, lpos_t *lpos, pos_t *pos) { | ||
176 | lpos_t tmp = *lpos; | ||
177 | |||
178 | tmp.x = ( tmp.x/bounds->scale) + bounds->center.x; | ||
179 | tmp.y = (-tmp.y/bounds->scale) + bounds->center.y; | ||
180 | |||
181 | pos->lon = RAD2DEG(tmp.x / POS_EQ_RADIUS); | ||
182 | pos->lat = RAD2DEG(2 * atan(exp(tmp.y/POS_EQ_RADIUS)) - M_PI/2); | ||
183 | } | ||
184 | |||
185 | void pos_dist_str(char *str, int len, double dist, gboolean is_mil) { | ||
186 | /* is this to be displayed as miles? */ | ||
187 | if(is_mil) dist /= KMPMIL; // kilometer per mile | ||
188 | |||
189 | snprintf(str, len, "%.4f", dist); | ||
190 | /* eliminate trailing zeros */ | ||
191 | if((strchr(str, '.') != NULL) || (strchr(str, ',') != NULL)) { | ||
192 | char *p = str+strlen(str)-1; | ||
193 | while(*p == '0') *p-- = 0; | ||
194 | if((*p == '.')||(*p == ',')) | ||
195 | *p = 0; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | void pos_dist_entry_set(GtkWidget *entry, double dist, gboolean is_mil) { | ||
200 | char str[32]; | ||
201 | pos_dist_str(str, sizeof(str), dist, is_mil); | ||
202 | gtk_entry_set_text(GTK_ENTRY(entry), str); | ||
203 | } | ||
204 | |||
205 | double pos_parse_dist(char *str, gboolean is_mil) { | ||
206 | return g_strtod(str, NULL) * (is_mil?KMPMIL:1.0); | ||
207 | } | ||
208 | |||
209 | double pos_dist_get(GtkWidget *widget, gboolean is_mil) { | ||
210 | char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget)); | ||
211 | return pos_parse_dist(p, is_mil); | ||
212 | } |