sky: speedup - now faster.
[nova.git] / src / objects / star.c
blobd83c9061c258c7b28bc0b74ad843c5b97a5f073d
1 /*
2 * Copyright (C) 2008 Liam Girdwood
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 2 of the License, or
7 * (at your option) any later version.
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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #define _GNU_SOURCE /* for NAN */
22 #include <errno.h>
23 #include <string.h>
24 #include <math.h>
25 #include <cairo.h>
26 #include "star.h"
28 #define SP_NUM 180
30 struct star_colour_data {
31 gchar *sp;
32 gdouble r,g,b;
35 struct star_pixmap_cache {
36 cairo_t *cr[SP_NUM][RENDER_MAG_BANDS];
37 cairo_surface_t *surface[SP_NUM][RENDER_MAG_BANDS];
38 gint offset[SP_NUM][RENDER_MAG_BANDS];
39 gdouble object_size[SP_NUM][RENDER_MAG_BANDS];
43 struct star_render_size {
44 gdouble size;
45 gdouble alpha;
48 static const struct star_render_size star_sizes[RENDER_MAG_BANDS] = {
49 {1.0, 0.5},
50 {1.0, 0.8},
51 {1.0, 1.0},
52 {1.5, 1.0},
53 {2.0, 1.0},
54 {3.0, 1.0},
55 {4.0, 1.0},
56 {5.0, 1.0},
57 {7.0, 1.0},
58 {8.0, 1.0},
59 {9.0, 1.0},
60 {10.0, 1.0},
61 {11.0, 1.0},
62 {12.0, 1.0},
63 {13.0, 1.0},
64 {14.0, 1.0},
65 {15.0, 1.0},
66 {16.0, 1.0},
67 {17.0, 1.0},
68 {18.0, 1.0},
69 {19.0, 1.0},
70 {20.0, 1.0},
71 {21.0, 1.0},
72 {22.0, 1.0},
73 {23.0, 1.0},
74 {24.0, 1.0},
75 {25.0, 1.0},
76 {26.0, 1.0},
77 {27.0, 1.0},
78 {28.0, 1.0},
79 {29.0, 1.0},
80 {30.0, 1.0},
83 static struct star_pixmap_cache cache;
85 /* rgb star colours */
86 static const struct star_colour_data sp [SP_NUM] = {
87 {"O5V", 0.607843, 0.690196, 1.000000},
88 {"O6V", 0.635294, 0.721569, 1.000000},
89 {"O7V", 0.615686, 0.694118, 1.000000},
90 {"O8V", 0.615686, 0.694118, 1.000000},
91 {"O9V", 0.603922, 0.698039, 1.000000},
92 {"O9.5V", 0.643137, 0.729412, 1.000000},
93 {"B0V", 0.611765, 0.698039, 1.000000},
94 {"B0.5V", 0.654902, 0.737255, 1.000000},
95 {"B1V", 0.627451, 0.713725, 1.000000},
96 {"B2V", 0.627451, 0.705882, 1.000000},
97 {"B3V", 0.647059, 0.725490, 1.000000},
98 {"B4V", 0.643137, 0.721569, 1.000000},
99 {"B5V", 0.666667, 0.749020, 1.000000},
100 {"B6V", 0.674510, 0.741176, 1.000000},
101 {"B7V", 0.678431, 0.749020, 1.000000},
102 {"B8V", 0.694118, 0.764706, 1.000000},
103 {"B9V", 0.709804, 0.776471, 1.000000},
104 {"A0V", 0.725490, 0.788235, 1.000000},
105 {"A1V", 0.709804, 0.780392, 1.000000},
106 {"A2V", 0.733333, 0.796078, 1.000000},
107 {"A5V", 0.792157, 0.843137, 1.000000},
108 {"A6V", 0.780392, 0.831373, 1.000000},
109 {"A7V", 0.784314, 0.835294, 1.000000},
110 {"A8V", 0.835294, 0.870588, 1.000000},
111 {"A9V", 0.858824, 0.878431, 1.000000},
112 {"F0V", 0.878431, 0.898039, 1.000000},
113 {"F2V", 0.925490, 0.937255, 1.000000},
114 {"F4V", 0.878431, 0.886275, 1.000000},
115 {"F5V", 0.972549, 0.968627, 1.000000},
116 {"F6V", 0.956863, 0.945098, 1.000000},
117 {"F7V", 0.964706, 0.952941, 1.000000},
118 {"F8V", 1.000000, 0.968627, 0.988235},
119 {"F9V", 1.000000, 0.968627, 0.988235},
120 {"G0V", 1.000000, 0.972549, 0.988235},
121 {"G1V", 1.000000, 0.968627, 0.972549},
122 {"G2V", 1.000000, 0.960784, 0.949020},
123 {"G4V", 1.000000, 0.945098, 0.898039},
124 {"G5V", 1.000000, 0.956863, 0.917647},
125 {"G6V", 1.000000, 0.956863, 0.921569},
126 {"G7V", 1.000000, 0.956863, 0.921569},
127 {"G8V", 1.000000, 0.929412, 0.870588},
128 {"G9V", 1.000000, 0.937255, 0.866667},
129 {"K0V", 1.000000, 0.933333, 0.866667},
130 {"K1V", 1.000000, 0.878431, 0.737255},
131 {"K2V", 1.000000, 0.890196, 0.768627},
132 {"K3V", 1.000000, 0.870588, 0.764706},
133 {"K4V", 1.000000, 0.847059, 0.709804},
134 {"K5V", 1.000000, 0.823529, 0.631373},
135 {"K7V", 1.000000, 0.780392, 0.556863},
136 {"K8V", 1.000000, 0.819608, 0.682353},
137 {"M0V", 1.000000, 0.764706, 0.545098},
138 {"M1V", 1.000000, 0.800000, 0.556863},
139 {"M2V", 1.000000, 0.768627, 0.513725},
140 {"M3V", 1.000000, 0.807843, 0.505882},
141 {"M4V", 1.000000, 0.788235, 0.498039},
142 {"M5V", 1.000000, 0.800000, 0.435294},
143 {"M6V", 1.000000, 0.764706, 0.439216},
144 {"M8V", 1.000000, 0.776471, 0.427451},
145 {"B1IV", 0.615686, 0.705882, 1.000000},
146 {"B2IV", 0.623529, 0.701961, 1.000000},
147 {"B3IV", 0.650980, 0.737255, 1.000000},
148 {"B6IV", 0.686275, 0.760784, 1.000000},
149 {"B7IV", 0.666667, 0.741176, 1.000000},
150 {"B9IV", 0.705882, 0.772549, 1.000000},
151 {"A0IV", 0.701961, 0.772549, 1.000000},
152 {"A3IV", 0.745098, 0.803922, 1.000000},
153 {"A4IV", 0.764706, 0.823529, 1.000000},
154 {"A5IV", 0.831373, 0.862745, 1.000000},
155 {"A7IV", 0.752941, 0.811765, 1.000000},
156 {"A9IV", 0.878431, 0.890196, 1.000000},
157 {"F0IV", 0.854902, 0.878431, 1.000000},
158 {"F2IV", 0.890196, 0.901961, 1.000000},
159 {"F3IV", 0.890196, 0.901961, 1.000000},
160 {"F5IV", 0.945098, 0.937255, 1.000000},
161 {"F7IV", 0.941176, 0.937255, 1.000000},
162 {"F8IV", 1.000000, 0.988235, 0.992157},
163 {"G0IV", 1.000000, 0.972549, 0.960784},
164 {"G2IV", 1.000000, 0.956863, 0.949020},
165 {"G3IV", 1.000000, 0.933333, 0.886275},
166 {"G4IV", 1.000000, 0.960784, 0.933333},
167 {"G5IV", 1.000000, 0.921569, 0.835294},
168 {"G6IV", 1.000000, 0.949020, 0.917647},
169 {"G7IV", 1.000000, 0.905882, 0.803922},
170 {"G8IV", 1.000000, 0.913725, 0.827451},
171 {"K0IV", 1.000000, 0.882353, 0.741176},
172 {"K1IV", 1.000000, 0.847059, 0.670588},
173 {"K2IV", 1.000000, 0.898039, 0.792157},
174 {"K3IV", 1.000000, 0.858824, 0.654902},
175 {"O7III", 0.619608, 0.694118, 1.000000},
176 {"O8III", 0.615686, 0.698039, 1.000000},
177 {"O9III", 0.619608, 0.694118, 1.000000},
178 {"B0III", 0.619608, 0.694118, 1.000000},
179 {"B1III", 0.619608, 0.694118, 1.000000},
180 {"B2III", 0.623529, 0.705882, 1.000000},
181 {"B3III", 0.639216, 0.733333, 1.000000},
182 {"B5III", 0.658824, 0.741176, 1.000000},
183 {"B7III", 0.670588, 0.749020, 1.000000},
184 {"B9III", 0.698039, 0.764706, 1.000000},
185 {"A0III", 0.737255, 0.803922, 1.000000},
186 {"A3III", 0.741176, 0.796078, 1.000000},
187 {"A5III", 0.792157, 0.843137, 1.000000},
188 {"A6III", 0.819608, 0.858824, 1.000000},
189 {"A7III", 0.823529, 0.858824, 1.000000},
190 {"A8III", 0.819608, 0.858824, 1.000000},
191 {"A9III", 0.819608, 0.858824, 1.000000},
192 {"F0III", 0.835294, 0.870588, 1.000000},
193 {"F2III", 0.945098, 0.945098, 1.000000},
194 {"F4III", 0.945098, 0.941176, 1.000000},
195 {"F5III", 0.949020, 0.941176, 1.000000},
196 {"F6III", 0.945098, 0.941176, 1.000000},
197 {"F7III", 0.945098, 0.941176, 1.000000},
198 {"G0III", 1.000000, 0.949020, 0.913725},
199 {"G1III", 1.000000, 0.952941, 0.913725},
200 {"G2III", 1.000000, 0.952941, 0.913725},
201 {"G3III", 1.000000, 0.952941, 0.913725},
202 {"G4III", 1.000000, 0.952941, 0.913725},
203 {"G5III", 1.000000, 0.925490, 0.827451},
204 {"G6III", 1.000000, 0.925490, 0.843137},
205 {"G8III", 1.000000, 0.905882, 0.780392},
206 {"G9III", 1.000000, 0.905882, 0.768627},
207 {"K0III", 1.000000, 0.890196, 0.745098},
208 {"K1III", 1.000000, 0.874510, 0.709804},
209 {"K2III", 1.000000, 0.866667, 0.686275},
210 {"K3III", 1.000000, 0.847059, 0.654902},
211 {"K4III", 1.000000, 0.827451, 0.572549},
212 {"K5III", 1.000000, 0.800000, 0.541176},
213 {"K7III", 1.000000, 0.815686, 0.556863},
214 {"M0III", 1.000000, 0.796078, 0.517647},
215 {"M1III", 1.000000, 0.784314, 0.474510},
216 {"M2III", 1.000000, 0.776471, 0.462745},
217 {"M3III", 1.000000, 0.784314, 0.466667},
218 {"M4III", 1.000000, 0.807843, 0.498039},
219 {"M5III", 1.000000, 0.772549, 0.486275},
220 {"M6III", 1.000000, 0.698039, 0.474510},
221 {"M7III", 1.000000, 0.647059, 0.380392},
222 {"M8III", 1.000000, 0.654902, 0.380392},
223 {"M9III", 1.000000, 0.913725, 0.603922},
224 {"B2II", 0.647059, 0.752941, 1.000000},
225 {"B5II", 0.686275, 0.764706, 1.000000},
226 {"F0II", 0.796078, 0.850980, 1.000000},
227 {"F2II", 0.898039, 0.913725, 1.000000},
228 {"G5II", 1.000000, 0.921569, 0.796078},
229 {"M3II", 1.000000, 0.788235, 0.466667},
230 {"O9I", 0.643137, 0.725490, 1.000000},
231 {"B0I", 0.631373, 0.741176, 1.000000},
232 {"B1I", 0.658824, 0.756863, 1.000000},
233 {"B2I", 0.694118, 0.768627, 1.000000},
234 {"B3I", 0.686275, 0.760784, 1.000000},
235 {"B4I", 0.733333, 0.796078, 1.000000},
236 {"B5I", 0.701961, 0.792157, 1.000000},
237 {"B6I", 0.749020, 0.811765, 1.000000},
238 {"B7I", 0.764706, 0.819608, 1.000000},
239 {"B8I", 0.713725, 0.807843, 1.000000},
240 {"B9I", 0.800000, 0.847059, 1.000000},
241 {"A0I", 0.733333, 0.807843, 1.000000},
242 {"A1I", 0.839216, 0.874510, 1.000000},
243 {"A2I", 0.780392, 0.839216, 1.000000},
244 {"A5I", 0.874510, 0.898039, 1.000000},
245 {"F0I", 0.792157, 0.843137, 1.000000},
246 {"F2I", 0.956863, 0.952941, 1.000000},
247 {"F5I", 0.858824, 0.882353, 1.000000},
248 {"F8I", 1.000000, 0.988235, 0.968627},
249 {"G0I", 1.000000, 0.937255, 0.858824},
250 {"G2I", 1.000000, 0.925490, 0.803922},
251 {"G3I", 1.000000, 0.905882, 0.796078},
252 {"G5I", 1.000000, 0.901961, 0.717647},
253 {"G8I", 1.000000, 0.862745, 0.654902},
254 {"K0I", 1.000000, 0.866667, 0.709804},
255 {"K1I", 1.000000, 0.862745, 0.694118},
256 {"K2I", 1.000000, 0.827451, 0.529412},
257 {"K3I", 1.000000, 0.800000, 0.501961},
258 {"K4I", 1.000000, 0.788235, 0.462745},
259 {"K5I", 1.000000, 0.819608, 0.603922},
260 {"M0I", 1.000000, 0.800000, 0.560784},
261 {"M1I", 1.000000, 0.792157, 0.541176},
262 {"M2I", 1.000000, 0.756863, 0.407843},
263 {"M3I", 1.000000, 0.752941, 0.462745},
264 {"M4I", 1.000000, 0.725490, 0.407843},
265 {"N", 1.000000, 0.615686, 0.000000},
266 {"", 1.0, 1.0, 1.0}
269 static struct astrodb_schema_object star_fields[] = {
270 astrodb_member("Name", "Name", struct star_object, dobject.aobject.name,
271 CT_STRING, "", 0, NULL),
272 astrodb_member("ID", "ID", struct star_object, dobject.aobject.id,
273 CT_STRING, "", 0, NULL),
274 astrodb_member("RA", "RA", struct star_object, dobject.posn.ra,
275 CT_DOUBLE, "degrees", 0, NULL),
276 astrodb_member("DEC", "DEC", struct star_object, dobject.posn.dec,
277 CT_DOUBLE, "degrees", 0, NULL),
278 astrodb_gmember("RA Hours", "RAh", struct star_object, dobject.posn.ra,
279 CT_DOUBLE_HMS_HRS, "hours", 2, NULL),
280 astrodb_gmember("RA Minutes", "RAm", struct star_object, dobject.posn.ra,
281 CT_DOUBLE_HMS_MINS, "minutes", 1, NULL),
282 astrodb_gmember("RA Seconds", "RAs", struct star_object, dobject.posn.ra,
283 CT_DOUBLE_HMS_SECS, "seconds", 0, NULL),
284 astrodb_gmember("DEC Degrees", "DEd", struct star_object, dobject.posn.dec,
285 CT_DOUBLE_DMS_DEGS, "degrees", 3, NULL),
286 astrodb_gmember("DEC Minutes", "DEm", struct star_object, dobject.posn.dec,
287 CT_DOUBLE_DMS_MINS, "minutes", 2, NULL),
288 astrodb_gmember("DEC Seconds", "DEs", struct star_object, dobject.posn.dec,
289 CT_DOUBLE_DMS_SECS, "seconds", 1, NULL),
290 astrodb_gmember("DEC sign", "DE-", struct star_object, dobject.posn.dec,
291 CT_SIGN, "", 0, NULL),
292 astrodb_member("Visual Mag", "Vmag", struct star_object, dobject.Vmag,
293 CT_FLOAT, "", 0, NULL),
294 astrodb_member("sp", "Sp", struct star_object, sp,
295 CT_STRING, "", 0, NULL),
296 astrodb_member("HD", "HD", struct star_object, HD,
297 CT_STRING, "", 0, NULL),
298 astrodb_member("SAO", "SAO", struct star_object, SAO,
299 CT_INT, "", 0, NULL),
302 void star_object_render(struct render_object *robject)
304 struct star_object *object = (struct star_object*)robject->object;
305 guint i = object->dobject.aobject.type;
306 gint size;
308 size = 2 + ceil(
309 (robject->context.faintest_magnitude - object->dobject.Vmag)
310 * 2.5);
312 if (size >= RENDER_MAG_BANDS)
313 size = RENDER_MAG_BANDS - 1;
314 if (size < 0)
315 size = 0;
316 if (i >= SP_NUM)
317 i = SP_NUM - 1;
319 robject->coord[0].object_size = cache.object_size[i][size];
321 cairo_set_source_surface(robject->cr, cache.surface[i][size],
322 robject->coord[0].x - cache.offset[i][size],
323 robject->coord[0].y - cache.offset[i][size]);
324 cairo_paint(robject->cr);
327 static gint render_pixmap(gint spi, gint mag)
329 gint size = star_sizes[mag].size;
330 gint surface_size = size + 3;
331 gdouble radius = (gdouble)size / 2.0;
332 gdouble centre = ((gdouble)size / 2.0) + 1.5;
334 cache.surface[spi][mag] =
335 cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_size,
336 surface_size);
338 if (cache.surface[spi][mag] == NULL)
339 return -ENOMEM;
341 cache.cr[spi][mag] = cairo_create(cache.surface[spi][mag]);
342 if (cache.cr[spi][mag] == NULL)
343 return -ENOMEM;
345 cache.offset[spi][mag] = centre;
346 cache.object_size[spi][mag] = radius * 2.0;
348 /* render_object transparent background */
349 cairo_set_source_rgba(cache.cr[spi][mag], 0.0, 0.0, 0.0, 0.0);
350 cairo_rectangle(cache.cr[spi][mag], 0, 0, surface_size, surface_size);
351 cairo_fill (cache.cr[spi][mag]);
353 /* star shadow */
354 cairo_set_source_rgba(cache.cr[spi][mag], 0.0, 0.0, 0.0, 1.0);
355 cairo_arc (cache.cr[spi][mag], centre, centre,
356 radius * 1.1, 0, 2 * M_PI);
357 cairo_fill (cache.cr[spi][mag]);
359 /* star */
360 cairo_set_source_rgba(cache.cr[spi][mag],
361 sp[spi].r, sp[spi].g, sp[spi].b,
362 star_sizes[mag].alpha);
363 cairo_arc(cache.cr[spi][mag], centre, centre, radius, 0, 2 * M_PI);
364 cairo_fill(cache.cr[spi][mag]);
366 return 0;
369 static gint render_cache(struct astrodb_table *table)
371 gint spi, mag, ret;
373 for (spi = 0; spi < SP_NUM; spi++) {
374 for (mag = 0; mag < RENDER_MAG_BANDS; mag++) {
375 ret = render_pixmap(spi, mag);
376 if (ret < 0)
377 return ret;
380 return 0;
383 void star_object_free(struct astrodb_table *table)
385 gint spi, mag;
387 for (spi = 0; spi < SP_NUM; spi++) {
388 for (mag = 0; mag < RENDER_MAG_BANDS; mag++) {
389 cairo_destroy(cache.cr[spi][mag]);
394 gint star_object_init(struct astrodb_table *table)
396 /* Vmag is blank in some records in the dataset, so we use can Vder
397 * as an alternate field.
399 if (astrodb_table_alt_column(table, "Vmag", "Vder", 0))
400 g_warning("%s: failed to add alt index\n", __func__);
402 if (astrodb_table_register_schema(table, star_fields,
403 astrodb_size(star_fields)) < 0)
404 g_critical("%s: failed to register object type\n", __func__);
406 /* We want to quickly search the dataset based on object ID and HD number */
407 if (astrodb_table_hash_key(table, "ID"))
408 g_warning("%s: failed to hash on ID\n", __func__);
409 if (astrodb_table_hash_key(table, "HD"))
410 g_warning("%s: failed to hash on HD\n", __func__);
412 if (astrodb_table_open(table, 20, 10, 20) < 0)
413 g_critical("%s: table init failed\n", __func__);
415 /* create pixmap cache for fast rendering */
416 if (render_cache(table) < 0)
417 g_critical("%s: failed to render cache\n", __func__);
419 return 0;