// 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 <libnova/libnova.h>
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<SkyFlat*>(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<const xmlpp::ContentNode*>(node);
const xmlpp::TextNode* nodeText = dynamic_cast<const xmlpp::TextNode*>(node);
const xmlpp::CommentNode* nodeComment = dynamic_cast<const xmlpp::CommentNode*>(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<const xmlpp::Element*>(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;
}
}
syntax highlighted by Code2HTML, v. 0.9.1