sky: grid and projection - minor cleanups.
[nova.git] / src / sky / grid.c
blobdda28f6a41b540b0ad9a8d2fa951cd94bd6cebfc
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)
572 gdouble divs = 5.0;//proj->pixels_per_degree
573 gdouble step = (end->dec - pos->dec) / divs;
575 /* draw to RA end */
576 for (pos->dec = pos->dec + step;
577 pos->dec <= end->dec; pos->dec += step) {
579 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
580 cairo_line_to(robject->cr,
581 robject->coord[0].x, robject->coord[0].y);
585 static inline void equ_dec_line(struct render_object *robject,
586 struct projection *proj, struct ln_equ_posn *pos,
587 struct ln_equ_posn *end)
589 gdouble divs = 5.0;//proj->pixels_per_degree
590 gdouble step = (end->ra - pos->ra) / divs;
592 /* draw to DEC end */
593 for (pos->ra = pos->ra + step;
594 pos->ra <= end->ra; pos->ra += step) {
596 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
597 cairo_line_to(robject->cr,
598 robject->coord[0].x, robject->coord[0].y);
602 static inline void hrz_ra_line(struct render_object *robject,
603 struct projection *proj, struct ln_equ_posn *pos,
604 struct ln_equ_posn *end)
606 gdouble divs = 5.0;//proj->pixels_per_degree
607 gdouble step = (end->dec - pos->dec) / divs;
609 /* draw to RA end */
610 for (pos->dec = pos->dec + step;
611 pos->dec <= end->dec; pos->dec += step) {
613 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
614 cairo_line_to(robject->cr,
615 robject->coord[0].x, robject->coord[0].y);
619 static inline void hrz_dec_line(struct render_object *robject,
620 struct projection *proj, struct ln_equ_posn *pos,
621 struct ln_equ_posn *end)
623 gdouble divs = 5.0;//proj->pixels_per_degree
624 gdouble step = (end->ra - pos->ra) / divs;
626 /* draw to DEC end */
627 for (pos->ra = pos->ra + step;
628 pos->ra <= end->ra; pos->ra += step) {
630 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
631 cairo_line_to(robject->cr,
632 robject->coord[0].x, robject->coord[0].y);
636 static inline void equ_render_square(struct render_object *robject,
637 struct projection *proj, gint ra, gint dec)
639 gdouble ra_step_delta, dec_step_delta;
640 struct ln_equ_posn pos, start_pos, end_pos;
642 ra_step_delta = get_ra_step_delta(proj);
643 dec_step_delta = get_dec_step_delta(proj);
644 robject->coord[0].posn = &pos;
646 /* start corner */
647 start_pos.ra = pos.ra = ra * GRID_RA_TILE_SIZE;
648 start_pos.dec = pos.dec = PROJ_MIN_DEC + dec * GRID_DEC_TILE_SIZE;
650 /* end corner */
651 end_pos.ra = start_pos.ra + GRID_RA_TILE_SIZE;
652 end_pos.dec = start_pos.dec + GRID_DEC_TILE_SIZE;
654 /* RA lines */
655 for (; pos.ra <= end_pos.ra; pos.ra += ra_step_delta) {
657 /* move to RA start */
658 pos.dec = start_pos.dec;
659 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
660 cairo_move_to(robject->cr,
661 robject->coord[0].x, robject->coord[0].y);
663 equ_ra_line(robject, proj, &pos, &end_pos);
666 /* DEC lines */
667 for (pos.dec = start_pos.dec; pos.dec <= end_pos.dec;
668 pos.dec += dec_step_delta) {
670 /* move to DEC start */
671 pos.ra = start_pos.ra;
672 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
673 cairo_move_to(robject->cr,
674 robject->coord[0].x, robject->coord[0].y);
676 equ_dec_line(robject, proj, &pos, &end_pos);
680 static inline void hrz_render_square(struct render_object *robject,
681 struct projection *proj, gint ra, gint dec)
683 gdouble ra_step_delta, dec_step_delta;
684 struct ln_equ_posn pos, start_pos, end_pos;
686 ra_step_delta = get_ra_step_delta(proj);
687 dec_step_delta = get_dec_step_delta(proj);
688 robject->coord[0].posn = &pos;
690 /* start corner */
691 start_pos.ra = pos.ra = ra * GRID_RA_TILE_SIZE;
692 start_pos.dec = pos.dec = PROJ_MIN_DEC + dec * GRID_DEC_TILE_SIZE;
694 /* end corner */
695 end_pos.ra = start_pos.ra + GRID_RA_TILE_SIZE;
696 end_pos.dec = start_pos.dec + GRID_DEC_TILE_SIZE;
698 /* RA lines */
699 for (; pos.ra <= end_pos.ra; pos.ra += ra_step_delta) {
701 /* move to RA start */
702 pos.dec = start_pos.dec;
703 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
704 cairo_move_to(robject->cr,
705 robject->coord[0].x, robject->coord[0].y);
707 hrz_ra_line(robject, proj, &pos, &end_pos);
710 /* DEC lines */
711 for (pos.dec = start_pos.dec; pos.dec <= end_pos.dec;
712 pos.dec += dec_step_delta) {
714 /* move to DEC start */
715 pos.ra = start_pos.ra;
716 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
717 cairo_move_to(robject->cr,
718 robject->coord[0].x, robject->coord[0].y);
720 hrz_dec_line(robject, proj, &pos, &end_pos);
724 void equ_render_grid(struct render_object *robject, struct projection *proj,
725 gint labels)
727 gint ra, dec;
729 /* render grid squares */
730 for (ra = 0; ra < GRID_RA_TILES; ra++) {
731 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
732 if (proj->grid_tile[ra][dec])
733 equ_render_square(robject, proj, ra, dec);
736 if (!labels)
737 return;
739 /* render DEC labels */
740 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++) {
741 for (ra = 0; ra < GRID_RA_TILES; ra++) {
742 if (proj->grid_tile[ra][dec]) {
743 gdouble dec_s = (dec - 9) * GRID_DEC_TILE_SIZE,
744 dec_e = dec_s + GRID_DEC_TILE_SIZE;
746 if (dec_e >= 80.0)
747 dec_e = 80.0;
749 equ_render_dec_labels(robject, proj, dec_s, dec_e);
750 break;
755 /* render RA labels */
756 for (ra = 0; ra < GRID_RA_TILES; ra++) {
757 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
758 if (proj->grid_tile[ra][dec]) {
759 gdouble ra_s = ra * GRID_RA_TILE_SIZE,
760 ra_e = ra_s + GRID_RA_TILE_SIZE;
762 if (ra_e >= PROJ_MAX_RA)
763 ra_e = 0.0;
765 equ_render_ra_labels(robject, proj, ra_s, ra_e);
766 break;
771 void hrz_render_grid(struct render_object *robject, struct projection *proj,
772 gint labels)
774 gint ra, dec;
776 /* render grid squares */
777 for (ra = 0; ra < GRID_RA_TILES; ra++) {
778 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
779 if (proj->grid_tile[ra][dec])
780 hrz_render_square(robject, proj, ra, dec);
783 if (!labels)
784 return;
786 /* render DEC labels */
787 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++) {
788 for (ra = 0; ra < GRID_RA_TILES; ra++) {
789 if (proj->grid_tile[ra][dec]) {
790 gdouble dec_s = (dec - 9) * GRID_DEC_TILE_SIZE,
791 dec_e = dec_s + GRID_DEC_TILE_SIZE;
793 if (dec_e >= 80.0)
794 dec_e = 80.0;
796 hrz_render_dec_labels(robject, proj, dec_s, dec_e);
797 break;
802 /* render RA labels */
803 for (ra = 0; ra < GRID_RA_TILES; ra++) {
804 for (dec = 1; dec < GRID_DEC_TILES - 1; dec++)
805 if (proj->grid_tile[ra][dec]) {
806 gdouble ra_s = ra * GRID_RA_TILE_SIZE,
807 ra_e = ra_s + GRID_RA_TILE_SIZE;
809 if (ra_e >= PROJ_MAX_RA)
810 ra_e = 0.0;
812 hrz_render_ra_labels(robject, proj, ra_s, ra_e);
813 break;
818 void render_ecliptic(struct render_object *robject, struct projection *proj)
820 /* TODO */
821 #if 0
822 gdouble step;
823 struct ln_equ_posn pos1;
824 int start_visible, end_visible;
826 pos1.ra = 0;
827 pos1.dec = 0;
828 robject->coord[0].posn = &pos1;
829 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
830 start_visible = projection_is_visible0(proj, robject);
831 cairo_move_to(robject->cr,
832 robject->coord[0].x,
833 robject->coord[0].y);
835 for (step = 10; step <= PROJ_MAX_RA; step += 10) {
836 pos1.ra = step;
837 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
838 end_visible = projection_is_visible0(proj, robject);
839 if (start_visible || end_visible)
840 cairo_line_to(robject->cr,
841 robject->coord[0].x,
842 robject->coord[0].y);
843 else
844 cairo_move_to(robject->cr,
845 robject->coord[0].x,
846 robject->coord[0].y);
847 start_visible = end_visible;
849 #endif
852 void render_horizon(struct render_object *robject, struct projection *proj)
854 gdouble step;
855 struct ln_equ_posn pos1;
856 int start_visible, end_visible;
858 cairo_save(robject->cr);
859 cairo_set_source_rgba(robject->cr, 1, 0.35, 0.55, 0.7);
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 for (step = 10; step <= PROJ_MAX_RA; step += 10) {
872 pos1.ra = step;
873 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
874 end_visible = projection_is_visible0(proj, robject);
875 if (start_visible || end_visible)
876 cairo_line_to(robject->cr,
877 robject->coord[0].x,
878 robject->coord[0].y);
879 else
880 cairo_move_to(robject->cr,
881 robject->coord[0].x,
882 robject->coord[0].y);
883 start_visible = end_visible;
885 cairo_stroke(robject->cr);
886 cairo_restore(robject->cr);
889 void render_horizon_NEWS(struct render_object *robject, struct projection *proj)
891 struct ln_equ_posn pos1;
893 cairo_save(robject->cr);
894 cairo_set_font_size (robject->cr, 20.0);
895 cairo_set_source_rgba(robject->cr, 1, 0.35, 0.55, 0.7);
896 robject->coord[0].posn = &pos1;
897 pos1.dec = 0;
899 /* South */
900 pos1.ra = 0;
901 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
902 cairo_move_to(robject->cr,
903 robject->coord[0].x,
904 robject->coord[0].y);
905 cairo_show_text(robject->cr, "S");
907 /* West */
908 pos1.ra = 90;
909 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
910 cairo_move_to(robject->cr,
911 robject->coord[0].x,
912 robject->coord[0].y);
913 cairo_show_text(robject->cr, "W");
915 /* North */
916 pos1.ra = 180;
917 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
918 cairo_move_to(robject->cr,
919 robject->coord[0].x,
920 robject->coord[0].y);
921 cairo_show_text(robject->cr, "N");
923 /* East */
924 pos1.ra = 270;
925 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
926 cairo_move_to(robject->cr,
927 robject->coord[0].x,
928 robject->coord[0].y);
929 cairo_show_text(robject->cr, "E");
931 cairo_restore(robject->cr);
934 void grid_render(Sky *sky)
936 struct render_object *robject = &sky->robject;
937 struct projection *proj = &sky->projection;
938 gint labels = sky->marker_settings.show_grid_labels;
939 gdouble alpha;
941 if (robject->flags.night_mode)
942 alpha = GRID_NIGHT_ALPHA;
943 else
944 alpha = GRID_DAY_ALPHA;
946 cairo_save(robject->cr);
947 cairo_set_source_rgba(robject->cr, 0, 0.35, 0.55, alpha);
948 cairo_set_font_size (robject->cr, 13.0);
950 if (robject->type == RT_FAST) //TODO make step size * 2.0 when fast
951 cairo_set_tolerance (robject->cr, 1.0);
953 switch (proj->grid_coords) {
954 case PC_RA_DEC:
955 equ_get_visible_tiles(proj);
956 equ_render_grid(robject, proj, labels);
957 break;
958 case PC_ALT_AZ:
959 hrz_get_visible_tiles(proj);
960 hrz_render_grid(robject, proj, labels);
961 break;
963 cairo_stroke(robject->cr);
965 render_horizon(robject, proj);
966 render_horizon_NEWS(robject, proj);
968 if (robject->type == RT_FAST)
969 cairo_set_tolerance (robject->cr, 0.1); /* do we need this */
970 cairo_restore(robject->cr);