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 */
29 struct star_colour_data
{
34 struct star_pixmap_cache
{
35 cairo_t
*cr
[SP_NUM
][RENDER_MAG_BANDS
];
36 cairo_surface_t
*surface
[SP_NUM
][RENDER_MAG_BANDS
];
37 gint offset
[SP_NUM
][RENDER_MAG_BANDS
];
38 gdouble object_size
[SP_NUM
][RENDER_MAG_BANDS
];
42 struct star_render_size
{
47 static const struct star_render_size star_sizes
[RENDER_MAG_BANDS
] = {
64 static struct star_pixmap_cache cache
;
66 /* rgb star colours */
67 static const struct star_colour_data sp
[SP_NUM
] = {
68 {"O5V", 0.607843, 0.690196, 1.000000},
69 {"O6V", 0.635294, 0.721569, 1.000000},
70 {"O7V", 0.615686, 0.694118, 1.000000},
71 {"O8V", 0.615686, 0.694118, 1.000000},
72 {"O9V", 0.603922, 0.698039, 1.000000},
73 {"O9.5V", 0.643137, 0.729412, 1.000000},
74 {"B0V", 0.611765, 0.698039, 1.000000},
75 {"B0.5V", 0.654902, 0.737255, 1.000000},
76 {"B1V", 0.627451, 0.713725, 1.000000},
77 {"B2V", 0.627451, 0.705882, 1.000000},
78 {"B3V", 0.647059, 0.725490, 1.000000},
79 {"B4V", 0.643137, 0.721569, 1.000000},
80 {"B5V", 0.666667, 0.749020, 1.000000},
81 {"B6V", 0.674510, 0.741176, 1.000000},
82 {"B7V", 0.678431, 0.749020, 1.000000},
83 {"B8V", 0.694118, 0.764706, 1.000000},
84 {"B9V", 0.709804, 0.776471, 1.000000},
85 {"A0V", 0.725490, 0.788235, 1.000000},
86 {"A1V", 0.709804, 0.780392, 1.000000},
87 {"A2V", 0.733333, 0.796078, 1.000000},
88 {"A5V", 0.792157, 0.843137, 1.000000},
89 {"A6V", 0.780392, 0.831373, 1.000000},
90 {"A7V", 0.784314, 0.835294, 1.000000},
91 {"A8V", 0.835294, 0.870588, 1.000000},
92 {"A9V", 0.858824, 0.878431, 1.000000},
93 {"F0V", 0.878431, 0.898039, 1.000000},
94 {"F2V", 0.925490, 0.937255, 1.000000},
95 {"F4V", 0.878431, 0.886275, 1.000000},
96 {"F5V", 0.972549, 0.968627, 1.000000},
97 {"F6V", 0.956863, 0.945098, 1.000000},
98 {"F7V", 0.964706, 0.952941, 1.000000},
99 {"F8V", 1.000000, 0.968627, 0.988235},
100 {"F9V", 1.000000, 0.968627, 0.988235},
101 {"G0V", 1.000000, 0.972549, 0.988235},
102 {"G1V", 1.000000, 0.968627, 0.972549},
103 {"G2V", 1.000000, 0.960784, 0.949020},
104 {"G4V", 1.000000, 0.945098, 0.898039},
105 {"G5V", 1.000000, 0.956863, 0.917647},
106 {"G6V", 1.000000, 0.956863, 0.921569},
107 {"G7V", 1.000000, 0.956863, 0.921569},
108 {"G8V", 1.000000, 0.929412, 0.870588},
109 {"G9V", 1.000000, 0.937255, 0.866667},
110 {"K0V", 1.000000, 0.933333, 0.866667},
111 {"K1V", 1.000000, 0.878431, 0.737255},
112 {"K2V", 1.000000, 0.890196, 0.768627},
113 {"K3V", 1.000000, 0.870588, 0.764706},
114 {"K4V", 1.000000, 0.847059, 0.709804},
115 {"K5V", 1.000000, 0.823529, 0.631373},
116 {"K7V", 1.000000, 0.780392, 0.556863},
117 {"K8V", 1.000000, 0.819608, 0.682353},
118 {"M0V", 1.000000, 0.764706, 0.545098},
119 {"M1V", 1.000000, 0.800000, 0.556863},
120 {"M2V", 1.000000, 0.768627, 0.513725},
121 {"M3V", 1.000000, 0.807843, 0.505882},
122 {"M4V", 1.000000, 0.788235, 0.498039},
123 {"M5V", 1.000000, 0.800000, 0.435294},
124 {"M6V", 1.000000, 0.764706, 0.439216},
125 {"M8V", 1.000000, 0.776471, 0.427451},
126 {"B1IV", 0.615686, 0.705882, 1.000000},
127 {"B2IV", 0.623529, 0.701961, 1.000000},
128 {"B3IV", 0.650980, 0.737255, 1.000000},
129 {"B6IV", 0.686275, 0.760784, 1.000000},
130 {"B7IV", 0.666667, 0.741176, 1.000000},
131 {"B9IV", 0.705882, 0.772549, 1.000000},
132 {"A0IV", 0.701961, 0.772549, 1.000000},
133 {"A3IV", 0.745098, 0.803922, 1.000000},
134 {"A4IV", 0.764706, 0.823529, 1.000000},
135 {"A5IV", 0.831373, 0.862745, 1.000000},
136 {"A7IV", 0.752941, 0.811765, 1.000000},
137 {"A9IV", 0.878431, 0.890196, 1.000000},
138 {"F0IV", 0.854902, 0.878431, 1.000000},
139 {"F2IV", 0.890196, 0.901961, 1.000000},
140 {"F3IV", 0.890196, 0.901961, 1.000000},
141 {"F5IV", 0.945098, 0.937255, 1.000000},
142 {"F7IV", 0.941176, 0.937255, 1.000000},
143 {"F8IV", 1.000000, 0.988235, 0.992157},
144 {"G0IV", 1.000000, 0.972549, 0.960784},
145 {"G2IV", 1.000000, 0.956863, 0.949020},
146 {"G3IV", 1.000000, 0.933333, 0.886275},
147 {"G4IV", 1.000000, 0.960784, 0.933333},
148 {"G5IV", 1.000000, 0.921569, 0.835294},
149 {"G6IV", 1.000000, 0.949020, 0.917647},
150 {"G7IV", 1.000000, 0.905882, 0.803922},
151 {"G8IV", 1.000000, 0.913725, 0.827451},
152 {"K0IV", 1.000000, 0.882353, 0.741176},
153 {"K1IV", 1.000000, 0.847059, 0.670588},
154 {"K2IV", 1.000000, 0.898039, 0.792157},
155 {"K3IV", 1.000000, 0.858824, 0.654902},
156 {"O7III", 0.619608, 0.694118, 1.000000},
157 {"O8III", 0.615686, 0.698039, 1.000000},
158 {"O9III", 0.619608, 0.694118, 1.000000},
159 {"B0III", 0.619608, 0.694118, 1.000000},
160 {"B1III", 0.619608, 0.694118, 1.000000},
161 {"B2III", 0.623529, 0.705882, 1.000000},
162 {"B3III", 0.639216, 0.733333, 1.000000},
163 {"B5III", 0.658824, 0.741176, 1.000000},
164 {"B7III", 0.670588, 0.749020, 1.000000},
165 {"B9III", 0.698039, 0.764706, 1.000000},
166 {"A0III", 0.737255, 0.803922, 1.000000},
167 {"A3III", 0.741176, 0.796078, 1.000000},
168 {"A5III", 0.792157, 0.843137, 1.000000},
169 {"A6III", 0.819608, 0.858824, 1.000000},
170 {"A7III", 0.823529, 0.858824, 1.000000},
171 {"A8III", 0.819608, 0.858824, 1.000000},
172 {"A9III", 0.819608, 0.858824, 1.000000},
173 {"F0III", 0.835294, 0.870588, 1.000000},
174 {"F2III", 0.945098, 0.945098, 1.000000},
175 {"F4III", 0.945098, 0.941176, 1.000000},
176 {"F5III", 0.949020, 0.941176, 1.000000},
177 {"F6III", 0.945098, 0.941176, 1.000000},
178 {"F7III", 0.945098, 0.941176, 1.000000},
179 {"G0III", 1.000000, 0.949020, 0.913725},
180 {"G1III", 1.000000, 0.952941, 0.913725},
181 {"G2III", 1.000000, 0.952941, 0.913725},
182 {"G3III", 1.000000, 0.952941, 0.913725},
183 {"G4III", 1.000000, 0.952941, 0.913725},
184 {"G5III", 1.000000, 0.925490, 0.827451},
185 {"G6III", 1.000000, 0.925490, 0.843137},
186 {"G8III", 1.000000, 0.905882, 0.780392},
187 {"G9III", 1.000000, 0.905882, 0.768627},
188 {"K0III", 1.000000, 0.890196, 0.745098},
189 {"K1III", 1.000000, 0.874510, 0.709804},
190 {"K2III", 1.000000, 0.866667, 0.686275},
191 {"K3III", 1.000000, 0.847059, 0.654902},
192 {"K4III", 1.000000, 0.827451, 0.572549},
193 {"K5III", 1.000000, 0.800000, 0.541176},
194 {"K7III", 1.000000, 0.815686, 0.556863},
195 {"M0III", 1.000000, 0.796078, 0.517647},
196 {"M1III", 1.000000, 0.784314, 0.474510},
197 {"M2III", 1.000000, 0.776471, 0.462745},
198 {"M3III", 1.000000, 0.784314, 0.466667},
199 {"M4III", 1.000000, 0.807843, 0.498039},
200 {"M5III", 1.000000, 0.772549, 0.486275},
201 {"M6III", 1.000000, 0.698039, 0.474510},
202 {"M7III", 1.000000, 0.647059, 0.380392},
203 {"M8III", 1.000000, 0.654902, 0.380392},
204 {"M9III", 1.000000, 0.913725, 0.603922},
205 {"B2II", 0.647059, 0.752941, 1.000000},
206 {"B5II", 0.686275, 0.764706, 1.000000},
207 {"F0II", 0.796078, 0.850980, 1.000000},
208 {"F2II", 0.898039, 0.913725, 1.000000},
209 {"G5II", 1.000000, 0.921569, 0.796078},
210 {"M3II", 1.000000, 0.788235, 0.466667},
211 {"O9I", 0.643137, 0.725490, 1.000000},
212 {"B0I", 0.631373, 0.741176, 1.000000},
213 {"B1I", 0.658824, 0.756863, 1.000000},
214 {"B2I", 0.694118, 0.768627, 1.000000},
215 {"B3I", 0.686275, 0.760784, 1.000000},
216 {"B4I", 0.733333, 0.796078, 1.000000},
217 {"B5I", 0.701961, 0.792157, 1.000000},
218 {"B6I", 0.749020, 0.811765, 1.000000},
219 {"B7I", 0.764706, 0.819608, 1.000000},
220 {"B8I", 0.713725, 0.807843, 1.000000},
221 {"B9I", 0.800000, 0.847059, 1.000000},
222 {"A0I", 0.733333, 0.807843, 1.000000},
223 {"A1I", 0.839216, 0.874510, 1.000000},
224 {"A2I", 0.780392, 0.839216, 1.000000},
225 {"A5I", 0.874510, 0.898039, 1.000000},
226 {"F0I", 0.792157, 0.843137, 1.000000},
227 {"F2I", 0.956863, 0.952941, 1.000000},
228 {"F5I", 0.858824, 0.882353, 1.000000},
229 {"F8I", 1.000000, 0.988235, 0.968627},
230 {"G0I", 1.000000, 0.937255, 0.858824},
231 {"G2I", 1.000000, 0.925490, 0.803922},
232 {"G3I", 1.000000, 0.905882, 0.796078},
233 {"G5I", 1.000000, 0.901961, 0.717647},
234 {"G8I", 1.000000, 0.862745, 0.654902},
235 {"K0I", 1.000000, 0.866667, 0.709804},
236 {"K1I", 1.000000, 0.862745, 0.694118},
237 {"K2I", 1.000000, 0.827451, 0.529412},
238 {"K3I", 1.000000, 0.800000, 0.501961},
239 {"K4I", 1.000000, 0.788235, 0.462745},
240 {"K5I", 1.000000, 0.819608, 0.603922},
241 {"M0I", 1.000000, 0.800000, 0.560784},
242 {"M1I", 1.000000, 0.792157, 0.541176},
243 {"M2I", 1.000000, 0.756863, 0.407843},
244 {"M3I", 1.000000, 0.752941, 0.462745},
245 {"M4I", 1.000000, 0.725490, 0.407843},
246 {"N", 1.000000, 0.615686, 0.000000},
250 static struct astrodb_schema_object star_fields
[] = {
251 astrodb_member("Name", "Name", struct star_object
, dobject
.aobject
.name
,
252 CT_STRING
, "", 0, NULL
),
253 astrodb_member("ID", "ID", struct star_object
, dobject
.aobject
.id
,
254 CT_STRING
, "", 0, NULL
),
255 astrodb_member("RA", "RA", struct star_object
, dobject
.posn
.ra
,
256 CT_DOUBLE
, "degrees", 0, NULL
),
257 astrodb_member("DEC", "DEC", struct star_object
, dobject
.posn
.dec
,
258 CT_DOUBLE
, "degrees", 0, NULL
),
259 astrodb_gmember("RA Hours", "RAh", struct star_object
, dobject
.posn
.ra
,
260 CT_DOUBLE_HMS_HRS
, "hours", 2, NULL
),
261 astrodb_gmember("RA Minutes", "RAm", struct star_object
, dobject
.posn
.ra
,
262 CT_DOUBLE_HMS_MINS
, "minutes", 1, NULL
),
263 astrodb_gmember("RA Seconds", "RAs", struct star_object
, dobject
.posn
.ra
,
264 CT_DOUBLE_HMS_SECS
, "seconds", 0, NULL
),
265 astrodb_gmember("DEC Degrees", "DEd", struct star_object
, dobject
.posn
.dec
,
266 CT_DOUBLE_DMS_DEGS
, "degrees", 3, NULL
),
267 astrodb_gmember("DEC Minutes", "DEm", struct star_object
, dobject
.posn
.dec
,
268 CT_DOUBLE_DMS_MINS
, "minutes", 2, NULL
),
269 astrodb_gmember("DEC Seconds", "DEs", struct star_object
, dobject
.posn
.dec
,
270 CT_DOUBLE_DMS_SECS
, "seconds", 1, NULL
),
271 astrodb_gmember("DEC sign", "DE-", struct star_object
, dobject
.posn
.dec
,
272 CT_SIGN
, "", 0, NULL
),
273 astrodb_member("Visual Mag", "Vmag", struct star_object
, dobject
.Vmag
,
274 CT_FLOAT
, "", 0, NULL
),
275 astrodb_member("sp", "Sp", struct star_object
, sp
,
276 CT_STRING
, "", 0, NULL
),
277 astrodb_member("HD", "HD", struct star_object
, HD
,
278 CT_STRING
, "", 0, NULL
),
279 astrodb_member("SAO", "SAO", struct star_object
, SAO
,
280 CT_INT
, "", 0, NULL
),
283 void star_object_render(struct render_object
*robject
)
285 struct star_object
*object
= (struct star_object
*)robject
->object
;
286 guint i
= object
->dobject
.aobject
.type
;
289 if (object
->dobject
.Vmag
== FP_NAN
)
292 size
= object
->dobject
.Vmag
- RENDER_MIN_MAG
+
293 robject
->context
.mag_zero_offset
;
295 if (size
>= RENDER_MAG_BANDS
)
296 size
= RENDER_MAG_BANDS
- 1;
300 robject
->coord
[0].object_size
= cache
.object_size
[i
][size
];
302 cairo_set_source_surface(robject
->cr
, cache
.surface
[i
][size
],
303 robject
->coord
[0].x
- cache
.offset
[i
][size
],
304 robject
->coord
[0].y
- cache
.offset
[i
][size
]);
305 cairo_paint(robject
->cr
);
306 //printf("name %s\n", object->dobject.aobject.name);
309 static gint
render_pixmap(gint spi
, gint mag
)
311 gint size
= star_sizes
[mag
].size
;
312 gint surface_size
= size
+ 3;
313 gdouble radius
= (gdouble
)size
/ 2.0;
314 gdouble centre
= ((gdouble
)size
/ 2.0) + 1.5;
316 cache
.surface
[spi
][mag
] =
317 cairo_image_surface_create(CAIRO_FORMAT_ARGB32
, surface_size
,
320 if (cache
.surface
[spi
][mag
] == NULL
)
323 cache
.cr
[spi
][mag
] = cairo_create(cache
.surface
[spi
][mag
]);
324 if (cache
.cr
[spi
][mag
] == NULL
)
327 cache
.offset
[spi
][mag
] = centre
;
328 cache
.object_size
[spi
][mag
] = radius
* 2.0;
330 /* render_object transparent background */
331 cairo_set_source_rgba(cache
.cr
[spi
][mag
], 0.0, 0.0, 0.0, 0.0);
332 cairo_rectangle(cache
.cr
[spi
][mag
], 0, 0, surface_size
, surface_size
);
333 cairo_fill (cache
.cr
[spi
][mag
]);
336 cairo_set_source_rgba(cache
.cr
[spi
][mag
], 0.0, 0.0, 0.0, 1.0);
337 cairo_arc (cache
.cr
[spi
][mag
], centre
, centre
,
338 radius
* 1.1, 0, 2 * M_PI
);
339 cairo_fill (cache
.cr
[spi
][mag
]);
342 cairo_set_source_rgba(cache
.cr
[spi
][mag
],
343 sp
[spi
].r
, sp
[spi
].g
, sp
[spi
].b
,
344 star_sizes
[mag
].alpha
);
345 cairo_arc(cache
.cr
[spi
][mag
], centre
, centre
, radius
, 0, 2 * M_PI
);
346 cairo_fill(cache
.cr
[spi
][mag
]);
351 static gint
render_cache(struct astrodb_table
*table
)
355 for (spi
= 0; spi
< SP_NUM
; spi
++) {
356 for (mag
= 0; mag
< RENDER_MAG_BANDS
; mag
++) {
357 ret
= render_pixmap(spi
, mag
);
365 void star_object_free(struct astrodb_table
*table
)
369 for (spi
= 0; spi
< SP_NUM
; spi
++) {
370 for (mag
= 0; mag
< RENDER_MAG_BANDS
; mag
++) {
371 cairo_destroy(cache
.cr
[spi
][mag
]);
376 gint
star_object_init(struct astrodb_table
*table
)
378 /* Vmag is blank in some records in the dataset, so we use can Vder
379 * as an alternate field.
381 if (astrodb_table_alt_column(table
, "Vmag", "Vder", 0))
382 g_warning("%s: failed to add alt index\n", __func__
);
384 if (astrodb_table_register_schema(table
, star_fields
,
385 astrodb_size(star_fields
)) < 0)
386 g_critical("%s: failed to register object type\n", __func__
);
388 /* We want to quickly search the dataset based on object ID and HD number */
389 if (astrodb_table_hash_key(table
, "ID"))
390 g_warning("%s: failed to hash on ID\n", __func__
);
391 if (astrodb_table_hash_key(table
, "HD"))
392 g_warning("%s: failed to hash on HD\n", __func__
);
394 if (astrodb_table_open(table
, 90, 45, 20) < 0)
395 g_critical("%s: table init failed\n", __func__
);
397 /* create pixmap cache for fast rendering */
398 if (render_cache(table
) < 0)
399 g_critical("%s: failed to render cache\n", __func__
);