// 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_proj.hh"
/*! \namespace Vega
* \brief Nova Virtual Sky Engine
*/
namespace Vega
{
/*! \fn SkyProj::SkyProj()
* Constructor
*/
SkyProj::SkyProj()
{
// default sky settings
m_centre_ra = MAX_RA / 2;
m_centre_dec = 0;
m_fov = MAX_RA / 2;
m_clip_mag_max = 4;
m_clip_mag_min = -2;
m_show_const_lines = true;
m_show_const_bounds = true;
m_show_const_names = true;
m_show_grid = true;
m_show_planets = true;
m_root = root();
// canvas groups
m_object_group = 0;
m_grid_group = 0;
m_const_group = 0;
}
void SkyProj::clone (SkyProj* proj)
{
m_centre_ra = proj->m_centre_ra;
m_centre_dec = proj->m_centre_dec;
m_fov = proj->m_fov;
m_show_const_lines = proj->m_show_const_lines;
m_show_const_bounds = proj->m_show_const_bounds;
m_show_const_names = proj->m_show_const_names;
m_show_grid = proj->m_show_grid;
m_JD = proj->m_JD;
}
/*! \fn void SkyProj::show_sky()
*
* Create and show the sky projection.
*/
void SkyProj::show_sky()
{
set_pixels_per_unit(1);
set_scroll_region(0, 0, m_canvas_width, m_canvas_height);
// render sky
render_background();
render_sky(FULL);
}
/*! \fn SkyProj::~SkyProj()
* Destructor
*/
SkyProj::~SkyProj()
{
}
/*! \fn void SkyProj::show_grid(bool show)
*
* Set whether a position marker is rendered
*/
void SkyProj::show_grid(bool show)
{
m_show_grid = show;
}
/*! \fn void SkyProj::show_const_lines(bool show)
*
* Set whether constellation outlines are rendered
*/
void SkyProj::show_const_lines(bool show)
{
m_show_const_lines = show;
}
/*! \fn void SkyProj::show_const_names(bool show)
*
* Set whether constellation names are rendered
*/
void SkyProj::show_const_names(bool show)
{
m_show_const_names = show;
}
/*! \fn void SkyProj::show_const_bounds(bool show)
*
* Set whether constellation boundaries are rendered
*/
void SkyProj::show_const_bounds(bool show)
{
m_show_const_bounds = show;
}
/*! \fn bool SkyProj::show_grid()
*
* True if position marker is rendered
*/
bool SkyProj::is_grid()
{
return m_show_grid;
}
/*! \fn bool SkyProj::is_const_lines()
*
* True if constellation outlines are rendered
*/
bool SkyProj::is_const_lines()
{
return m_show_const_lines;
}
/*! \fn bool SkyProj::is_const_names()
*
* True if constellation names are rendered
*/
bool SkyProj::is_const_names()
{
return m_show_const_names;
}
/*! \fn bool SkyProj::is_const_bounds()
*
* True if constellation boundaries are rendered
*/
bool SkyProj::is_const_bounds()
{
return m_show_const_bounds;
}
/*! \fn void SkyProj::set_jd (double jd)
*
* Set sky projection Julian day
*/
void SkyProj::set_jd (double jd)
{
m_JD = jd;
}
/*! \fn double SkyProj::get_jd()
*
* Get sky projection Julian day
*/
double SkyProj::get_jd()
{
return m_JD;
}
/*! \fn void SkyProj::add_bright_catalog(Pollux::Catalog* cat)
* \param cat Bright object catalog
*
* Add a bright object catalog to the sky projection
*/
void SkyProj::add_bright_catalog(Pollux::Catalog* cat)
{
m_bright_cat = cat;
}
/*! \fn void SkyProj::set_size(int width, int height)
*
* Set the sky projection size
*/
void SkyProj::set_size(int width, int height)
{
m_canvas_height = height;
m_canvas_width = width;
std::cout << " height " << m_canvas_height << " width " << m_canvas_width << std::endl;
calc_fov_bounds();
}
/*! \fn void SkyProj::calc_fov_bounds()
*
* Calculate the boundaries, magnitude level and field of view for the
* virtual sky projection.
*/
void SkyProj::calc_fov_bounds()
{
m_canvas_ratio = (double)m_canvas_width / (double)m_canvas_height;
m_is_ra_over = false;
m_is_ra_under = false;
m_ra_offset = 0;
m_dec_offset = 0;
if (m_spherical)
m_clip_ra_min = m_centre_ra - (m_fov / 2.0) * m_canvas_ratio;
else
m_clip_ra_min = m_centre_ra - (m_fov / 2.0);
if (m_clip_ra_min < MIN_RA) {
m_is_ra_under = true;
m_ra_offset = m_centre_ra - (m_fov / 2.0);
m_clip_ra_min = MIN_RA;
}
if (m_spherical)
m_clip_ra_max = m_centre_ra + (m_fov / 2.0) * m_canvas_ratio;
else
m_clip_ra_max = m_centre_ra + (m_fov / 2.0);
if (m_clip_ra_max > MAX_RA) {
m_is_ra_over = true;
m_ra_offset = m_centre_ra + (m_fov / 2.0);
m_clip_ra_max = MAX_RA;
}
if (m_spherical)
m_clip_dec_min = m_centre_dec - (m_fov / 2.0);
else
m_clip_dec_min = m_centre_dec - (m_fov / 2.0) / m_canvas_ratio;
if (m_clip_dec_min <= MIN_DEC) {
m_dec_offset = m_clip_dec_min - MIN_DEC;
m_clip_dec_min = MIN_DEC;
}
if (m_spherical)
m_clip_dec_max = m_centre_dec + (m_fov / 2.0);
else
m_clip_dec_max = m_centre_dec + (m_fov / 2.0) / m_canvas_ratio;
if (m_clip_dec_max > MAX_DEC) {
m_clip_dec_max = MAX_DEC;
}
// are we over/under lapping
if (m_is_ra_over || m_is_ra_under)
calc_ra_overlap();
m_ra_ppd = m_canvas_width / m_fov;
m_dec_ppd = m_canvas_height / (m_fov / m_canvas_ratio);
// a look up table - there must be a better way......
double mag_const = MAG_CONST;
if (m_fov < 145.0 && m_fov >= 60.0)
mag_const *= 1.65;
else if (m_fov < 60.0 && m_fov >= 35.0)
mag_const *= 2.0;
else if (m_fov < 35.0 && m_fov >= 10.0)
mag_const *= 2.5;
else if (m_fov < 10.0 && m_fov >= 5.0)
mag_const *= 3.0;
else if (m_fov < 5.0 && m_fov >= 2.0)
mag_const *= 4.0;
else if (m_fov < 2.0)
mag_const *= 5.0;
m_clip_mag_max = MAG_BASE + (MAX_FOV - m_fov) * mag_const;
std::cout << " mag max " << m_clip_mag_max << " fov " << m_fov << std::endl;
std::cout << " min ra " << m_clip_ra_min <<" max " << m_clip_ra_max << std::endl;
std::cout << " min dec " << m_clip_dec_min << " max " << m_clip_dec_max << std::endl;
}
/*! \fn void SkyProj::move_ra (double pixels)
* \param pixels Number of pixels to move the sky projection in RA.
*
* Move the virtual sky east or west in RA.
*/
void SkyProj::move_ra (double pixels)
{
m_centre_ra += pixels / m_ra_ppd;
// do we need to reset RA if there is a large overlap
if (m_centre_ra > MAX_RA) {
m_centre_ra = MIN_RA;
} else if (m_centre_ra < MIN_RA) {
m_centre_ra = MAX_RA;
}
}
/*! \fn void SkyProj::move_dec (double pixels)
* \param pixels Number of pixels to move the sky projection in DEC.
*
* Move the virtual sky north or south in DEC.
*/
void SkyProj::move_dec (double pixels)
{
// are we at the limits
if ((m_centre_dec == MAX_DEC && pixels > 0) ||
(m_centre_dec == MIN_DEC && pixels < 0))
return;
m_centre_dec += pixels / m_dec_ppd;
// do we need to reset DEC
if (m_centre_dec > MAX_DEC) {
m_centre_dec = MAX_DEC;
} else if (m_centre_dec < MIN_DEC) {
m_centre_dec = MIN_DEC;
}
}
/*! \fn bool SkyProj::zoom (double zoom)
* \param zoom Zoom in/out factor
* \return false if the sky cannot be zoomed.
*
* Zoom the sky projection in or out.
*/
bool SkyProj::zoom (double zoom)
{
// are we at the limits
if (m_fov * zoom >= MAX_FOV) {
m_fov = MAX_FOV;
return false;
}
if (m_fov * zoom <= MIN_FOV) {
m_fov = MIN_FOV;
return false;
}
m_fov *= zoom;
return true;
}
/*! \fn double SkyProj::calc_size (Castor::AstroObject* object)
* \param object Astro object
* \return Virtual sky canvas size in pixels.
*
* Calculate the sky projection canvas size of an object based
* on it's visual magnitude.
*/
double SkyProj::calc_size (Castor::AstroObject* object)
{
double mag = object->get_mag();
return (m_clip_mag_max + 1) - mag;
}
/*! \fn void SkyProj::render_bg()
*
* Render the sky projection black background
*/
void SkyProj::render_background()
{
m_bg_group = Gtk::manage (new Gnome::Canvas::Group (*m_root, 0, 0));
m_bg_rect = Gtk::manage (new Gnome::Canvas::Rect(*m_bg_group, 0, 0, m_canvas_width, m_canvas_height));
*m_bg_rect << Gnome::Canvas::Properties::fill_color("black");
m_bg_rect->set_data (Glib::Quark ("background"), (gpointer)0);
}
/*! \fn calc_ra_overlap()
*
* Calculate the projection RA over/under lap size and clipping area.
*/
void SkyProj::calc_ra_overlap()
{
if (m_is_ra_under) {
// we are < MIN_RA, so extra is rhs (under) OK
m_clip_ra_min_overlap = MAX_RA + m_ra_offset;
m_clip_ra_max_overlap = MAX_RA;
m_clip_dec_min_overlap = m_clip_dec_min;
m_clip_dec_max_overlap = m_clip_dec_max;
} else {
// we are > MIN_RA, so extra is lhs (over) OK
m_clip_ra_min_overlap = MIN_RA;
m_clip_ra_max_overlap = m_ra_offset - MAX_RA;
m_clip_dec_min_overlap = m_clip_dec_min;
m_clip_dec_max_overlap = m_clip_dec_max;
}
}
/*! \fn void SkyProj::render_sky(Render type)
*
* Update the Sky projection canvas.
* The update can either be for bright objects (fast) or for
* faint objects and other artifacts (slower).
* The fast update is used for moving and zooming around the sky.
*/
void SkyProj::render_sky(Render type)
{
Glib::TimeVal t1, t2;
t1.assign_current_time();
std::cout << "Update started " << std::endl;
calc_fov_bounds();
// delete existing objects if we are starting a new update
if (type != FAINT) {
if (m_object_group) {
delete m_object_group;
m_object_group = 0;
}
if (m_const_group) {
delete m_const_group;
m_const_group = 0;
}
if (m_grid_group) {
delete m_grid_group;
m_grid_group = 0;
}
}
if (type == BRIGHT || type == FULL) {
if (m_show_grid) {
m_grid_group = Gtk::manage (new Gnome::Canvas::Group (*m_root, 0, 0));
render_grid();
}
// render all bright objects
m_object_group = Gtk::manage (new Gnome::Canvas::Group (*m_root, 0, 0));
render_planets();
render_bright_objects(type);
}
if (type == FAINT || type == FULL) {
// do we need to render constellations boundaries/names
if (m_show_const_bounds || m_show_const_names || m_show_const_lines) {
m_const_group = Gtk::manage (new Gnome::Canvas::Group (*m_root, 0, 0));
m_const_group->lower_to_bottom();
m_const_group->raise(1);
if (m_show_const_lines)
render_const_lines();
if (m_show_const_bounds)
render_const_bounds();
if (m_show_const_names)
render_const_names();
}
// render faint objects
render_remaining_objects();
}
t2.assign_current_time();
t2 = t2 - t1;
std::cout << "Update Complete " << t2.as_double() << std::endl;
}
/*! \fn void SkyFlat::render_bright_objects(Render type)
*
* Render the bright objects on the
* entire sky projection.
*/
void SkyProj::render_bright_objects(Render type)
{
render_basic();
render_main_sector(type);
if (m_is_ra_over || m_is_ra_under)
render_overlap_sector(type);
update_now();
}
/*! \fn void SkyFlat::render_bright_objects()
*
* Render the faint and other objects on the
* entire sky projection.
*/
void SkyProj::render_remaining_objects()
{
render_main_sector(FAINT);
if (m_is_ra_over || m_is_ra_under)
render_overlap_sector(FAINT);
}
/*! \fn void SkyFlat::render_main_sector()
*
* Render <type> objects on the sky projection
* main sector.
*/
void SkyProj::render_main_sector(Render type)
{
std::vector<Castor::AstroObject*>::iterator i;
std::vector<Castor::AstroObject*> object_band[OBJECT_GROUPS];
std::vector<Castor::AstroObject*> objects;
double x, y, size, ra_offset;
double mag_min, mag_max;
int index;
bool bright;
// are we only rendering bright stars
if (type == BRIGHT) {
mag_max = m_clip_mag_max - BRIGHT_DIFF;
mag_min = m_clip_mag_min;
bright = true;
} else {
if (type == FULL) {
mag_max = m_clip_mag_max - BRIGHT_DIFF;
mag_min = m_clip_mag_min;
bright = false;
} else {
mag_max = m_clip_mag_max;
mag_min = m_clip_mag_max - BRIGHT_DIFF;
bright = false;
}
}
// clip the catalog
m_bright_cat->clip(m_clip_ra_min, m_clip_dec_min,
m_clip_ra_max , m_clip_dec_max,
mag_min, mag_max);
// get visible objects
std::cout << " objects " << m_bright_cat->get_objects(objects) << std::endl;
// sort into magnitude bands
for (i = objects.begin(); i != objects.end(); i++) {
index = (int)((*i)->get_mag());
object_band[index + 2].push_back(*i);
}
// calc offset
if (m_is_ra_over)
ra_offset = MIN_RA;
else
ra_offset = m_ra_offset;
// render objects, brightest first
for (int j=0; j<OBJECT_GROUPS; j++) {
for (i = object_band[j].begin(); i != object_band[j].end(); i++) {
(*i)->get_equ_posn(0, x, y);
transform(x, y, ra_offset);
if (is_visible(x,y))
(*i)->render(x, y, m_clip_mag_max, *m_object_group, bright);
}
}
}
/*! \fn void SkyFlat::render_main_sector()
*
* Render <type> objects on the sky projection
* overlap sector.
*/
void SkyProj::render_overlap_sector(Render type)
{
std::vector<Castor::AstroObject*>::iterator i;
std::vector<Castor::AstroObject*> object_band[OBJECT_GROUPS];
std::vector<Castor::AstroObject*> objects;
double x, y, size, ra_offset;
double mag_min, mag_max;
int index;
bool bright;
// are we only rendering bright stars
if (type == BRIGHT) {
mag_max = m_clip_mag_max - BRIGHT_DIFF;
mag_min = m_clip_mag_min;
bright = true;
} else {
mag_max = m_clip_mag_max;
mag_min = m_clip_mag_max - BRIGHT_DIFF;
bright = false;
}
// clip the catalog
m_bright_cat->clip(m_clip_ra_min_overlap, m_clip_dec_min_overlap,
m_clip_ra_max_overlap , m_clip_dec_max_overlap,
mag_min, mag_max);
// get visible objects
std::cout << " overlap objects " << m_bright_cat->get_objects(objects) << std::endl;
// sort into magnitude band
for (i = objects.begin(); i != objects.end(); i++) {
index = (int)((*i)->get_mag());
object_band[index + 2].push_back(*i);
}
// get ra offset
if (m_is_ra_under)
ra_offset = m_ra_offset + MAX_RA; //rhs
else
ra_offset = -MAX_RA; //lhs
// render objects, brightest first
for (int j=0; j<OBJECT_GROUPS; j++) {
for (i = object_band[j].begin(); i != object_band[j].end(); i++) {
(*i)->get_equ_posn(0, x, y);
transform(x, y, ra_offset);
if (is_visible(x,y))
(*i)->render(x, y, m_clip_mag_max, *m_object_group, bright);
}
}
}
/*! \fn double SkyProj::get_ra ()
* \return RA (degrees)
*
* Get the current sky projection centre RA.
*/
double SkyProj::get_ra ()
{
return m_centre_ra;
}
/*! \fn double SkyProj::get_dec ()
* \return DEC (degrees)
*
* Get the current sky projection centre DEC.
*/
double SkyProj::get_dec ()
{
return m_centre_dec;
}
/*! \fn double SkyProj::get_fov ();
* \return FOV (degrees)
*
* Get the sky projection field of view in degrees
*/
double SkyProj::get_fov ()
{
return m_fov;
}
/*! \fn void SkyProj::set_ra (double ra)
*
* Set the sky projection centre RA.
*/
void SkyProj::set_ra (double ra)
{
m_centre_ra = ra;
}
/*! \fn void SkyProj::set_dec (double dec)
*
* Set the sky projection centre DEC.
*/
void SkyProj::set_dec (double dec)
{
m_centre_dec = dec;
}
/*! \fn void SkyProj::set_fov (double fov)
*
* Set the sky projection field of view in degrees.
*/
void SkyProj::set_fov (double fov)
{
m_fov = fov;
}
}
syntax highlighted by Code2HTML, v. 0.9.1