// 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 2003 Liam Girdwood
#include "catalog.hh"
#include "deep_object.hh"
#include "star_object.hh"
#include "skymap_object.hh"
#include "galaxy.hh"
#include "nebula.hh"
#include "asteroid.hh"
#include "comet.hh"
#include <iostream>
namespace Pollux
{
/*! \fn Catalog::Catalog ()
*
* Constructor
*/
Catalog::Catalog ()
{
m_size = 0;
m_progress = 0;
m_ra_div_size = 360 / RA_DIV;
m_dec_div_size = 180 / DEC_DIV;
unclip();
}
/*! \fn Catalog::Catalog(std::string& name, std::string& description,
std::string& maintainer, std::string& type,
std::string& created, std::string& cat_version,
std::string& cat_history, std::string& cat_ack)
* \param name Catalog name
* \param description Catalog description
* \param maintainer Catalog maintainer
* \param type Catalog type
* \param created Catalog creation date
* \param version catalog version
* \param history catalog history
* \param ack catalog acknowledgements
*
* Constructor
*/
Catalog::Catalog(std::string& name, std::string& description,
std::string& maintainer, std::string& type,
std::string& created, std::string& version,
std::string& history, std::string& ack)
{
// init catalog details
m_name = name;
m_description = description;
m_maintainer = maintainer;
m_type = type;
m_version = version;
m_history = history;
m_acknowledge = ack;
m_size = 0;
m_add_size = 0;
m_date = created;
m_ra_div_size = 360 / RA_DIV;
m_dec_div_size = 180 / DEC_DIV;
// init catalog config
unclip();
}
/*! \fn Catalog::~Catalog()
*
* Free all memory
*/
Catalog::~Catalog()
{
for (int ra = 0; ra < RA_DIV; ra++) {
for (int dec = 0; dec < DEC_DIV; dec++) {
for (int mag = 0; mag < MAG_MAX - MAG_MIN; mag++) {
m_objects[ra][dec][mag].clear();
}
}
}
}
/*! \fn double Catalog::get_progress()
* \return Catalog loading progresss 0..1
*
* get the catalog load progress
*/
double Catalog::get_progress()
{
return m_progress;
}
/*! \fn bool Catalog::add (Castor::AstroObject* object)
* \param object Pointer to object to be added
* \return true if successfully added.
*
* Add an object to the catalog. This will fail if any object
* properties are out of bounds. i.e. RA > 360
*/
bool Catalog::add (Castor::AstroObject* object)
{
// init any object properties
object->init();
// calculate offset into catalog
double ra, dec;
std::string id;
object->get_equ_posn(0, ra, dec);
object->get_id(id);
int ra_offset = (int)(ra / m_ra_div_size);
int dec_offset = ((int)dec + 90) / m_dec_div_size;
int mag_offset = (int)object->get_mag();
// throw out bad values
// i.e. no ID, mag, ra or dec out of range
if ((mag_offset < MAG_MIN || mag_offset > MAG_MAX) ||
(ra_offset > RA_DIV || ra_offset < 0) ||
(dec_offset > DEC_DIV || dec_offset < 0) || id == "") {
std::cerr << "Catalog:: value out of range " << ra_offset <<" " << dec_offset <<
" " << mag_offset << " id " << id << std::endl;
return false;
}
m_objects[ra_offset][dec_offset][mag_offset - MAG_MIN].push_back(object);
m_add_size++;
return true;
}
/*! \fn void Catalog::clip (double min_ra, double min_dec, double max_ra, double max_dec)
* \param min_ra Minimum RA
* \param min_dec Minimum DEC
* \param max_ra Maximum RA
* \param max_dec Maximum DEC
* \param min_mag Minimum magnitude
* \param max_mag Maximum magnitude
*
* Set the catalog clipping area
*/
void Catalog::clip (double min_ra, double min_dec, double max_ra, double max_dec, double min_mag, double max_mag)
{
m_clip_min_ra = (int)min_ra / m_ra_div_size;
m_clip_min_dec = ((int)min_dec + 90) / m_dec_div_size;
m_clip_max_ra = ((int)max_ra / m_ra_div_size) + 1;
if (m_clip_max_ra > RA_DIV)
m_clip_max_ra = RA_DIV;
m_clip_max_dec = (((int)max_dec + 90) / m_dec_div_size) + 1;
if (m_clip_max_dec > DEC_DIV)
m_clip_max_dec = DEC_DIV;
m_clip_min_mag = (int)min_mag;
if (m_clip_min_mag < MAG_MIN)
m_clip_min_mag = MAG_MIN;
m_clip_max_mag = (int)max_mag;
if (m_clip_max_mag > MAG_MAX)
m_clip_max_mag = MAG_MAX;
}
/*! \fn void Catalog::unclip ()
*
* Reset the catalog clipping area, i.e. ra = 0..360, dec = -90..90
*/
void Catalog::unclip ()
{
m_clip_min_ra = 0;
m_clip_min_dec = 0;
m_clip_max_ra = RA_DIV;
m_clip_max_dec = DEC_DIV;
m_clip_min_mag = MAG_MIN;
m_clip_max_mag = MAG_MAX;
}
/*! \fn int Catalog::get_objects (std::vector<Castor::AstroObject*>& result);
* \param result Catalog objects
* \return Number of objects found.
*
* Get all catalog objects within clipping area.
*/
int Catalog::get_objects(std::vector<Castor::AstroObject*>& result)
{
int count = 0;
std::vector<Castor::AstroObject*>::iterator i;
for (int ra = m_clip_min_ra; ra < m_clip_max_ra; ra++) {
for (int dec = m_clip_min_dec; dec < m_clip_max_dec; dec++) {
for (int mag = m_clip_min_mag; mag < m_clip_max_mag; mag++) {
for (i = m_objects[ra][dec][mag - MAG_MIN].begin(); i != m_objects[ra][dec][mag - MAG_MIN].end(); i++) {
result.push_back(*i);
count ++;
}
}
}
}
return count;
}
/*! \fn int Catalog::load (std::string& name, std::string& path, Glib::Dispatcher* signal)
* \param name Catalog name
* \param path Catalog path
* \param signal Pointer to update thread signal
* \return Number of catalog objects loaded.
*
* Load an astro catalog from disk into memory.
*/
int Catalog::load (std::string& name, std::string& path, Glib::Dispatcher* signal)
{
std::ifstream* file;
int count = 0;
// load the catalog descriptor file
std::string file_name = path + name + ".ncd";
file = new std::ifstream(file_name.c_str());
if (file->is_open()) {
// get the file header
file_header* header = new file_header();
file->read((char*)header, sizeof(file_header));
m_name = header->cat_name;
m_description = header->cat_description;
m_type = header->cat_type;
m_date = header->cat_date;
m_size = header->cat_size;
std::cout << "cat size " << m_size << std::endl;
unclip();
// get any unknown element descriptors
extra_element e;
for (int i = 0; i < header->unknown_elements; i++) {
file_extra_element element;
file->read ((char*)&element, sizeof(file_extra_element));
e.name = element.name;
e.units = element.units;
e.description = element.description;
m_extra_info.push_back(e);
}
file->close();
} else {
std::cerr << __FILE__ << " " << __LINE__ << " could not load " << file_name << std::endl;
delete file;
return 0;
}
delete file;
// load the objects
std::string lfile = path + name;
count = load_sectors (lfile, signal);
// update the catalog with the unknown element names
if (count) {
std::vector<extra_element>::iterator i;
// object unknown name is static, so pos does not matter
for (i=m_extra_info.begin(); i != m_extra_info.end(); ++i) {
m_unknown_names.push_back((*i).name);
}
}
// did we load the correct amount of objects
if (m_add_size != m_size) {
std::cerr << __FILE__ << " " << __LINE__ << " error catalog size mismatch." <<
" Loaded " << m_add_size << " expected " << m_size << std::endl;
}
return count;
}
/*! \fn int Catalog::save (std::string& name, std::string& path, Glib::Dispatcher* signal)
* \param name Catalog file name
* \param path Catalog path
* \return number of objects saved to file
*
* Save catalog from memory to file.
*/
int Catalog::save (std::string& name, std::string& path, Glib::Dispatcher* signal)
{
std::ofstream* file;
int count = 0;
std::cout << path << " " << m_name << " " << std::endl;
std::string file_name = path + m_name + ".ncd";
file = new std::ofstream(file_name.c_str());
if (file->is_open()) {
// write the file header
file_header* header = new file_header();
strncpy (header->cat_name, m_name.c_str(), CAT_NAME_SIZE);
strncpy (header->cat_description, m_description.c_str(), CAT_DESCRIPTION_SIZE);
strncpy (header->cat_type, m_type.c_str(), CAT_TYPE_SIZE);
strncpy (header->cat_date, m_date.c_str(), CAT_DATE_SIZE);
strncpy (header->cat_maintainer, m_maintainer.c_str(), CAT_MAINTAINER_SIZE);
header->cat_size = m_size;
header->unknown_elements = m_extra_info.size();
file->write ((char*)header, sizeof(file_header));
//write the extra elements
std::vector<extra_element>::iterator i;
for (i = m_extra_info.begin(); i != m_extra_info.end(); i++) {
file_extra_element e;
strncpy (e.name, (*i).name.c_str(), ELEMENT_NAME_SIZE);
strncpy (e.units, (*i).units.c_str(), ELEMENT_UNIT_SIZE);
strncpy (e.description, (*i).description.c_str(), ELEMENT_DESCRIPTION_SIZE);
file->write ((char*)&e, sizeof (file_extra_element));
}
file->close();
} else {
std::cerr << __FILE__ << "could not save " << file_name << std::endl;
}
delete file;
// save the objects
std::string sfile = path + m_name;
return save_sectors (sfile, signal);
}
/*! \fn bool Catalog::add_description (std::string& name, std::string& units,
std::string& description)
* \param name Parameter name
* \param units Parameter units
* \param description Parameter description
*
* Add a new object parameter description to the catalog
*/
void Catalog::add_description (std::string& name, std::string& units,
std::string& description)
{
extra_element element;
element.name = name;
element.units = units;
element.description = description;
m_extra_info.push_back(element);
}
/*! \fn int Catalog::save_sectors (std::string& file, Glib::Dispatcher* signal)
* \param file filename
* \return number of objects saved
*
* Save catalog sectors to file. Sectors are based on
* magnitude bands for deep objects and semi-major axis
* for near sky objects.
*
*/
int Catalog::save_sectors (std::string& file, Glib::Dispatcher* signal)
{
int count = 0, num_objects;
char buffer[256];
std::vector<Castor::AstroObject*> list;
std::vector<Castor::AstroObject*>::iterator i;
// save naked eye objects < mag 6
sprintf(buffer, "%s-m6.noc",file.c_str());
std::ofstream* ofile = new std::ofstream (buffer);
if (ofile->is_open()) {
clip (0, -90, 360, 90, MAG_MIN, MAG_EYE);
count += get_objects (list);
for (i = list.begin(); i != list.end(); i++)
(*i)->save(ofile);
}
list.clear();
ofile->close();
delete ofile;
// save faint magnitude divisions > mag 6
for (int mag_idx = MAG_EYE; mag_idx < MAG_MAX; mag_idx++) {
sprintf(buffer, "%s-m%d.noc", file.c_str(), mag_idx + 1);
ofile = new std::ofstream (buffer);
if (ofile->is_open()) {
clip (0, -90, 360, 90, mag_idx, mag_idx + 1);
num_objects = get_objects (list);
std::cout << __FILE__ << " saving " << mag_idx << " " << num_objects << std::endl;
if (num_objects > 0 ) {
count += num_objects;
for (i = list.begin(); i != list.end(); i++)
(*i)->save(ofile);
}
ofile->close();
list.clear();
}
delete ofile;
}
unclip();
return count;
}
/*! \fn int Catalog::load_file (char* file)
* \return number of objects loaded.
*
* Load catalog file.
*/
int Catalog::load_file (char* file)
{
int count = 0;
std::ifstream* ifile = new std::ifstream (file);
if (ifile->is_open()) {
std::cout << "opening " << file << std::endl;
while (!(ifile->eof())) {
// create new object
Castor::AstroObject* object = 0;
if (m_type == "skymap")
object = new Castor::SkymapObject();
else if (m_type == "star")
object = new Castor::StarObject();
else if (m_type == "galaxy")
object = new Castor::Galaxy();
else if (m_type == "asteroid")
object = new Castor::Asteroid();
else if (m_type == "comet")
object = new Castor::Comet();
else {
// error, unsupported type
std::cerr << __FILE__ << "unsupported type" << std::endl;
ifile->close();
delete ifile;
return 0;
}
// load in the object data
if (object) {
object->load(ifile);
if (!(ifile->eof())) {
add (object);
count++;
} else
delete object;
}
}
} else {
std::cerr << __FILE__ << " could not load " << file << std::endl;
}
ifile->close();
delete ifile;
return count;
}
/*! \fn int Catalog::load_sectors (std::string& file, Glib::Dispatcher* signal)
*
* Load catalog sector into memory
*/
int Catalog::load_sectors (std::string& file, Glib::Dispatcher* signal)
{
int count = 0;
char buffer[256];
// set progressbar
if (signal) {
m_progress = 0.0;
(*signal)();
}
// mag division < mag 6
sprintf(buffer, "%s/%s-m6.noc",file.c_str(), m_name.c_str());
count += load_file(buffer);
if (signal) {
m_progress = (double)count / m_size;
(*signal)();
}
// faint objects mag > 6
for (int i = MAG_EYE; i < MAG_MAX; i++) {
sprintf(buffer, "%s/%s-m%d.noc",file.c_str(), m_name.c_str(),i+1);
count += load_file(buffer);
if (!count)
break;
if (signal) {
m_progress = (double)count / m_size;
(*signal)();
}
}
m_progress = 0;
return count;
}
/*! \fn void Catalog::get_name (std::string& name);
*
* Get catalog name
*/
void Catalog::get_name (std::string& name)
{
name = m_name;
}
/*! \fn void Catalog::get_description (std::string& desc);
*
* Get catalog description
*/
void Catalog::get_description (std::string& desc)
{
desc = m_description;
}
/*! \fn void Catalog::get_type (std::string& type);
*
* Get catalog type
*/
void Catalog::get_type (std::string& type)
{
type = m_type;
}
/*! \fn void Catalog::get_maintainer (std::string& maintainer);
*
* Get catalog maintainer
*/
void Catalog::get_maintainer (std::string& maintainer)
{
maintainer = m_maintainer;
}
/*! \fn void Catalog::get_date (std::string& date);
*
* Get catalog creation date
*/
void Catalog::get_date (std::string& date)
{
date = m_date;
}
/*! \fn int Catalog::get_size ();
*
* Get catalog size
*/
int Catalog::get_size ()
{
return m_size;
}
/*! \fn void Catalog::get_ack (std::string& date);
*
* Get catalog creation date
*/
void Catalog::get_ack (std::string& ack)
{
ack = m_acknowledge;
}
/*! \fn void Catalog::get_history (std::string& history);
*
* Get catalog history
*/
void Catalog::get_history (std::string& history)
{
history = m_history;
}
/*! \fn void Catalog::get_version (std::string& version);
*
* Get catalog version
*/
void Catalog::get_version (std::string& version)
{
version = m_version;
}
}
syntax highlighted by Code2HTML, v. 0.9.1