sky: render - now have alt-az projection better, still need to fix grid.
[nova.git] / src / sky / grid.c
blob7c189dc253cbb77064209934f717ac9699b1b233
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).
22 * TODO: Clip RA grid lines at 80 and -80 on DEC. This needs cairo_arc_to() or
23 * someone who knows another solution.
26 #define _GNU_SOURCE /* for NAN and INF */
28 #include <math.h>
29 #include <stdio.h>
30 #include "astro_object.h"
32 #include "grid.h"
34 #define D2R (1.7453292519943295769e-2) /* deg->radian */
35 #define R2D (5.7295779513082320877e1) /* radian->deg */
37 #define ARC_MAGIC 1000.0 /* need better method to determine line from arc */
38 #define GRID_BISECT 128.0
39 #define GRID_NIGHT_ALPHA 0.35
40 #define GRID_DAY_ALPHA 0.55
43 /* RA grid in arcsecs */
44 static const gdouble grid_hms_ra[] = {
45 15.0 * 60.0 * 60.0,
46 15.0 * 60.0 * 10.0,
47 15.0 * 60.0 * 5.0,
48 15.0 * 60.0,
49 15.0 * 10.0,
50 15.0 * 5.0,
51 15.0,
52 7.5,
53 1.5,
56 /* DEC drid in arcsecs */
57 static const gdouble grid_dms_dec[] = {
58 3600.0 * 10.0,
59 3600.0 * 5.0,
60 3600.0,
61 1200.0,
62 600.0,
63 300.0,
64 60.0,
65 10.0,
66 5.0,
67 1.0,
70 /* get grid RA step size for projection in arcsecs */
71 static gdouble get_ra_step_delta(struct projection *proj)
73 gint i;
75 for (i = 0; i < nsize(grid_hms_ra); i++) {
76 if (proj->fov / 1.1 > grid_hms_ra[i] / 3600.0)
77 return grid_hms_ra[i] / 3600.0;
79 return grid_hms_ra[i] / 3600.0;
82 /* get grid DEC step size for projection in arcsecs */
83 static gdouble get_dec_step_delta(struct projection *proj)
85 gint i;
87 for (i = 0; i < nsize(grid_dms_dec); i++) {
88 if (proj->fov / 1.1 > grid_dms_dec[i] / 3600.0)
89 return grid_dms_dec[i] / 3600.0;
91 return grid_dms_dec[i] / 3600.0;
94 /* clip DEC grid to current projection FOV */
95 static void clip_dec_equ_grid(struct projection *proj, gdouble step_size,
96 gdouble *south, gdouble *north)
98 *south = proj->centre_dec - proj->fov / 2.0;
99 if (*south <= -90.0)
100 *south = -90.0 + step_size;
101 else
102 *south = floor(*south / step_size) * step_size;
104 *north = proj->centre_dec + proj->fov / 2.0;
105 if (*north >= 90.0)
106 *north = 90.0 - step_size;
107 else
108 *north = floor(*north / step_size) * step_size;
111 /* clip RA grid to current projection FOV */
112 static void clip_ra_equ_grid(struct projection *proj, gdouble step_size,
113 gdouble *start, gdouble *end)
115 struct render_object robject;
116 struct ln_equ_posn pos[4];
117 gdouble start_, end_;
118 gint i;
120 /* get RA at each projection corner */
121 robject.coord[0].x = 0;
122 robject.coord[0].y = 0;
123 robject.coord[0].posn = &pos[0];
124 proj->trans->proj_to_sky_hrz(proj, &robject.coord[0]);
125 if (pos[0].ra < 0.0)
126 pos[0].ra += 360.0;
127 else if (pos[0].ra >= 360.0)
128 pos[0].ra -= 360.0;
130 robject.coord[0].x = proj->sky_width;
131 robject.coord[0].y = 0;
132 robject.coord[0].posn = &pos[1];
133 proj->trans->proj_to_sky_hrz(proj, &robject.coord[0]);
134 if (pos[1].ra < 0.0)
135 pos[1].ra += 360.0;
136 else if (pos[1].ra >= 360.0)
137 pos[1].ra -= 360.0;
139 robject.coord[0].x = 0;
140 robject.coord[0].y = proj->sky_height;
141 robject.coord[0].posn = &pos[2];
142 proj->trans->proj_to_sky_hrz(proj, &robject.coord[0]);
143 if (pos[2].ra < 0.0)
144 pos[2].ra += 360.0;
145 else if (pos[2].ra >= 360.0)
146 pos[2].ra -= 360.0;
148 robject.coord[0].x = proj->sky_width;
149 robject.coord[0].y = proj->sky_height;
150 robject.coord[0].posn = &pos[3];
151 proj->trans->proj_to_sky_hrz(proj, &robject.coord[0]);
152 if (pos[3].ra < 0.0)
153 pos[3].ra += 360.0;
154 else if (pos[3].ra >= 360.0)
155 pos[3].ra -= 360.0;
157 /* get highest and lowest RA from corners */
158 start_ = 360.0;
159 end_ = 0.0;
160 for (i = 0; i < 4; i++) {
161 printf("pos %d ra %3.2f dec %3.2f\n",i, pos[i].ra, pos[i].dec);
162 if (start_ > pos[i].ra)
163 start_ = pos[i].ra;
164 if (end_ < pos[i].ra)
165 end_ = pos[i].ra;
168 start_ = floor(start_ / step_size) * step_size;
169 if (start_ < 0.0)
170 start_ += 360.0;
171 else if (start_ >= 360.0)
172 start_ -= 360.0;
174 end_ = ceil(end_ / step_size) * step_size;
175 if (end_ < 0.0)
176 end_ += 360.0;
177 else if (end_ >= 360.0)
178 end_ -= 360.0;
180 if (start_ > end_) {
181 *start = end_;
182 *end = start_;
183 } else {
184 *start = start_;
185 *end = end_;
188 printf("start %3.2f end %3.2f\n", *start, *end);
191 /* should we render a line of this radius as an arc or a straight line */
192 static inline gint is_arc_line(struct projection *proj, gdouble radius)
194 /* magic number - must refine */
195 if (radius > proj->sky_width * ARC_MAGIC ||
196 radius < proj->sky_width * -ARC_MAGIC) {
197 //printf("%s rad %f\n", __func__, radius);
198 return 1;
200 return 0;
203 /* is this arc visible in projection */
204 static gint is_arc_visible(struct projection *proj, gdouble x, gdouble y,
205 gdouble radius)
207 gdouble x1, y1, x2, y2;
209 /* sanity check */
210 if (radius == FP_NAN
211 || radius == FP_INFINITE
212 || radius == -FP_INFINITE) {
213 return 0;
216 /* create clip area sky size + radius */
217 x1 = -radius;
218 y1 = -radius;
219 x2 = proj->sky_width + radius;
220 y2 = proj->sky_height + radius;
222 /* are we inside ? */
223 if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
224 return 1;
226 return 0;
229 static inline void do_ra_line(struct render_object *robject,
230 struct projection *proj, gdouble x, gdouble y, gdouble my)
232 gdouble x1, y1, x2, y2;
234 x1 = x - my * y;
235 y1 = 0;
236 x2 = my * (proj->sky_height - y) + x;
237 y2 = proj->sky_height;
239 cairo_move_to(robject->cr, x1, y1);
240 cairo_line_to(robject->cr, x2, y2);
243 /* draw a straight RA grid line */
244 static inline void draw_ra_line(struct render_object *robject,
245 struct projection *proj, gdouble step)
247 struct ln_equ_posn pos1, pos2;
248 gdouble my;
250 /* calc based on small RA line */
251 pos1.dec = proj->centre_dec + 1.0;
252 pos2.dec = proj->centre_dec -1.0;
254 pos1.ra = step;
255 pos2.ra = step + 180.0;
257 robject->coord[0].posn = &pos1;
258 robject->coord[1].posn = &pos2;
260 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
261 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
263 /* calculate line gradient */
264 my = (robject->coord[1].x - robject->coord[0].x) /
265 (robject->coord[1].y - robject->coord[0].y);
267 do_ra_line(robject, proj,
268 robject->coord[0].x, robject->coord[0].y, my);
271 static inline void do_dec_line(struct render_object *robject,
272 struct projection *proj, gdouble x, gdouble y, gdouble mx)
274 gdouble x1, y1, x2, y2;
276 x1 = 0;
277 y1 = y -mx * y;
278 x2 = proj->sky_width;
279 y2 = mx * (proj->sky_width - x) + y;
281 cairo_move_to(robject->cr, x1, y1);
282 cairo_line_to(robject->cr, x2, y2);
285 /* draw a straight DEC grid line */
286 static inline void draw_dec_line(struct render_object *robject,
287 struct projection *proj, gdouble step)
289 struct ln_equ_posn pos1, pos2;
290 gdouble mx;
292 /* calc based on small DEC line */
293 pos1.ra = proj->centre_ra + 1.0;
294 pos2.ra = proj->centre_ra -1.0;
296 pos1.dec = step;
297 pos2.dec = step;
299 robject->coord[0].posn = &pos1;
300 robject->coord[1].posn = &pos2;
302 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
303 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
305 /* calculate line gradient */
306 mx = (robject->coord[1].y - robject->coord[0].y) /
307 (robject->coord[1].x - robject->coord[0].x);
309 do_dec_line(robject, proj,
310 robject->coord[0].x, robject->coord[0].y, mx);
313 #if 0
314 /* render all visible RA grid lines */
315 static void equ_render_ra(struct render_object *robject,
316 struct projection *proj, gint labels)
318 gdouble centre_x, centre_y, radius, x, y, step,
319 step_delta, ra_start, ra_end;
320 struct ln_equ_posn pos1, pos2;
322 pos1.dec = -proj->centre_dec;
323 pos2.dec = -proj->centre_dec;
325 step_delta = get_ra_step_delta(proj);
326 clip_ra_equ_grid(proj, step_delta, &ra_start, &ra_end);
328 for (step = ra_start; step <= ra_end; step += step_delta) {
330 pos1.ra = step;
331 pos2.ra = step + 180.0;
333 robject->coord[0].posn = &pos1;
334 robject->coord[1].posn = &pos2;
336 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
337 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
339 centre_x = robject->coord[0].x +
340 ((robject->coord[1].x - robject->coord[0].x) / 2.0);
341 centre_y = robject->coord[0].y +
342 ((robject->coord[1].y - robject->coord[0].y) / 2.0);
343 x = centre_x - robject->coord[0].x;
344 y = centre_y - robject->coord[0].y;
345 radius = sqrt(x * x + y * y);
347 if (!is_arc_visible(proj, centre_x, centre_y, radius) &&
348 step != proj->centre_ra)
349 continue;
351 /* need cairo_arc_to() */
352 #if 0
353 if (step == 0.0 || step == 90.0 ||
354 step == 180.0 || step == 270.0) {
355 struct ln_equ_posn pos1, pos2;
357 pos1.dec = 80.0;
358 pos2.dec = -80.0;
359 pos1.ra = step;
360 pos2.ra = step;
361 robject->num_coords = 2;
363 robject->coord[0].posn = &pos1;
364 robject->coord[1].posn = &pos2;
365 proj->trans->sky_to_proj_equ(proj, robject);
367 cairo_new_sub_path(robject->cr);
368 cairo_arc_to(robject->cr,
369 robject->coord[0].x, robject->coord[0].y,
370 robject->coord[1].x, robject->coord[1].y,
371 radius);
372 } else {
373 if (is_arc_line(proj, centre_x))
374 draw_ra_line(robject, proj, step);
375 else {
376 cairo_new_sub_path(robject->cr);
377 cairo_arc(robject->cr, centre_x, centre_y,
378 radius, circle_start, circle_end);
381 #else
382 if (is_arc_line(proj, centre_x))
383 draw_ra_line(robject, proj, step);
384 else {
385 cairo_new_sub_path(robject->cr);
386 cairo_arc(robject->cr, centre_x, centre_y,
387 radius, 0, 2 * M_PI);
389 #endif
392 #endif
394 #if 0
395 /* render all visible DEC grid lines */
396 static void equ_render_dec(struct render_object *robject,
397 struct projection *proj, gint labels)
399 gdouble centre_x, centre_y, radius, x, y, step,
400 step_delta, dec_start, dec_end;
401 struct ln_equ_posn pos1, pos2;
403 pos1.ra = proj->centre_ra;
404 pos2.ra = proj->centre_ra + 180.0;
406 step_delta = get_dec_step_delta(proj);
407 clip_dec_equ_grid(proj, step_delta, &dec_start, &dec_end);
409 for (step = dec_start; step <= dec_end; step += step_delta) {
411 pos1.dec = step;
412 pos2.dec = step;
414 robject->coord[0].posn = &pos1;
415 robject->coord[1].posn = &pos2;
417 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
418 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
420 centre_x = robject->coord[0].x +
421 ((robject->coord[1].x - robject->coord[0].x) / 2.0);
422 centre_y = robject->coord[0].y +
423 ((robject->coord[1].y - robject->coord[0].y) / 2.0);
424 x = centre_x - robject->coord[0].x;
425 y = centre_y - robject->coord[0].y;
426 radius = sqrt(x * x + y * y);
428 if (!is_arc_visible(proj, centre_x, centre_y, radius) &&
429 step != proj->centre_dec)
430 continue;
432 cairo_new_sub_path(robject->cr);
434 if (is_arc_line(proj, centre_x))
435 draw_dec_line(robject, proj, step);
436 else
437 cairo_arc(robject->cr, centre_x, centre_y,
438 radius, 0, 2 * M_PI);
441 #endif
443 /* render all visible RA grid lines */
444 static void hrz_render_ra(struct render_object *robject,
445 struct projection *proj, gint labels)
447 gdouble centre_x, centre_y, radius, x, y, step,
448 step_delta, ra_start, ra_end;
449 struct ln_equ_posn pos1, pos2;
451 pos1.dec = -proj->centre_dec;
452 pos2.dec = -proj->centre_dec;
454 step_delta = get_ra_step_delta(proj);
455 clip_ra_equ_grid(proj, step_delta, &ra_start, &ra_end);
457 for (step = ra_start; step <= ra_end; step += step_delta) {
459 pos1.ra = step;
460 pos2.ra = step + 180.0;
462 robject->coord[0].posn = &pos1;
463 robject->coord[1].posn = &pos2;
465 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
466 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
468 centre_x = robject->coord[0].x +
469 ((robject->coord[1].x - robject->coord[0].x) / 2.0);
470 centre_y = robject->coord[0].y +
471 ((robject->coord[1].y - robject->coord[0].y) / 2.0);
472 x = centre_x - robject->coord[0].x;
473 y = centre_y - robject->coord[0].y;
474 radius = sqrt(x * x + y * y);
476 if (!is_arc_visible(proj, centre_x, centre_y, radius) &&
477 step != proj->centre_ra)
478 continue;
480 /* need cairo_arc_to() */
481 #if 0
482 if (step == 0.0 || step == 90.0 ||
483 step == 180.0 || step == 270.0) {
484 struct ln_equ_posn pos1, pos2;
486 pos1.dec = 80.0;
487 pos2.dec = -80.0;
488 pos1.ra = step;
489 pos2.ra = step;
490 robject->num_coords = 2;
492 robject->coord[0].posn = &pos1;
493 robject->coord[1].posn = &pos2;
494 proj->trans->sky_to_proj_hrz(proj, robject);
496 cairo_new_sub_path(robject->cr);
497 cairo_arc_to(robject->cr,
498 robject->coord[0].x, robject->coord[0].y,
499 robject->coord[1].x, robject->coord[1].y,
500 radius);
501 } else {
502 if (is_arc_line(proj, centre_x))
503 draw_ra_line(robject, proj, step);
504 else {
505 cairo_new_sub_path(robject->cr);
506 cairo_arc(robject->cr, centre_x, centre_y,
507 radius, circle_start, circle_end);
510 #else
511 if (is_arc_line(proj, centre_x))
512 draw_ra_line(robject, proj, step);
513 else {
514 cairo_new_sub_path(robject->cr);
515 cairo_arc(robject->cr, centre_x, centre_y,
516 radius, 0, 2 * M_PI);
518 #endif
522 /* render all visible DEC grid lines */
523 static void hrz_render_dec(struct render_object *robject,
524 struct projection *proj, gint labels)
526 gdouble centre_x, centre_y, radius, x, y, step,
527 step_delta, dec_start, dec_end;
528 struct ln_equ_posn pos1, pos2;
530 pos1.ra = proj->centre_ra;
531 pos2.ra = proj->centre_ra + 180.0;
533 step_delta = get_dec_step_delta(proj);
534 clip_dec_equ_grid(proj, step_delta, &dec_start, &dec_end);
536 for (step = dec_start; step <= dec_end; step += step_delta) {
538 pos1.dec = step;
539 pos2.dec = step;
541 robject->coord[0].posn = &pos1;
542 robject->coord[1].posn = &pos2;
544 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
545 proj->trans->sky_to_proj_hrz(proj, &robject->coord[1]);
547 centre_x = robject->coord[0].x +
548 ((robject->coord[1].x - robject->coord[0].x) / 2.0);
549 centre_y = robject->coord[0].y +
550 ((robject->coord[1].y - robject->coord[0].y) / 2.0);
551 x = centre_x - robject->coord[0].x;
552 y = centre_y - robject->coord[0].y;
553 radius = sqrt(x * x + y * y);
555 if (!is_arc_visible(proj, centre_x, centre_y, radius) &&
556 step != proj->centre_dec)
557 continue;
559 cairo_new_sub_path(robject->cr);
561 if (is_arc_line(proj, centre_x))
562 draw_dec_line(robject, proj, step);
563 else
564 cairo_arc(robject->cr, centre_x, centre_y,
565 radius, 0, 2 * M_PI);
569 static void render_dec_labels_at(struct projection *proj,
570 struct render_object *robject, gdouble dec)
572 gchar text[32];
573 gdouble step_delta, delta_div = 2.0;
574 struct ln_equ_posn pos_start, pos_end;
575 struct ln_dms dms;
577 step_delta = get_dec_step_delta(proj);
579 pos_start.ra = proj->centre_ra;
580 pos_end.ra = proj->centre_ra;
581 pos_start.dec = pos_end.dec = dec;
582 robject->coord[0].posn = &pos_start;
583 robject->coord[1].posn = &pos_end;
585 /* find start position */
586 do {
587 pos_start.ra -= step_delta;
588 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
589 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
590 } while (projection_is_visible0(proj, robject) &&
591 proj->centre_ra - pos_start.ra < 90.0);
592 pos_start.ra += step_delta;
594 /* binary chop start */
595 do {
596 pos_start.ra -= step_delta / delta_div;
597 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
598 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
599 if (!projection_is_visible0(proj, robject))
600 pos_start.ra += step_delta / delta_div;
601 delta_div *= 2.0;
602 } while (delta_div < GRID_BISECT);
604 /* find end position */
605 do {
606 pos_end.ra += step_delta;
607 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
608 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
609 } while (projection_is_visible1(proj, robject) &&
610 pos_end.ra - proj->centre_ra < 90.0);
611 pos_end.ra -= step_delta;
613 /* binary chop end */
614 delta_div = 2.0;
615 do {
616 pos_end.ra += step_delta / delta_div;
617 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
618 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
619 if (!projection_is_visible1(proj, robject))
620 pos_end.ra -= step_delta / delta_div;
621 delta_div *= 2.0;
622 } while (delta_div < GRID_BISECT);
624 ln_deg_to_dms(dec, &dms);
625 if (dms.neg)
626 text[0] = '-';
627 else
628 text[0] = '+';
629 if (dms.minutes == 0 && dms.seconds == 0.0)
630 sprintf(&text[1], "%2.2dº", dms.degrees);
631 else if (dms.seconds < 0.1)
632 sprintf(&text[1], "%2.2dº%2.2dm", dms.degrees, dms.minutes);
633 else
634 sprintf(&text[1], "%2.2dº%2.2dm%2.0f", dms.degrees, dms.minutes,
635 dms.seconds);
637 cairo_move_to(robject->cr,
638 robject->coord[0].x - 30.0,
639 robject->coord[0].y - 1.0);
640 cairo_show_text(robject->cr, text);
641 cairo_move_to(robject->cr,
642 robject->coord[1].x + 1.0,
643 robject->coord[1].y - 1.0);
644 cairo_show_text(robject->cr, text);
647 static void render_ra_labels_at(struct projection *proj,
648 struct render_object *robject, gdouble ra)
650 gchar text[32];
651 gdouble step_delta, delta_div = 2.0;
652 struct ln_equ_posn pos_start, pos_end;
653 struct ln_hms hms;
655 step_delta = get_ra_step_delta(proj);
657 pos_start.dec = proj->centre_dec;
658 pos_end.dec = proj->centre_dec;
659 pos_start.ra = pos_end.ra = ra;
660 robject->coord[0].posn = &pos_start;
661 robject->coord[1].posn = &pos_end;
663 /* find start position */
664 do {
665 pos_start.dec -= step_delta;
666 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
667 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
668 } while (projection_is_visible0(proj, robject) &&
669 proj->centre_dec - pos_start.dec < 90.0);
670 pos_start.dec += step_delta;
672 /* binary chop start */
673 do {
674 pos_start.dec -= step_delta / delta_div;
675 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
676 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
677 if (!projection_is_visible0(proj, robject))
678 pos_start.dec += step_delta / delta_div;
679 delta_div *= 2.0;
680 } while (delta_div < GRID_BISECT);
682 /* find end position */
683 do {
684 pos_end.dec += step_delta;
685 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
686 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
687 } while (projection_is_visible1(proj, robject) &&
688 pos_end.dec - proj->centre_dec < 90.0);
689 pos_end.dec -= step_delta;
691 /* binary chop end */
692 delta_div = 2.0;
693 do {
694 pos_end.dec += step_delta / delta_div;
695 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
696 proj->trans->sky_to_proj_equ(proj, &robject->coord[1]);
697 if (!projection_is_visible1(proj, robject))
698 pos_end.dec -= step_delta / delta_div;
699 delta_div *= 2.0;
700 } while (delta_div < GRID_BISECT);
702 ln_deg_to_hms(ra, &hms);
703 if (hms.minutes == 0 && hms.seconds == 0.0)
704 sprintf(text, "%2.0dh", hms.hours);
705 else if (hms.seconds < 0.1)
706 sprintf(text, "%2.0dh%2.2dm", hms.hours, hms.minutes);
707 else
708 sprintf(text, "%2.0dh%2.2dm%2.0f", hms.hours, hms.minutes,
709 hms.seconds);
711 cairo_move_to(robject->cr,
712 robject->coord[0].x,
713 robject->coord[0].y);
714 cairo_show_text(robject->cr, text);
715 cairo_move_to(robject->cr,
716 robject->coord[1].x,
717 robject->coord[1].y + 15.0); // font size
718 cairo_show_text(robject->cr, text);
722 void equ_render_dec_labels(struct render_object *robject, struct projection *proj)
724 gdouble step, step_delta, dec_start, dec_end;
725 struct ln_equ_posn pos1;
727 pos1.ra = proj->centre_ra;
729 step_delta = get_dec_step_delta(proj);
730 clip_dec_equ_grid(proj, step_delta, &dec_start, &dec_end);
731 robject->coord[0].posn = &pos1;
733 for (step = dec_start; step <= dec_end; step += step_delta) {
734 pos1.dec = step;
735 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
736 render_dec_labels_at(proj, robject, step);
740 void equ_render_ra_labels(struct render_object *robject, struct projection *proj)
742 gdouble step, step_delta, ra_start, ra_end;
743 struct ln_equ_posn pos1;
745 pos1.ra = proj->centre_dec;
747 step_delta = get_ra_step_delta(proj);
748 clip_ra_equ_grid(proj, step_delta, &ra_start, &ra_end);
749 robject->coord[0].posn = &pos1;
751 for (step = ra_start; step <= ra_end; step += step_delta) {
752 pos1.ra = step;
753 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
754 render_ra_labels_at(proj, robject, step);
758 void hrz_render_dec_labels(struct render_object *robject, struct projection *proj)
760 gdouble step, step_delta, dec_start, dec_end;
761 struct ln_equ_posn pos1;
763 pos1.ra = proj->centre_ra;
765 step_delta = get_dec_step_delta(proj);
766 clip_dec_equ_grid(proj, step_delta, &dec_start, &dec_end);
767 robject->coord[0].posn = &pos1;
769 for (step = dec_start; step <= dec_end; step += step_delta) {
770 pos1.dec = step;
771 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
772 render_dec_labels_at(proj, robject, step);
776 void hrz_render_ra_labels(struct render_object *robject, struct projection *proj)
778 gdouble step, step_delta, ra_start, ra_end;
779 struct ln_equ_posn pos1;
781 pos1.ra = proj->centre_dec;
783 step_delta = get_ra_step_delta(proj);
784 clip_ra_equ_grid(proj, step_delta, &ra_start, &ra_end);
785 robject->coord[0].posn = &pos1;
787 for (step = ra_start; step <= ra_end; step += step_delta) {
788 pos1.ra = step;
789 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
790 render_ra_labels_at(proj, robject, step);
794 static void equ_render_dec(struct render_object *robject,
795 struct projection *proj, gint labels)
797 gdouble step, dec_start = -90, dec_end = 90, step_delta;
798 struct ln_equ_posn pos1;
799 int start_visible, end_visible;
801 step_delta = get_dec_step_delta(proj);
802 //clip_dec_equ_grid(proj, step_delta, &dec_start, &dec_end);
803 robject->coord[0].posn = &pos1;
805 for (pos1.dec = dec_start; pos1.dec <= dec_end; pos1.dec += step_delta) {
807 pos1.ra = 0;
808 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
809 start_visible = projection_is_visible0(proj, robject);
810 cairo_move_to(robject->cr,
811 robject->coord[0].x,
812 robject->coord[0].y);
814 for (step = 5; step <= 360; step += 5) {
815 pos1.ra = step;
816 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
817 end_visible = projection_is_visible0(proj, robject);
818 if (start_visible || end_visible)
819 cairo_line_to(robject->cr,
820 robject->coord[0].x,
821 robject->coord[0].y);
822 else
823 cairo_move_to(robject->cr,
824 robject->coord[0].x,
825 robject->coord[0].y);
826 start_visible = end_visible;
831 static void equ_render_ra(struct render_object *robject,
832 struct projection *proj, gint labels)
834 gdouble step, ra_start =0, ra_end = 360, step_delta;
835 struct ln_equ_posn pos1;
836 int start_visible, end_visible;
838 step_delta = get_ra_step_delta(proj);
839 //clip_ra_equ_grid(proj, step_delta, &ra_start, &ra_end);
840 robject->coord[0].posn = &pos1;
842 for (pos1.ra = ra_start; pos1.ra <= ra_end; pos1.ra += step_delta) {
844 pos1.dec = -80;
845 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
846 start_visible = projection_is_visible0(proj, robject);
847 cairo_move_to(robject->cr,
848 robject->coord[0].x,
849 robject->coord[0].y);
851 for (step = -75; step <= 80; step += 5) {
852 pos1.dec = step;
853 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
854 end_visible = projection_is_visible0(proj, robject);
855 if (start_visible || end_visible)
856 cairo_line_to(robject->cr,
857 robject->coord[0].x,
858 robject->coord[0].y);
859 else
860 cairo_move_to(robject->cr,
861 robject->coord[0].x,
862 robject->coord[0].y);
863 start_visible = end_visible;
868 void grid_horizon_ra(struct render_object *robject, struct projection *proj)
870 gdouble step;
871 struct ln_equ_posn pos1;
872 int start_visible, end_visible;
874 pos1.ra = 0;
875 pos1.dec = 0;
876 robject->coord[0].posn = &pos1;
877 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
878 start_visible = projection_is_visible0(proj, robject);
879 cairo_move_to(robject->cr,
880 robject->coord[0].x,
881 robject->coord[0].y);
883 for (step = 10; step <= 360; step += 10) {
884 pos1.ra = step;
885 proj->trans->sky_to_proj_equ(proj, &robject->coord[0]);
886 end_visible = projection_is_visible0(proj, robject);
887 if (start_visible || end_visible)
888 cairo_line_to(robject->cr,
889 robject->coord[0].x,
890 robject->coord[0].y);
891 else
892 cairo_move_to(robject->cr,
893 robject->coord[0].x,
894 robject->coord[0].y);
895 start_visible = end_visible;
899 void grid_horizon_altaz(struct render_object *robject, struct projection *proj)
901 gdouble step;
902 struct ln_equ_posn pos1;
903 int start_visible, end_visible;
905 cairo_save(robject->cr);
906 cairo_set_source_rgba(robject->cr, 1, 0.35, 0.55, 0.7);
908 pos1.ra = 0;
909 pos1.dec = 0;
910 robject->coord[0].posn = &pos1;
912 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
913 start_visible = projection_is_visible0(proj, robject);
914 cairo_move_to(robject->cr,
915 robject->coord[0].x,
916 robject->coord[0].y);
918 for (step = 10; step <= 360; step += 10) {
919 pos1.ra = step;
920 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
921 end_visible = projection_is_visible0(proj, robject);
922 if (start_visible || end_visible)
923 cairo_line_to(robject->cr,
924 robject->coord[0].x,
925 robject->coord[0].y);
926 else
927 cairo_move_to(robject->cr,
928 robject->coord[0].x,
929 robject->coord[0].y);
930 start_visible = end_visible;
932 cairo_stroke(robject->cr);
933 cairo_restore(robject->cr);
936 void grid_horizon_news(struct render_object *robject, struct projection *proj)
938 struct ln_equ_posn pos1;
940 cairo_save(robject->cr);
941 cairo_set_font_size (robject->cr, 18.0);
942 cairo_set_source_rgba(robject->cr, 1, 0.35, 0.55, 0.7);
943 robject->coord[0].posn = &pos1;
944 pos1.dec = 0;
946 pos1.ra = 0;
947 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
948 cairo_move_to(robject->cr,
949 robject->coord[0].x,
950 robject->coord[0].y);
951 cairo_show_text(robject->cr, "S");
953 pos1.ra = 90;
954 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
955 cairo_move_to(robject->cr,
956 robject->coord[0].x,
957 robject->coord[0].y);
958 cairo_show_text(robject->cr, "W");
960 pos1.ra = 180;
961 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
962 cairo_move_to(robject->cr,
963 robject->coord[0].x,
964 robject->coord[0].y);
965 cairo_show_text(robject->cr, "N");
967 pos1.ra = 270;
968 proj->trans->sky_to_proj_hrz(proj, &robject->coord[0]);
969 cairo_move_to(robject->cr,
970 robject->coord[0].x,
971 robject->coord[0].y);
972 cairo_show_text(robject->cr, "E");
974 cairo_restore(robject->cr);
977 void grid_render(Sky *sky)
979 struct render_object *robject = &sky->robject;
980 struct projection *proj = &sky->projection;
981 gint labels = sky->marker_settings.show_grid_labels;
982 gdouble alpha;
984 if (robject->flags.night_mode)
985 alpha = GRID_NIGHT_ALPHA;
986 else
987 alpha = GRID_DAY_ALPHA;
989 cairo_save(robject->cr);
990 cairo_set_source_rgba(robject->cr, 0, 0.35, 0.55, alpha);
991 cairo_set_font_size (robject->cr, 13.0);
993 if (robject->type == RT_FAST) //TODO make step size * 2.0 when fast
994 cairo_set_tolerance (robject->cr, 1.0);
996 switch (proj->grid_coords) {
997 case PC_RA_DEC:
998 equ_render_ra(robject, proj, labels);
999 equ_render_dec(robject, proj, labels);
1000 equ_render_dec_labels(robject, proj);
1001 equ_render_ra_labels(robject, proj);
1002 break;
1003 case PC_ALT_AZ:
1004 hrz_render_ra(robject, proj, labels);
1005 hrz_render_dec(robject, proj, labels);
1006 hrz_render_dec_labels(robject, proj);
1007 hrz_render_ra_labels(robject, proj);
1008 break;
1010 cairo_stroke(robject->cr);
1012 //grid_horizon_ra(robject, proj);
1013 grid_horizon_altaz(robject, proj);
1016 grid_horizon_news(robject, proj);
1018 if (robject->type == RT_FAST)
1019 cairo_set_tolerance (robject->cr, 0.1); /* do we need this */
1020 cairo_restore(robject->cr);