// 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 "virtual_sky.hh" #include "astro_object.hh" #include namespace Vega { VirtualSky::VirtualSky() { // draw default catalog objects m_proj_type = FLAT; m_epoch = 2000.0; m_library = Pollux::Library::get_library(); std::string cat_name("default"); m_default_cat = m_library->get_catalog (cat_name); m_filename =""; pack_end (m_appbar, Gtk::PACK_SHRINK, 0); // create sky projection switch (m_proj_type) { case FLAT: m_projection = new SkyFlat(); break; case SPHERICAL: m_projection = new SkySpherical(); break; } } VirtualSky::~VirtualSky() { } /*! \fn bool VirtualSky::create_sky () * \return true on success * * Create and display a virtual sky view */ bool VirtualSky::create_sky () { pack_start (*m_projection, Gtk::PACK_EXPAND_WIDGET, 0); m_projection->add_bright_catalog(m_default_cat); m_projection->show_const_lines(true); m_projection->show_grid(true); m_projection->set_jd(m_JD); m_projection->set_size(m_width, m_height); m_projection->show_sky(); m_projection->grab_focus(); show_all(); // add labels appbar_set_equ(0,0); appbar_set_hrz(0,0); appbar_set_object(0); appbar_set_fov(); // attach signal handlers m_projection->signal_enter_notify_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_enter_notify_event)); m_projection->signal_leave_notify_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_leave_notify_event)); m_projection->signal_key_press_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_key_press_event)); m_projection->signal_key_release_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_key_release_event)); m_projection->signal_motion_notify_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_motion_event)); m_projection->signal_button_press_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_button_press_event)); m_projection->signal_button_release_event().connect (SigC::slot(*this, &VirtualSky::on_canvas_button_release_event)); return true; } /*! \fn int VirtualSky::save() * * save virtual sky state to file */ bool VirtualSky::save() { char attr[64]; try { xmlpp::Document document; xmlpp::Element* node_root = document.create_root_node("root", "http://gnova.org", "vsky"); // sky xmlpp::Element* node_sky = node_root->add_child("sky"); sprintf(attr, "%f", m_projection->get_ra()); node_sky->set_attribute("ra", attr); sprintf(attr, "%f", m_projection->get_dec()); node_sky->set_attribute("dec", attr); sprintf(attr, "%f", m_projection->get_fov()); node_sky->set_attribute("fov", attr); sprintf(attr, "%s", m_projection->is_const_lines() ? "true" : "false"); node_sky->set_attribute("constLines", attr); sprintf(attr, "%s", m_projection->is_const_bounds() ? "true" : "false"); node_sky->set_attribute("constBounds", attr); sprintf(attr, "%s", m_projection->is_const_names() ? "true" : "false"); node_sky->set_attribute("constNames", attr); sprintf(attr, "%s", m_projection->is_grid() ? "true" : "false"); node_sky->set_attribute("grid", attr); sprintf(attr, "%s", m_live ? "true" : "false"); node_sky->set_attribute("live", attr); sprintf(attr, "%s", dynamic_cast(m_projection) ? "flat" : "spherical"); node_sky->set_attribute("projection", attr); sprintf(attr, "%f", m_epoch); node_sky->set_attribute("epoch", attr); // observer xmlpp::Element* node_observer = node_root->add_child("observer"); node_observer->set_attribute("location", m_location); sprintf(attr, "%f", m_JD); node_observer->set_attribute("jd", attr); sprintf(attr, "%f", m_observer.lat); node_observer->set_attribute("latitude", attr); sprintf(attr, "%f", m_observer.lng); node_observer->set_attribute("longitude", attr); sprintf(attr, "%f", m_elevation); node_observer->set_attribute("elevation", attr); document.write_to_file_formatted(m_filename); } catch(const std::exception& ex) { std::cerr << __FILE__ << " " << __LINE__ << " Exception caught: " << ex.what() << std::endl; return false; } m_is_modified = false; return true; } bool VirtualSky::save_as(Glib::ustring file) { m_filename = file; save(); } bool VirtualSky::print() { } bool VirtualSky::open(Glib::ustring file) { m_filename = file; try { xmlpp::DomParser parser; parser.set_substitute_entities(); parser.parse_file(m_filename); if(parser) { const xmlpp::Node* pNode = parser.get_document()->get_root_node(); parse_node(pNode); } } catch(const std::exception& ex) { std::cout << "Exception caught: " << ex.what() << std::endl; return false; } return true; } void VirtualSky::parse_node(const xmlpp::Node* node) { const xmlpp::ContentNode* nodeContent = dynamic_cast(node); const xmlpp::TextNode* nodeText = dynamic_cast(node); const xmlpp::CommentNode* nodeComment = dynamic_cast(node); const xmlpp::Attribute* attribute; if(nodeText && nodeText->is_white_space()) return; std::string nodename = node->get_name(); if(const xmlpp::Element* nodeElement = dynamic_cast(node)) { attribute = nodeElement->get_attribute("ra"); if(attribute) m_projection->set_ra(atof(attribute->get_value().c_str())); attribute = nodeElement->get_attribute("dec"); if(attribute) m_projection->set_dec(atof(attribute->get_value().c_str())); attribute = nodeElement->get_attribute("fov"); if(attribute) m_projection->set_fov(atof(attribute->get_value().c_str())); attribute = nodeElement->get_attribute("jd"); if(attribute) m_JD = atof(attribute->get_value().c_str()); attribute = nodeElement->get_attribute("latitude"); if(attribute) m_observer.lat = atof(attribute->get_value().c_str()); attribute = nodeElement->get_attribute("longitude"); if(attribute) m_observer.lng = atof(attribute->get_value().c_str()); attribute = nodeElement->get_attribute("elevation"); if(attribute) m_elevation = atof(attribute->get_value().c_str()); attribute = nodeElement->get_attribute("epoch"); if(attribute) m_epoch = atof(attribute->get_value().c_str()); attribute = nodeElement->get_attribute("location"); if(attribute) m_location = attribute->get_value(); attribute = nodeElement->get_attribute("constLines"); if(attribute) m_projection->show_const_lines(attribute->get_value() == "true" ? true : false); attribute = nodeElement->get_attribute("constBounds"); if(attribute) m_projection->show_const_bounds(attribute->get_value() == "true" ? true : false); attribute = nodeElement->get_attribute("constNames"); if(attribute) m_projection->show_const_names(attribute->get_value() == "true" ? true : false); attribute = nodeElement->get_attribute("grid"); if(attribute) m_projection->show_grid(attribute->get_value() == "true" ? true : false); attribute = nodeElement->get_attribute("projection"); if(attribute) m_proj_type = attribute->get_value() == "flat" ? FLAT : SPHERICAL; } if(!nodeContent) { //Recurse through child nodes: xmlpp::Node::NodeList list = node->get_children(); for(xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter) { parse_node(*iter); //recursive } } } /*! \fn void VirtualSky::set_live(bool live) * * Set true if the sky has to update with the * current system time. */ void VirtualSky::set_live(bool live) { m_live = live; } void VirtualSky::set_size(int width, int height) { m_width = width; m_height = height; } /*! \fn bool VirtualSky::change_projection() * \return true on success * * Change the virtual sky projection type */ bool VirtualSky::change_projection() { // create sky projection SkyProj* projection; if (m_proj_type == FLAT) m_proj_type = SPHERICAL; else m_proj_type = FLAT; switch (m_proj_type) { case FLAT: projection = new SkyFlat(); break; case SPHERICAL: projection = new SkySpherical(); break; default: return false; } projection->clone(m_projection); remove(*m_projection); delete m_projection; m_projection = projection; m_is_modified = true; return create_sky(); } /*! \fn bool VirtualSky::move_north(double move) * * Move sky in declination */ void VirtualSky::move_dec(double pixels) { m_projection->move_dec(pixels); m_projection->render_sky(SkyProj::BRIGHT); m_is_modified = true; } /*! \fn bool VirtualSky::move_south(double move) * * Move sky in RA */ void VirtualSky::move_ra(double pixels) { m_projection->move_ra(pixels); m_projection->render_sky(SkyProj::BRIGHT); m_is_modified = true; } /*! \fn bool VirtualSky::zoom(double zoom) * * zoom in sky */ bool VirtualSky::zoom (double zoom) { bool ret; ret = m_projection->zoom(zoom); m_projection->render_sky(SkyProj::FULL); m_is_modified = true; appbar_set_fov(); return ret; } // sky info void VirtualSky::set_jd(double JD) { m_JD = JD; } void VirtualSky::set_elevation(double m) { m_elevation = m; } double VirtualSky::get_elevation() { return m_elevation; } void VirtualSky::set_epoch(double epoch) { m_epoch = epoch; } double VirtualSky::get_epoch() { return m_epoch; } double VirtualSky::get_latitude() { return m_observer.lat; } void VirtualSky::set_latitude(double latitude) { m_observer.lat = latitude; } double VirtualSky::get_longitude() { return m_observer.lng; } void VirtualSky::set_longitude(double longitude) { m_observer.lng = longitude; } void VirtualSky::get_location(Glib::ustring& location) { location = m_location; } void VirtualSky::set_location(Glib::ustring& location) { m_location = location; } /*! \fn void VirtualSky::appbar_set_equ (double x, double y, bool transform = true) * \param x canvas x position * \param y canvas y position * * Display the current pointer position in the appbar. */ void VirtualSky::appbar_set_equ (double x, double y, bool transform) { double ra, dec; if (transform) { m_projection->get_position(x, y, ra, dec); m_appbar.set_equ_posn(ra, dec); } else m_appbar.set_equ_posn(x,y); } /*! \fn void VirtualSky::appbar_push_object (Castor::AstroObject* object) * \param object Object to display details. * * Display an astro objects details on the app bar. */ void VirtualSky::appbar_set_object (Castor::AstroObject* object) { m_appbar.set_object(object); } void VirtualSky::appbar_set_hrz (double x, double y, bool transform) { double ra, dec; ln_equ_posn equ; ln_hrz_posn hrz; if (transform) { m_projection->get_position(x, y, ra, dec); equ.ra = ra; equ.dec = dec; ln_get_hrz_from_equ(&equ, &m_observer, m_JD, &hrz); m_appbar.set_hrz_posn(hrz.alt, hrz.az); } else m_appbar.set_hrz_posn(x,y); } void VirtualSky::appbar_set_fov () { m_appbar.set_fov(m_projection->get_fov()); } // // Signal Handlers // Handle mouse movement, mouse press and key presses // // some mouse button clicked on sky bool VirtualSky::on_canvas_button_press_event(GdkEventButton *ev) { double x,y; // left,centre or right button switch (ev->button) { case 1: break; case 2: break; case 3: break; } return true; } // mouse button released on sky bool VirtualSky::on_canvas_button_release_event(GdkEventButton *ev) { double x,y; // left,centre or right button switch (ev->button) { case 1: break; case 2: break; case 3: break; } return true; } /*! \fn bool VirtualSky::on_canvas_motion_event(GdkEventMotion *ev) * \param ev Motion event * \return zero ? * * Proccess mouse movement on virtual sky */ bool VirtualSky::on_canvas_motion_event(GdkEventMotion *ev) { double x, y; // get sky position (ra,dec) m_projection->c2w ((int)(ev->x), (int)(ev->y), x, y); // are we currently over an object, then add it to appbar Gnome::Canvas::Item* item = m_projection->get_item_at (x, y); if (item) { Castor::AstroObject* object = (Castor::AstroObject*)item->get_data(Glib::Quark("object")); if (object != 0) { struct ln_hrz_posn hrz; appbar_set_object (object); object->get_equ_posn(m_JD, x,y); appbar_set_equ (x, y, false); object->get_hrz_posn(m_JD, &m_observer, &hrz); appbar_set_hrz (hrz.alt, hrz.az, false); } else { appbar_set_object (0); appbar_set_equ (x, y); appbar_set_hrz (x, y); } } return true; } // mouse pointer entered sky, set pointer to cross bool VirtualSky::on_canvas_enter_notify_event(GdkEventCrossing *ev) { // set cursor Gdk::Cursor cursor(Gdk::CROSSHAIR); grab_focus(); get_window()->set_cursor(cursor); return true; } // mouse pointer no longer in sky, set pointer to arrow bool VirtualSky::on_canvas_leave_notify_event(GdkEventCrossing *ev) { // set cursor Gdk::Cursor cursor(Gdk::LEFT_PTR); get_window()->set_cursor(cursor); return true; } // key pressed in sky bool VirtualSky::on_canvas_key_press_event(GdkEventKey *ev) { // need correct key codes std::cout << "Event "; switch (ev->keyval) { case 65362: std::cout << "Press down" << std::endl; move_dec(25); grab_focus(); break; case 65364: std::cout << "Press up" << std::endl; move_dec(-25); grab_focus(); break; case 65363: std::cout << "Press right" << std::endl; move_ra(-25); grab_focus(); break; case 65361: std::cout << "Press left" << std::endl; move_ra(25); grab_focus(); break; } return true; } // key released in sky bool VirtualSky::on_canvas_key_release_event(GdkEventKey *ev) { std::cout << "Key released " << std::endl; switch (ev->keyval) { case 65362: case 65364: case 65363: case 65361: m_projection->render_sky(SkyProj::FULL); grab_focus(); break; } return true; } }