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

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 "stardb.h"
  18. using namespace std;
  19. static string MainDatabaseFile("hip_main.dat");
  20. static string ComponentDatabaseFile("h_dm_com.dat");
  21. static string OrbitalDatabase("hip_dm_o.dat");
  22. static const int HipStarRecordLength = 451;
  23. static const int HipComponentRecordLength = 239;
  24. static uint32 NullCCDMIdentifier = 0xffffffff;
  25. static uint32 NullCatalogNumber = 0xffffffff;
  26. class HipparcosStar
  27. {
  28. public:
  29.     HipparcosStar();
  30.     void write(ostream&);
  31.   
  32.     uint32 HIPCatalogNumber;
  33.     uint32 HDCatalogNumber;
  34.     float ascension;
  35.     float declination;
  36.     float parallax;
  37.     float appMag;
  38.     StellarClass stellarClass;
  39.     uint32 CCDMIdentifier;
  40.     uint8 starsWithCCDM;
  41.     uint8 nComponents;
  42.     uint8 parallaxError;
  43. };
  44. HipparcosStar::HipparcosStar() :
  45.     HIPCatalogNumber(NullCatalogNumber),
  46.     HDCatalogNumber(NullCatalogNumber),
  47.     ascension(0.0f),
  48.     declination(0.0f),
  49.     parallax(0.0f),
  50.     appMag(0.0f),
  51.     CCDMIdentifier(NullCCDMIdentifier),
  52.     starsWithCCDM(0),
  53.     nComponents(1),
  54.     parallaxError(0)
  55. {
  56. }
  57. template<class T> void binwrite(ostream& out, T x)
  58. {
  59.     out.write(reinterpret_cast<char*>(&x), sizeof(T));
  60. }
  61. void HipparcosStar::write(ostream& out)
  62. {
  63. #if 0
  64.     if (HDCatalogNumber != NullCatalogNumber)
  65.         binwrite(out, HDCatalogNumber);
  66.     else
  67.         binwrite(out, HIPCatalogNumber | 0x10000000);
  68. #endif
  69.     binwrite(out, HIPCatalogNumber);
  70.     binwrite(out, HDCatalogNumber);
  71.     binwrite(out, ascension);
  72.     binwrite(out, declination);
  73.     binwrite(out, parallax);
  74.     binwrite(out, (short) (appMag * 256));
  75.     binwrite(out, stellarClass);
  76.     binwrite(out, parallaxError);
  77. }
  78. bool operator<(const HipparcosStar& a, const HipparcosStar& b)
  79. {
  80.     return a.HIPCatalogNumber < b.HIPCatalogNumber;
  81. }
  82. struct HIPCatalogComparePredicate
  83. {
  84.     HIPCatalogComparePredicate() : dummy(0)
  85.     {
  86.     }
  87.     bool operator()(const HipparcosStar* star0, const HipparcosStar* star1) const
  88.     {
  89.         return star0->HIPCatalogNumber < star1->HIPCatalogNumber;
  90.     }
  91.     bool operator()(const HipparcosStar* star0, uint32 hip)
  92.     {
  93.         return star0->HIPCatalogNumber < hip;
  94.     }
  95.     int dummy;
  96. };
  97. class MultistarSystem
  98. {
  99. public:
  100.     int nStars; // Never greater than four in the HIPPARCOS catalog
  101.     HipparcosStar* stars[4];
  102. };
  103. class HipparcosComponent
  104. {
  105. public:
  106.     HipparcosComponent();
  107.     HipparcosStar* star;
  108.     char componentID;
  109.     char refComponentID;
  110.     float ascension;
  111.     float declination;
  112.     float appMag;
  113.     float bMag;
  114.     float vMag;
  115.     bool hasBV;
  116.     float positionAngle;
  117.     float separation;
  118. };
  119. HipparcosComponent::HipparcosComponent() :
  120.     star(NULL),
  121.     componentID('A'),
  122.     refComponentID('A'),
  123.     appMag(0.0f),
  124.     bMag(0.0f),
  125.     vMag(0.0f),
  126.     hasBV(false),
  127.     positionAngle(0.0f),
  128.     separation(0.0f)
  129. {
  130. }
  131. vector<HipparcosStar> stars;
  132. vector<HipparcosStar> companions;
  133. vector<HipparcosComponent> components;
  134. vector<HipparcosStar*> starIndex;
  135. typedef map<uint32, MultistarSystem*> MultistarSystemCatalog;
  136. MultistarSystemCatalog starSystems;
  137. HipparcosStar* findStar(uint32 hip)
  138. {
  139.     HIPCatalogComparePredicate pred;
  140.     vector<HipparcosStar*>::iterator iter = lower_bound(starIndex.begin(),
  141.                                                         starIndex.end(),
  142.                                                         hip, pred);
  143.     if (iter == starIndex.end())
  144.         return NULL;
  145.     HipparcosStar* star = *iter;
  146.     if (star->HIPCatalogNumber == hip)
  147.         return star;
  148.     else
  149.         return NULL;
  150. }
  151. StellarClass ParseStellarClass(char *starType)
  152. {
  153.     StellarClass::StarType type = StellarClass::NormalStar;
  154.     StellarClass::SpectralClass specClass = StellarClass::Spectral_A;
  155.     StellarClass::LuminosityClass lum = StellarClass::Lum_V;
  156.     unsigned short number = 5;
  157.     int i = 0;
  158.     // Subdwarves (luminosity class VI) are prefixed with sd
  159.     if (starType[i] == 's' && starType[i + 1] == 'd')
  160.     {
  161.         lum = StellarClass::Lum_VI;
  162.         i += 2;
  163.     }
  164.     switch (starType[i])
  165.     {
  166.     case 'O':
  167.         specClass = StellarClass::Spectral_O;
  168.         break;
  169.     case 'B':
  170.         specClass = StellarClass::Spectral_B;
  171.         break;
  172.     case 'A':
  173.         specClass = StellarClass::Spectral_A;
  174.         break;
  175.     case 'F':
  176.         specClass = StellarClass::Spectral_F;
  177.         break;
  178.     case 'G':
  179.         specClass = StellarClass::Spectral_G;
  180.         break;
  181.     case 'K':
  182.         specClass = StellarClass::Spectral_K;
  183.         break;
  184.     case 'M':      
  185.         specClass = StellarClass::Spectral_M;
  186.         break;
  187.     case 'R':
  188.         specClass = StellarClass::Spectral_R;
  189.         break;
  190.     case 'N':
  191.         specClass = StellarClass::Spectral_S;
  192.         break;
  193.     case 'S':
  194.         specClass = StellarClass::Spectral_N;
  195.         break;
  196.     case 'W':
  197. i++;
  198. if (starType[i] == 'C')
  199.       specClass = StellarClass::Spectral_WC;
  200. else if (starType[i] == 'N')
  201.     specClass = StellarClass::Spectral_WN;
  202. else
  203.     i--;
  204. break;
  205.     case 'D':
  206.         type = StellarClass::WhiteDwarf;
  207.         return StellarClass(type, specClass, 0, lum);
  208.     default:
  209.         specClass = StellarClass::Spectral_Unknown;
  210.         break;
  211.     }
  212.     i++;
  213.     if (starType[i] >= '0' && starType[i] <= '9')
  214.     {
  215.         number = starType[i] - '0';
  216.     }
  217.     else
  218.     {
  219.         // No number given for spectral class; assume it's a 5 unless
  220.         // the star is type O, as O5 stars are exceedingly rare.
  221.         if (specClass == StellarClass::Spectral_O)
  222.             number = 9;
  223.         else
  224.             number = 5;
  225.     }
  226.     if (lum != StellarClass::Lum_VI)
  227.     {
  228.         i++;
  229.         lum = StellarClass::Lum_V;
  230.         while (i < 13 && starType[i] != '') {
  231.             if (starType[i] == 'I') {
  232.                 if (starType[i + 1] == 'I') {
  233.                     if (starType[i + 2] == 'I') {
  234.                         lum = StellarClass::Lum_III;
  235.                     } else {
  236.                         lum = StellarClass::Lum_II;
  237.                     }
  238.                 } else if (starType[i + 1] == 'V') {
  239.                     lum = StellarClass::Lum_IV;
  240.                 } else if (starType[i + 1] == 'a') {
  241.                     if (starType[i + 2] == '0')
  242.                         lum = StellarClass::Lum_Ia0;
  243.                     else
  244.                         lum = StellarClass::Lum_Ia;
  245.                 } else if (starType[i + 1] == 'b') {
  246.                     lum = StellarClass::Lum_Ib;
  247.                 } else {
  248.                     lum = StellarClass::Lum_Ib;
  249.                 }
  250.                 break;
  251.             } else if (starType[i] == 'V') {
  252.                 if (starType[i + 1] == 'I')
  253.                     lum = StellarClass::Lum_VI;
  254.                 else
  255.                     lum = StellarClass::Lum_V;
  256.                 break;
  257.             }
  258.             i++;
  259.         }
  260.     }
  261.     return StellarClass(type, specClass, number, lum);
  262. }
  263. HipparcosStar TheSun()
  264. {
  265.     HipparcosStar star;
  266.     star.HDCatalogNumber = 0;
  267.     star.HIPCatalogNumber = 0;
  268.     star.ascension = 0.0f;
  269.     star.declination = 0.0f;
  270.     star.parallax = 1000000.0f;
  271.     star.appMag = -15.17f;
  272.     star.stellarClass = StellarClass(StellarClass::NormalStar,
  273.                                      StellarClass::Spectral_G, 2,
  274.                                      StellarClass::Lum_V);
  275.     return star;
  276. }
  277. bool ReadStarRecord(istream& in)
  278. {
  279.     HipparcosStar star;
  280.     char buf[HipStarRecordLength];
  281.     in.read(buf, HipStarRecordLength);
  282.     
  283.     if (sscanf(buf + 2, "%d", &star.HIPCatalogNumber) != 1)
  284.     {
  285.         cout << "Error reading catalog number.n";
  286.         return false;
  287.     }
  288.     sscanf(buf + 390, "%d", &star.HDCatalogNumber);
  289.     if (sscanf(buf + 41, "%f", &star.appMag) != 1)
  290.     {
  291.         cout << "Error reading magnitude.n";
  292.         return false;
  293.     }
  294.     if (sscanf(buf + 79, "%f", &star.parallax) != 1)
  295.     {
  296.         // cout << "Error reading parallax.n";
  297.     }
  298.     bool coordReadError = false;
  299.     if (sscanf(buf + 51, "%f", &star.ascension) != 1)
  300.         coordReadError = true;
  301.     if (sscanf(buf + 64, "%f", &star.declination) != 1)
  302.         coordReadError = true;
  303.     star.ascension = (float) (star.ascension * 24.0 / 360.0);
  304.     // Read the lower resolution coordinates in hhmmss form if we failed
  305.     // to read the coordinates in degrees.  Not sure why the high resolution
  306.     // coordinates are occasionally missing . . .
  307.     if (coordReadError)
  308.     {
  309.         int hh = 0;
  310.         int mm = 0;
  311.         float seconds;
  312.         if (sscanf(buf + 17, "%d %d %f", &hh, &mm, &seconds) != 3)
  313.         {
  314.             cout << "Error reading ascension.n";
  315.             return false;
  316.         }
  317.         star.ascension = hh + (float) mm / 60.0f + (float) seconds / 3600.0f;
  318.     
  319.         char decSign;
  320.         int deg;
  321.         if (sscanf(buf + 29, "%c%d %d %f", &decSign, &deg, &mm, &seconds) != 4)
  322.         {
  323.             cout << "Error reading declination.n";
  324.             return false;
  325.         }
  326.         star.declination = deg + (float) mm / 60.0f + (float) seconds / 3600.0f;
  327.         if (decSign == '-')
  328.             star.declination = -star.declination;
  329.     }
  330.     char* spectralType = buf + 435;
  331.     spectralType[12] = '';
  332.     star.stellarClass = ParseStellarClass(spectralType);
  333.     int asc = 0;
  334.     int dec = 0;
  335.     char decSign = ' ';
  336.     if (sscanf(buf + 327, "%d%c%d", &asc, &decSign, &dec) == 3)
  337.     {
  338.         if (decSign == '-')
  339.             dec = -dec;
  340.         star.CCDMIdentifier = asc << 16 | (dec & 0xffff);
  341.         int n = 1;
  342.         sscanf(buf + 340, "%d", &n);
  343.         star.starsWithCCDM = (uint8) n;
  344.         sscanf(buf + 343, "%d", &n);
  345.         star.nComponents = (uint8) n;
  346.     }
  347.     float parallaxError = 0.0f;
  348.     if (sscanf(buf + 119, "%f", &parallaxError) != 0)
  349.     {
  350.         if (star.parallax < 0.0f || parallaxError / star.parallax > 1.0f)
  351.             star.parallaxError = (int8) 255;
  352.         else
  353.             star.parallaxError = (int8) (parallaxError / star.parallax * 200);
  354.     }
  355.     
  356.     stars.insert(stars.end(), star);
  357.     return true;
  358. }
  359. bool ReadComponentRecord(istream& in)
  360. {
  361.     HipparcosComponent component;
  362.     char buf[HipComponentRecordLength];
  363.     in.read(buf, HipComponentRecordLength);
  364.     uint32 hip;
  365.     if (sscanf(buf + 42, "%ud", &hip) != 1)
  366.     {
  367.         cout << "Missing HIP catalog number for component.n";
  368.         return false;
  369.     }
  370.     component.star = findStar(hip);
  371.     if (component.star == NULL)
  372.     {
  373.         cout << "Nonexistent HIP catalog number for component.n";
  374.         return false;
  375.     }
  376.     if (sscanf(buf + 40, "%c", &component.componentID) != 1)
  377.     {
  378.         cout << "Missing component identifier.n";
  379.         return false;
  380.     }
  381.     if (sscanf(buf + 175, "%c", &component.refComponentID) != 1)
  382.     {
  383.         cout << "Error reading reference component.n";
  384.         return false;
  385.     }
  386.     if (component.refComponentID == ' ')
  387.         component.refComponentID = component.componentID;
  388.     // Read astrometric information
  389.     if (sscanf(buf + 88, "%f", &component.ascension) != 1)
  390.     {
  391.         cout << "Missing ascension for component.n";
  392.         return false;
  393.     }
  394.     component.ascension = (float) (component.ascension * 24.0 / 360.0);
  395.     if (sscanf(buf + 101, "%f", &component.declination) != 1)
  396.     {
  397.         cout << "Missing declination for component.n";
  398.         return false;
  399.     }
  400.     // Read photometric information
  401.     if (sscanf(buf + 49, "%f", &component.appMag) != 1)
  402.     {
  403.         cout << "Missing magnitude for component.n";
  404.         return false;
  405.     }
  406.     // vMag and bMag may be necessary to guess the spectral type
  407.     if (sscanf(buf + 62, "%f", &component.bMag) != 1 ||
  408.         sscanf(buf + 69, "%f", &component.vMag) != 1)
  409.     {
  410.         component.bMag = component.vMag = component.appMag;
  411.     }
  412.     else
  413.     {
  414.         component.hasBV = true;
  415.     }
  416.     if (component.componentID != component.refComponentID)
  417.     {
  418.         if (sscanf(buf + 177, "%f", &component.positionAngle) != 1)
  419.         {
  420.             cout << "Missing position angle for component.n";
  421.             return false;
  422.         }
  423.         if (sscanf(buf + 185, "%f", &component.separation) != 1)
  424.         {
  425.             cout << "Missing separation for component.n";
  426.             return false;
  427.         }
  428.     }
  429.     components.insert(components.end(), component);
  430.     return true;
  431. };
  432. void BuildMultistarSystemCatalog()
  433. {
  434.     for (vector<HipparcosStar>::iterator iter = stars.begin();
  435.          iter != stars.end(); iter++)
  436.     {
  437.         if (iter->CCDMIdentifier != NullCCDMIdentifier)
  438.         {
  439.             MultistarSystemCatalog::iterator it =
  440.                 starSystems.find(iter->CCDMIdentifier);
  441.             if (it == starSystems.end())
  442.             {
  443.                 MultistarSystem* multiSystem = new MultistarSystem();
  444.                 multiSystem->nStars = 1;
  445.                 multiSystem->stars[0] = iter;
  446.                 starSystems.insert(MultistarSystemCatalog::value_type(iter->CCDMIdentifier, multiSystem));
  447.             }
  448.             else
  449.             {
  450.                 MultistarSystem* multiSystem = it->second;
  451.                 if (multiSystem->nStars == 4)
  452.                 {
  453.                     cout << "Number of stars in system exceeds 4n";
  454.                 }
  455.                 else
  456.                 {
  457.                     multiSystem->stars[multiSystem->nStars] = iter;
  458.                     multiSystem->nStars++;
  459.                 }
  460.             }
  461.         }
  462.     }
  463. }
  464. StellarClass guessSpectralType(float colorIndex, float absMag)
  465. {
  466.     StellarClass::SpectralClass specClass = StellarClass::Spectral_Unknown;
  467.     float subclass = 0.0f;
  468.     if (colorIndex < -0.25f)
  469.     {
  470.         specClass = StellarClass::Spectral_O;
  471.         subclass = (colorIndex + 0.5f) / 0.25f;
  472.     }
  473.     else if (colorIndex < 0.0f)
  474.     {
  475.         specClass = StellarClass::Spectral_B;
  476.         subclass = (colorIndex + 0.25f) / 0.25f;
  477.     }
  478.     else if (colorIndex < 0.25f)
  479.     {
  480.         specClass = StellarClass::Spectral_A;
  481.         subclass = (colorIndex - 0.0f) / 0.25f;
  482.     }
  483.     else if (colorIndex < 0.6f)
  484.     {
  485.         specClass = StellarClass::Spectral_F;
  486.         subclass = (colorIndex - 0.25f) / 0.35f;
  487.     }
  488.     else if (colorIndex < 0.85f)
  489.     {
  490.         specClass = StellarClass::Spectral_G;
  491.         subclass = (colorIndex - 0.6f) / 0.25f;
  492.     }
  493.     else if (colorIndex < 1.4f)
  494.     {
  495.         specClass = StellarClass::Spectral_K;
  496.         subclass = (colorIndex - 0.85f) / 0.55f;
  497.     }
  498.     else
  499.     {
  500.         specClass = StellarClass::Spectral_M;
  501.         subclass = (colorIndex - 1.4f) / 1.0f;
  502.     }
  503.     if (subclass < 0.0f)
  504.         subclass = 0.0f;
  505.     else if (subclass > 1.0f)
  506.         subclass = 1.0f;
  507.     return StellarClass(StellarClass::NormalStar,
  508.                         specClass,
  509.                         (unsigned int) (subclass * 9.99f),
  510.                         StellarClass::Lum_V);
  511. }
  512. void ConstrainComponentParallaxes()
  513. {
  514.     for (MultistarSystemCatalog::iterator iter = starSystems.begin();
  515.          iter != starSystems.end(); iter++)
  516.     {
  517.         MultistarSystem* multiSystem = iter->second;
  518.         if (multiSystem->nStars > 1)
  519.         {
  520.             for (int i = 1; i < multiSystem->nStars; i++)
  521.                 multiSystem->stars[i]->parallax = multiSystem->stars[0]->parallax;
  522.         }
  523. #if 0
  524.         if (multiSystem->nStars > 2)
  525.         {
  526.             cout << multiSystem->nStars << ": ";
  527.             if (multiSystem->stars[0]->HDCatalogNumber != NullCatalogNumber)
  528.                 cout << "HD " << multiSystem->stars[0]->HDCatalogNumber;
  529.             else
  530.                 cout << "HIP " << multiSystem->stars[0]->HIPCatalogNumber;
  531.             cout << 'n';
  532.         }
  533. #endif
  534.     }
  535. }
  536. void CorrectErrors()
  537. {
  538.     for (vector<HipparcosStar>::iterator iter = stars.begin();
  539.          iter != stars.end(); iter++)
  540.     {
  541.         // Fix the spectral class of Capella, listed for some reason
  542.         // as M1 in the database.
  543.         if (iter->HDCatalogNumber == 34029)
  544.         {
  545.             iter->stellarClass = StellarClass(StellarClass::NormalStar,
  546.                                               StellarClass::Spectral_G, 0,
  547.                                               StellarClass::Lum_III);
  548.         }
  549.     }
  550. }
  551. // Process the vector of star components and insert those that are companions
  552. // of stars in the primary database into the companions vector.
  553. void CreateCompanionList()
  554. {
  555.     for (vector<HipparcosComponent>::iterator iter = components.begin();
  556.          iter != components.end(); iter++)
  557.     {
  558.         // Don't insert the reference component, as this star should already
  559.         // be in the primary database.
  560.         if (iter->componentID != iter->refComponentID)
  561.         {
  562.             int componentNumber = iter->componentID - 'A';
  563.             if (componentNumber > 0 && componentNumber < 8)
  564.             {
  565.                 HipparcosStar star;
  566.                 star.HDCatalogNumber = NullCatalogNumber;
  567.                 star.HIPCatalogNumber = iter->star->HIPCatalogNumber | 
  568.                     (componentNumber << 25);
  569.                 star.ascension = iter->ascension;
  570.                 star.declination = iter->declination;
  571.                 star.parallax = iter->star->parallax;
  572.                 star.appMag = iter->appMag;
  573.                 if (iter->hasBV)
  574.                     star.stellarClass = guessSpectralType(iter->bMag - iter->vMag, 0.0f);
  575.                 else
  576.                     star.stellarClass = StellarClass(StellarClass::NormalStar,
  577.                                                      StellarClass::Spectral_Unknown,
  578.                                                      0, StellarClass::Lum_V);
  579.                 star.CCDMIdentifier = iter->star->CCDMIdentifier;
  580.                 star.parallaxError = iter->star->parallaxError;
  581.                 companions.insert(companions.end(), star);
  582.             }
  583.         }
  584.     }
  585. }
  586. void ShowStarsWithComponents()
  587. {
  588.     cout << "nStars with >2 componentsn";
  589.     for (vector<HipparcosStar>::iterator iter = stars.begin();
  590.          iter != stars.end(); iter++)
  591.     {
  592.         if (iter->nComponents > 2)
  593.         {
  594.             cout << (int) iter->nComponents << ": ";
  595.             if (iter->HDCatalogNumber != NullCatalogNumber)
  596.                 cout << "HD " << iter->HDCatalogNumber;
  597.             else
  598.                 cout << "HIP " << iter->HIPCatalogNumber;
  599.             cout << 'n';
  600.         }
  601.     }
  602. }
  603. int main(int argc, char* argv[])
  604. {
  605.     assert(sizeof(StellarClass) == 2);
  606.     // Read star records from the primary HIPPARCOS catalog
  607.     {
  608.         ifstream mainDatabase(MainDatabaseFile.c_str(), ios::in | ios::binary);
  609.         if (!mainDatabase.good())
  610.         {
  611.             cout << "Error opening " << MainDatabaseFile << 'n';
  612.             exit(1);
  613.         }
  614.         cout << "Reading HIPPARCOS data set.n";
  615.         while (mainDatabase.good())
  616.         {
  617.             ReadStarRecord(mainDatabase);
  618.             if (stars.size() % 10000 == 0)
  619.                 cout << stars.size() << " records.n";
  620.         }
  621.     }
  622.     cout << "Read " << stars.size() << " stars from main database.n";
  623.     cout << "Adding the Sun...n";
  624.     stars.insert(stars.end(), TheSun());
  625.     cout << "Sorting stars...n";
  626.     {
  627.         starIndex.reserve(stars.size());
  628.         for (vector<HipparcosStar>::iterator iter = stars.begin();
  629.              iter != stars.end(); iter++)
  630.         {
  631.             starIndex.insert(starIndex.end(), iter);
  632.         }
  633.         HIPCatalogComparePredicate pred;
  634.         // It may not even be necessary to sort the records, if the
  635.         // HIPPARCOS catalog is strictly ordered by catalog number.  I'm not
  636.         // sure about this however,
  637.         random_shuffle(starIndex.begin(), starIndex.end());
  638.         sort(starIndex.begin(), starIndex.end(), pred);
  639.     }
  640.         
  641.     // Read component records
  642.     {
  643.         ifstream componentDatabase(ComponentDatabaseFile.c_str(),
  644.                                    ios::in | ios::binary);
  645.         if (!componentDatabase.good())
  646.         {
  647.             cout << "Error opening " << ComponentDatabaseFile << 'n';
  648.             exit(1);
  649.         }
  650.         cout << "Reading HIPPARCOS component database.n";
  651.         while (componentDatabase.good())
  652.         {
  653.             ReadComponentRecord(componentDatabase);
  654.         }
  655.     }
  656.     cout << "Read " << components.size() << " components.n";
  657.     {    
  658.         int aComp = 0, bComp = 0, cComp = 0, dComp = 0, eComp = 0, otherComp = 0;
  659.         int bvComp = 0;
  660.         for (int i = 0; i < components.size(); i++)
  661.         {
  662.             switch (components[i].componentID)
  663.             {
  664.             case 'A':
  665.                 aComp++; break;
  666.             case 'B':
  667.                 bComp++; break;
  668.             case 'C':
  669.                 cComp++; break;
  670.             case 'D':
  671.                 dComp++; break;
  672.             case 'E':
  673.                 eComp++; break;
  674.             default:
  675.                 otherComp++; break;
  676.             }
  677.             if (components[i].hasBV && components[i].componentID != 'A')
  678.                 bvComp++;
  679.         }
  680.         
  681.         cout << "A:" << aComp << "  B:" << bComp << "  C:" << cComp << "  D:" << dComp << "  E:" << eComp << 'n';
  682.         cout << "Components with B-V mag: " << bvComp << 'n';
  683.     }
  684.     cout << "Building catalog of multiple star systems.n";
  685.     BuildMultistarSystemCatalog();
  686.     
  687.     int nMultipleSystems = starSystems.size();
  688.     cout << "Stars in multiple star systems: " << nMultipleSystems << 'n';
  689.     ConstrainComponentParallaxes();
  690.     CorrectErrors();
  691.     // CreateCompanionList();
  692.     cout << "Companion stars: " << companions.size() << 'n';
  693.     cout << "Total stars: " << stars.size() + companions.size() << 'n';
  694.     ShowStarsWithComponents();
  695.     char* outputFile = "stars.dat";
  696.     if (argc > 1)
  697.         outputFile = argv[1];
  698.     cout << "Writing processed star records to " << outputFile << 'n';
  699.     ofstream out(outputFile, ios::out | ios::binary);
  700.     if (!out.good())
  701.     {
  702.         cout << "Error opening " << outputFile << 'n';
  703.         exit(1);
  704.     }
  705.     binwrite(out, stars.size() + companions.size());
  706.     {
  707.         vector<HipparcosStar>::iterator iter;
  708.         for (iter = stars.begin(); iter != stars.end(); iter++)
  709.             iter->write(out);
  710.         for (iter = companions.begin(); iter != companions.end(); iter++)
  711.             iter->write(out);
  712.     }
  713. #if 0
  714.     char* hdOutputFile = "hdxref.dat";
  715.     
  716.     cout << "Writing out HD cross reference to " << hdOutputFile << 'n';
  717.     ofstream hdout(hdOutputFile, ios::out | ios::binary);
  718.     if (!out.good())
  719.     {
  720.         cout << "Error opening " << hdOutputFile << 'n';
  721.         exit(1);
  722.     }
  723.     {
  724.         int nHD = 0;
  725.         vector<HipparcosStar>::iterator iter;
  726.         for (iter = stars.begin(); iter != stars.end(); iter++)
  727.         {
  728.             if (iter->HDCatalogNumber != NullCatalogNumber)
  729.                 nHD++;
  730.         }
  731.         binwrite(hdout, nHD);
  732.         cout << nHD << " stars have HD numbers.n";
  733.         
  734.         for (iter = stars.begin(); iter != stars.end(); iter++)
  735.         {
  736.             if (iter->HDCatalogNumber != NullCatalogNumber)
  737.             {
  738.                 binwrite(hdout, iter->HDCatalogNumber);
  739.                 binwrite(hdout, iter->HIPCatalogNumber);
  740.             }
  741.         }        
  742.     }
  743. #endif
  744.     return 0;
  745. }