]> git.street.me.uk Git - andy/viking.git/blob - src/vikcoordlayer.c
Update TODO/ChangeLog
[andy/viking.git] / src / vikcoordlayer.c
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  */
21
22 #include "viking.h"
23 #include "vikcoordlayer_pixmap.h"
24
25 static VikCoordLayer *coord_layer_copy ( VikCoordLayer *vcl, gpointer vp );
26 static gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp );
27 static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id );
28 static void coord_layer_update_gc ( VikCoordLayer *vcl, VikViewport *vp, const gchar *color );
29 static void coord_layer_post_read ( VikCoordLayer *vcl, VikViewport *vp );
30
31 VikLayerParamScale param_scales[] = {
32   { 0.05, 60.0, 0.25, 10 },
33   { 1, 10, 1, 0 },
34 };
35
36 VikLayerParam coord_layer_params[] = {
37   { "color", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, "Color:", VIK_LAYER_WIDGET_ENTRY },
38   { "min_inc", VIK_LAYER_PARAM_DOUBLE, VIK_LAYER_GROUP_NONE, "Minutes Width:", VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 0 },
39   { "line_thickness", VIK_LAYER_PARAM_UINT, VIK_LAYER_GROUP_NONE, "Line Thickness:", VIK_LAYER_WIDGET_SPINBUTTON, param_scales + 1 },
40 };
41
42
43 enum { PARAM_COLOR = 0, PARAM_MIN_INC, PARAM_LINE_THICKNESS, NUM_PARAMS };
44
45 VikLayerInterface vik_coord_layer_interface = {
46   "Coord",
47   &coordlayer_pixbuf,
48
49   NULL,
50   0,
51
52   coord_layer_params,
53   NUM_PARAMS,
54   NULL,
55   0,
56
57   (VikLayerFuncCreate)                  vik_coord_layer_create,
58   (VikLayerFuncRealize)                 NULL,
59   (VikLayerFuncPostRead)                coord_layer_post_read,
60   (VikLayerFuncFree)                    vik_coord_layer_free,
61
62   (VikLayerFuncProperties)              NULL,
63   (VikLayerFuncDraw)                    vik_coord_layer_draw,
64   (VikLayerFuncChangeCoordMode)         NULL,
65
66   (VikLayerFuncAddMenuItems)            NULL,
67   (VikLayerFuncSublayerAddMenuItems)    NULL,
68
69   (VikLayerFuncSublayerRenameRequest)   NULL,
70   (VikLayerFuncSublayerToggleVisible)   NULL,
71
72   (VikLayerFuncCopy)                    coord_layer_copy,
73
74   (VikLayerFuncSetParam)                coord_layer_set_param,
75   (VikLayerFuncGetParam)                coord_layer_get_param,
76
77   (VikLayerFuncReadFileData)            NULL,
78   (VikLayerFuncWriteFileData)           NULL,
79
80   (VikLayerFuncCopyItem)                NULL,
81   (VikLayerFuncPasteItem)               NULL,
82   (VikLayerFuncFreeCopiedItem)          NULL,
83 };
84
85 struct _VikCoordLayer {
86   VikLayer vl;
87   GdkGC *gc;
88   gdouble deg_inc;
89   guint8 line_thickness;
90   gchar *color;
91 };
92
93 GType vik_coord_layer_get_type ()
94 {
95   static GType vcl_type = 0;
96
97   if (!vcl_type)
98   {
99     static const GTypeInfo vcl_info =
100     {
101       sizeof (VikCoordLayerClass),
102       NULL, /* base_init */
103       NULL, /* base_finalize */
104       NULL, /* class init */
105       NULL, /* class_finalize */
106       NULL, /* class_data */
107       sizeof (VikCoordLayer),
108       0,
109       NULL /* instance init */
110     };
111     vcl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikCoordLayer", &vcl_info, 0 );
112   }
113
114   return vcl_type;
115 }
116
117 static VikCoordLayer *coord_layer_copy ( VikCoordLayer *vcl, gpointer vp )
118 {
119   VikCoordLayer *rv = vik_coord_layer_new ( );
120
121   rv->color = g_strdup ( vcl->color );
122   rv->deg_inc = vcl->deg_inc;
123   rv->line_thickness = vcl->line_thickness;
124   rv->gc = vcl->gc;
125   g_object_ref ( rv->gc );
126   return rv;
127 }
128
129 gboolean coord_layer_set_param ( VikCoordLayer *vcl, guint16 id, VikLayerParamData data, VikViewport *vp )
130 {
131   switch ( id )
132   {
133     case PARAM_COLOR: if ( vcl->color ) g_free ( vcl->color ); vcl->color = g_strdup ( data.s ); break;
134     case PARAM_MIN_INC: vcl->deg_inc = data.d / 60.0; break;
135     case PARAM_LINE_THICKNESS: if ( data.u >= 1 && data.u <= 15 ) vcl->line_thickness = data.u; break;
136   }
137   return TRUE;
138 }
139
140 static VikLayerParamData coord_layer_get_param ( VikCoordLayer *vcl, guint16 id )
141 {
142   VikLayerParamData rv;
143   switch ( id )
144   {
145     case PARAM_COLOR: rv.s = vcl->color ? vcl->color : ""; break;
146     case PARAM_MIN_INC: rv.d = vcl->deg_inc * 60.0; break;
147     case PARAM_LINE_THICKNESS: rv.i = vcl->line_thickness; break;
148   }
149   return rv;
150 }
151
152 static void coord_layer_post_read ( VikCoordLayer *vcl, VikViewport *vp )
153 {
154   if ( vcl->gc )
155     g_object_unref ( G_OBJECT(vcl->gc) );
156
157   vcl->gc = vik_viewport_new_gc ( vp, vcl->color, vcl->line_thickness );
158 }
159
160 VikCoordLayer *vik_coord_layer_new ( )
161 {
162   VikCoordLayer *vcl = VIK_COORD_LAYER ( g_object_new ( VIK_COORD_LAYER_TYPE, NULL ) );
163   vik_layer_init ( VIK_LAYER(vcl), VIK_LAYER_COORD );
164
165   vcl->gc = NULL;
166   vcl->deg_inc = 1.0/60.0;
167   vcl->line_thickness = 3;
168   vcl->color = NULL;
169   return vcl;
170 }
171
172 void vik_coord_layer_draw ( VikCoordLayer *vcl, gpointer data )
173 {
174   VikViewport *vp = (VikViewport *) data;
175   if ( vik_viewport_get_coord_mode(vp) != VIK_COORD_UTM )
176     return;
177   if ( vcl->gc != NULL)
178   {
179     const struct UTM *center = (const struct UTM *)vik_viewport_get_center ( vp );
180     gdouble xmpp = vik_viewport_get_xmpp ( vp ), ympp = vik_viewport_get_ympp ( vp );
181     guint16 width = vik_viewport_get_width ( vp ), height = vik_viewport_get_height ( vp );
182     struct LatLon ll, ll2, min, max;
183     double lon;
184     int x1, x2;
185     struct UTM utm;
186
187     utm = *center;
188     utm.northing = center->northing - ( ympp * height / 2 );
189
190     a_coords_utm_to_latlon ( &utm, &ll );
191
192     utm.northing = center->northing + ( ympp * height / 2 );
193
194     a_coords_utm_to_latlon ( &utm, &ll2 );
195
196     {
197       /* find corner coords in lat/lon.
198         start at whichever is less: top or bottom left lon. goto whichever more: top or bottom right lon
199       */
200       struct LatLon topleft, topright, bottomleft, bottomright;
201       struct UTM temp_utm;
202       temp_utm = *center;
203       temp_utm.easting -= (width/2)*xmpp;
204       temp_utm.northing += (height/2)*ympp;
205       a_coords_utm_to_latlon ( &temp_utm, &topleft );
206       temp_utm.easting += (width*xmpp);
207       a_coords_utm_to_latlon ( &temp_utm, &topright );
208       temp_utm.northing -= (height*ympp);
209       a_coords_utm_to_latlon ( &temp_utm, &bottomright );
210       temp_utm.easting -= (width*xmpp);
211       a_coords_utm_to_latlon ( &temp_utm, &bottomleft );
212       min.lon = (topleft.lon < bottomleft.lon) ? topleft.lon : bottomleft.lon;
213       max.lon = (topright.lon > bottomright.lon) ? topright.lon : bottomright.lon;
214       min.lat = (bottomleft.lat < bottomright.lat) ? bottomleft.lat : bottomright.lat;
215       max.lat = (topleft.lat > topright.lat) ? topleft.lat : topright.lat;
216     }
217
218     lon = ((double) ((long) ((min.lon)/ vcl->deg_inc))) * vcl->deg_inc;
219     ll.lon = ll2.lon = lon;
220
221     for (; ll.lon <= max.lon; ll.lon+=vcl->deg_inc, ll2.lon+=vcl->deg_inc )
222     {
223       a_coords_latlon_to_utm ( &ll, &utm );
224       x1 = ( (utm.easting - center->easting) / xmpp ) + (width / 2);
225       a_coords_latlon_to_utm ( &ll2, &utm );
226       x2 = ( (utm.easting - center->easting) / xmpp ) + (width / 2);
227       vik_viewport_draw_line (vp, vcl->gc, x1, height, x2, 0);
228     }
229
230     utm = *center;
231     utm.easting = center->easting - ( xmpp * width / 2 );
232
233     a_coords_utm_to_latlon ( &utm, &ll );
234
235     utm.easting = center->easting + ( xmpp * width / 2 );
236
237     a_coords_utm_to_latlon ( &utm, &ll2 );
238
239     /* really lat, just reusing a variable */
240     lon = ((double) ((long) ((min.lat)/ vcl->deg_inc))) * vcl->deg_inc;
241     ll.lat = ll2.lat = lon;
242
243     for (; ll.lat <= max.lat ; ll.lat+=vcl->deg_inc, ll2.lat+=vcl->deg_inc )
244     {
245       a_coords_latlon_to_utm ( &ll, &utm );
246       x1 = (height / 2) - ( (utm.northing - center->northing) / ympp );
247       a_coords_latlon_to_utm ( &ll2, &utm );
248       x2 = (height / 2) - ( (utm.northing - center->northing) / ympp );
249       vik_viewport_draw_line (vp, vcl->gc, width, x2, 0, x1);
250     }
251   }
252 }
253
254 void vik_coord_layer_free ( VikCoordLayer *vcl )
255 {
256   if ( vcl->gc != NULL )
257     g_object_unref ( G_OBJECT(vcl->gc) );
258
259   if ( vcl->color != NULL )
260     g_free ( vcl->color );
261 }
262
263 static void coord_layer_update_gc ( VikCoordLayer *vcl, VikViewport *vp, const gchar *color )
264 {
265   if ( vcl->color )
266     g_free ( vcl->color );
267
268   vcl->color = g_strdup ( color );
269
270   if ( vcl->gc )
271     g_object_unref ( G_OBJECT(vcl->gc) );
272
273   vcl->gc = vik_viewport_new_gc ( vp, vcl->color, vcl->line_thickness );
274 }
275
276 VikCoordLayer *vik_coord_layer_create ( VikViewport *vp )
277 {
278   VikCoordLayer *vcl = vik_coord_layer_new ();
279   coord_layer_update_gc ( vcl, vp, "red" );
280   return vcl;
281 }
282