]> Pileus Git - grits/blob - src/gis-viewer.c
Add primitive rendering types
[grits] / src / gis-viewer.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
23 /* Constants */
24 enum {
25         PROP_0,
26         PROP_TIME,
27         PROP_SITE,
28         PROP_OFFLINE,
29 };
30 enum {
31         SIG_TIME_CHANGED,
32         SIG_SITE_CHANGED,
33         SIG_LOCATION_CHANGED,
34         SIG_ROTATION_CHANGED,
35         SIG_REFRESH,
36         SIG_OFFLINE,
37         NUM_SIGNALS,
38 };
39 static guint signals[NUM_SIGNALS];
40
41 /* Misc helpers */
42 static void _gis_view_fix_location(GisView *self)
43 {
44         while (self->location[0] <  -90) self->location[0] += 180;
45         while (self->location[0] >   90) self->location[0] -= 180;
46         while (self->location[1] < -180) self->location[1] += 360;
47         while (self->location[1] >  180) self->location[1] -= 360;
48         self->location[2] = ABS(self->location[2]);
49 }
50
51 /* Signal helpers */
52 static void _gis_view_emit_location_changed(GisView *self)
53 {
54         g_signal_emit(self, signals[SIG_LOCATION_CHANGED], 0,
55                         self->location[0],
56                         self->location[1],
57                         self->location[2]);
58 }
59 static void _gis_view_emit_rotation_changed(GisView *self)
60 {
61         g_signal_emit(self, signals[SIG_ROTATION_CHANGED], 0,
62                         self->rotation[0],
63                         self->rotation[1],
64                         self->rotation[2]);
65 }
66 static void _gis_view_emit_time_changed(GisView *self)
67 {
68         g_signal_emit(self, signals[SIG_TIME_CHANGED], 0,
69                         self->time);
70 }
71 static void _gis_view_emit_site_changed(GisView *self)
72 {
73         g_signal_emit(self, signals[SIG_SITE_CHANGED], 0,
74                         self->site);
75 }
76 static void _gis_world_emit_refresh(GisWorld *world)
77 {
78         g_signal_emit(world, signals[SIG_REFRESH], 0);
79 }
80 static void _gis_world_emit_offline(GisWorld *world)
81 {
82         g_signal_emit(world, signals[SIG_OFFLINE], 0,
83                         world->offline);
84 }
85
86
87 /***********
88  * Methods *
89  ***********/
90 GisView *gis_view_new()
91 {
92         g_debug("GisView: new");
93         return g_object_new(GIS_TYPE_VIEW, NULL);
94 }
95
96 void gis_view_set_time(GisView *self, const char *time)
97 {
98         g_assert(GIS_IS_VIEW(self));
99         g_debug("GisView: set_time - time=%s", time);
100         g_free(self->time);
101         self->time = g_strdup(time);
102         _gis_view_emit_time_changed(self);
103 }
104
105 gchar *gis_view_get_time(GisView *self)
106 {
107         g_assert(GIS_IS_VIEW(self));
108         g_debug("GisView: get_time");
109         return self->time;
110 }
111
112 void gis_view_set_location(GisView *self, gdouble lat, gdouble lon, gdouble elev)
113 {
114         g_assert(GIS_IS_VIEW(self));
115         g_debug("GisView: set_location");
116         self->location[0] = lat;
117         self->location[1] = lon;
118         self->location[2] = elev;
119         _gis_view_fix_location(self);
120         _gis_view_emit_location_changed(self);
121 }
122
123 void gis_view_get_location(GisView *self, gdouble *lat, gdouble *lon, gdouble *elev)
124 {
125         g_assert(GIS_IS_VIEW(self));
126         //g_debug("GisView: get_location");
127         *lat  = self->location[0];
128         *lon  = self->location[1];
129         *elev = self->location[2];
130 }
131
132 void gis_view_pan(GisView *self, gdouble lat, gdouble lon, gdouble elev)
133 {
134         g_assert(GIS_IS_VIEW(self));
135         g_debug("GisView: pan - lat=%8.3f, lon=%8.3f, elev=%8.3f", lat, lon, elev);
136         self->location[0] += lat;
137         self->location[1] += lon;
138         self->location[2] += elev;
139         _gis_view_fix_location(self);
140         _gis_view_emit_location_changed(self);
141 }
142
143 void gis_view_zoom(GisView *self, gdouble scale)
144 {
145         g_assert(GIS_IS_VIEW(self));
146         g_debug("GisView: zoom");
147         self->location[2] *= scale;
148         _gis_view_emit_location_changed(self);
149 }
150
151 void gis_view_set_rotation(GisView *self, gdouble x, gdouble y, gdouble z)
152 {
153         g_assert(GIS_IS_VIEW(self));
154         g_debug("GisView: set_rotation");
155         self->rotation[0] = x;
156         self->rotation[1] = y;
157         self->rotation[2] = z;
158         _gis_view_emit_rotation_changed(self);
159 }
160
161 void gis_view_get_rotation(GisView *self, gdouble *x, gdouble *y, gdouble *z)
162 {
163         g_assert(GIS_IS_VIEW(self));
164         g_debug("GisView: get_rotation");
165         *x = self->rotation[0];
166         *y = self->rotation[1];
167         *z = self->rotation[2];
168 }
169
170 void gis_view_rotate(GisView *self, gdouble x, gdouble y, gdouble z)
171 {
172         g_assert(GIS_IS_VIEW(self));
173         g_debug("GisView: rotate - x=%.0f, y=%.0f, z=%.0f", x, y, z);
174         self->rotation[0] += x;
175         self->rotation[1] += y;
176         self->rotation[2] += z;
177         _gis_view_emit_rotation_changed(self);
178 }
179
180 /* To be deprecated, use {get,set}_location */
181 void gis_view_set_site(GisView *self, const gchar *site)
182 {
183         g_assert(GIS_IS_VIEW(self));
184         g_debug("GisView: set_site");
185         g_free(self->site);
186         self->site = g_strdup(site);
187         _gis_view_emit_site_changed(self);
188 }
189
190 gchar *gis_view_get_site(GisView *self)
191 {
192         g_assert(GIS_IS_VIEW(self));
193         g_debug("GisView: get_site - %s", self->site);
194         return self->site;
195 }
196
197 void gis_world_refresh(GisWorld *world)
198 {
199         g_debug("GisWorld: refresh");
200         _gis_world_emit_refresh(world);
201 }
202
203 void gis_world_set_offline(GisWorld *world, gboolean offline)
204 {
205         g_assert(GIS_IS_WORLD(world));
206         g_debug("GisWorld: set_offline - %d", offline);
207         world->offline = offline;
208         _gis_world_emit_offline(world);
209 }
210
211 gboolean gis_world_get_offline(GisWorld *world)
212 {
213         g_assert(GIS_IS_WORLD(world));
214         g_debug("GisWorld: get_offline - %d", world->offline);
215         return world->offline;
216 }
217
218
219 /****************
220  * GObject code *
221  ****************/
222 G_DEFINE_TYPE(GisView, gis_view, G_TYPE_OBJECT);
223 static void gis_view_init(GisView *self)
224 {
225         g_debug("GisView: init");
226         /* Default values */
227         self->time = g_strdup("");
228         self->site = g_strdup("");
229         self->location[0] = 40;
230         self->location[1] = -100;
231         self->location[2] = 1.5*EARTH_R;
232         self->rotation[0] = 0;
233         self->rotation[1] = 0;
234         self->rotation[2] = 0;
235 }
236 static void gis_view_dispose(GObject *gobject)
237 {
238         g_debug("GisView: dispose");
239         /* Drop references to other GObjects */
240         G_OBJECT_CLASS(gis_view_parent_class)->dispose(gobject);
241 }
242 static void gis_view_finalize(GObject *gobject)
243 {
244         g_debug("GisView: finalize");
245         GisView *self = GIS_VIEW(gobject);
246         g_free(self->time);
247         g_free(self->site);
248         G_OBJECT_CLASS(gis_view_parent_class)->finalize(gobject);
249 }
250 static void gis_view_set_property(GObject *object, guint property_id,
251                 const GValue *value, GParamSpec *pspec)
252 {
253         g_debug("GisView: set_property");
254         GisView *self = GIS_VIEW(object);
255         switch (property_id) {
256         case PROP_TIME:     gis_view_set_time(self, g_value_get_string (value));  break;
257         case PROP_SITE:     gis_view_set_site(self, g_value_get_string (value));  break;
258         case PROP_OFFLINE:  gis_view_set_site(self, g_value_get_boolean(value)); break;
259         default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
260         }
261 }
262 static void gis_view_get_property(GObject *object, guint property_id,
263                 GValue *value, GParamSpec *pspec)
264 {
265         g_debug("GisView: get_property");
266         GisView *self = GIS_VIEW(object);
267         switch (property_id) {
268         case PROP_TIME:     g_value_set_string (value, gis_view_get_time(self)); break;
269         case PROP_SITE:     g_value_set_string (value, gis_view_get_site(self)); break;
270         case PROP_OFFLINE:  g_value_set_boolean(value, gis_view_get_site(self)); break;
271         default:            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
272         }
273 }
274 static void gis_view_class_init(GisViewClass *klass)
275 {
276         g_debug("GisView: class_init");
277         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
278         gobject_class->dispose      = gis_view_dispose;
279         gobject_class->finalize     = gis_view_finalize;
280         gobject_class->get_property = gis_view_get_property;
281         gobject_class->set_property = gis_view_set_property;
282         g_object_class_install_property(gobject_class, PROP_TIME,
283                 g_param_spec_pointer(
284                         "time",
285                         "time of the current frame",
286                         "(format unknown)",
287                         G_PARAM_READWRITE));
288         g_object_class_install_property(gobject_class, PROP_SITE,
289                 g_param_spec_pointer(
290                         "site",
291                         "site seen by the viewport",
292                         "Site of the viewport. Currently this is the name of the radar site.",
293                         G_PARAM_READWRITE));
294         g_object_class_install_property(gobject_class, PROP_OFFLINE,
295                 g_param_spec_pointer(
296                         "offline",
297                         "whether the viewer should access the network",
298                         "Offline state of the viewer. If set to true, the viewer will not access the network",
299                         G_PARAM_READWRITE));
300         signals[SIG_TIME_CHANGED] = g_signal_new(
301                         "time-changed",
302                         G_TYPE_FROM_CLASS(gobject_class),
303                         G_SIGNAL_RUN_LAST,
304                         0,
305                         NULL,
306                         NULL,
307                         g_cclosure_marshal_VOID__STRING,
308                         G_TYPE_NONE,
309                         1,
310                         G_TYPE_STRING);
311         signals[SIG_SITE_CHANGED] = g_signal_new(
312                         "site-changed",
313                         G_TYPE_FROM_CLASS(gobject_class),
314                         G_SIGNAL_RUN_LAST,
315                         0,
316                         NULL,
317                         NULL,
318                         g_cclosure_marshal_VOID__STRING,
319                         G_TYPE_NONE,
320                         1,
321                         G_TYPE_STRING);
322         signals[SIG_LOCATION_CHANGED] = g_signal_new(
323                         "location-changed",
324                         G_TYPE_FROM_CLASS(gobject_class),
325                         G_SIGNAL_RUN_LAST,
326                         0,
327                         NULL,
328                         NULL,
329                         gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
330                         G_TYPE_NONE,
331                         3,
332                         G_TYPE_DOUBLE,
333                         G_TYPE_DOUBLE,
334                         G_TYPE_DOUBLE);
335         signals[SIG_ROTATION_CHANGED] = g_signal_new(
336                         "rotation-changed",
337                         G_TYPE_FROM_CLASS(gobject_class),
338                         G_SIGNAL_RUN_LAST,
339                         0,
340                         NULL,
341                         NULL,
342                         gis_cclosure_marshal_VOID__DOUBLE_DOUBLE_DOUBLE,
343                         G_TYPE_NONE,
344                         3,
345                         G_TYPE_DOUBLE,
346                         G_TYPE_DOUBLE,
347                         G_TYPE_DOUBLE);
348         signals[SIG_REFRESH] = g_signal_new(
349                         "refresh",
350                         G_TYPE_FROM_CLASS(gobject_class),
351                         G_SIGNAL_RUN_LAST,
352                         0,
353                         NULL,
354                         NULL,
355                         g_cclosure_marshal_VOID__VOID,
356                         G_TYPE_NONE,
357                         0);
358         signals[SIG_OFFLINE] = g_signal_new(
359                         "offline",
360                         G_TYPE_FROM_CLASS(gobject_class),
361                         G_SIGNAL_RUN_LAST,
362                         0,
363                         NULL,
364                         NULL,
365                         g_cclosure_marshal_VOID__BOOLEAN,
366                         G_TYPE_NONE,
367                         1,
368                         G_TYPE_BOOLEAN);
369 }