catalogs: updated to new libastro API.
[nova.git] / src / sky / grid.c
blob3f08801e3a6e01f67298c12e8dab9fa1fcd4bc48
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.
19 * Fast sky grid render engine. Mostly working, although probably needs
20 * checking by a maths trig guru to further optimise (and clip RA line at 80).
24 #define _GNU_SOURCE /* for NAN and INF */
26 #include <math.h>
27 #include <stdio.h>
29 #include "astro_object.h"
30 #include "grid.h"
32 #define D2R (1.7453292519943295769e-2) /* deg->radian */
33 #define R2D (5.7295779513082320877e1) /* radian->deg */
35 #define GRID_BISECT 128.0
36 #define GRID_NIGHT_ALPHA 0.35
37 #define GRID_DAY_ALPHA 0.45
38 #define GRID_HALF_MAX_FOV (PROJ_MAX_FOV / 2.0)
41 /* RA grid in arcsecs */
42 static const gdouble grid_hms_ra[] = {
43 15.0 * 60.0 * 60.0,
44 15.0 * 60.0 * 10.0,
45 15.0 * 60.0 * 5.0,
46 15.0 * 60.0,
47 15.0 * 10.0,
48 15.0 * 5.0,
49 15.0,
50 7.5,
51 1.5,
54 /* DEC drid in arcsecs */
55 static const gdouble grid_dms_dec[] = {
56 3600.0 * 10.0,
57 3600.0 * 5.0,
58 3600.0,
59 1200.0,
60 600.0,
61 300.0,
62 60.0,
63 10.0,
64 5.0,
65 1.0,
68 static inline int equ_is_tile_visible(struct projection *proj, gint ra, gint dec)
70 struct render_object robject;
71 struct ln_equ_posn pos;
73 pos.ra = ra * GRID_RA_TILE_SIZE;
74 pos.dec = PROJ_MIN_DEC + dec * GRID_DEC_TILE_SIZE;
75 robject.coord[0].posn = &pos;
76 proj->trans->sky_to_proj_equ(proj, &robject.coord[0]);
77 return projection_is_visible0(proj, &robject);
80 static inline int hrz_is_tile_visible(struct projection *proj, gint ra, gint dec)
82 struct render_object robject;
83 struct ln_equ_posn pos;
85 pos.ra = ra * GRID_RA_TILE_SIZE;
86 pos.dec = PROJ_MIN_DEC + dec * GRID_DEC_TILE_SIZE;
87 robject.coord[0].posn = &pos;
88 proj->trans->sky_to_proj_hrz(proj, &robject.coord[0]);
89 return projection_is_visible0(proj, &robject);
92 static inline void mark_tiles(struct projection *proj,
93 gint ra, gint dec)
95 gint ra_start = ra - 1, ra_end = ra + 1;
96 gint dec_start = dec - 1, dec_end = dec + 1;
98 if (ra_start < 0)
99 ra_start = GRID_RA_TILES -1;
100 if (ra_end == GRID_RA_TILES)
101 ra_end = 0;
102 if (dec_start < 0)
103 dec_start = 0;
104 if (dec_end == GRID_DEC_TILES)
105 dec_end = GRID_DEC_TILES - 1;
107 proj->grid_tile[ra][dec] = 1;
108 proj->grid_tile[ra_start][dec_start] = 1;
109 proj->grid_tile[ra_end][dec_start] = 1;
110 proj->grid_tile[ra_start][dec_end] = 1;
111 proj->grid_tile[ra_end][dec_end] = 1;
112 proj->grid_tile[ra][dec_start] = 1;
113 proj->grid_tile[ra][dec_end] = 1;
114 proj->grid_tile[ra_start][dec] = 1;
115 proj->grid_tile[ra_end][dec] = 1;
118 static void equ_get_visible_tiles(struct projection *proj)
120 gint ra, dec;
122 /* clear all tiles first */
123 for (ra = 0; ra < GRID_RA_TILES; ra++) {
124 for (dec = 0; dec < GRID_DEC_TILES; dec++) {
125 proj->grid_tile[ra][dec] = 0;
129 /* check each tile */
130 for (ra = 0; ra < GRID_RA_TILES; ra++) {
131 for (dec = 0; dec < GRID_DEC_TILES; dec++) {
132 if (equ_is_tile_visible(proj, ra, dec))
133 mark_tiles(proj, ra, dec);
137 /* now check centre RA, DEC if tile size > fov */
138 if (proj->fov <= GRID_RA_TILE_SIZE * 1.1)
139 mark_tiles(proj, (gint)(proj->centre_az / GRID_RA_TILE_SIZE),
140 (gint)(proj->centre_alt / GRID_DEC_TILE_SIZE + 9));
143 static void hrz_get_visible_tiles(struct projection *proj)
145 gint ra, dec;
147 /* clear all tiles first */
148 for (ra = 0; ra < GRID_RA_TILES; ra++) {
149 for (dec = 0; dec < GRID_DEC_TILES; dec++) {
150 proj->grid_tile[ra][dec] = 0;
154 /* check each tile */
155 for (ra = 0; ra < GRID_RA_TILES; ra++) {
156 for (dec = 0; dec < GRID_DEC_TILES; dec++) {
157 if (hrz_is_tile_visible(proj, ra, dec))
158 mark_tiles(proj, ra, dec);
162 /* now check centre RA, DEC if tile size > fov */
163 if (proj->fov <= GRID_RA_TILE_SIZE * 1.1)
164 mark_tiles(proj, (gint)(proj->centre_az / GRID_RA_TILE_SIZE),
165 (gint)(proj->centre_alt / GRID_DEC_TILE_SIZE + 9));
168 /* get grid RA step size for projection in arcsecs */
169 static gdouble get_ra_step_delta(struct projection *proj)
171 gint i;
173 for (i = 0; i < nsize(grid_hms_ra); i++) {
174 if (proj->fov / 1.1 > grid_hms_ra[i] / 3600.0)
175 return grid_hms_ra[i] / 3600.0;
177 return grid_hms_ra[i] / 3600.0;
180 /* get grid DEC step size for projection in arcsecs */
181 static gdouble get_dec_step_delta(struct projection *proj)
183 gint i;
185 for (i = 0; i < nsize(grid_dms_dec); i++) {
186 if (proj->fov / 1.1 > grid_dms_dec[i] / 3600.0)
187 return grid_dms_dec[i] / 3600.0;
189 return grid_dms_dec[i] / 3600.0;
192 static void equ_render_dec_labels_at(struct projection *proj,
193 struct render_object *robject, gdouble dec)
195 gchar text[32];
196 gdouble step_delta, delta_div = 2.0;
197 struct ln_equ_posn pos_start, pos_end;
198 struct ln_dms dms;
200 step_delta = get_dec_step_delta(proj);
202 pos_start.ra = proj->centre_az;
203 pos_end.ra = proj->centre_az;
204 pos_start.dec = pos_end.dec = dec;
205 robject->coord[0].posn = &pos_start;
206 robject->coord[1].posn = &pos_end;
208 /* find start position */
209 do {
210 pos_start.ra -= step_delta;
211 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
212 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
213 } while (projection_is_visible0(proj, robject) &&
214 proj->centre_az - pos_start.ra < GRID_HALF_MAX_FOV);
215 pos_start.ra += step_delta;
217 /* binary chop start */
218 do {
219 pos_start.ra -= step_delta / delta_div;
220 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
221 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
222 if (!projection_is_visible0(proj, robject))
223 pos_start.ra += step_delta / delta_div;
224 delta_div *= 2.0;
225 } while (delta_div < GRID_BISECT);
227 /* find end position */
228 do {
229 pos_end.ra += step_delta;
230 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
231 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
232 } while (projection_is_visible1(proj, robject) &&
233 pos_end.ra - proj->centre_az < GRID_HALF_MAX_FOV);
234 pos_end.ra -= step_delta;
236 /* binary chop end */
237 delta_div = 2.0;
238 do {
239 pos_end.ra += step_delta / delta_div;
240 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
241 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
242 if (!projection_is_visible1(proj, robject))
243 pos_end.ra -= step_delta / delta_div;
244 delta_div *= 2.0;
245 } while (delta_div < GRID_BISECT);
247 ln_deg_to_dms(dec, &dms);
248 if (dms.neg)
249 text[0] = '-';
250 else
251 text[0] = '+';
252 if (dms.minutes == 0 && dms.seconds == 0.0)
253 sprintf(&text[1], "%2.2dº", dms.degrees);
254 else if (dms.seconds < 0.1)
255 sprintf(&text[1], "%2.2dº%2.2dm", dms.degrees, dms.minutes);
256 else
257 sprintf(&text[1], "%2.2dº%2.2dm%2.0f", dms.degrees, dms.minutes,
258 dms.seconds);
260 cairo_move_to(robject->cr,
261 robject->coord[0].x - 30.0,
262 robject->coord[0].y - 1.0);
263 cairo_show_text(robject->cr, text);
264 cairo_move_to(robject->cr,
265 robject->coord[1].x + 1.0,
266 robject->coord[1].y - 1.0);
267 cairo_show_text(robject->cr, text);
270 static void equ_render_ra_labels_at(struct projection *proj,
271 struct render_object *robject, gdouble ra)
273 gchar text[32];
274 gdouble step_delta, delta_div = 2.0;
275 struct ln_equ_posn pos_start, pos_end;
276 struct ln_hms hms;
278 step_delta = get_ra_step_delta(proj);
280 pos_start.dec = proj->centre_alt;
281 pos_end.dec = proj->centre_alt;
282 pos_start.ra = pos_end.ra = ra;
283 robject->coord[0].posn = &pos_start;
284 robject->coord[1].posn = &pos_end;
286 /* find start position */
287 do {
288 pos_start.dec -= step_delta;
289 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
290 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
291 } while (projection_is_visible0(proj, robject) &&
292 proj->centre_alt - pos_start.dec < GRID_HALF_MAX_FOV);
293 pos_start.dec += step_delta;
295 /* binary chop start */
296 do {
297 pos_start.dec -= step_delta / delta_div;
298 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
299 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
300 if (!projection_is_visible0(proj, robject))
301 pos_start.dec += step_delta / delta_div;
302 delta_div *= 2.0;
303 } while (delta_div < GRID_BISECT);
305 /* find end position */
306 do {
307 pos_end.dec += step_delta;
308 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
309 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
310 } while (projection_is_visible1(proj, robject) &&
311 pos_end.dec - proj->centre_alt < GRID_HALF_MAX_FOV);
312 pos_end.dec -= step_delta;
314 /* binary chop end */
315 delta_div = 2.0;
316 do {
317 pos_end.dec += step_delta / delta_div;
318 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
319 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
320 if (!projection_is_visible1(proj, robject))
321 pos_end.dec -= step_delta / delta_div;
322 delta_div *= 2.0;
323 } while (delta_div < GRID_BISECT);
325 ln_deg_to_hms(ra, &hms);
326 if (hms.minutes == 0 && hms.seconds == 0.0)
327 sprintf(text, "%2.2dh", hms.hours);
328 else if (hms.seconds < 0.1)
329 sprintf(text, "%2.0dh%2.2dm", hms.hours, hms.minutes);
330 else
331 sprintf(text, "%2.0dh%2.2dm%2.0f", hms.hours, hms.minutes,
332 hms.seconds);
334 cairo_move_to(robject->cr,
335 robject->coord[0].x,
336 robject->coord[0].y);
337 cairo_show_text(robject->cr, text);
338 cairo_move_to(robject->cr,
339 robject->coord[1].x,
340 robject->coord[1].y + 15.0); // font size
341 cairo_show_text(robject->cr, text);
344 static void hrz_render_dec_labels_at(struct projection *proj,
345 struct render_object *robject, gdouble dec)
347 gchar text[32];
348 gdouble step_delta, delta_div = 2.0;
349 struct ln_equ_posn pos_start, pos_end;
350 struct ln_dms dms;
352 step_delta = get_dec_step_delta(proj);
354 pos_start.ra = proj->centre_ra;
355 pos_end.ra = proj->centre_ra;
356 pos_start.dec = pos_end.dec = dec;
357 robject->coord[0].posn = &pos_start;
358 robject->coord[1].posn = &pos_end;
360 /* find start position */
361 do {
362 pos_start.ra -= step_delta;
363 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
364 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
365 } while (projection_is_visible0(proj, robject) &&
366 proj->centre_ra - pos_start.ra < GRID_HALF_MAX_FOV);
367 pos_start.ra += step_delta;
369 /* binary chop start */
370 do {
371 pos_start.ra -= step_delta / delta_div;
372 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
373 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
374 if (!projection_is_visible0(proj, robject))
375 pos_start.ra += step_delta / delta_div;
376 delta_div *= 2.0;
377 } while (delta_div < GRID_BISECT);
379 /* find end position */
380 do {
381 pos_end.ra += step_delta;
382 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
383 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
384 } while (projection_is_visible1(proj, robject) &&
385 pos_end.ra - proj->centre_ra < GRID_HALF_MAX_FOV);
386 pos_end.ra -= step_delta;
388 /* binary chop end */
389 delta_div = 2.0;
390 do {
391 pos_end.ra += step_delta / delta_div;
392 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
393 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
394 if (!projection_is_visible1(proj, robject))
395 pos_end.ra -= step_delta / delta_div;
396 delta_div *= 2.0;
397 } while (delta_div < GRID_BISECT);
399 ln_deg_to_dms(dec, &dms);
400 if (dms.neg)
401 text[0] = '-';
402 else
403 text[0] = '+';
404 if (dms.minutes == 0 && dms.seconds == 0.0)
405 sprintf(&text[1], "%2.2dº", dms.degrees);
406 else if (dms.seconds < 0.1)
407 sprintf(&text[1], "%2.2dº%2.2dm", dms.degrees, dms.minutes);
408 else
409 sprintf(&text[1], "%2.2dº%2.2dm%2.0f", dms.degrees, dms.minutes,
410 dms.seconds);
412 cairo_move_to(robject->cr,
413 robject->coord[0].x - 30.0,
414 robject->coord[0].y - 1.0);
415 cairo_show_text(robject->cr, text);
416 cairo_move_to(robject->cr,
417 robject->coord[1].x + 1.0,
418 robject->coord[1].y - 1.0);
419 cairo_show_text(robject->cr, text);
422 static void hrz_render_ra_labels_at(struct projection *proj,
423 struct render_object *robject, gdouble ra)
425 gchar text[32];
426 gdouble step_delta, delta_div = 2.0;
427 struct ln_equ_posn pos_start, pos_end;
428 struct ln_hms hms;
430 step_delta = get_ra_step_delta(proj);
432 pos_start.dec = proj->centre_dec;
433 pos_end.dec = proj->centre_dec;
434 pos_start.ra = pos_end.ra = ra;
435 robject->coord[0].posn = &pos_start;
436 robject->coord[1].posn = &pos_end;
438 /* find start position */
439 do {
440 pos_start.dec -= step_delta;
441 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
442 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
443 } while (projection_is_visible0(proj, robject) &&
444 proj->centre_dec - pos_start.dec < GRID_HALF_MAX_FOV);
445 pos_start.dec += step_delta;
447 /* binary chop start */
448 do {
449 pos_start.dec -= step_delta / delta_div;
450 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
451 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
452 if (!projection_is_visible0(proj, robject))
453 pos_start.dec += step_delta / delta_div;
454 delta_div *= 2.0;
455 } while (delta_div < GRID_BISECT);
457 /* find end position */
458 do {
459 pos_end.dec += step_delta;
460 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
461 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
462 } while (projection_is_visible1(proj, robject) &&
463 pos_end.dec - proj->centre_dec < GRID_HALF_MAX_FOV);
464 pos_end.dec -= step_delta;
466 /* binary chop end */
467 delta_div = 2.0;
468 do {
469 pos_end.dec += step_delta / delta_div;
470 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
471 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
472 if (!projection_is_visible1(proj, robject))
473 pos_end.dec -= step_delta / delta_div;
474 delta_div *= 2.0;
475 } while (delta_div < GRID_BISECT);
477 ln_deg_to_hms(ra, &hms);
478 if (hms.minutes == 0 && hms.seconds == 0.0)
479 sprintf(text, "%2.2dh", hms.hours);
480 else if (hms.seconds < 0.1)
481 sprintf(text, "%2.0dh%2.2dm", hms.hours, hms.minutes);
482 else
483 sprintf(text, "%2.0dh%2.2dm%2.0f", hms.hours, hms.minutes,
484 hms.seconds);
486 cairo_move_to(robject->cr,
487 robject->coord[0].x,
488 robject->coord[0].y);
489 cairo_show_text(robject->cr, text);
490 cairo_move_to(robject->cr,
491 robject->coord[1].x,
492 robject->coord[1].y + 15.0); // font size
493 cairo_show_text(robject->cr, text);
496 void equ_render_dec_labels(struct render_object *robject,
497 struct projection *proj, gdouble dec_start, gdouble dec_end)
499 gdouble step, step_delta;
500 struct ln_equ_posn pos1;
502 pos1.ra = proj->centre_az;
504 step_delta = get_dec_step_delta(proj);
505 robject->coord[0].posn = &pos1;
507 for (step = dec_start; step <= dec_end; step += step_delta) {
508 pos1.dec = step;
509 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
510 equ_render_dec_labels_at(proj, robject, step);
514 void equ_render_ra_labels(struct render_object *robject,
515 struct projection *proj, gdouble ra_start, gdouble ra_end)
517 gdouble step, step_delta;
518 struct ln_equ_posn pos1;
520 pos1.dec = proj->centre_alt;
522 step_delta = get_ra_step_delta(proj);
523 robject->coord[0].posn = &pos1;
525 for (step = ra_start; step <= ra_end; step += step_delta) {
526 pos1.ra = step;
527 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
528 equ_render_ra_labels_at(proj, robject, step);
532 void hrz_render_dec_labels(struct render_object *robject,
533 struct projection *proj, gdouble dec_start, gdouble dec_end)
535 gdouble step, step_delta;
536 struct ln_equ_posn pos1;
538 pos1.ra = proj->centre_ra;
540 step_delta = get_dec_step_delta(proj);
541 robject->coord[0].posn = &pos1;
543 for (step = dec_start; step <= dec_end; step += step_delta) {
544 pos1.dec = step;
545 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
546 hrz_render_dec_labels_at(proj, robject, step);
550 void hrz_render_ra_labels(struct render_object *robject,
551 struct projection *proj, gdouble ra_start, gdouble ra_end)
553 gdouble step, step_delta;
554 struct ln_equ_posn pos1;
556 pos1.dec = proj->centre_dec;
558 step_delta = get_ra_step_delta(proj);
559 robject->coord[0].posn = &pos1;
561 for (step = ra_start; step <= ra_end; step += step_delta) {
562 pos1.ra = step;
563 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
564 hrz_render_ra_labels_at(proj, robject, step);
568 static inline void equ_ra_line(struct render_object *robject,
569 struct projection *proj, struct ln_equ_posn *pos,
570 struct ln_equ_posn *end, gdouble divs)
572 gint i = divs;
573 gdouble step = (end->dec - pos->dec) / divs;
575 /* draw to RA end */
576 for (pos->dec = pos->dec + step; i > 0; pos->dec += step, i--) {
578 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
579 cairo_line_to(robject->cr,
580 robject->coord[0].x, robject->coord[0].y);
584 static inline void equ_dec_line(struct render_object *robject,
585 struct projection *proj, struct ln_equ_posn *pos,
586 struct ln_equ_posn *end, gdouble divs)
588 gint i = divs;
589 gdouble step = (end->ra - pos->ra) / divs;
591 /* draw to DEC end */
592 for (pos->ra = pos->ra + step; i > 0; pos->ra += step, i--) {
594 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
595 cairo_line_to(robject->cr,
596 robject->coord[0].x, robject->coord[0].y);
600 static inline void hrz_ra_line(struct render_object *robject,
601 struct projection *proj, struct ln_equ_posn *pos,
602 struct ln_equ_posn *end, gdouble divs)
604 gint i = divs;
605 gdouble step = (end->dec - pos->dec) / divs;
607 /* draw to RA end */
608 for (pos->dec = pos->dec + step; i > 0; pos->dec += step, i--) {
610 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
611 cairo_line_to(robject->cr,
612 robject->coord[0].x, robject->coord[0].y);
616 static inline void hrz_dec_line(struct render_object *robject,
617 struct projection *proj, struct ln_equ_posn *pos,
618 struct ln_equ_posn *end, gdouble divs)
620 gint i = divs;
621 gdouble step = (end->ra - pos->ra) / divs;
623 /* draw to DEC end */
624 for (pos->ra = pos->ra + step; i > 0; pos->ra += step, i--) {
626 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
627 cairo_line_to(robject->cr,
628 robject->coord[0].x, robject->coord[0].y);
632 static inline void equ_render_square(struct render_object *robject,
633 struct projection *proj, gint ra, gint dec, gdouble divs)
635 gdouble ra_step_delta, dec_step_delta;
636 struct ln_equ_posn pos, start_pos, end_pos;
638 ra_step_delta = get_ra_step_delta(proj);
639 dec_step_delta = get_dec_step_delta(proj);
640 robject->coord[0].posn = &pos;
642 /* start corner */
643 start_pos.ra = pos.ra = ra * GRID_RA_TILE_SIZE;
644 start_pos.dec = pos.dec = PROJ_MIN_DEC + dec * GRID_DEC_TILE_SIZE;
646 /* end corner */
647 end_pos.ra = start_pos.ra + GRID_RA_TILE_SIZE;
648 end_pos.dec = start_pos.dec + GRID_DEC_TILE_SIZE;
650 /* RA lines */
651 for (; pos.ra <= end_pos.ra; pos.ra += ra_step_delta) {
653 /* move to RA start */
654 pos.dec = start_pos.dec;
655 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
656 cairo_move_to(robject->cr,
657 robject->coord[0].x, robject->coord[0].y);
659 equ_ra_line(robject, proj, &pos, &end_pos, divs);
662 /* DEC lines */
663 for (pos.dec = start_pos.dec; pos.dec <= end_pos.dec;
664 pos.dec += dec_step_delta) {
666 /* move to DEC start */
667 pos.ra = start_pos.ra;
668 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
669 cairo_move_to(robject->cr,
670 robject->coord[0].x, robject->coord[0].y);
672 equ_dec_line(robject, proj, &pos, &end_pos, divs);
676 static inline void hrz_render_square(struct render_object *robject,
677 struct projection *proj, gint ra, gint dec, gdouble divs)
679 gdouble ra_step_delta, dec_step_delta;
680 struct ln_equ_posn pos, start_pos, end_pos;
682 ra_step_delta = get_ra_step_delta(proj);
683 dec_step_delta = get_dec_step_delta(proj);
684 robject->coord[0].posn = &pos;
686 /* start corner */
687 start_pos.ra = pos.ra = ra * GRID_RA_TILE_SIZE;
688 start_pos.dec = pos.dec = PROJ_MIN_DEC + dec * GRID_DEC_TILE_SIZE;
690 /* end corner */
691 end_pos.ra = start_pos.ra + GRID_RA_TILE_SIZE;
692 end_pos.dec = start_pos.dec + GRID_DEC_TILE_SIZE;
694 /* RA lines */
695 for (; pos.ra <= end_pos.ra; pos.ra += ra_step_delta) {
697 /* move to RA start */
698 pos.dec = start_pos.dec;
699 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
700 cairo_move_to(robject->cr,
701 robject->coord[0].x, robject->coord[0].y);
703 hrz_ra_line(robject, proj, &pos, &end_pos, divs);
706 /* DEC lines */
707 for (pos.dec = start_pos.dec; pos.dec <= end_pos.dec;
708 pos.dec += dec_step_delta) {
710 /* move to DEC start */
711 pos.ra = start_pos.ra;
712 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
713 cairo_move_to(robject->cr,
714 robject->coord[0].x, robject->coord[0].y);
716 hrz_dec_line(robject, proj, &pos, &end_pos, divs);
720 void equ_render_grid(struct render_object *robject, struct projection *proj,
721 gint labels, gdouble divs)
723 gint ra, dec;
725 /* render grid squares */
726 for (ra = 0; ra < GRID_RA_TILES; ra++) {
727 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
728 if (proj->grid_tile[ra][dec])
729 equ_render_square(robject, proj, ra, dec, divs);
732 if (!labels)
733 return;
735 /* render DEC labels */
736 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++) {
737 for (ra = 0; ra < GRID_RA_TILES; ra++) {
738 if (proj->grid_tile[ra][dec]) {
739 gdouble dec_s = (dec - 9) * GRID_DEC_TILE_SIZE,
740 dec_e = dec_s + GRID_DEC_TILE_SIZE;
742 if (dec_e >= 80.0)
743 dec_e = 80.0;
745 equ_render_dec_labels(robject, proj, dec_s, dec_e);
746 break;
751 /* render RA labels */
752 for (ra = 0; ra < GRID_RA_TILES; ra++) {
753 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
754 if (proj->grid_tile[ra][dec]) {
755 gdouble ra_s = ra * GRID_RA_TILE_SIZE,
756 ra_e = ra_s + GRID_RA_TILE_SIZE;
758 if (ra_e >= PROJ_MAX_RA)
759 ra_e = 0.0;
761 equ_render_ra_labels(robject, proj, ra_s, ra_e);
762 break;
767 void hrz_render_grid(struct render_object *robject, struct projection *proj,
768 gint labels, gdouble divs)
770 gint ra, dec;
772 /* render grid squares */
773 for (ra = 0; ra < GRID_RA_TILES; ra++) {
774 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
775 if (proj->grid_tile[ra][dec])
776 hrz_render_square(robject, proj, ra, dec, divs);
779 if (!labels)
780 return;
782 /* render DEC labels */
783 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++) {
784 for (ra = 0; ra < GRID_RA_TILES; ra++) {
785 if (proj->grid_tile[ra][dec]) {
786 gdouble dec_s = (dec - 9) * GRID_DEC_TILE_SIZE,
787 dec_e = dec_s + GRID_DEC_TILE_SIZE;
789 if (dec_e >= 80.0)
790 dec_e = 80.0;
792 hrz_render_dec_labels(robject, proj, dec_s, dec_e);
793 break;
798 /* render RA labels */
799 for (ra = 0; ra < GRID_RA_TILES; ra++) {
800 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
801 if (proj->grid_tile[ra][dec]) {
802 gdouble ra_s = ra * GRID_RA_TILE_SIZE,
803 ra_e = ra_s + GRID_RA_TILE_SIZE;
805 if (ra_e >= PROJ_MAX_RA)
806 ra_e = 0.0;
808 hrz_render_ra_labels(robject, proj, ra_s, ra_e);
809 break;
814 static inline void render_ecliptic(struct render_object *robject,
815 struct projection *proj)
817 /* TODO */
818 #if 0
819 gdouble step;
820 struct ln_equ_posn pos1;
821 int start_visible, end_visible;
823 pos1.ra = 0;
824 pos1.dec = 0;
825 robject->coord[0].posn = &pos1;
826 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
827 start_visible = projection_is_visible0(proj, robject);
828 cairo_move_to(robject->cr,
829 robject->coord[0].x,
830 robject->coord[0].y);
832 for (step = 10; step <= PROJ_MAX_RA; step += 10) {
833 pos1.ra = step;
834 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
835 end_visible = projection_is_visible0(proj, robject);
836 if (start_visible || end_visible)
837 cairo_line_to(robject->cr,
838 robject->coord[0].x,
839 robject->coord[0].y);
840 else
841 cairo_move_to(robject->cr,
842 robject->coord[0].x,
843 robject->coord[0].y);
844 start_visible = end_visible;
846 #endif
849 static inline void render_horizon(struct render_object *robject,
850 struct projection *proj)
852 gdouble step, size;
853 struct ln_equ_posn pos1;
854 int start_visible, end_visible;
855 double dashes[] = {3.0, 1.0, 3.0, 1.0};
857 cairo_save(robject->cr);
858 cairo_set_source_rgba(robject->cr, 0.6, 0.6, 0.6, 0.7);
859 cairo_set_dash (robject->cr, dashes, 4, 0);
861 pos1.ra = 0;
862 pos1.dec = 0;
863 robject->coord[0].posn = &pos1;
865 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
866 start_visible = projection_is_visible0(proj, robject);
867 cairo_move_to(robject->cr,
868 robject->coord[0].x,
869 robject->coord[0].y);
871 if (robject->type == RT_FAST) {
872 cairo_set_tolerance(robject->cr, 1.0);
873 size = 10.0;
874 } else {
875 cairo_set_tolerance(robject->cr, 0.1);
876 size = 3.0;
879 for (step = 10; step <= PROJ_MAX_RA; step += size) {
880 pos1.ra = step;
881 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
882 end_visible = projection_is_visible0(proj, robject);
883 if (start_visible || end_visible)
884 cairo_line_to(robject->cr,
885 robject->coord[0].x,
886 robject->coord[0].y);
887 else
888 cairo_move_to(robject->cr,
889 robject->coord[0].x,
890 robject->coord[0].y);
891 start_visible = end_visible;
893 cairo_stroke(robject->cr);
895 if (robject->type == RT_FAST)
896 cairo_set_tolerance(robject->cr, 0.1); /* do we need this */
897 cairo_restore(robject->cr);
900 static inline void render_horizon_NEWS(struct render_object *robject,
901 struct projection *proj)
903 struct ln_equ_posn pos1;
905 cairo_save(robject->cr);
906 cairo_set_font_size (robject->cr, 20.0);
907 cairo_set_source_rgba(robject->cr, 1, 0.35, 0.55, 0.7);
908 robject->coord[0].posn = &pos1;
909 pos1.dec = 0;
911 /* South */
912 pos1.ra = 0;
913 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
914 cairo_move_to(robject->cr,
915 robject->coord[0].x,
916 robject->coord[0].y);
917 cairo_show_text(robject->cr, "S");
919 /* West */
920 pos1.ra = 90;
921 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
922 cairo_move_to(robject->cr,
923 robject->coord[0].x,
924 robject->coord[0].y);
925 cairo_show_text(robject->cr, "W");
927 /* North */
928 pos1.ra = 180;
929 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
930 cairo_move_to(robject->cr,
931 robject->coord[0].x,
932 robject->coord[0].y);
933 cairo_show_text(robject->cr, "N");
935 /* East */
936 pos1.ra = 270;
937 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
938 cairo_move_to(robject->cr,
939 robject->coord[0].x,
940 robject->coord[0].y);
941 cairo_show_text(robject->cr, "E");
943 cairo_restore(robject->cr);
946 void markers_grid_render(Sky *sky)
948 struct render_object *robject = &sky->robject;
949 struct projection *proj = &sky->projection;
950 gint labels = sky->marker_settings.show_grid_labels;
951 gdouble alpha, divs;
953 if (robject->flags.night_mode)
954 alpha = GRID_NIGHT_ALPHA;
955 else
956 alpha = GRID_DAY_ALPHA;
958 cairo_save(robject->cr);
959 cairo_set_source_rgba(robject->cr, 0, 0.35, 0.55, alpha);
960 cairo_set_font_size (robject->cr, 13.0);
962 if (robject->type == RT_FAST) {
963 cairo_set_tolerance(robject->cr, 1.0);
964 divs = 6.0;
965 } else {
966 cairo_set_tolerance(robject->cr, 0.1);
967 divs = 10.0;
970 switch (proj->grid_coords) {
971 case PC_RA_DEC:
972 equ_get_visible_tiles(proj);
973 equ_render_grid(robject, proj, labels, divs);
974 break;
975 case PC_ALT_AZ:
976 hrz_get_visible_tiles(proj);
977 hrz_render_grid(robject, proj, labels, divs);
978 break;
980 cairo_stroke(robject->cr);
982 if (robject->type == RT_FAST)
983 cairo_set_tolerance(robject->cr, 0.1); /* do we need this */
984 cairo_restore(robject->cr);
987 void markers_horizon_render(Sky *sky)
989 struct render_object *robject = &sky->robject;
990 struct projection *proj = &sky->projection;
992 render_horizon(robject, proj);
995 void markers_horizon_NEWS_render(Sky *sky)
997 struct render_object *robject = &sky->robject;
998 struct projection *proj = &sky->projection;
1000 render_horizon_NEWS(robject, proj);
1003 void markers_ecliptic_render(Sky *sky)
1005 struct render_object *robject = &sky->robject;
1006 struct projection *proj = &sky->projection;
1008 render_ecliptic(robject, proj);
1011 void markers_galactic_poles_render(Sky *sky)