Parent Directory | Revision Log
Various pickers
1 | harbaum | 1 | /* |
2 | * Copyright (C) 2008 Till Harbaum <till@harbaum.org>. | ||
3 | * | ||
4 | * This file is part of GPXView. | ||
5 | * | ||
6 | * GPXView 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 | * GPXView 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 GPXView. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include "gpxview.h" | ||
21 | #include <math.h> | ||
22 | |||
23 | harbaum | 198 | #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5) |
24 | #include <hildon/hildon-entry.h> | ||
25 | #endif | ||
26 | |||
27 | harbaum | 1 | #define STR_NAN "----" |
28 | |||
29 | typedef struct { | ||
30 | appdata_t *appdata; | ||
31 | |||
32 | GtkWidget *lon1, *lat1, *dist1, *dir1; | ||
33 | GtkWidget *lon2, *lat2; | ||
34 | |||
35 | GtkWidget *distance, *proj_lat, *proj_lon; | ||
36 | } math_dialog_state_t; | ||
37 | |||
38 | static gboolean mark(GtkWidget *widget, gboolean valid) { | ||
39 | gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE); | ||
40 | return valid; | ||
41 | } | ||
42 | |||
43 | /* a label that is colored red when being "active" */ | ||
44 | static GtkWidget *gtk_red_label_new(char *str) { | ||
45 | GdkColor color; | ||
46 | harbaum | 198 | GtkWidget *widget = left_label_new(str); |
47 | harbaum | 1 | gdk_color_parse("#ff0000", &color); |
48 | gtk_widget_modify_fg(widget, TAG_STATE, &color); | ||
49 | return widget; | ||
50 | } | ||
51 | |||
52 | static void on_calc_clicked(GtkButton *button, gpointer user_data) { | ||
53 | math_dialog_state_t *state = (math_dialog_state_t*)user_data; | ||
54 | pos_t pos1, pos2; | ||
55 | gboolean pos1_ok = FALSE, pos2_ok = FALSE; | ||
56 | float dist1; | ||
57 | gboolean dist1_ok = FALSE; | ||
58 | float dir1; | ||
59 | gboolean dir1_ok = FALSE; | ||
60 | |||
61 | /* parse input */ | ||
62 | harbaum | 221 | pos1.lat = lat_entry_get(state->lat1); |
63 | pos1.lon = lon_entry_get(state->lon1); | ||
64 | harbaum | 1 | if(!isnan(pos1.lat) && !isnan(pos1.lon)) pos1_ok = TRUE; |
65 | |||
66 | harbaum | 221 | pos2.lat = lat_entry_get(state->lat2); |
67 | pos2.lon = lon_entry_get(state->lon2); | ||
68 | harbaum | 1 | if(!isnan(pos2.lat) && !isnan(pos2.lon)) pos2_ok = TRUE; |
69 | |||
70 | harbaum | 223 | dist1 = dist_entry_get(state->dist1, state->appdata->imperial); |
71 | harbaum | 1 | if(!isnan(dist1)) dist1_ok = TRUE; |
72 | |||
73 | harbaum | 223 | dir1 = angle_entry_get(state->dir1); |
74 | harbaum | 1 | if(!isnan(dir1)) dir1_ok = TRUE; |
75 | |||
76 | /* ------------------- do all calculations ------------------- */ | ||
77 | |||
78 | |||
79 | /* ------------------- distance of coo1 and coo2 ------------------- */ | ||
80 | if(mark(state->distance, pos1_ok && pos2_ok)) { | ||
81 | char str[32]; | ||
82 | float dist = gpx_pos_get_distance(pos1, pos2, state->appdata->imperial); | ||
83 | distance_str(str, sizeof(str), dist, state->appdata->imperial); | ||
84 | |||
85 | gtk_label_set_text(GTK_LABEL(state->distance), str); | ||
86 | } else | ||
87 | gtk_label_set_text(GTK_LABEL(state->distance), STR_NAN); | ||
88 | |||
89 | // N 53° 09.033' W 001° 50.666' 100km / 30° = N 53° 55.616, W001° 04.850 | ||
90 | /* ------------------- coordinate projection ---------------- */ | ||
91 | mark(state->proj_lat, pos1_ok && dist1_ok && dir1_ok); | ||
92 | if(mark(state->proj_lon, pos1_ok && dist1_ok && dir1_ok)) { | ||
93 | pos_t pro; | ||
94 | |||
95 | /* get great circle radius in miles/kilometers */ | ||
96 | float gcrad = state->appdata->imperial?3959.0:6371.0; | ||
97 | |||
98 | // from: http://www.movable-type.co.uk/scripts/latlong.html | ||
99 | pro.lat = asin(sin(pos1.lat/180*M_PI) * cos(dist1/gcrad) + | ||
100 | cos(pos1.lat/180*M_PI) * sin(dist1/gcrad) * | ||
101 | cos(dir1/180*M_PI) )/M_PI*180; | ||
102 | pro.lon = pos1.lon + atan2(sin(dir1/180*M_PI)*sin(dist1/gcrad)* | ||
103 | cos(pos1.lat/180*M_PI), | ||
104 | cos(dist1/gcrad)-sin(pos1.lat/180*M_PI)* | ||
105 | sin(pro.lat/180*M_PI))/M_PI*180; | ||
106 | pro.lon = fmodf(pro.lon+180,360) - 180; // normalise to -180...+180 | ||
107 | |||
108 | harbaum | 221 | lat_label_set(state->proj_lat, pro.lat); |
109 | lon_label_set(state->proj_lon, pro.lon); | ||
110 | harbaum | 1 | |
111 | if(!isnan(pro.lat) && !isnan(pro.lon)) | ||
112 | state->appdata->geomath = pro; | ||
113 | } else { | ||
114 | gtk_label_set_text(GTK_LABEL(state->proj_lat), STR_NAN); | ||
115 | gtk_label_set_text(GTK_LABEL(state->proj_lon), STR_NAN); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | void geomath_dialog(appdata_t *appdata) { | ||
120 | static pos_t pos1 = { 0.0, 0.0 }, pos2 = { 0.0, 0.0 }; | ||
121 | static float dist1 = 0.0; | ||
122 | static float dir1 = 0.0; | ||
123 | static gboolean is_imperial = FALSE; | ||
124 | |||
125 | math_dialog_state_t state; | ||
126 | |||
127 | /* this is quite ugly. It would be nice to run the entire system on */ | ||
128 | /* one specific system (e.g. metric) and only convert for in- and output */ | ||
129 | if(!appdata->imperial && is_imperial) | ||
130 | dist1 *= 6371.0/3959.0; /* we just switched to metric */ | ||
131 | if(appdata->imperial && !is_imperial) | ||
132 | dist1 *= 3959.0/6371.0; /* we just switched to imperial */ | ||
133 | is_imperial = appdata->imperial; | ||
134 | |||
135 | state.appdata = appdata; | ||
136 | |||
137 | #ifdef USE_MAEMO | ||
138 | if(appdata->cur_cache) | ||
139 | printf("current cache is %s\n", appdata->cur_cache->id); | ||
140 | else | ||
141 | printf("no current cache\n"); | ||
142 | #endif | ||
143 | |||
144 | GtkWidget *dialog = gtk_dialog_new_with_buttons(_("Geomath"), | ||
145 | GTK_WINDOW(appdata->window), | ||
146 | // GTK_DIALOG_NO_SEPARATOR | | ||
147 | GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, | ||
148 | GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, | ||
149 | NULL); | ||
150 | |||
151 | #if defined(USE_MAEMO) && defined(HILDON_HELP) | ||
152 | hildon_help_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_GEOMATH, | ||
153 | appdata->osso_context); | ||
154 | #endif | ||
155 | |||
156 | gtk_window_set_default_size(GTK_WINDOW(dialog), DIALOG_WIDTH, DIALOG_HEIGHT); | ||
157 | |||
158 | /* do geomath dialog */ | ||
159 | GtkWidget *hbox = gtk_hbox_new(FALSE, 0); | ||
160 | |||
161 | /* ------------------------- input area ------------------------- */ | ||
162 | harbaum | 214 | GtkWidget *table = gtk_table_new(5, 5, FALSE); |
163 | gtk_table_set_col_spacing(GTK_TABLE(table), 2, 20); | ||
164 | harbaum | 1 | |
165 | harbaum | 214 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Latitude:")), 0, 1, 1, 2); |
166 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Longitude:")), 0, 1, 2, 3); | ||
167 | harbaum | 1 | |
168 | harbaum | 223 | #ifdef FREMANTLE |
169 | harbaum | 214 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Coordinate 1")), 1, 3, 0, 1); |
170 | harbaum | 223 | #endif |
171 | harbaum | 214 | gtk_table_attach_defaults(GTK_TABLE(table), state.lat1 = lat_entry_new(pos1.lat), 1, 2, 1, 2); |
172 | gtk_table_attach_defaults(GTK_TABLE(table), state.lon1 = lon_entry_new(pos1.lon), 1, 2, 2, 3); | ||
173 | harbaum | 221 | gtk_table_attach_defaults(GTK_TABLE(table), preset_coordinate_picker(appdata, state.lat1, state.lon1), 2, 3, 1, 2); |
174 | harbaum | 1 | |
175 | harbaum | 223 | #ifdef FREMANTLE |
176 | harbaum | 214 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Coordinate 2")), 3, 5, 0, 1); |
177 | harbaum | 223 | #endif |
178 | harbaum | 214 | gtk_table_attach_defaults(GTK_TABLE(table), state.lat2 = lat_entry_new(pos2.lat), 3, 4, 1, 2); |
179 | gtk_table_attach_defaults(GTK_TABLE(table), state.lon2 = lon_entry_new(pos2.lon), 3, 4, 2, 3); | ||
180 | harbaum | 221 | gtk_table_attach_defaults(GTK_TABLE(table), preset_coordinate_picker(appdata, state.lat2, state.lon2), 4, 5, 1, 2); |
181 | harbaum | 1 | |
182 | harbaum | 198 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Distance:")), 0, 1, 3, 4); |
183 | harbaum | 214 | gtk_table_attach_defaults(GTK_TABLE(table), state.dist1 = dist_entry_new(dist1, appdata->imperial), 1, 3, 3, 4); |
184 | |||
185 | harbaum | 198 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Direction:")), 0, 1, 4, 5); |
186 | harbaum | 223 | gtk_table_attach_defaults(GTK_TABLE(table), state.dir1 = angle_entry_new(dir1), 1, 3, 4, 5); |
187 | harbaum | 1 | |
188 | gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 0); | ||
189 | |||
190 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0); | ||
191 | |||
192 | /* ------------------------- do-it-button ------------------------- */ | ||
193 | |||
194 | GtkWidget *button = gtk_button_new_with_label(_("Calculate!")); | ||
195 | harbaum | 198 | g_signal_connect(button, "clicked", (GCallback)on_calc_clicked, &state); |
196 | |||
197 | harbaum | 223 | #ifdef FREMANTLE |
198 | harbaum | 133 | hildon_gtk_widget_set_theme_size(button, |
199 | (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH)); | ||
200 | harbaum | 214 | gtk_table_attach(GTK_TABLE(table), button, 3,5,3,5, GTK_EXPAND, GTK_EXPAND, 0, 0); |
201 | harbaum | 198 | #else |
202 | /* in non-maemo5 the button has its own row */ | ||
203 | hbox = gtk_hbox_new(FALSE, 0); | ||
204 | harbaum | 1 | gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0); |
205 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, FALSE, 0); | ||
206 | harbaum | 198 | #endif |
207 | harbaum | 1 | |
208 | /* ------------------------- output area ------------------------- */ | ||
209 | |||
210 | table = gtk_table_new(3, 3, FALSE); | ||
211 | |||
212 | harbaum | 198 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Distance = ")), |
213 | harbaum | 1 | 0, 1, 0, 1); |
214 | gtk_table_attach_defaults(GTK_TABLE(table), state.distance = gtk_red_label_new(STR_NAN), | ||
215 | 1, 3, 0, 1); | ||
216 | |||
217 | harbaum | 198 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Projection = ")), |
218 | harbaum | 1 | 0, 1, 1, 2); |
219 | gtk_table_attach_defaults(GTK_TABLE(table), state.proj_lat = gtk_red_label_new(STR_NAN), | ||
220 | 1, 2, 1, 2); | ||
221 | gtk_table_attach_defaults(GTK_TABLE(table), state.proj_lon = gtk_red_label_new(STR_NAN), | ||
222 | 2, 3, 1, 2); | ||
223 | #if 0 | ||
224 | harbaum | 198 | gtk_table_attach_defaults(GTK_TABLE(table), left_label_new(_("Middle = ")), |
225 | harbaum | 1 | 0, 1, 2, 3); |
226 | gtk_table_attach_defaults(GTK_TABLE(table), state.middle_lat = gtk_red_label_new(STR_NAN), | ||
227 | 1, 2, 2, 3); | ||
228 | gtk_table_attach_defaults(GTK_TABLE(table), state.middle_lon = gtk_red_label_new(STR_NAN), | ||
229 | 2, 3, 2, 3); | ||
230 | #endif | ||
231 | |||
232 | gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table, TRUE, TRUE, 0); | ||
233 | |||
234 | |||
235 | gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE); | ||
236 | |||
237 | gtk_widget_show_all(dialog); | ||
238 | gtk_dialog_run(GTK_DIALOG(dialog)); | ||
239 | |||
240 | /* copy values back to local static variables so they re-appear if */ | ||
241 | /* the dialog is re-opened, convert illegal values (NAN) to 0 */ | ||
242 | |||
243 | harbaum | 221 | pos1.lat = lat_entry_get(state.lat1); if(isnan(pos1.lat)) pos1.lat=0; |
244 | pos1.lon = lon_entry_get(state.lon1); if(isnan(pos1.lon)) pos1.lon=0; | ||
245 | pos2.lat = lat_entry_get(state.lat2); if(isnan(pos2.lat)) pos2.lat=0; | ||
246 | pos2.lon = lon_entry_get(state.lon2); if(isnan(pos2.lon)) pos2.lon=0; | ||
247 | harbaum | 223 | dist1 = dist_entry_get(state.dist1, state.appdata->imperial); |
248 | if(isnan(dist1)) dist1=0; | ||
249 | dir1 = angle_entry_get(state.dir1); if(isnan(dir1)) dir1=0; | ||
250 | harbaum | 1 | |
251 | gtk_widget_destroy(dialog); | ||
252 | } |