Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

startextdump.cpp

Go to the documentation of this file.
00001 // startextdump.cpp
00002 //
00003 // Copyright (C) 2004, Chris Laurel <claurel@shatters.net>
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // Dump the contents of a Celestia star database file in a text
00011 // format that's easy read and edit.
00012 
00013 #include <iostream>
00014 #include <fstream>
00015 #include <iomanip>
00016 #include <celutil/basictypes.h>
00017 #include <celutil/bytes.h>
00018 #include <celengine/astro.h>
00019 #include <celengine/stellarclass.h>
00020 
00021 using namespace std;
00022 
00023 
00024 static string inputFilename;
00025 static string outputFilename;
00026 static string hdFilename;
00027 static bool useOldFormat = false;
00028 static bool useSphericalCoords = false;
00029 
00030 
00031 void Usage()
00032 {
00033     cerr << "Usage: startextdump [options] <star database file> [output file]\n";
00034     cerr << "  Options:\n";
00035     cerr << "    --old (or -o)       : input star database is pre-2.0 format\n";
00036     cerr << "    --hd                : dump HD catalog cross reference\n";
00037     cerr << "    --spherical (or -s) : output spherical coordinates (RA/dec/distance\n";
00038 }
00039 
00040 
00041 static uint32 readUint(istream& in)
00042 {
00043     uint32 n;
00044     in.read(reinterpret_cast<char*>(&n), sizeof n);
00045     LE_TO_CPU_INT32(n, n);
00046     return n;
00047 }
00048 
00049 static float readFloat(istream& in)
00050 {
00051     float f;
00052     in.read(reinterpret_cast<char*>(&f), sizeof f);
00053     LE_TO_CPU_FLOAT(f, f);
00054     return f;
00055 }
00056 
00057 static int16 readShort(istream& in)
00058 {
00059     int16 n;
00060     in.read(reinterpret_cast<char*>(&n), sizeof n);
00061     LE_TO_CPU_INT16(n, n);
00062     return n;
00063 }
00064 
00065 static uint16 readUshort(istream& in)
00066 {
00067     uint16 n;
00068     in.read(reinterpret_cast<char*>(&n), sizeof n);
00069     LE_TO_CPU_INT16(n, n);
00070     return n;
00071 }
00072 
00073 static uint8 readUbyte(istream& in)
00074 {
00075     uint8 n;
00076     in.read((char*) &n, 1);
00077     return n;
00078 }
00079 
00080 
00081 void printStellarClass(uint16 sc, ostream& out)
00082 {
00083     StellarClass::StarType st = (StellarClass::StarType) (sc >> 12);
00084 
00085     if (st == StellarClass::WhiteDwarf)
00086     {
00087         out << "WD";
00088     }
00089     else if (st == StellarClass::NeutronStar)
00090     {
00091         out << "Q";
00092     }
00093     else if (st == StellarClass::BlackHole)
00094     {
00095         out << "X";
00096     }
00097     else if (st == StellarClass::NormalStar)
00098     {
00099         unsigned int spectralClass = (sc >> 8 & 0xf);
00100         unsigned int spectralSubclass = (sc >> 4 & 0xf);
00101         unsigned int luminosityClass = (sc & 0xf);
00102 
00103         if (spectralClass == 12)
00104         {
00105             out << '?';
00106         }
00107         else
00108         {
00109             out << "OBAFGKMRSNWW?LTC"[spectralClass];
00110             out << "0123456789"[spectralSubclass];
00111             switch (luminosityClass)
00112             {
00113             case StellarClass::Lum_Ia0:
00114                 out << "I-a0";
00115                 break;
00116             case StellarClass::Lum_Ia:
00117                 out << "I-a";
00118                 break;
00119             case StellarClass::Lum_Ib:
00120                 out << "I-b";
00121                 break;
00122             case StellarClass::Lum_II:
00123                 out << "II";
00124                 break;
00125             case StellarClass::Lum_III:
00126                 out << "III";
00127                 break;
00128             case StellarClass::Lum_IV:
00129                 out << "IV";
00130                 break;
00131             case StellarClass::Lum_V:
00132                 out << "V";
00133                 break;
00134             case StellarClass::Lum_VI:
00135                 out << "VI";
00136                 break;
00137             }
00138         }
00139     }
00140     else
00141     {
00142         out << '?';
00143     }
00144 }
00145 
00146 
00147 bool DumpOldStarDatabase(istream& in, ostream& out, ostream* hdOut,
00148                          bool spherical)
00149 {
00150     uint32 nStarsInFile = readUint(in);
00151     if (!in.good())
00152     {
00153         cerr << "Error reading count of stars from database.\n";
00154         return false;
00155     }
00156 
00157     out << nStarsInFile << '\n';
00158 
00159     for (uint32 i = 0; i < nStarsInFile; i++)
00160     {
00161         if (!in.good())
00162         {
00163             cerr << "Error reading from star database at record " << i << endl;
00164             return false;
00165         }
00166 
00167         uint32 catalogNum    = readUint(in);
00168         uint32 HDCatalogNum  = readUint(in);
00169         float  RA            = readFloat(in);
00170         float  dec           = readFloat(in);
00171         float  parallax      = readFloat(in);
00172         int16  appMag        = readShort(in);
00173         uint16 stellarClass  = readUshort(in);
00174         uint8  parallaxError = readUbyte(in);
00175 
00176         // Compute distance based on parallax
00177         double distance = LY_PER_PARSEC / (parallax > 0.0 ? parallax / 1000.0 : 1e-6);
00178         out << catalogNum << ' ';
00179         out << setprecision(8);
00180 
00181         if (spherical)
00182         {
00183             out << RA * 360.0 / 24.0 << ' ' << dec << ' ' << distance << ' ';
00184             out << setprecision(6);
00185             out << (float) appMag / 256.0f << ' ';
00186         }
00187         else
00188         {
00189             Point3d pos = astro::equatorialToCelestialCart((double) RA, (double) dec, distance);
00190             float absMag = (float) (appMag / 256.0 + 5 -
00191                                     5 * log10(distance / 3.26));
00192             out << (float) pos.x << ' ' <<
00193                    (float) pos.y << ' ' <<
00194                    (float) pos.z << ' ';
00195             out << setprecision(5);
00196             out << absMag << ' ';
00197         }
00198         printStellarClass(stellarClass, out);
00199         out << '\n';
00200 
00201         // Dump HD catalog cross reference
00202         if (hdOut != NULL && HDCatalogNum != ~0)
00203             *hdOut << HDCatalogNum << ' ' << catalogNum << '\n';
00204     }
00205 
00206     return true;
00207 }
00208 
00209 
00210 bool DumpStarDatabase(istream& in, ostream& out, ostream* hdOut)
00211 {
00212     char header[8];
00213     in.read(header, sizeof header);
00214     if (strncmp(header, "CELSTARS", sizeof header))
00215     {
00216         cerr << "Missing header in star database.\n";
00217         return false;
00218     }
00219 
00220     uint16 version = readUshort(in);
00221     if (version != 0x0100)
00222     {
00223         cerr << "Unsupported file version " << (version >> 8) << '.' <<
00224             (version & 0xff) << '\n';
00225         return false;
00226     }
00227 
00228     uint32 nStarsInFile = readUint(in);
00229     if (!in.good())
00230     {
00231         cerr << "Error reading count of stars from database.\n";
00232         return false;
00233     }
00234 
00235     out << nStarsInFile << '\n';
00236 
00237     for (uint32 i = 0; i < nStarsInFile; i++)
00238     {
00239         if (!in.good())
00240         {
00241             cerr << "Error reading from star database at record " << i << endl;
00242             return false;
00243         }
00244 
00245         uint32 catalogNum    = readUint(in);
00246         float  x             = readFloat(in);
00247         float  y             = readFloat(in);
00248         float  z             = readFloat(in);
00249         int16  absMag        = readShort(in);
00250         uint16 stellarClass  = readUshort(in);
00251 
00252         out << catalogNum << ' ';
00253         out << setprecision(7);
00254         out << x << ' ' << y << ' ' << z << ' ';
00255         out << setprecision(4);
00256         out << ((float) absMag / 256.0f) << ' ';
00257         printStellarClass(stellarClass, out);
00258         out << '\n';
00259     }
00260 
00261     return true;
00262 }
00263 
00264 
00265 bool parseCommandLine(int argc, char* argv[])
00266 {
00267     int i = 1;
00268     int fileCount = 0;
00269 
00270     while (i < argc)
00271     {
00272         if (argv[i][0] == '-')
00273         {
00274             if (!strcmp(argv[i], "--hd"))
00275             {
00276                 if (i == argc - 1)
00277                 {
00278                     return false;
00279                 }
00280                 else
00281                 {
00282                     i++;
00283                     hdFilename = string(argv[i]);
00284                 }
00285             }
00286             else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--old"))
00287             {
00288                 useOldFormat = true;
00289             }
00290             else if (!strcmp(argv[i], "-s") || !strcmp(argv[i], "--spherical"))
00291             {
00292                 useSphericalCoords = true;
00293             }
00294             else
00295             {
00296                 cerr << "Unknown command line switch: " << argv[i] << '\n';
00297                 return false;
00298             }
00299             i++;
00300         }
00301         else
00302         {
00303             if (fileCount == 0)
00304             {
00305                 // input filename first
00306                 inputFilename = string(argv[i]);
00307                 fileCount++;
00308             }
00309             else if (fileCount == 1)
00310             {
00311                 // output filename second
00312                 outputFilename = string(argv[i]);
00313                 fileCount++;
00314             }
00315             else
00316             {
00317                 // more than two filenames on the command line is an error
00318                 return false;
00319             }
00320             i++;
00321         }
00322     }
00323 
00324     return true;
00325 }
00326 
00327 
00328 int main(int argc, char* argv[])
00329 {
00330     if (!parseCommandLine(argc, argv) || inputFilename.empty())
00331     {
00332         Usage();
00333         return 1;
00334     }
00335 
00336     ifstream stardbFile(inputFilename.c_str(), ios::in | ios::binary);
00337     if (!stardbFile.good())
00338     {
00339         cerr << "Error opening star database file " << inputFilename << '\n';
00340         return 1;
00341     }
00342 
00343     ofstream* hdOut = NULL;
00344     if (!hdFilename.empty())
00345     {
00346         hdOut = new ofstream(hdFilename.c_str(), ios::out);
00347         if (!hdOut->good())
00348         {
00349             cerr << "Error opening HD catalog output file " << hdFilename << '\n';
00350             return 1;
00351         }
00352     }
00353 
00354     bool success;
00355     ostream* out = &cout;
00356     if (!outputFilename.empty())
00357     {
00358         out = new ofstream(outputFilename.c_str(), ios::out);
00359         if (!out->good())
00360         {
00361             cerr << "Error opening output file " << outputFilename << '\n';
00362             return 1;
00363         }
00364     }
00365 
00366     if (useOldFormat)
00367     {
00368         success = DumpOldStarDatabase(stardbFile, *out, hdOut,
00369                                       useSphericalCoords);
00370     }
00371     else
00372     {
00373         success = DumpStarDatabase(stardbFile, *out, hdOut);
00374     }
00375 
00376     return success ? 0 : 1;
00377 }

Generated on Sat Jan 14 22:30:33 2006 for Celestia by  doxygen 1.4.1