]> git.street.me.uk Git - andy/viking.git/blame - src/vikcoordlayer.c
Improve documentation of background.c
[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,
50a14534 87
0a6cab71
AF
88 (VikLayerFuncMarshall) coord_layer_marshall,
89 (VikLayerFuncUnmarshall) coord_layer_unmarshall,
50a14534
EB
90
91 (VikLayerFuncSetParam) coord_layer_set_param,
92 (VikLayerFuncGetParam) coord_layer_get_param,
93
94 (VikLayerFuncReadFileData) NULL,
95 (VikLayerFuncWriteFileData) NULL,
96
33534cd8 97 (VikLayerFuncDeleteItem) NULL,
d5874ef9 98 (VikLayerFuncCutItem) NULL,
50a14534
EB
99 (VikLayerFuncCopyItem) NULL,
100 (VikLayerFuncPasteItem) NULL,
101 (VikLayerFuncFreeCopiedItem) NULL,
70a23263 102 (VikLayerFuncDragDropRequest) NULL,
50a14534
EB
103};
104
105struct _VikCoordLayer {
106 VikLayer vl;
107 GdkGC *gc;
108 gdouble deg_inc;
109 guint8 line_thickness;
ac68cea3 110 GdkColor *color;
50a14534
EB
111};
112
113GType vik_coord_layer_get_type ()
114{
115 static GType vcl_type = 0;
116
117 if (!vcl_type)
118 {
119 static const GTypeInfo vcl_info =
120 {
121 sizeof (VikCoordLayerClass),
122 NULL, /* base_init */
123 NULL, /* base_finalize */
124 NULL, /* class init */
125 NULL, /* class_finalize */
126 NULL, /* class_data */
127 sizeof (VikCoordLayer),
128 0,
129 NULL /* instance init */
130 };
131 vcl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikCoordLayer", &vcl_info, 0 );
132 }
133
134 return vcl_type;
135}
136
0a6cab71
AF
137static void coord_layer_marshall( VikCoordLayer *vcl, guint8 **data, gint *len )
138{
139 vik_layer_marshall_params ( VIK_LAYER(vcl), data, len );
140}
141
142static VikCoordLayer *coord_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
143{
c8430548 144 VikCoordLayer *rv = vik_coord_layer_new ();
0a6cab71
AF
145 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
146 return rv;
147}
148
158b3642 149gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
50a14534
EB
150{
151 switch ( id )
152 {
ac68cea3 153 case PARAM_COLOR: if ( vcl->color ) gdk_color_free ( vcl->color ); vcl->color = gdk_color_copy( &(data.c)); break;
50a14534
EB
154 case PARAM_MIN_INC: vcl->deg_inc = data.d / 60.0; break;
155 case PARAM_LINE_THICKNESS: if ( data.u >= 1 && data.u <= 15 ) vcl->line_thickness = data.u; break;
156 }
157 return TRUE;
158}
159
158b3642 160static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id, gboolean is_file_operation )
50a14534
EB
161{
162 VikLayerParamData rv;
163 switch ( id )
164 {
ac68cea3
MA
165 case PARAM_COLOR:
166 if (vcl->color)
167 {
168 rv.c.pixel = vcl->color->pixel;
169 rv.c.red = vcl->color->red;
170 rv.c.green = vcl->color->green;
171 rv.c.blue = vcl->color->blue;
172 }
173 break;
50a14534
EB
174 case PARAM_MIN_INC: rv.d = vcl->deg_inc * 60.0; break;
175 case PARAM_LINE_THICKNESS: rv.i = vcl->line_thickness; break;
176 }
177 return rv;
178}
179
07059501 180static void coord_layer_post_read ( VikLayer *vl, VikViewport *vp, gboolean from_file )
50a14534 181{
94933cb8 182 VikCoordLayer *vcl = VIK_COORD_LAYER(vl);
50a14534
EB
183 if ( vcl->gc )
184 g_object_unref ( G_OBJECT(vcl->gc) );
185
ac68cea3
MA
186 vcl->gc = vik_viewport_new_gc_from_color ( vp, vcl->color, vcl->line_thickness );
187
50a14534
EB
188}
189
190VikCoordLayer *vik_coord_layer_new ( )
191{
ac68cea3
MA
192 GdkColor InitColor;
193
50a14534
EB
194 VikCoordLayer *vcl = VIK_COORD_LAYER ( g_object_new ( VIK_COORD_LAYER_TYPE, NULL ) );
195 vik_layer_init ( VIK_LAYER(vcl), VIK_LAYER_COORD );
196
ac68cea3 197 InitColor.pixel = 0;
3750ef3e
GB
198 InitColor.red = 65535;
199 InitColor.green = 65535;
200 InitColor.blue = 65535;
ac68cea3 201
50a14534
EB
202 vcl->gc = NULL;
203 vcl->deg_inc = 1.0/60.0;
204 vcl->line_thickness = 3;
ac68cea3 205 vcl->color = gdk_color_copy (&InitColor);
50a14534
EB
206 return vcl;
207}
208
209void vik_coord_layer_draw ( VikCoordLayer *vcl, gpointer data )
210{
211 VikViewport *vp = (VikViewport *) data;
80e450c0
AF
212
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;
ac68cea3
MA
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
385void vik_coord_layer_free ( VikCoordLayer *vcl )
386{
387 if ( vcl->gc != NULL )
388 g_object_unref ( G_OBJECT(vcl->gc) );
389
390 if ( vcl->color != NULL )
ac68cea3 391 gdk_color_free ( vcl->color );
50a14534
EB
392}
393
394static void coord_layer_update_gc ( VikCoordLayer *vcl, VikViewport *vp, const gchar *color )
395{
ac68cea3
MA
396 GdkColor InitColor;
397
50a14534 398 if ( vcl->color )
ac68cea3 399 gdk_color_free ( vcl->color );
50a14534 400
ac68cea3
MA
401 gdk_color_parse( color, &InitColor);
402 vcl->color = gdk_color_copy( &InitColor );
50a14534
EB
403
404 if ( vcl->gc )
405 g_object_unref ( G_OBJECT(vcl->gc) );
406
ac68cea3 407 vcl->gc = vik_viewport_new_gc_from_color ( vp, vcl->color, vcl->line_thickness );
50a14534
EB
408}
409
410VikCoordLayer *vik_coord_layer_create ( VikViewport *vp )
411{
412 VikCoordLayer *vcl = vik_coord_layer_new ();
413 coord_layer_update_gc ( vcl, vp, "red" );
414 return vcl;
415}
416