// 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 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& result); * \param result Catalog objects * \return Number of objects found. * * Get all catalog objects within clipping area. */ int Catalog::get_objects(std::vector& result) { int count = 0; std::vector::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::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::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 list; std::vector::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; } }