]> git.street.me.uk Git - andy/viking.git/blame - src/vikcoordlayer.c
Remove now unused alphabetical sort functions as they have been superseded.
[andy/viking.git] / src / vikcoordlayer.c
CommitLineData
50a14534
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 *
6 * This program 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 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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 this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
4c77d5e0
GB
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
8c00358d
GB
24
25#ifdef HAVE_MATH_H
80e450c0 26#include <math.h>
8c00358d 27#endif
4c77d5e0 28#include <glib/gi18n.h>
50a14534
EB
29
30#include "viking.h"
5bfafde9 31#include "icons/icons.h"
50a14534 32
a7023a1b 33static VikCoordLayer *coord_layer_new ( );
8997679e
RN
34static void coord_layer_draw ( VikCoordLayer *vcl, VikViewport *vp );
35static void coord_layer_free ( VikCoordLayer *vcl );
36static VikCoordLayer *coord_layer_create ( VikViewport *vp );
0a6cab71
AF
37static void coord_layer_marshall( VikCoordLayer *vcl, guint8 **data, gint *len );
38static VikCoordLayer *coord_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
158b3642
RN
39static gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
40static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id, gboolean is_file_operation );
07059501 41static void coord_layer_post_read ( VikLayer *vl, VikViewport *vp, gboolean from_file );
50a14534 42
ad0a8c2d 43static VikLayerParamScale param_scales[] = {
50a14534
EB
44 { 0.05, 60.0, 0.25, 10 },
45 { 1, 10, 1, 0 },
46};
47
a7023a1b
RN
48static VikLayerParamData color_default ( void ) {
49 VikLayerParamData data; gdk_color_parse ( "red", &data.c ); return data;
50 // or: return VIK_LPD_COLOR ( 0, 65535, 0, 0 );
51}
52static VikLayerParamData min_inc_default ( void ) { return VIK_LPD_DOUBLE ( 1.0 ); }
53static VikLayerParamData line_thickness_default ( void ) { return VIK_LPD_UINT ( 3 ); }
54
ad0a8c2d 55static VikLayerParam coord_layer_params[] = {
a7023a1b
RN
56 { VIK_LAYER_COORD, "color", VIK_LAYER_PARAM_COLOR, VIK_LAYER_GROUP_NONE, N_("Color:"), VIK_LAYER_WIDGET_COLOR, NULL, NULL, NULL, color_default },
57 { VIK_LAYER_COORD, "min_inc", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, N_("Minutes Width:"), VIK_LAYER_WIDGET_SPINBUTTON, &param_scales[0], NULL, NULL, min_inc_default },
58 { VIK_LAYER_COORD, "line_thickness", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, N_("Line Thickness:"), VIK_LAYER_WIDGET_SPINBUTTON, &param_scales[1], NULL, NULL, line_thickness_default },
50a14534
EB
59};
60
50a14534
EB
61enum { PARAM_COLOR = 0, PARAM_MIN_INC, PARAM_LINE_THICKNESS, NUM_PARAMS };
62
63VikLayerInterface vik_coord_layer_interface = {
db386630 64 "Coord",
affcc0f2 65 N_("Coordinate"),
75078768 66 NULL,
5bfafde9 67 &vikcoordlayer_pixbuf,
50a14534
EB
68
69 NULL,
70 0,
71
72 coord_layer_params,
73 NUM_PARAMS,
74 NULL,
75 0,
76
5a4a28bf
QT
77 VIK_MENU_ITEM_ALL,
78
8997679e 79 (VikLayerFuncCreate) coord_layer_create,
50a14534 80 (VikLayerFuncRealize) NULL,
b112cbf5 81 (VikLayerFuncPostRead) coord_layer_post_read,
8997679e 82 (VikLayerFuncFree) coord_layer_free,
50a14534
EB
83
84 (VikLayerFuncProperties) NULL,
8997679e 85 (VikLayerFuncDraw) coord_layer_draw,
50a14534
EB
86 (VikLayerFuncChangeCoordMode) NULL,
87
20c7a3a0
QT
88 (VikLayerFuncSetMenuItemsSelection) NULL,
89 (VikLayerFuncGetMenuItemsSelection) NULL,
90
50a14534
EB
91 (VikLayerFuncAddMenuItems) NULL,
92 (VikLayerFuncSublayerAddMenuItems) NULL,
93
94 (VikLayerFuncSublayerRenameRequest) NULL,
95 (VikLayerFuncSublayerToggleVisible) NULL,
9da7faf2 96 (VikLayerFuncSublayerTooltip) NULL,
1e8b7f57 97 (VikLayerFuncLayerTooltip) NULL,
a5dcfdb7 98 (VikLayerFuncLayerSelected) NULL,
50a14534 99
0a6cab71
AF
100 (VikLayerFuncMarshall) coord_layer_marshall,
101 (VikLayerFuncUnmarshall) coord_layer_unmarshall,
50a14534
EB
102
103 (VikLayerFuncSetParam) coord_layer_set_param,
104 (VikLayerFuncGetParam) coord_layer_get_param,
105
106 (VikLayerFuncReadFileData) NULL,
107 (VikLayerFuncWriteFileData) NULL,
108
33534cd8 109 (VikLayerFuncDeleteItem) NULL,
d5874ef9 110 (VikLayerFuncCutItem) NULL,
50a14534
EB
111 (VikLayerFuncCopyItem) NULL,
112 (VikLayerFuncPasteItem) NULL,
113 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 114 (VikLayerFuncDragDropRequest) NULL,
77ad64fa
RN
115
116 (VikLayerFuncSelectClick) NULL,
08f14055
RN
117 (VikLayerFuncSelectMove) NULL,
118 (VikLayerFuncSelectRelease) NULL,
e46f259a 119 (VikLayerFuncSelectedViewportMenu) NULL,
50a14534
EB
120};
121
122struct _VikCoordLayer {
123 VikLayer vl;
124 GdkGC *gc;
125 gdouble deg_inc;
126 guint8 line_thickness;
280e71ab 127 GdkColor color;
50a14534
EB
128};
129
130GType vik_coord_layer_get_type ()
131{
132 static GType vcl_type = 0;
133
134 if (!vcl_type)
135 {
136 static const GTypeInfo vcl_info =
137 {
138 sizeof (VikCoordLayerClass),
139 NULL, /* base_init */
140 NULL, /* base_finalize */
141 NULL, /* class init */
142 NULL, /* class_finalize */
143 NULL, /* class_data */
144 sizeof (VikCoordLayer),
145 0,
146 NULL /* instance init */
147 };
148 vcl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikCoordLayer", &vcl_info, 0 );
149 }
150
151 return vcl_type;
152}
153
0a6cab71
AF
154static void coord_layer_marshall( VikCoordLayer *vcl, guint8 **data, gint *len )
155{
156 vik_layer_marshall_params ( VIK_LAYER(vcl), data, len );
157}
158
159static VikCoordLayer *coord_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
160{
a7023a1b 161 VikCoordLayer *rv = coord_layer_new ();
0a6cab71
AF
162 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
163 return rv;
164}
165
280e71ab 166// NB VikViewport can be null as it's not used ATM
158b3642 167gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
50a14534
EB
168{
169 switch ( id )
170 {
280e71ab 171 case PARAM_COLOR: vcl->color = data.c; break;
50a14534
EB
172 case PARAM_MIN_INC: vcl->deg_inc = data.d / 60.0; break;
173 case PARAM_LINE_THICKNESS: if ( data.u >= 1 && data.u <= 15 ) vcl->line_thickness = data.u; break;
174 }
175 return TRUE;
176}
177
158b3642 178static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id, gboolean is_file_operation )
50a14534
EB
179{
180 VikLayerParamData rv;
181 switch ( id )
182 {
280e71ab 183 case PARAM_COLOR: rv.c = vcl->color; break;
50a14534
EB
184 case PARAM_MIN_INC: rv.d = vcl->deg_inc * 60.0; break;
185 case PARAM_LINE_THICKNESS: rv.i = vcl->line_thickness; break;
186 }
187 return rv;
188}
189
07059501 190static void coord_layer_post_read ( VikLayer *vl, VikViewport *vp, gboolean from_file )
50a14534 191{
94933cb8 192 VikCoordLayer *vcl = VIK_COORD_LAYER(vl);
50a14534
EB
193 if ( vcl->gc )
194 g_object_unref ( G_OBJECT(vcl->gc) );
195
280e71ab 196 vcl->gc = vik_viewport_new_gc_from_color ( vp, &(vcl->color), vcl->line_thickness );
50a14534
EB
197}
198
a7023a1b 199static VikCoordLayer *coord_layer_new ( VikViewport *vvp )
50a14534
EB
200{
201 VikCoordLayer *vcl = VIK_COORD_LAYER ( g_object_new ( VIK_COORD_LAYER_TYPE, NULL ) );
a0c65899 202 vik_layer_set_type ( VIK_LAYER(vcl), VIK_LAYER_COORD );
50a14534 203
a7023a1b 204 vik_layer_set_defaults ( VIK_LAYER(vcl), vvp );
ac68cea3 205
50a14534 206 vcl->gc = NULL;
a7023a1b 207
50a14534
EB
208 return vcl;
209}
210
8997679e 211static void coord_layer_draw ( VikCoordLayer *vcl, VikViewport *vp )
50a14534 212{
80e450c0 213 if ( !vcl->gc ) {
50a14534 214 return;
80e450c0
AF
215 }
216
217 if ( vik_viewport_get_coord_mode(vp) != VIK_COORD_UTM )
218 {
219 VikCoord left, right, left2, right2;
220 gdouble l, r, i, j;
221 gint x1, y1, x2, y2, smod = 1, mmod = 1;
222 gboolean mins = FALSE, secs = FALSE;
280e71ab
RN
223 GdkGC *dgc = vik_viewport_new_gc_from_color(vp, &(vcl->color), vcl->line_thickness);
224 GdkGC *mgc = vik_viewport_new_gc_from_color(vp, &(vcl->color), MAX(vcl->line_thickness/2, 1));
225 GdkGC *sgc = vik_viewport_new_gc_from_color(vp, &(vcl->color), MAX(vcl->line_thickness/5, 1));
80e450c0
AF
226
227 vik_viewport_screen_to_coord ( vp, 0, 0, &left );
228 vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), 0, &right );
229 vik_viewport_screen_to_coord ( vp, 0, vik_viewport_get_height(vp), &left2 );
230 vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp), vik_viewport_get_height(vp), &right2 );
231
232#define CLINE(gc, c1, c2) { \
233 vik_viewport_coord_to_screen(vp, (c1), &x1, &y1); \
234 vik_viewport_coord_to_screen(vp, (c2), &x2, &y2); \
235 vik_viewport_draw_line (vp, (gc), x1, y1, x2, y2); \
236 }
237
238 l = left.east_west;
239 r = right.east_west;
240 if (60*fabs(l-r) < 4) {
241 secs = TRUE;
242 smod = MIN(6, (int)ceil(3600*fabs(l-r)/30.0));
243 }
244 if (fabs(l-r) < 4) {
245 mins = TRUE;
246 mmod = MIN(6, (int)ceil(60*fabs(l-r)/30.0));
247 }
248 for (i=floor(l*60); i<ceil(r*60); i+=1.0) {
249 if (secs) {
250 for (j=i*60+1; j<(i+1)*60; j+=1.0) {
251 left.east_west = j/3600.0;
252 left2.east_west = j/3600.0;
253 if ((int)j % smod == 0) CLINE(sgc, &left, &left2);
254 }
255 }
256 if (mins) {
257 left.east_west = i/60.0;
258 left2.east_west = i/60.0;
259 if ((int)i % mmod == 0) CLINE(mgc, &left, &left2);
260 }
261 if ((int)i % 60 == 0) {
262 left.east_west = i/60.0;
263 left2.east_west = i/60.0;
264 CLINE(dgc, &left, &left2);
265 }
266 }
267
268 vik_viewport_screen_to_coord ( vp, 0, 0, &left );
269 l = left2.north_south;
270 r = left.north_south;
271 for (i=floor(l*60); i<ceil(r*60); i+=1.0) {
272 if (secs) {
273 for (j=i*60+1; j<(i+1)*60; j+=1.0) {
274 left.north_south = j/3600.0;
275 right.north_south = j/3600.0;
276 if ((int)j % smod == 0) CLINE(sgc, &left, &right);
277 }
278 }
279 if (mins) {
280 left.north_south = i/60.0;
281 right.north_south = i/60.0;
282 if ((int)i % mmod == 0) CLINE(mgc, &left, &right);
283 }
284 if ((int)i % 60 == 0) {
285 left.north_south = i/60.0;
286 right.north_south = i/60.0;
287 CLINE(dgc, &left, &right);
288 }
289 }
290#undef CLINE
291 g_object_unref(dgc);
292 g_object_unref(sgc);
293 g_object_unref(mgc);
294 return;
295 }
296
297 if ( vik_viewport_get_coord_mode(vp) == VIK_COORD_UTM )
50a14534
EB
298 {
299 const struct UTM *center = (const struct UTM *)vik_viewport_get_center ( vp );
300 gdouble xmpp = vik_viewport_get_xmpp ( vp ), ympp = vik_viewport_get_ympp ( vp );
301 guint16 width = vik_viewport_get_width ( vp ), height = vik_viewport_get_height ( vp );
302 struct LatLon ll, ll2, min, max;
303 double lon;
304 int x1, x2;
305 struct UTM utm;
306
307 utm = *center;
308 utm.northing = center->northing - ( ympp * height / 2 );
309
310 a_coords_utm_to_latlon ( &utm, &ll );
311
312 utm.northing = center->northing + ( ympp * height / 2 );
313
314 a_coords_utm_to_latlon ( &utm, &ll2 );
315
316 {
317 /* find corner coords in lat/lon.
318 start at whichever is less: top or bottom left lon. goto whichever more: top or bottom right lon
319 */
320 struct LatLon topleft, topright, bottomleft, bottomright;
321 struct UTM temp_utm;
322 temp_utm = *center;
323 temp_utm.easting -= (width/2)*xmpp;
324 temp_utm.northing += (height/2)*ympp;
325 a_coords_utm_to_latlon ( &temp_utm, &topleft );
326 temp_utm.easting += (width*xmpp);
327 a_coords_utm_to_latlon ( &temp_utm, &topright );
328 temp_utm.northing -= (height*ympp);
329 a_coords_utm_to_latlon ( &temp_utm, &bottomright );
330 temp_utm.easting -= (width*xmpp);
331 a_coords_utm_to_latlon ( &temp_utm, &bottomleft );
332 min.lon = (topleft.lon < bottomleft.lon) ? topleft.lon : bottomleft.lon;
333 max.lon = (topright.lon > bottomright.lon) ? topright.lon : bottomright.lon;
334 min.lat = (bottomleft.lat < bottomright.lat) ? bottomleft.lat : bottomright.lat;
335 max.lat = (topleft.lat > topright.lat) ? topleft.lat : topright.lat;
336 }
337
5b1d90a5
RN
338 /* Can zoom out more than whole world and so the above can give invalid positions */
339 /* Restrict values properly so drawing doesn't go into a near 'infinite' loop */
340 if ( min.lon < -180.0 )
341 min.lon = -180.0;
342 if ( max.lon > 180.0 )
343 max.lon = 180.0;
344 if ( min.lat < -90.0 )
345 min.lat = -90.0;
346 if ( max.lat > 90.0 )
347 max.lat = 90.0;
348
50a14534
EB
349 lon = ((double) ((long) ((min.lon)/ vcl->deg_inc))) * vcl->deg_inc;
350 ll.lon = ll2.lon = lon;
351
352 for (; ll.lon <= max.lon; ll.lon+=vcl->deg_inc, ll2.lon+=vcl->deg_inc )
353 {
354 a_coords_latlon_to_utm ( &ll, &utm );
355 x1 = ( (utm.easting - center->easting) / xmpp ) + (width / 2);
356 a_coords_latlon_to_utm ( &ll2, &utm );
357 x2 = ( (utm.easting - center->easting) / xmpp ) + (width / 2);
358 vik_viewport_draw_line (vp, vcl->gc, x1, height, x2, 0);
359 }
360
361 utm = *center;
362 utm.easting = center->easting - ( xmpp * width / 2 );
363
364 a_coords_utm_to_latlon ( &utm, &ll );
365
366 utm.easting = center->easting + ( xmpp * width / 2 );
367
368 a_coords_utm_to_latlon ( &utm, &ll2 );
369
370 /* really lat, just reusing a variable */
371 lon = ((double) ((long) ((min.lat)/ vcl->deg_inc))) * vcl->deg_inc;
372 ll.lat = ll2.lat = lon;
373
374 for (; ll.lat <= max.lat ; ll.lat+=vcl->deg_inc, ll2.lat+=vcl->deg_inc )
375 {
376 a_coords_latlon_to_utm ( &ll, &utm );
377 x1 = (height / 2) - ( (utm.northing - center->northing) / ympp );
378 a_coords_latlon_to_utm ( &ll2, &utm );
379 x2 = (height / 2) - ( (utm.northing - center->northing) / ympp );
380 vik_viewport_draw_line (vp, vcl->gc, width, x2, 0, x1);
381 }
382 }
383}
384
8997679e 385static void coord_layer_free ( VikCoordLayer *vcl )
50a14534
EB
386{
387 if ( vcl->gc != NULL )
388 g_object_unref ( G_OBJECT(vcl->gc) );
50a14534
EB
389}
390
280e71ab 391static void coord_layer_update_gc ( VikCoordLayer *vcl, VikViewport *vp )
50a14534 392{
50a14534
EB
393 if ( vcl->gc )
394 g_object_unref ( G_OBJECT(vcl->gc) );
395
280e71ab 396 vcl->gc = vik_viewport_new_gc_from_color ( vp, &(vcl->color), vcl->line_thickness );
50a14534
EB
397}
398
8997679e 399static VikCoordLayer *coord_layer_create ( VikViewport *vp )
50a14534 400{
a7023a1b 401 VikCoordLayer *vcl = coord_layer_new ( vp );
8aff54f2 402 if ( vp )
a7023a1b 403 coord_layer_update_gc ( vcl, vp );
50a14534
EB
404 return vcl;
405}