buildstardb.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:38k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // buildstardb.cpp
  2. //
  3. // Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. #include <string>
  10. #include <vector>
  11. #include <map>
  12. #include <algorithm>
  13. #include <iostream>
  14. #include <fstream>
  15. #include <cstdio>
  16. #include <assert.h>
  17. #include <unistd.h>
  18. #include "celengine/stardb.h"
  19. using namespace std;
  20. #ifdef _WIN32
  21. static string MainDatabaseFile("hip_main.dat");
  22. static string TychoDatabaseFile("tyc_main.dat");
  23. static string ComponentDatabaseFile("h_dm_com.dat");
  24. static string OrbitalDatabase("hip_dm_o.dat");
  25. #else
  26. #ifndef MACOSX_PB
  27. #include <config.h>
  28. #endif /*MACOSX_PB*/
  29. static string MainDatabaseFile(HIP_DATA_DIR "/hip_main.dat");
  30. static string TychoDatabaseFile(HIP_DATA_DIR "/tyc_main.dat");
  31. static string ComponentDatabaseFile(HIP_DATA_DIR "/h_dm_com.dat");
  32. static string OrbitalDatabase(HIP_DATA_DIR "/hip_dm_o.dat");
  33. #endif
  34. static const int HipStarRecordLength = 451;
  35. static const int HipComponentRecordLength = 239;
  36. static const int TycStarRecordLength = 351;
  37. static uint32 NullCCDMIdentifier = 0xffffffff;
  38. static uint32 NullCatalogNumber = 0xffffffff;
  39. static int verbose, dropstars;
  40. class HipparcosStar
  41. {
  42. public:
  43.     HipparcosStar();
  44.     void write(ostream&);
  45.     void analyze();
  46.     uint32 HIPCatalogNumber;
  47.     uint32 HDCatalogNumber;
  48.     float ascension;
  49.     float declination;
  50.     float parallax;
  51.     float appMag;
  52.     StellarClass stellarClass;
  53.     uint32 CCDMIdentifier;
  54.     uint8 starsWithCCDM;
  55.     uint8 nComponents;
  56.     uint8 parallaxError;
  57.     uint tycline;
  58.     uint status;
  59.     float e_RA;  // Errors in Right Ascension,
  60.     float e_DE;  // Declination,
  61.     float e_Mag; // and Magnitude
  62. };
  63. HipparcosStar::HipparcosStar() :
  64.     HIPCatalogNumber(NullCatalogNumber),
  65.     HDCatalogNumber(NullCatalogNumber),
  66.     ascension(0.0f),
  67.     declination(0.0f),
  68.     parallax(0.0f),
  69.     appMag(0.0f),
  70.     CCDMIdentifier(NullCCDMIdentifier),
  71.     starsWithCCDM(0),
  72.     nComponents(1),
  73.     parallaxError(0),
  74.     tycline(0),
  75.     e_RA(0.0f),
  76.     e_DE(0.0f),
  77.     e_Mag(0.0f)
  78. {
  79. }
  80. template<class T> void binwrite(ostream& out, T x)
  81. {
  82.     out.write(reinterpret_cast<char*>(&x), sizeof(T));
  83. }
  84. void HipparcosStar::write(ostream& out)
  85. {
  86.     if (status>=2)
  87.         return;
  88. #if 0
  89.     if (HDCatalogNumber != NullCatalogNumber)
  90.         binwrite(out, HDCatalogNumber);
  91.     else
  92.         binwrite(out, HIPCatalogNumber | 0x10000000);
  93. #endif
  94.     binwrite(out, HIPCatalogNumber);
  95.     binwrite(out, HDCatalogNumber);
  96.     binwrite(out, ascension);
  97.     binwrite(out, declination);
  98.     binwrite(out, parallax);
  99.     binwrite(out, (short) (appMag * 256));
  100.     binwrite(out, stellarClass);
  101.     binwrite(out, parallaxError);
  102. }
  103.                     // Statistic Values:
  104. float s_er;         // Sum of Error in RA
  105. float s_erq;        // Sum of Squares of Errors in RA
  106. unsigned int n_er;  // Number of Error Values
  107. float s_ed, s_edq;  // Ditto for Declination
  108. unsigned int n_ed;
  109. unsigned int n_drop,n_dub; // number of stars to drop, number dubious
  110. void HipparcosStar::analyze()
  111. {
  112.     int dubious=0;
  113.     status=0;
  114.     if ((parallax) <= 0.4 && ((dropstars==0) || (dropstars==1 && appMag<6.0)))
  115.         parallax=0.4;  /* fix strange paralaxes so the stars aren't *way*
  116.                           out there. A parallax of 0.4 will put them at
  117.                           just a touch above 8154 LY away. */
  118.     if (parallax <= 0.0)
  119.         dubious+=400;
  120.     else if (parallax<0.2)
  121.         dubious+=4;
  122.     else if (parallax<0.4)
  123.         dubious+=2;
  124.     if (parallax<=parallaxError)
  125.         dubious+=2;
  126.     else if (parallax<=(2*parallaxError))
  127.         dubious++;
  128.     if (e_RA<1000.0)
  129.     {
  130.         s_er+=e_RA;
  131.         s_erq+=square(e_RA);
  132.         n_er++;
  133.         if (e_RA>20.0)
  134.             dubious+=100;
  135.         else if (e_RA>15.0)
  136.             dubious+=2;
  137.         else if (e_RA>10.0)
  138.             dubious++;
  139.     }
  140.     else
  141.         dubious+=4;  /* No error given, assume it's rather dubious */
  142.     if (e_DE<1000.0)
  143.     {
  144.         s_ed+=e_DE;
  145.         s_edq+=square(e_DE);
  146.         n_ed++;
  147.         if (e_DE>20.0)
  148.             dubious+=100;
  149.         else if (e_DE>15.0)
  150.             dubious+=2;
  151.         else if (e_DE>10.0)
  152.             dubious++;
  153.     }
  154.     else
  155.         dubious+=4;  /* No error given, assume it's rather dubious */
  156.     if (dubious>3)
  157.     {
  158.         status=1;
  159.         n_dub++;
  160.     }
  161.     if ((dubious>5) && (dropstars) && (!(dropstars==1 && appMag<6.0)))
  162.     {
  163.         status=2;
  164.         n_drop++;
  165.     }
  166. }
  167. bool operator<(const HipparcosStar& a, const HipparcosStar& b)
  168. {
  169.     return a.HIPCatalogNumber < b.HIPCatalogNumber;
  170. }
  171. struct HIPCatalogComparePredicate
  172. {
  173.     HIPCatalogComparePredicate() : dummy(0)
  174.     {
  175.     }
  176.     bool operator()(const HipparcosStar* star0, const HipparcosStar* star1) const
  177.     {
  178.         return star0->HIPCatalogNumber < star1->HIPCatalogNumber;
  179.     }
  180.     bool operator()(const HipparcosStar* star0, uint32 hip)
  181.     {
  182.         return star0->HIPCatalogNumber < hip;
  183.     }
  184.     int dummy;
  185. };
  186. class MultistarSystem
  187. {
  188. public:
  189.     int nStars; // Never greater than four in the HIPPARCOS catalog
  190.     HipparcosStar* stars[4];
  191. };
  192. class HipparcosComponent
  193. {
  194. public:
  195.     HipparcosComponent();
  196.     HipparcosStar* star;
  197.     char componentID;
  198.     char refComponentID;
  199.     float ascension;
  200.     float declination;
  201.     float appMag;
  202.     float bMag;
  203.     float vMag;
  204.     bool hasBV;
  205.     float positionAngle;
  206.     float separation;
  207. };
  208. HipparcosComponent::HipparcosComponent() :
  209.     star(NULL),
  210.     componentID('A'),
  211.     refComponentID('A'),
  212.     appMag(0.0f),
  213.     bMag(0.0f),
  214.     vMag(0.0f),
  215.     hasBV(false),
  216.     positionAngle(0.0f),
  217.     separation(0.0f)
  218. {
  219. }
  220. vector<HipparcosStar> stars;
  221. vector<HipparcosStar> companions;
  222. vector<HipparcosComponent> components;
  223. vector<HipparcosStar*> starIndex;
  224. typedef map<uint32, MultistarSystem*> MultistarSystemCatalog;
  225. MultistarSystemCatalog starSystems;
  226. HipparcosStar* findStar(uint32 hip)
  227. {
  228.     HIPCatalogComparePredicate pred;
  229.     vector<HipparcosStar*>::iterator iter = lower_bound(starIndex.begin(),
  230.                                                         starIndex.end(),
  231.                                                         hip, pred);
  232.     if (iter == starIndex.end())
  233.         return NULL;
  234.     HipparcosStar* star = *iter;
  235.     if (star->HIPCatalogNumber == hip)
  236.         return star;
  237.     else
  238.         return NULL;
  239. }
  240. StellarClass ParseStellarClass(char *starType)
  241. {
  242.     StellarClass::StarType type = StellarClass::NormalStar;
  243.     StellarClass::SpectralClass specClass = StellarClass::Spectral_A;
  244.     StellarClass::LuminosityClass lum = StellarClass::Lum_V;
  245.     unsigned short number = 5;
  246.     int i = 0;
  247.     // Subdwarves (luminosity class VI) are prefixed with sd
  248.     if (starType[i] == 's' && starType[i + 1] == 'd')
  249.     {
  250.         lum = StellarClass::Lum_VI;
  251.         i += 2;
  252.     }
  253.     switch (starType[i])
  254.     {
  255.     case 'O':
  256.         specClass = StellarClass::Spectral_O;
  257.         break;
  258.     case 'B':
  259.         specClass = StellarClass::Spectral_B;
  260.         break;
  261.     case 'A':
  262.         specClass = StellarClass::Spectral_A;
  263.         break;
  264.     case 'F':
  265.         specClass = StellarClass::Spectral_F;
  266.         break;
  267.     case 'G':
  268.         specClass = StellarClass::Spectral_G;
  269.         break;
  270.     case 'K':
  271.         specClass = StellarClass::Spectral_K;
  272.         break;
  273.     case 'M':
  274.         specClass = StellarClass::Spectral_M;
  275.         break;
  276.     case 'R':
  277.         specClass = StellarClass::Spectral_R;
  278.         break;
  279.     case 'N':
  280.         specClass = StellarClass::Spectral_S;
  281.         break;
  282.     case 'S':
  283.         specClass = StellarClass::Spectral_N;
  284.         break;
  285.     case 'W':
  286.         i++;
  287.         if (starType[i] == 'C')
  288.              specClass = StellarClass::Spectral_WC;
  289.         else if (starType[i] == 'N')
  290.             specClass = StellarClass::Spectral_WN;
  291.         else
  292.             i--;
  293.         break;
  294.     case 'D':
  295.         type = StellarClass::WhiteDwarf;
  296.         return StellarClass(type, specClass, 0, lum);
  297.     default:
  298.         specClass = StellarClass::Spectral_Unknown;
  299.         break;
  300.     }
  301.     i++;
  302.     if (starType[i] >= '0' && starType[i] <= '9')
  303.     {
  304.         number = starType[i] - '0';
  305.     }
  306.     else
  307.     {
  308.         // No number given for spectral class; assume it's a 5 unless
  309.         // the star is type O, as O5 stars are exceedingly rare.
  310.         if (specClass == StellarClass::Spectral_O)
  311.             number = 9;
  312.         else
  313.             number = 5;
  314.     }
  315.     if (lum != StellarClass::Lum_VI)
  316.     {
  317.         i++;
  318.         lum = StellarClass::Lum_V;
  319.         while (i < 13 && starType[i] != '') {
  320.             if (starType[i] == 'I') {
  321.                 if (starType[i + 1] == 'I') {
  322.                     if (starType[i + 2] == 'I') {
  323.                         lum = StellarClass::Lum_III;
  324.                     } else {
  325.                         lum = StellarClass::Lum_II;
  326.                     }
  327.                 } else if (starType[i + 1] == 'V') {
  328.                     lum = StellarClass::Lum_IV;
  329.                 } else if (starType[i + 1] == 'a') {
  330.                     if (starType[i + 2] == '0')
  331.                         lum = StellarClass::Lum_Ia0;
  332.                     else
  333.                         lum = StellarClass::Lum_Ia;
  334.                 } else if (starType[i + 1] == 'b') {
  335.                     lum = StellarClass::Lum_Ib;
  336.                 } else {
  337.                     lum = StellarClass::Lum_Ib;
  338.                 }
  339.                 break;
  340.             } else if (starType[i] == 'V') {
  341.                 if (starType[i + 1] == 'I')
  342.                     lum = StellarClass::Lum_VI;
  343.                 else
  344.                     lum = StellarClass::Lum_V;
  345.                 break;
  346.             }
  347.             i++;
  348.         }
  349.     }
  350.     return StellarClass(type, specClass, number, lum);
  351. }
  352. HipparcosStar TheSun()
  353. {
  354.     HipparcosStar star;
  355.     star.HDCatalogNumber = 0;
  356.     star.HIPCatalogNumber = 0;
  357.     star.ascension = 0.0f;
  358.     star.declination = 0.0f;
  359.     star.parallax = 1000000.0f;
  360.     star.appMag = -15.17f;
  361.     star.stellarClass = StellarClass(StellarClass::NormalStar,
  362.                                      StellarClass::Spectral_G, 2,
  363.                                      StellarClass::Lum_V);
  364.     return star;
  365. }
  366. StellarClass guessSpectralType(float colorIndex, float /*absMag*/)
  367. {
  368.     StellarClass::SpectralClass specClass = StellarClass::Spectral_Unknown;
  369.     float subclass = 0.0f;
  370.     if (colorIndex < -0.25f)
  371.     {
  372.         specClass = StellarClass::Spectral_O;
  373.         subclass = (colorIndex + 0.5f) / 0.25f;
  374.     }
  375.     else if (colorIndex < 0.0f)
  376.     {
  377.         specClass = StellarClass::Spectral_B;
  378.         subclass = (colorIndex + 0.25f) / 0.25f;
  379.     }
  380.     else if (colorIndex < 0.25f)
  381.     {
  382.         specClass = StellarClass::Spectral_A;
  383.         subclass = (colorIndex - 0.0f) / 0.25f;
  384.     }
  385.     else if (colorIndex < 0.6f)
  386.     {
  387.         specClass = StellarClass::Spectral_F;
  388.         subclass = (colorIndex - 0.25f) / 0.35f;
  389.     }
  390.     else if (colorIndex < 0.85f)
  391.     {
  392.         specClass = StellarClass::Spectral_G;
  393.         subclass = (colorIndex - 0.6f) / 0.25f;
  394.     }
  395.     else if (colorIndex < 1.4f)
  396.     {
  397.         specClass = StellarClass::Spectral_K;
  398.         subclass = (colorIndex - 0.85f) / 0.55f;
  399.     }
  400.     else
  401.     {
  402.         specClass = StellarClass::Spectral_M;
  403.         subclass = (colorIndex - 1.4f) / 1.0f;
  404.     }
  405.     if (subclass < 0.0f)
  406.         subclass = 0.0f;
  407.     else if (subclass > 1.0f)
  408.         subclass = 1.0f;
  409.     return StellarClass(StellarClass::NormalStar,
  410.                         specClass,
  411.                         (unsigned int) (subclass * 9.99f),
  412.                         StellarClass::Lum_V);
  413. }
  414. static unsigned int okStars, lineno, changes, tested;
  415. bool CheckStarRecord(istream& in)
  416. {
  417.     HipparcosStar star,*hipstar;
  418.     char buf[HipStarRecordLength];
  419.     bool ok=true;
  420.     in.read(buf, TycStarRecordLength);
  421.     lineno++;
  422.     if (sscanf(buf + 210, "%d", &star.HIPCatalogNumber) != 1)
  423.     {
  424.         // Not in Hipparcos, skip it.
  425.         if (verbose>1)
  426.             cout << "Error reading HIPPARCOS catalog number.n";
  427.         return false;
  428.     }
  429.     if (verbose>1)
  430.         cout << "Testing HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  431.     if (!(hipstar=findStar(star.HIPCatalogNumber)))
  432.     {
  433.         cout << "Error finding HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  434.         return false;
  435.     }
  436.     if (hipstar->tycline)
  437.     {
  438.         if (verbose>0)
  439.             cout << "Duplicate Tycho Line for HIP " << star.HIPCatalogNumber << " from Line " << lineno << ", earlier Line at " << hipstar->tycline << " ." << endl;
  440.     }
  441.     else
  442.         hipstar->tycline=lineno;
  443.     tested++;
  444.     sscanf(buf + 309, "%d", &star.HDCatalogNumber);
  445.     if (sscanf(buf + 224, "%f", &star.e_Mag) != 1)
  446.         /* Tycho Database gives no error in for VMag, so we use error on BTmag
  447.            instead.*/
  448.     {
  449.             /* no standard Error given even in BTmag, give it a large value so
  450.                CheckStarRecord() will use the Tycho value if possible */
  451.             star.e_Mag = 1000.0f;
  452.     }
  453.     else if (star.e_Mag >1000.0)
  454.     {
  455.         cout << "Huge BTmag error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  456.     }
  457.     if (sscanf(buf + 41, "%f", &star.appMag) != 1)
  458.     {
  459.         if (verbose>0)
  460.             cout << "Error reading magnitude for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  461.     }
  462.     else if (star.e_Mag < hipstar->e_Mag)
  463.     {
  464.         hipstar->appMag=star.appMag;
  465.         hipstar->e_Mag=star.e_Mag;
  466.         changes++;
  467.         if (verbose > 2)
  468.             cout << "  Change Mag.n";
  469.     }
  470.     float parallaxError = 0.0f;
  471.     if (sscanf(buf + 119, "%f", &parallaxError) != 0)
  472.     {
  473.         if (star.parallax < 0.0f || parallaxError / star.parallax > 1.0f)
  474.             star.parallaxError = 255u;
  475.         else
  476.             star.parallaxError = (uint8) (parallaxError / star.parallax * 200);
  477.     }
  478.     if (sscanf(buf + 79, "%f", &star.parallax) != 1)
  479.     {
  480.         if (verbose>0)
  481.             cout << "Error reading parallax for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  482.         ok=false;
  483.     }
  484.     else if (star.parallax< 0.0)
  485.     {
  486.         if (hipstar->parallax< 0.0)
  487.         {
  488.             if (verbose>0)
  489.                 cout << "Negative parallax for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  490.         ok=false;
  491.         }
  492.     }
  493.     else if (star.parallaxError < hipstar->parallaxError)
  494.     {
  495.         hipstar->parallax=star.parallax;
  496.         hipstar->parallaxError=star.parallaxError;
  497.         changes++;
  498.         if (verbose > 2)
  499.             cout << "  Change Parallax.n";
  500.     }
  501.     if (sscanf(buf + 105, "%f", &star.e_RA) != 1)
  502.     {
  503.             /* no standard Error givenfor Right Ascension , give it a large
  504.                value so original HIPPARCOS value will be used */
  505.             if (verbose>0)
  506.                 cout << "No RA error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  507.             star.e_RA = 2000.0f;
  508.     }
  509.     else if (star.e_RA >1000.0)
  510.     {
  511.         cout << "Huge RA error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  512.     }
  513.     if (sscanf(buf + 112, "%f", &star.e_DE) != 1)
  514.     {
  515.             /* no standard Error given for Declination, give it a large value
  516.                so original HIPPARCOS value will be used. */
  517.             if (verbose>0)
  518.                 cout << "No DE error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  519.             star.e_DE = 2000.0f;
  520.     }
  521.     else if (star.e_DE >1000.0)
  522.     {
  523.         cout << "Huge DE error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  524.     }
  525.     bool coordReadError = false;
  526.     if (sscanf(buf + 51, "%f", &star.ascension) != 1)
  527.         coordReadError = true;
  528.     if (sscanf(buf + 64, "%f", &star.declination) != 1)
  529.         coordReadError = true;
  530.     star.ascension = (float) (star.ascension * 24.0 / 360.0);
  531.     // Read the lower resolution coordinates in hhmmss form if we failed
  532.     // to read the coordinates in degrees.  Not sure why the high resolution
  533.     // coordinates are occasionally missing . . .
  534.     if (coordReadError)
  535.     {
  536.         int hh = 0;
  537.         int mm = 0;
  538.         float seconds;
  539.         coordReadError=false;
  540.         if (sscanf(buf + 17, "%d %d %f", &hh, &mm, &seconds) != 3)
  541.         {
  542.             cout << "Error reading ascension for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  543.             coordReadError=true;;
  544.         }
  545.         else
  546.         {
  547.             star.ascension = hh + (float) mm / 60.0f + (float) seconds / 3600.0f;
  548.             char decSign;
  549.             int deg;
  550.             if (sscanf(buf + 29, "%c%d %d %f", &decSign, &deg, &mm, &seconds) != 4)
  551.             {
  552.                 cout << "Error reading declination for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  553.                 coordReadError=true;;
  554.             }
  555.             else
  556.             {
  557.                 star.declination = deg + (float) mm / 60.0f + (float) seconds / 3600.0f;
  558.                 if (decSign == '-')
  559.                     star.declination = -star.declination;
  560.             }
  561.         }
  562.     }
  563.     if (!((coordReadError) || ((star.ascension==hipstar->ascension) && (star.declination==hipstar->declination))))
  564.     {
  565.         float ast=star.e_RA * star.e_DE;
  566.         float ahi=hipstar->e_RA * hipstar->e_DE;
  567.         if ((ast<ahi) || ((ast==ahi) && ((star.e_RA + star.e_DE) < (hipstar->e_RA + hipstar->e_DE))))
  568.         //if ((star.e_RA * star.e_DE) < (hipstar->e_RA * hipstar->e_DE))
  569.         {
  570.             // Error on the Tycho value is smaller, use it.
  571.             hipstar->ascension=star.ascension;
  572.             hipstar->declination=star.declination;
  573.             hipstar->e_RA=star.e_RA;
  574.             hipstar->e_DE=star.e_DE;
  575.             changes++;
  576.             if (verbose > 2)
  577.                 cout << "  Change Position.n";
  578.         }
  579.     }
  580.     int asc = 0;
  581.     int dec = 0;
  582.     char decSign = ' ';
  583.     if (sscanf(buf + 299, "%d%c%d", &asc, &decSign, &dec) == 3)
  584.     {
  585.         if (decSign == '-')
  586.             dec = -dec;
  587.         star.CCDMIdentifier = asc << 16 | (dec & 0xffff);
  588.         if (star.CCDMIdentifier != hipstar->CCDMIdentifier)
  589.         {
  590.             cout << "Diffrence in CCDM Identifier for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  591.         ok=false;
  592.         }
  593.     }
  594.     if (ok)
  595.         okStars++;
  596.     return true;
  597. }
  598. bool ReadStarRecord(istream& in)
  599. {
  600.     HipparcosStar star;
  601.     char buf[HipStarRecordLength];
  602.     in.read(buf, HipStarRecordLength);
  603.     if (sscanf(buf + 8, "%d", &star.HIPCatalogNumber) != 1)
  604.     {
  605.         cout << "Error reading catalog number.n";
  606.         return false;
  607.     }
  608.     sscanf(buf + 390, "%d", &star.HDCatalogNumber);
  609.     star.tycline=0;
  610.     if (sscanf(buf + 41, "%f", &star.appMag) != 1)
  611.     {
  612.         if (verbose>0)
  613.             cout << "Error reading magnitude for HIP " << star.HIPCatalogNumber << " ." << endl;
  614.         return false;
  615.     }
  616.     if (sscanf(buf + 79, "%f", &star.parallax) != 1)
  617.     {
  618.         if (verbose>0)
  619.             cout << "Error reading parallax for HIP " << star.HIPCatalogNumber << " ." << endl;
  620.         return false;
  621.     }
  622.     if (star.parallax< 0.0)
  623.     {
  624.         if (verbose>0)
  625.             cout << "Negative parallax for HIP " << star.HIPCatalogNumber << " ." << endl;
  626.     }
  627.     bool coordReadError = false;
  628.     if (sscanf(buf + 51, "%f", &star.ascension) != 1)
  629.         coordReadError = true;
  630.     if (sscanf(buf + 64, "%f", &star.declination) != 1)
  631.         coordReadError = true;
  632.     star.ascension = (float) (star.ascension * 24.0 / 360.0);
  633.     // Read the lower resolution coordinates in hhmmss form if we failed
  634.     // to read the coordinates in degrees.  Not sure why the high resolution
  635.     // coordinates are occasionally missing . . .
  636.     if (coordReadError)
  637.     {
  638.         int hh = 0;
  639.         int mm = 0;
  640.         float seconds;
  641.         if (sscanf(buf + 17, "%d %d %f", &hh, &mm, &seconds) != 3)
  642.         {
  643.             cout << "Error reading ascension for HIP " << star.HIPCatalogNumber << " ." << endl;
  644.             return false;
  645.         }
  646.         star.ascension = hh + (float) mm / 60.0f + (float) seconds / 3600.0f;
  647.         char decSign;
  648.         int deg;
  649.         if (sscanf(buf + 29, "%c%d %d %f", &decSign, &deg, &mm, &seconds) != 4)
  650.         {
  651.             cout << "Error reading declination for HIP " << star.HIPCatalogNumber << " ." << endl;
  652.             return false;
  653.         }
  654.         star.declination = deg + (float) mm / 60.0f + (float) seconds / 3600.0f;
  655.         if (decSign == '-')
  656.             star.declination = -star.declination;
  657.     }
  658.     int asc = 0;
  659.     int dec = 0;
  660.     char decSign = ' ';
  661.     int n = 1;
  662.     if (sscanf(buf + 327, "%d%c%d", &asc, &decSign, &dec) == 3)
  663.     {
  664.         if (decSign == '-')
  665.             dec = -dec;
  666.         star.CCDMIdentifier = asc << 16 | (dec & 0xffff);
  667.         sscanf(buf + 340, "%d", &n);
  668.         star.starsWithCCDM = (uint8) n;
  669.         sscanf(buf + 343, "%d", &n);
  670.         star.nComponents = (uint8) n;
  671.     }
  672.     char* spectralType = buf + 435;
  673.     spectralType[12] = '';
  674.     star.stellarClass = ParseStellarClass(spectralType);
  675.     if (star.stellarClass.getSpectralClass() == StellarClass::Spectral_Unknown)
  676.     {
  677.         float bmag,vmag;
  678.         if ((sscanf(buf + 217, "%f", &bmag) == 1) &&
  679.             (sscanf(buf + 230, "%f", &vmag) == 1))
  680.             {
  681.             if (verbose>0)
  682.                 cout << "Guessing Type " << spectralType << "for HIP " << star.HIPCatalogNumber << " ." << endl;
  683.             star.stellarClass = guessSpectralType(bmag - vmag, 0.0f);
  684.             }
  685.         else if (verbose>0)
  686.             cout << "Unparsable stellar class " << spectralType << "for HIP " << star.HIPCatalogNumber << " ." << endl;
  687.     }
  688.     float parallaxError = 0.0f;
  689.     if (sscanf(buf + 119, "%f", &parallaxError) != 0)
  690.     {
  691.         if (star.parallax < 0.0f || parallaxError / star.parallax > 1.0f)
  692.             star.parallaxError = 255u;
  693.         else
  694.             star.parallaxError = (uint8) (parallaxError / star.parallax * 200);
  695.     }
  696.     if (sscanf(buf + 105, "%f", &star.e_RA) != 1)
  697.     {
  698.             /* no standard Error givenfor Right Ascension , give it a large
  699.                value so CheckStarRecord() will use Tycho value if possible */
  700.             star.e_RA = 1000.0f;
  701.     }
  702.     else if (star.e_RA >1000.0)
  703.     {
  704.         cout << "Huge RA error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  705.     }
  706.     if (sscanf(buf + 112, "%f", &star.e_DE) != 1)
  707.     {
  708.             /* no standard Error given for Declination, give it a large value
  709.                so CheckStarRecord() will use the Tycho value if possible */
  710.             star.e_DE = 1000.0f;
  711.     }
  712.     else if (star.e_DE >1000.0)
  713.     {
  714.         cout << "Huge DE error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  715.     }
  716.     if (sscanf(buf + 224, "%f", &star.e_Mag) != 1)
  717.         // No error in HIPPARCOS for VMag, use error on BTmag instead.
  718.     {
  719.             /* no standard Error given give it a large value so CheckStarRecord() will use the Tycho value if possible */
  720.             star.e_Mag = 1000.0f;
  721.     }
  722.     else if (star.e_Mag >1000.0)
  723.     {
  724.         cout << "Huge BTmag error for HIP " << star.HIPCatalogNumber << " from Line " << lineno << " ." << endl;
  725.     }
  726.     stars.insert(stars.end(), star);
  727.     return true;
  728. }
  729. bool ReadComponentRecord(istream& in)
  730. {
  731.     HipparcosComponent component;
  732.     char buf[HipComponentRecordLength];
  733.     in.read(buf, HipComponentRecordLength);
  734.     uint32 hip;
  735.     if (sscanf(buf + 42, "%ud", &hip) != 1)
  736.     {
  737.         cout << "Missing HIP catalog number for component.n";
  738.         return false;
  739.     }
  740.     component.star = findStar(hip);
  741.     if (component.star == NULL)
  742.     {
  743.         cout << "Nonexistent HIP catalog number for component.n";
  744.         return false;
  745.     }
  746.     if (sscanf(buf + 40, "%c", &component.componentID) != 1)
  747.     {
  748.         cout << "Missing component identifier.n";
  749.         return false;
  750.     }
  751.     if (sscanf(buf + 175, "%c", &component.refComponentID) != 1)
  752.     {
  753.         cout << "Error reading reference component.n";
  754.         return false;
  755.     }
  756.     if (component.refComponentID == ' ')
  757.         component.refComponentID = component.componentID;
  758.     // Read astrometric information
  759.     if (sscanf(buf + 88, "%f", &component.ascension) != 1)
  760.     {
  761.         cout << "Missing ascension for component.n";
  762.         return false;
  763.     }
  764.     component.ascension = (float) (component.ascension * 24.0 / 360.0);
  765.     if (sscanf(buf + 101, "%f", &component.declination) != 1)
  766.     {
  767.         cout << "Missing declination for component.n";
  768.         return false;
  769.     }
  770.     // Read photometric information
  771.     if (sscanf(buf + 49, "%f", &component.appMag) != 1)
  772.     {
  773.         cout << "Missing magnitude for component.n";
  774.         return false;
  775.     }
  776.     // vMag and bMag may be necessary to guess the spectral type
  777.     if (sscanf(buf + 62, "%f", &component.bMag) != 1 ||
  778.         sscanf(buf + 75, "%f", &component.vMag) != 1)
  779.     {
  780.         component.bMag = component.vMag = component.appMag;
  781.     }
  782.     else
  783.     {
  784.         component.hasBV = true;
  785.     }
  786.     if (component.componentID != component.refComponentID)
  787.     {
  788.         if (sscanf(buf + 177, "%f", &component.positionAngle) != 1)
  789.         {
  790.             cout << "Missing position angle for component.n";
  791.             return false;
  792.         }
  793.         if (sscanf(buf + 185, "%f", &component.separation) != 1)
  794.         {
  795.             cout << "Missing separation for component.n";
  796.             return false;
  797.         }
  798.     }
  799.     components.insert(components.end(), component);
  800.     return true;
  801. };
  802. void BuildMultistarSystemCatalog()
  803. {
  804.     for (vector<HipparcosStar>::iterator iter = stars.begin();
  805.          iter != stars.end(); iter++)
  806.     {
  807.         if (iter->CCDMIdentifier != NullCCDMIdentifier)
  808.         {
  809.             MultistarSystemCatalog::iterator it =
  810.                 starSystems.find(iter->CCDMIdentifier);
  811.             if (it == starSystems.end())
  812.             {
  813.                 MultistarSystem* multiSystem = new MultistarSystem();
  814.                 multiSystem->nStars = 1;
  815.                 multiSystem->stars[0] = &*iter;
  816.                 starSystems.insert(MultistarSystemCatalog::value_type(iter->CCDMIdentifier, multiSystem));
  817.             }
  818.             else
  819.             {
  820.                 MultistarSystem* multiSystem = it->second;
  821.                 if (multiSystem->nStars == 4)
  822.                 {
  823.                     cout << "Number of stars in system exceeds 4n";
  824.                 }
  825.                 else
  826.                 {
  827.                     multiSystem->stars[multiSystem->nStars] = &*iter;
  828.                     multiSystem->nStars++;
  829.                 }
  830.             }
  831.         }
  832.     }
  833. }
  834. void ConstrainComponentParallaxes()
  835. {
  836.     for (MultistarSystemCatalog::iterator iter = starSystems.begin();
  837.          iter != starSystems.end(); iter++)
  838.     {
  839.         MultistarSystem* multiSystem = iter->second;
  840.         if (multiSystem->nStars > 1)
  841.         {
  842.             for (int i = 1; i < multiSystem->nStars; i++)
  843.                 multiSystem->stars[i]->parallax = multiSystem->stars[0]->parallax;
  844.         }
  845. #if 0
  846.         if (multiSystem->nStars > 2)
  847.         {
  848.             cout << multiSystem->nStars << ": ";
  849.             if (multiSystem->stars[0]->HDCatalogNumber != NullCatalogNumber)
  850.                 cout << "HD " << multiSystem->stars[0]->HDCatalogNumber;
  851.             else
  852.                 cout << "HIP " << multiSystem->stars[0]->HIPCatalogNumber;
  853.             cout << 'n';
  854.         }
  855. #endif
  856.     }
  857. }
  858. void CorrectErrors()
  859. {
  860.     for (vector<HipparcosStar>::iterator iter = stars.begin();
  861.          iter != stars.end(); iter++)
  862.     {
  863.         // Fix the spectral class of Capella, listed for some reason
  864.         // as M1 in the database.
  865.         if (iter->HDCatalogNumber == 34029)
  866.         {
  867.             iter->stellarClass = StellarClass(StellarClass::NormalStar,
  868.                                               StellarClass::Spectral_G, 0,
  869.                                               StellarClass::Lum_III);
  870.         }
  871.     }
  872. }
  873. // Process the vector of star components and insert those that are companions
  874. // of stars in the primary database into the companions vector.
  875. void CreateCompanionList()
  876. {
  877.     for (vector<HipparcosComponent>::iterator iter = components.begin();
  878.          iter != components.end(); iter++)
  879.     {
  880.         // Don't insert the reference component, as this star should already
  881.         // be in the primary database.
  882.         if (iter->componentID != iter->refComponentID)
  883.         {
  884.             int componentNumber = iter->componentID - 'A';
  885.             if (componentNumber > 0 && componentNumber < 8)
  886.             {
  887.                 HipparcosStar star;
  888.                 star.HDCatalogNumber = NullCatalogNumber;
  889.                 star.HIPCatalogNumber = iter->star->HIPCatalogNumber |
  890.                     (componentNumber << 25);
  891.                 star.ascension = iter->ascension;
  892.                 star.declination = iter->declination;
  893.                 star.parallax = iter->star->parallax;
  894.                 star.appMag = iter->appMag;
  895.                 if (iter->hasBV)
  896.                     star.stellarClass = guessSpectralType(iter->bMag - iter->vMag, 0.0f);
  897.                 else
  898.                     star.stellarClass = StellarClass(StellarClass::NormalStar,
  899.                                                      StellarClass::Spectral_Unknown,
  900.                                                      0, StellarClass::Lum_V);
  901.                 star.CCDMIdentifier = iter->star->CCDMIdentifier;
  902.                 star.parallaxError = iter->star->parallaxError;
  903.                 companions.insert(companions.end(), star);
  904.             }
  905.         }
  906.     }
  907. }
  908. void ShowStarsWithComponents()
  909. {
  910.     cout << "nStars with >2 componentsn";
  911.     for (vector<HipparcosStar>::iterator iter = stars.begin();
  912.          iter != stars.end(); iter++)
  913.     {
  914.         if (iter->nComponents > 2)
  915.         {
  916.             cout << (int) iter->nComponents << ": ";
  917.             if (iter->HDCatalogNumber != NullCatalogNumber)
  918.                 cout << "HD " << iter->HDCatalogNumber;
  919.             else
  920.                 cout << "HIP " << iter->HIPCatalogNumber;
  921.             cout << 'n';
  922.         }
  923.     }
  924. }
  925. void CompareTycho()
  926. {
  927.     ifstream tycDatabase(TychoDatabaseFile.c_str(), ios::in | ios::binary);
  928.     if (!tycDatabase.is_open())
  929.     {
  930.         cout << "Error opening " << TychoDatabaseFile << 'n';
  931.         cout << "You may download this file from ftp://cdsarc.u-strasbg.fr/cats/I/239/n";
  932.         return;
  933.     }
  934.     int recs=0;
  935.     cout << "Comparing Tycho data set.n";
  936.     okStars=0;
  937.     lineno=0;
  938.     changes=0;
  939.     while (tycDatabase.good())
  940.     {
  941.         CheckStarRecord(tycDatabase);
  942.         if (++recs % 10000 == 0)
  943.             {
  944.             if (verbose>=0)
  945.                 cout << recs << " records.n";
  946.             else
  947.                 cout << ".";
  948.                 cout.flush();
  949.             }
  950.     }
  951.     if (verbose<0)
  952.         cout << "n";
  953.     else
  954.         cout << recs  << " records checked, " << tested << " tested,  " << okStars << " checked out OK, and " << changes << " changes were made.n";
  955. }
  956. int main(int argc, char* argv[])
  957. {
  958.     assert(sizeof(StellarClass) == 2);
  959.     verbose=0;
  960.     dropstars=1;
  961.     int c;
  962.     while((c=getopt(argc,argv,"v::qd:"))>-1)
  963.     {
  964.         if (c=='?')
  965.         {
  966.             cout << "Usage: buildstardb [-v[<verbosity_level>] [-q] [-d <drop-level>n";
  967.             exit(1);
  968.         }
  969.         else if (c=='v')
  970.         {
  971.             if (optarg)
  972.                 {
  973.                 verbose=(int)atol(optarg);
  974.                 if (verbose<-1)
  975.                     verbose=-1;
  976.                 else if (verbose>3)
  977.                     verbose=3;
  978.                 }
  979.             else
  980.                 verbose=1;
  981.         }
  982.         else if (c=='d')
  983.         {   /* Dropstar level. 0 = don't drop stars
  984.                                1 = drop only non-naked eye visible stars
  985.                                2 = drop all stars with strange values */
  986.             dropstars=(int)atol(optarg);
  987.             if (dropstars<0)
  988.                 dropstars=0;
  989.             else if (dropstars>2)
  990.                 dropstars=2;
  991.         }
  992.         else if (c=='q')
  993.         {
  994.             verbose=-1;
  995.         }
  996.     }
  997.     // Read star records from the primary HIPPARCOS catalog
  998.     {
  999.         ifstream mainDatabase(MainDatabaseFile.c_str(), ios::in | ios::binary);
  1000.         if (!mainDatabase.is_open())
  1001.         {
  1002.             cout << "Error opening " << MainDatabaseFile << 'n';
  1003.             cout << "You may download this file from ftp://cdsarc.u-strasbg.fr/cats/I/239/n";
  1004.             exit(1);
  1005.         }
  1006.         cout << "Reading HIPPARCOS data set.n";
  1007.         while (mainDatabase.good())
  1008.         {
  1009.             ReadStarRecord(mainDatabase);
  1010.             if (stars.size() % 10000 == 0)
  1011.                 {
  1012.                 if (verbose>=0)
  1013.                     cout << stars.size() << " records.n";
  1014.                 else
  1015.                     cout << ".";
  1016.                     cout.flush();
  1017.                 }
  1018.         }
  1019.         if (verbose<0)
  1020.             cout << "n";
  1021.     }
  1022.     if (verbose>=0)
  1023.     {
  1024.         cout << "Read " << stars.size() << " stars from main database.n";
  1025.         cout << "Adding the Sun...n";
  1026.     }
  1027.     stars.insert(stars.end(), TheSun());
  1028.     if (verbose>=0)
  1029.         cout << "Sorting stars...n";
  1030.     {
  1031.         starIndex.reserve(stars.size());
  1032.         for (vector<HipparcosStar>::iterator iter = stars.begin();
  1033.              iter != stars.end(); iter++)
  1034.         {
  1035.             starIndex.insert(starIndex.end(), &*iter);
  1036.         }
  1037.         HIPCatalogComparePredicate pred;
  1038.         // It may not even be necessary to sort the records, if the
  1039.         // HIPPARCOS catalog is strictly ordered by catalog number.  I'm not
  1040.         // sure about this however,
  1041.         random_shuffle(starIndex.begin(), starIndex.end());
  1042.         sort(starIndex.begin(), starIndex.end(), pred);
  1043.     }
  1044.     // Read component records
  1045.     {
  1046.         ifstream componentDatabase(ComponentDatabaseFile.c_str(),
  1047.                                    ios::in | ios::binary);
  1048.         if (!componentDatabase.is_open())
  1049.         {
  1050.             cout << "Error opening " << ComponentDatabaseFile << 'n';
  1051.             cout << "You may download this file from ftp://cdsarc.u-strasbg.fr/cats/I/239/n";
  1052.             exit(1);
  1053.         }
  1054.         if (verbose>=0)
  1055.             cout << "Reading HIPPARCOS component database.n";
  1056.         while (componentDatabase.good())
  1057.         {
  1058.             ReadComponentRecord(componentDatabase);
  1059.         }
  1060.     }
  1061.     if (verbose>=0)
  1062.         cout << "Read " << components.size() << " components.n";
  1063.     {
  1064.         int aComp = 0, bComp = 0, cComp = 0, dComp = 0, eComp = 0, otherComp = 0;
  1065.         int bvComp = 0;
  1066.         for (unsigned int i = 0; i < components.size(); i++)
  1067.         {
  1068.             switch (components[i].componentID)
  1069.             {
  1070.             case 'A':
  1071.                 aComp++; break;
  1072.             case 'B':
  1073.                 bComp++; break;
  1074.             case 'C':
  1075.                 cComp++; break;
  1076.             case 'D':
  1077.                 dComp++; break;
  1078.             case 'E':
  1079.                 eComp++; break;
  1080.             default:
  1081.                 otherComp++; break;
  1082.             }
  1083.             if (components[i].hasBV && components[i].componentID != 'A')
  1084.                 bvComp++;
  1085.         }
  1086.         if (verbose>=0)
  1087.         {
  1088.             cout << "A:" << aComp << "  B:" << bComp << "  C:" << cComp << "  D:" << dComp << "  E:" << eComp << 'n';
  1089.             cout << "Components with B-V mag: " << bvComp << 'n';
  1090.         }
  1091.     }
  1092.     if (verbose>=0)
  1093.         cout << "Building catalog of multiple star systems.n";
  1094.     BuildMultistarSystemCatalog();
  1095.     int nMultipleSystems = starSystems.size();
  1096.     if (verbose>=0)
  1097.         cout << "Stars in multiple star systems: " << nMultipleSystems << 'n';
  1098.     ConstrainComponentParallaxes();
  1099.     CorrectErrors();
  1100.     CompareTycho();
  1101.     // CreateCompanionList();
  1102.     if (verbose>=0)
  1103.     {
  1104.         cout << "Companion stars: " << companions.size() << 'n';
  1105.         cout << "Total stars: " << stars.size() + companions.size() << 'n';
  1106.     }
  1107.     if (verbose>0)
  1108.         ShowStarsWithComponents();
  1109.     const char* outputFile = "stars.dat";
  1110.     if (argv[optind])
  1111.         outputFile = argv[optind];
  1112.     cout << "Writing processed star records to " << outputFile << 'n';
  1113.     ofstream out(outputFile, ios::out | ios::binary);
  1114.     if (!out.good())
  1115.     {
  1116.         cout << "Error opening " << outputFile << 'n';
  1117.         exit(1);
  1118.     }
  1119.     s_er=0.0; // Zero the statistics values
  1120.     s_erq=0.0;
  1121.     n_er=0;
  1122.     s_er=0.0;
  1123.     s_erq=0.0;
  1124.     n_er=0;
  1125.     n_drop=0;
  1126.     n_dub=0;
  1127.     {
  1128.         vector<HipparcosStar>::iterator iter;
  1129.         for (iter = stars.begin(); iter != stars.end(); iter++)
  1130.             iter->analyze();
  1131.         for (iter = companions.begin(); iter != companions.end(); iter++)
  1132.             iter->analyze();
  1133.         binwrite(out, stars.size() + companions.size() - n_drop);
  1134.         float av_r,av_d; // average Right Ascension/Declination
  1135.         av_r=s_er/((float)n_er);
  1136.         av_d=s_ed/((float)n_ed);
  1137.         if (verbose>=0)
  1138.         {
  1139.             cout << "RA Error average: " << av_r << " with Standard Error: " << sqrt((s_erq+(square(s_er)/n_er) - (2*av_r*s_er))/(n_er-1)) << " .n";
  1140.             cout << "DE Error average: " << av_d << " with Standard Error: " << sqrt((s_edq+(square(s_ed)/n_ed) - (2*av_d*s_ed))/(n_ed-1)) << " .n";
  1141.         }
  1142.         for (iter = stars.begin(); iter != stars.end(); iter++)
  1143.             iter->write(out);
  1144.         for (iter = companions.begin(); iter != companions.end(); iter++)
  1145.             iter->write(out);
  1146.     }
  1147.     cout << "Stars processed: " << stars.size() + companions.size() << "   Number dropped: " << n_drop << "  number dubious: " << n_dub << " .n";
  1148. #if 0
  1149.     char* hdOutputFile = "hdxref.dat";
  1150.     cout << "Writing out HD cross reference to " << hdOutputFile << 'n';
  1151.     ofstream hdout(hdOutputFile, ios::out | ios::binary);
  1152.     if (!out.good())
  1153.     {
  1154.         cout << "Error opening " << hdOutputFile << 'n';
  1155.         exit(1);
  1156.     }
  1157.     {
  1158.         int nHD = 0;
  1159.         vector<HipparcosStar>::iterator iter;
  1160.         for (iter = stars.begin(); iter != stars.end(); iter++)
  1161.         {
  1162.             if (iter->HDCatalogNumber != NullCatalogNumber)
  1163.                 nHD++;
  1164.         }
  1165.         binwrite(hdout, nHD);
  1166.         cout << nHD << " stars have HD numbers.n";
  1167.         for (iter = stars.begin(); iter != stars.end(); iter++)
  1168.         {
  1169.             if (iter->HDCatalogNumber != NullCatalogNumber)
  1170.             {
  1171.                 binwrite(hdout, iter->HDCatalogNumber);
  1172.                 binwrite(hdout, iter->HIPCatalogNumber);
  1173.             }
  1174.         }
  1175.     }
  1176. #endif
  1177.     return 0;
  1178. }