]> Pileus Git - grits/blob - src/gis-view.c
0add4f6a6dcacee97f60bc3969f005e7a39eaf16
[grits] / src / gis-view.c
1 /*
2  * Copyright (C) 2009 Andy Spencer <spenceal@rose-hulman.edu>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <glib.h>
19
20 #include "gis-marshal.h"
21 #include "gis-view.h"
22 #include "gis-world.h"
23
24 /* Constants */
25 enum {
26         PROP_0,
27         PROP_TIME,
28         PROP_SITE,
29 };
30 enum {
31         SIG_TIME_CHANGED,
32         SIG_SITE_CHANGED,
33         SIG_LOCATION_CHANGED,
34         SIG_ROTATION_CHANGED,
35         NUM_SIGNALS,
36 };
37 static guint signals[NUM_SIGNALS];
38
39 /* Misc helpers */
40 static void _gis_view_fix_location(GisView *self)
41 {
42         while (self->location[0] <  -90) self->location[0] += 180;
43         while (self->location[0] >   90) self->location[0] -= 180;
44         while (self->location[1] < -180) self->location[1] += 360;
45         while (self->location[1] >  180) self->location[1] -= 360;
46         self->location[2] = ABS(self->location[2]);
47 }
48
49 /* Signal helpers */
50 static void _gis_view_emit_location_changed(GisView *self)
51 {
52         g_signal_emit(self, signals[SIG_LOCATION_CHANGED], 0,
53                         self->location[0],
54                         self->location[1],
55                         self->location[2]);
56 }
57 static void _gis_view_emit_rotation_changed(GisView *self)
58 {
59         g_signal_emit(self, signals[SIG_ROTATION_CHANGED], 0,
60                         self->rotation[0],
61                         self->rotation[1],
62                         self->rotation[2]);
63 }
64 static void _gis_view_emit_time_changed(GisView *self)
65 {
66         g_signal_emit(self, signals[SIG_TIME_CHANGED], 0,
67                         self->time);
68 }
69 static void _gis_view_emit_site_changed(GisView *self)
70 {
71         g_signal_emit(self, signals[SIG_SITE_CHANGED], 0,
72                         self->site);
73 }
74
75
76 /***********
77  * Methods *
78  ***********/
79 GisView *gis_view_new()
80 {
81         g_debug("GisView: new");
82         return g_object_new(GIS_TYPE_VIEW, NULL);
83 }
84
85 void gis_view_set_time(GisView *self, const char *time)
86 {
87         g_assert(GIS_IS_VIEW(self));
88         g_debug("GisView: set_time - time=%s", time);
89         g_free(self->time);
90         self->time = g_strdup(time);
91         _gis_view_emit_time_changed(self);
92 }
93
94 gchar *gis_view_get_time(GisView *self)
95 {
96         g_assert(GIS_IS_VIEW(self));
97         g_debug("GisView: get_time");
98         return self->time;
99 }
100
101 void gis_view_set_location(GisView *self, gdouble lat, gdouble lon, gdouble elev)
102 {
103         g_assert(GIS_IS_VIEW(self));
104         g_debug("GisView: set_location");
105         self->location[0] = lat;
106         self->location[1] = lon;
107         self->location[2] = elev;
108         _gis_view_fix_location(self);
109         _gis_view_emit_location_changed(self);
110 }
111
112 void gis_view_get_location(GisView *self, gdouble *lat, gdouble *lon, gdouble *elev)
113 {
114         g_assert(GIS_IS_VIEW(self));
115         //g_debug("GisView: get_location");
116         *lat  = self->location[0];
117         *lon  = self->location[1];
118         *elev = self->location[2];
119 }
120
121 void gis_view_pan(GisView *self, gdouble lat, gdouble lon, gdouble elev)
122 {
123         g_assert(GIS_IS_VIEW(self));
124         g_debug("GisView: pan - lat=%8.3f, lon=%8.3f, elev=%8.3f", lat, lon, elev);
125         self->location[0] += lat;
126         self->location[1] += lon;
127         self->location[2] += elev;
128         _gis_view_fix_location(self);
129         _gis_view_emit_location_changed(self);
130 }
131
132 void gis_view_zoom(GisView *self, gdouble scale)
133 {
134         g_assert(GIS_IS_VIEW(self));
135         g_debug("GisView: zoom");
136         self->location[2] *= scale;
137         _gis_view_emit_location_changed(self);
138 }
139
140 void gis_view_set_rotation(GisView *self, gdouble x, gdouble y, gdouble z)
141 {
142         g_assert(GIS_IS_VIEW(self));
143         g_debug("GisView: set_rotation");
144         self->rotation[0] = x;
145         self->rotation[1] = y;
146         self->rotation[2] = z;
147         _gis_view_emit_rotation_changed(self);
148 }
149
150 void gis_view_get_rotation(GisView *self, gdouble *x, gdouble *y, gdouble *z)
151 {
152         g_assert(GIS_IS_VIEW(self));
153         g_debug("GisView: get_rotation");
154         *x = self->rotation[0];
155         *y = self->rotation[1];
156         *z = self->rotation[2];
157 }
158
159 void gis_view_rotate(GisView *self, gdouble x, gdouble y, gdouble z)
160 {
161         g_assert(GIS_IS_VIEW(self));
162         g_debug("GisView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z);
163         self->rotation[0] += x;
164         self->rotation[1] += y;
165         self->rotation[2] += z;
166         _gis_view_emit_rotation_changed(self);
167 }
168
169 /* To be deprecated, use {get,set}_location */
170 void gis_view_set_site(GisView *self, const gchar *site)
171 {
172         g_assert(GIS_IS_VIEW(self));
173         g_debug("GisView: set_site");
174         g_free(self->site);
175         self->site = g_strdup(site);
176         _gis_view_emit_site_changed(self);
177 }
178
179 gchar *gis_view_get_site(GisView *self)
180 {
181         g_assert(GIS_IS_VIEW(self));
182         g_debug("GisView: get_site - %s", self->site);
183         return self->site;
184 }
185
186
187 /****************
188  * GObject code *
189  ****************/
190 G_DEFINE_TYPE(GisView, gis_view, G_TYPE_OBJECT);
191 static void gis_view_init(GisView *self)
192 {
193         g_debug("GisView: init");
194         /* Default values */
195         self->time = g_strdup("");
196         self->site = g_strdup("");
197         self->location[0] = 40;
198         self->location[1] = -100;
199         self->location[2] = 1.5*EARTH_R;
200         self->rotation[0] = 0;
201         self->rotation[1] = 0;
202         self->rotation[2] = 0;
203 }
204 static void gis_view_dispose(GObject *gobject)
205 {
206         g_debug("GisView: dispose");
207         /* Drop references to other GObjects */
208         G_OBJECT_CLASS(gis_view_parent_class)->dispose(gobject);
209 }
210 static void gis_view_finalize(GObject *gobject)
211 {
212         g_debug("GisView: finalize");
213         GisView *self = GIS_VIEW(gobject);
214         g_free(self->time);
215         g_free(self->site);
216         G_OBJECT_CLASS(gis_view_parent_class)->finalize(gobject);
217 }
218 static void gis_view_set_property(GObject *object, guint property_id,
219                 const GValue *value, GParamSpec *pspec)
220 {
221         g_debug("GisView: set_property");
222         GisView *self = GIS_VIEW(object);
223         switch (property_id) {
224         case PROP_TIME:     gis_view_set_time(self, g_value_get_string(value)); break;
225         case PROP_SITE:     gis_view_set_site(self, g_value_get_string(value)); break;
226         default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
227         }
228 }
229 static void gis_view_get_property(GObject *object, guint property_id,
230                 GValue *value, GParamSpec *pspec)
231 {
232         g_debug("GisView: get_property");
233         GisView *self = GIS_VIEW(object);
234         switch (property_id) {
235         case PROP_TIME:     g_value_set_string(value, gis_view_get_time(self)); break;
236         case PROP_SITE:     g_value_set_string(value, gis_view_get_site(self)); break;
237         default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
238         }
239 }
240 static void gis_view_class_init(GisViewClass *klass)
241 {
242         g_debug("GisView: class_init");
243         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
244         gobject_class->dispose      = gis_view_dispose;
245         gobject_class->finalize     = gis_view_finalize;
246         gobject_class->get_property = gis_view_get_property;
247         gobject_class->set_property = gis_view_set_property;
248         g_object_class_install_property(gobject_class, PROP_TIME,
249                 g_param_spec_pointer(
250                         "time",
251                         "time of the current frame",
252                         "(format unknown)",
253                         G_PARAM_READWRITE));
254         g_object_class_install_property(gobject_class, PROP_SITE,
255                 g_param_spec_pointer(
256                         "site",
257                         "site seen by the viewport",
258                         "Site of the viewport. Currently this is the name of the radar site.",
259                         G_PARAM_READWRITE));
260         signals[SIG_TIME_CHANGED] = g_signal_new(
261                         "time-changed",
262                         G_TYPE_FROM_CLASS(gobject_class),
263                         G_SIGNAL_RUN_LAST,
264                         0,
265                         NULL,
266                         NULL,
267                         g_cclosure_marshal_VOID__STRING,
268                         G_TYPE_NONE,
269                         1,
270                         G_TYPE_STRING);
271         signals[SIG_SITE_CHANGED] = g_signal_new(
272                         "site-changed",
273                         G_TYPE_FROM_CLASS(gobject_class),
274                         G_SIGNAL_RUN_LAST,
275                         0,
276                         NULL,
277                         NULL,
278                         g_cclosure_marshal_VOID__STRING,
279                         G_TYPE_NONE,
280                         1,
281                         G_TYPE_STRING);
282         signals[SIG_LOCATION_CHANGED] = g_signal_new(
283                         "location-changed",
284                         G_TYPE_FROM_CLASS(gobject_class),
285                         G_SIGNAL_RUN_LAST,
286                         0,
287                         NULL,
288                         NULL,
289                         gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
290                         G_TYPE_NONE,
291                         3,
292                         G_TYPE_DOUBLE,
293                         G_TYPE_DOUBLE,
294                         G_TYPE_DOUBLE);
295         signals[SIG_ROTATION_CHANGED] = g_signal_new(
296                         "rotation-changed",
297                         G_TYPE_FROM_CLASS(gobject_class),
298                         G_SIGNAL_RUN_LAST,
299                         0,
300                         NULL,
301                         NULL,
302                         gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
303                         G_TYPE_NONE,
304                         3,
305                         G_TYPE_DOUBLE,
306                         G_TYPE_DOUBLE,
307                         G_TYPE_DOUBLE);
308 }