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