// This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Copyright Liam Girdwood 2003 #include "sky_spherical.hh" #include #include #include #include /*! \namespace Vega * \brief Nova Virtual Sky Engine */ namespace Vega { /*! \fn SkySpherical::SkySpherical(double x_size, double y_size) * \param x_size Virtual sky x size * \param y_size Virtual sky y size * * Constructor */ SkySpherical::SkySpherical() { m_spherical = true; } /*! \fn SkySpherical::~SkySpherical() * Destructor */ SkySpherical::~SkySpherical() { } void SkySpherical::render_planets() { struct ln_equ_posn equ; double ra, dec; double ra_offset; // calc offset if (m_is_ra_over) ra_offset = MIN_RA; else ra_offset = m_ra_offset; if (m_mercury.get_mag(m_JD) < m_clip_mag_max) { m_mercury.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_mercury.set_render_jd(m_JD); m_mercury.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_venus.get_mag(m_JD) < m_clip_mag_max) { m_venus.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_venus.set_render_jd(m_JD); m_venus.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_mars.get_mag(m_JD) < m_clip_mag_max) { m_mars.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_mars.set_render_jd(m_JD); m_mars.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_jupiter.get_mag(m_JD) < m_clip_mag_max) { m_jupiter.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_jupiter.set_render_jd(m_JD); m_jupiter.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_saturn.get_mag(m_JD) < m_clip_mag_max) { m_saturn.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_saturn.set_render_jd(m_JD); m_saturn.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_uranus.get_mag(m_JD) < m_clip_mag_max) { m_uranus.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_uranus.set_render_jd(m_JD); m_uranus.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_neptune.get_mag(m_JD) < m_clip_mag_max) { m_neptune.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_neptune.set_render_jd(m_JD); m_neptune.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_pluto.get_mag(m_JD) < m_clip_mag_max) { m_pluto.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_pluto.set_render_jd(m_JD); m_pluto.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_is_ra_over || m_is_ra_under) { // get ra offset if (m_is_ra_under) ra_offset = m_ra_offset + MAX_RA; //rhs else ra_offset = -MAX_RA; //lhs if (m_mercury.get_mag(m_JD) < m_clip_mag_max) { m_mercury.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_mercury.set_render_jd(m_JD); m_mercury.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_venus.get_mag(m_JD) < m_clip_mag_max) { m_venus.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_venus.set_render_jd(m_JD); m_venus.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_mars.get_mag(m_JD) < m_clip_mag_max) { m_mars.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_mars.set_render_jd(m_JD); m_mars.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_jupiter.get_mag(m_JD) < m_clip_mag_max) { m_jupiter.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_jupiter.set_render_jd(m_JD); m_jupiter.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_saturn.get_mag(m_JD) < m_clip_mag_max) { m_saturn.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_saturn.set_render_jd(m_JD); m_saturn.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_uranus.get_mag(m_JD) < m_clip_mag_max) { m_uranus.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_uranus.set_render_jd(m_JD); m_uranus.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_neptune.get_mag(m_JD) < m_clip_mag_max) { m_neptune.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_neptune.set_render_jd(m_JD); m_neptune.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } if (m_pluto.get_mag(m_JD) < m_clip_mag_max) { m_pluto.get_equ_posn(m_JD, ra, dec); transform (ra, dec, ra_offset); m_pluto.set_render_jd(m_JD); m_pluto.render (ra, dec, m_clip_mag_max, *m_object_group, false, m_ra_ppd); } } } /*! \fn void SkySpherical::render_grid() * * Render grid on virtual sky. */ void SkySpherical::render_grid() { return; // for now std::vector ra_points, ra_overlap_points; std::vector dec_points, dec_overlap_points; std::vector::iterator ra; std::vector::iterator dec; double ra_offset; // clip and get lines m_grid.clip(m_clip_ra_min, m_clip_dec_min, m_clip_ra_max, m_clip_dec_max); std::cout << " bpath ra lines " << m_grid.get_ra_lines(ra_points); std::cout << " bpath dec lines " << m_grid.get_dec_lines(dec_points); // are we overlapping if (m_is_ra_over || m_is_ra_under) { m_grid.clip(m_clip_ra_min_overlap, m_clip_dec_min, m_clip_ra_max_overlap, m_clip_dec_max); m_grid.get_ra_lines(ra_overlap_points, true); m_grid.get_dec_lines(dec_overlap_points); } // calc offset if (m_is_ra_over) ra_offset = MIN_RA; else ra_offset = m_ra_offset; // now render ra grid for (ra = ra_points.begin(); ra != ra_points.end(); ra++) { double mid_x, mid_y; Glib::RefPtr path = Gnome::Canvas::PathDef::create(); mid_x = (*ra).x1 + (((*ra).x2 - (*ra).x1) / 2.0); mid_y = (*ra).y1 + (((*ra).y2 - (*ra).y1) / 2.0); transform_grid((*ra).x1, (*ra).y1, ra_offset); transform_grid(mid_x, mid_y, ra_offset); transform_grid((*ra).x2, (*ra).y2, ra_offset); path->moveto((*ra).x1, (*ra).y1); path->curveto((*ra).x1, (*ra).y1, mid_x, mid_y, (*ra).x2, (*ra).y2); Gnome::Canvas::Bpath* line = manage(new Gnome::Canvas::Bpath(*m_grid_group)); line->set_bpath(path); line->property_outline_color () = "grey"; line->property_width_pixels () = 1; } // render dec grid for (dec = dec_points.begin(); dec != dec_points.end(); dec++) { double mid_x, mid_y; Glib::RefPtr path = Gnome::Canvas::PathDef::create(); mid_x = (*dec).x1 + (((*dec).x2 - (*dec).x1) / 2.0); mid_y = (*dec).y1 + (((*dec).y2 - (*dec).y1) / 2.0); transform_grid((*dec).x1, (*dec).y1, ra_offset); transform_grid(mid_x, mid_y, ra_offset); transform_grid((*dec).x2, (*dec).y2, ra_offset); path->moveto((*dec).x1, (*dec).y1); path->curveto((*dec).x1, (*dec).y1, mid_x, mid_y, (*dec).x2, (*dec).y2); Gnome::Canvas::Bpath* line = manage(new Gnome::Canvas::Bpath(*m_grid_group)); line->set_bpath(path); line->property_outline_color () = "grey"; line->property_width_pixels () = 1; } if (m_is_ra_over || m_is_ra_under) { // get ra offset if (m_is_ra_under) ra_offset = m_ra_offset + MAX_RA; //rhs else ra_offset = -MAX_RA; //lhs // now render ra grid for (ra = ra_overlap_points.begin(); ra != ra_overlap_points.end(); ra++) { double mid_x, mid_y; Glib::RefPtr path = Gnome::Canvas::PathDef::create(); mid_x = (*ra).x1 + (((*ra).x2 - (*ra).x1) / 2.0); mid_y = (*ra).y1 + (((*ra).y2 - (*ra).y1) / 2.0); transform_grid((*ra).x1, (*ra).y1, ra_offset); transform_grid(mid_x, mid_y, ra_offset); transform_grid((*ra).x2, (*ra).y2, ra_offset); path->moveto((*ra).x1, (*ra).y1); path->curveto((*ra).x1, (*ra).y1, mid_x, mid_y, (*ra).x2, (*ra).y2); Gnome::Canvas::Bpath* line = manage(new Gnome::Canvas::Bpath(*m_grid_group)); line->set_bpath(path); line->property_outline_color () = "grey"; line->property_width_pixels () = 1; } // render dec grid for (dec = dec_overlap_points.begin(); dec != dec_overlap_points.end(); dec++) { double mid_x, mid_y; Glib::RefPtr path = Gnome::Canvas::PathDef::create(); mid_x = (*dec).x1 + (((*dec).x2 - (*dec).x1) / 2.0); mid_y = (*dec).y1 + (((*dec).y2 - (*dec).y1) / 2.0); transform_grid((*dec).x1, (*dec).y1, ra_offset); transform_grid(mid_x, mid_y, ra_offset); transform_grid((*dec).x2, (*dec).y2, ra_offset); path->moveto((*dec).x1, (*dec).y1); path->curveto((*dec).x1, (*dec).y1, mid_x, mid_y, (*dec).x2, (*dec).y2); Gnome::Canvas::Bpath* line = manage(new Gnome::Canvas::Bpath(*m_grid_group)); line->set_bpath(path); line->property_outline_color () = "grey"; line->property_width_pixels () = 1; } } } /*! \fn void SkySpherical::render_const_lines() * * Render virtual sky constellation lines. */ void SkySpherical::render_const_lines() { std::vector lines, overlap_lines; std::vector::iterator i; Gnome::Canvas::Line* line; double ra_offset; // delete constellations delete m_const_group; m_const_group = Gtk::manage (new Gnome::Canvas::Group (*m_root, 0, 0)); // clip and get lines m_constellation.clip(m_clip_ra_min, m_clip_dec_min, m_clip_ra_max, m_clip_dec_max); std::cout << " ra lines " << m_constellation.get_lines(lines); std::cout << " ratio " << m_canvas_ratio << std::endl; // are we overlapping if (m_is_ra_over || m_is_ra_under) { m_constellation.clip(m_clip_ra_min_overlap, m_clip_dec_min, m_clip_ra_max_overlap, m_clip_dec_max); m_constellation.get_lines(overlap_lines); } // calc offset if (m_is_ra_over) ra_offset = MIN_RA; else ra_offset = m_ra_offset; // now render each line for (i = lines.begin(); i != lines.end(); i++) { Gnome::Canvas::Points line_points; transform((*i).ra1, (*i).dec1, ra_offset); if (!is_visible((*i).ra1, (*i).dec1)) continue; transform((*i).ra2, (*i).dec2, ra_offset); if (!is_visible((*i).ra2, (*i).dec2)) continue; line_points.push_back(Gnome::Art::Point((*i).ra1, (*i).dec1)); line_points.push_back(Gnome::Art::Point((*i).ra2, (*i).dec2)); line = Gtk::manage(new Gnome::Canvas::Line(*m_const_group, line_points)); *line << Gnome::Canvas::Properties::fill_color("blue"); } if (m_is_ra_over || m_is_ra_under) { // get ra offset if (m_is_ra_under) ra_offset = m_ra_offset + MAX_RA; //rhs else ra_offset = -MAX_RA; //lhs // now render lines for (i = overlap_lines.begin(); i != overlap_lines.end(); i++) { Gnome::Canvas::Points line_points; transform((*i).ra1, (*i).dec1, ra_offset); if (!is_visible((*i).ra1, (*i).dec1)) continue; transform((*i).ra2, (*i).dec2, ra_offset); if (!is_visible((*i).ra2, (*i).dec2)) continue; line_points.push_back(Gnome::Art::Point((*i).ra1, (*i).dec1)); line_points.push_back(Gnome::Art::Point((*i).ra2, (*i).dec2)); line = Gtk::manage(new Gnome::Canvas::Line(*m_const_group, line_points)); *line << Gnome::Canvas::Properties::fill_color("blue"); } } } /*! \fn void SkySpherical::render_const_bounds() * * Render virtual sky constellation boundaries */ void SkySpherical::render_const_bounds() { } /*! \fn void SkySpherical::render_const_names() * * Render virtual sky constellation names. */ void SkySpherical::render_const_names() { } /*! \fn void SkySpherical::get_position (double x, double y, double& ra, double& dec); * \brief get sky ra,dec at x,y coordinates */ void SkySpherical::get_position (double x, double y, double& ra, double& dec) { } /*! \fn void SkySpherical::transform_grid (double& x, double& y, double dec_offset) * \param x X coordinate * \param y Y coordinate * \param object Astro object * * Transform the objects RA nad DEC into virtual sky coordinates. */ void SkySpherical::transform_grid (double& x, double& y, double ra_offset) { y += m_centre_dec; transform(x, y, ra_offset); } /*! \fn void SkySpherical::transform(double& x, double& y, Castor::AstroObject* object) * \param x X coordinate * \param y Y coordinate * \param object Astro object * * Transform the objects RA nad DEC into virtual sky coordinates. */ void SkySpherical::transform(double& x, double& y, double ra_offset) { double xd,yd,zd; double ratio; // subtract centre x -= m_centre_ra; y -= m_centre_dec; // convert to radians x = (x / 360.0) * 2.0 * M_PI; y = (y / 360.0) * 2.0 * M_PI; // project to spherical vsky xd = cos(y) * sin(x); yd = sin(y); zd = cos(y) * cos(x); x = xd / (1.0 + zd); y = yd / (1.0 + zd); //std::cout << x << " " << y << std::endl; // convert back to canvas scale ratio = MAX_FOV / m_fov; x = (m_canvas_width / 2) - ((x * m_canvas_height / 2.0) * ratio); y = (m_canvas_height / 2) - ((y * m_canvas_height / 2.0) * ratio); } /*! \fn virtual bool is_visible(double x, double y) = 0; * Is the object visible ? */ bool SkySpherical::is_visible(double x, double y) { double dx = x - (m_canvas_width / 2); double dy = y - (m_canvas_height / 2); double dist = dx * dx + dy * dy; dist = sqrt (dist); if (dist > m_outer_size) return false; else return true; } void SkySpherical::render_basic() { // delete existing delete m_object_group; m_object_group = Gtk::manage (new Gnome::Canvas::Group (*m_root, 0, 0)); // render outer circle m_outer_size = ((m_canvas_height / 2.0) * (MAX_FOV / m_fov)); if (m_outer_size > 1.5 * m_canvas_width) return; double xmin = m_canvas_width / 2.0 - m_outer_size; double xmax = m_canvas_width / 2.0 + m_outer_size; double ymin = m_canvas_height / 2.0 - m_outer_size; double ymax = m_canvas_height / 2.0 + m_outer_size; Gnome::Canvas::Ellipse * outer_bounds = manage(new Gnome::Canvas::Ellipse(*m_object_group, xmin, ymin, xmax, ymax)); outer_bounds->property_outline_color () = "grey"; outer_bounds->property_width_pixels () = 1; std::cout <<" outer size " << m_outer_size << std::endl; } };