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