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

OpenGL

开发平台:

Visual C++

  1. // stellarclass.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 <cstring>
  10. #include <cstdio>
  11. #include <cassert>
  12. #include "celestia.h"
  13. #include "stellarclass.h"
  14. using namespace std;
  15. Color StellarClass::getApparentColor() const
  16. {
  17.     return getApparentColor(getSpectralClass());
  18. }
  19. Color StellarClass::getApparentColor(StellarClass::SpectralClass sc) const
  20. {
  21.     switch (sc)
  22.     {
  23.     case Spectral_O:
  24.         return Color(0.7f, 0.8f, 1.0f);
  25.     case Spectral_B:
  26.         return Color(0.8f, 0.9f, 1.0f);
  27.     case Spectral_A:
  28.         return Color(1.0f, 1.0f, 1.0f);
  29.     case Spectral_F:
  30.         return Color(1.0f, 1.0f, 0.88f);
  31.     case Spectral_G:
  32.         return Color(1.0f, 1.0f, 0.75f);
  33.     case StellarClass::Spectral_K:
  34.         return Color(1.0f, 0.9f, 0.7f);
  35.     case StellarClass::Spectral_M:
  36.         return Color(1.0f, 0.7f, 0.7f);
  37.     case StellarClass::Spectral_R:
  38.     case StellarClass::Spectral_S:
  39.     case StellarClass::Spectral_N:
  40.     case StellarClass::Spectral_C:
  41.         return Color(1.0f, 0.4f, 0.4f);
  42.     case StellarClass::Spectral_L:
  43.     case StellarClass::Spectral_T:
  44.         return Color(0.75f, 0.2f, 0.2f);
  45.     default:
  46.         // TODO: Figure out reasonable colors for Wolf-Rayet stars,
  47.         // white dwarfs, and other oddities
  48.         return Color(1.0f, 1.0f, 1.0f);
  49.     }
  50. }
  51. // The << method of converting the stellar class to a string is
  52. // preferred, but it's not always practical, especially when you've
  53. // got a completely broken implemtation of stringstreams to
  54. // deal with (*cough* gcc *cough*).
  55. //
  56. // Return the buffer if successful or NULL if not (the buffer wasn't
  57. // large enough.)
  58. char* StellarClass::str(char* buf, unsigned int buflen) const
  59. {
  60.     StellarClass::StarType st = getStarType();
  61.     char s0[3];
  62.     char s1[2];
  63.     const char* s2 = "";
  64.     s0[0] = '';
  65.     s1[0] = '';
  66.     if (st == StellarClass::WhiteDwarf)
  67.     {
  68.         strcpy(s0, "WD");
  69.     }
  70.     else if (st == StellarClass::NeutronStar)
  71.     {
  72.         strcpy(s0, "Q");
  73.     }
  74.     else if (st == StellarClass::BlackHole)
  75.     {
  76.         strcpy(s0, "X");
  77.     }
  78.     else if (st == StellarClass::NormalStar)
  79.     {
  80. s0[0] = "OBAFGKMRSNWW?LTC"[(unsigned int) getSpectralClass()];
  81.         s0[1] = '';
  82. s1[0] = "0123456789"[getSubclass()];
  83.         s1[1] = '';
  84. switch (getLuminosityClass())
  85.         {
  86. case StellarClass::Lum_Ia0:
  87.     s2 = " I-a0";
  88.     break;
  89. case StellarClass::Lum_Ia:
  90.     s2 = " I-a";
  91.     break;
  92. case StellarClass::Lum_Ib:
  93.     s2 = " I-b";
  94.     break;
  95. case StellarClass::Lum_II:
  96.     s2 = " II";
  97.     break;
  98. case StellarClass::Lum_III:
  99.     s2 = " III";
  100.     break;
  101. case StellarClass::Lum_IV:
  102.     s2 = " IV";
  103.     break;
  104. case StellarClass::Lum_V:
  105.     s2 = " V";
  106.     break;
  107. case StellarClass::Lum_VI:
  108.     s2 = " VI";
  109.     break;
  110.         default: break;  // Do nothing, but prevent GCC4 warnings (Beware: potentially dangerous)
  111. }
  112.     }
  113.     else
  114.     {
  115.         strcpy(s0, "?");
  116.     }
  117.     if (strlen(s0) + strlen(s1) + strlen(s2) >= buflen)
  118.     {
  119.         return NULL;
  120.     }
  121.     else
  122.     {
  123.         sprintf(buf, "%s%s%s", s0, s1, s2);
  124.         return buf;
  125.     }
  126. }
  127. string StellarClass::str() const
  128. {
  129.     char buf[20];
  130.     str(buf, sizeof buf);
  131.     return string(buf);
  132. }
  133. uint16
  134. StellarClass::pack() const
  135. {
  136.     return (((uint16) starType << 12) |
  137.     (((uint16) specClass & 0xf) << 8) |
  138.     ((uint16) subclass << 4) |
  139.     ((uint16) lumClass));
  140. }
  141. bool
  142. StellarClass::unpack(uint16 st)
  143. {
  144.     starType = static_cast<StellarClass::StarType>(st >> 12);
  145.     switch (starType)
  146.     {
  147.     case NormalStar:
  148.         specClass = static_cast<SpectralClass>(st >> 8 & 0xf);
  149.         subclass = st >> 4 & 0xf;
  150.         lumClass = static_cast<LuminosityClass>(st & 0xf);
  151.         break;
  152.     case WhiteDwarf:
  153.         if ((st >> 8 & 0xf) >= WDClassCount)
  154.             return false;
  155.         specClass = static_cast<SpectralClass>((st >> 8 & 0xf) + Spectral_DA);
  156.         subclass = st >> 4 & 0xf;
  157.         lumClass = Lum_Unknown;
  158.         break;
  159.     case NeutronStar:
  160.     case BlackHole:
  161.         specClass = Spectral_Unknown;
  162.         subclass = Subclass_Unknown;
  163.         lumClass = Lum_Unknown;
  164.         break;
  165.     default:
  166.         return false;
  167.     }
  168.     return true;
  169. }
  170. ostream& operator<<(ostream& os, const StellarClass& sc)
  171. {
  172.     char buf[20];
  173.     char *scString = sc.str(buf, sizeof buf);
  174.     assert(scString != NULL);
  175.     os << scString;
  176.     return os;
  177. }
  178. bool operator<(const StellarClass& sc0, const StellarClass& sc1)
  179. {
  180.     return sc0.pack() < sc1.pack();
  181. }
  182. // The following code implements a state machine for parsing spectral
  183. // types.  It is a very forgiving parser, returning unknown for any of the
  184. // spectral type fields it can't find, and silently ignoring any extra
  185. // characters in the spectral type.  The parser is written this way because
  186. // the spectral type strings from the Hipparcos catalog are quite irregular.
  187. enum ParseState
  188. {
  189.     BeginState,
  190.     EndState,
  191.     NormalStarState,
  192.     WolfRayetTypeState,
  193.     NormalStarClassState,
  194.     NormalStarSubclassState,
  195.     NormalStarSubclassDecimalState,
  196.     NormalStarSubclassFinalState,
  197.     LumClassBeginState,
  198.     LumClassIState,
  199.     LumClassIIState,
  200.     LumClassVState,
  201.     LumClassIdashState,
  202.     LumClassIaState,
  203.     WDTypeState,
  204.     WDExtendedTypeState,
  205.     WDSubclassState,
  206.     SubdwarfPrefixState,
  207. };
  208. StellarClass
  209. StellarClass::parse(const string& st)
  210. {
  211.     uint32 i = 0;
  212.     ParseState state = BeginState;
  213.     StellarClass::StarType starType = StellarClass::NormalStar;
  214.     StellarClass::SpectralClass specClass = StellarClass::Spectral_Unknown;
  215.     StellarClass::LuminosityClass lumClass = StellarClass::Lum_Unknown;
  216.     unsigned int subclass = StellarClass::Subclass_Unknown;
  217.     while (state != EndState)
  218.     {
  219.         char c;
  220.         if (i < st.length())
  221.             c = st[i];
  222.         else
  223.             c = '';
  224.         switch (state)
  225.         {
  226.         case BeginState:
  227.             switch (c)
  228.             {
  229.             case 'Q':
  230.                 starType = StellarClass::NeutronStar;
  231.                 state = EndState;
  232.                 break;
  233.             case 'X':
  234.                 starType = StellarClass::BlackHole;
  235.                 state = EndState;
  236.                 break;
  237.             case 'D':
  238.                 starType = StellarClass::WhiteDwarf;
  239.                 specClass = StellarClass::Spectral_D;
  240.                 state = WDTypeState;
  241.                 i++;
  242.                 break;
  243.             case 's':
  244.                 // Hipparcos uses sd prefix for stars with luminosity
  245.                 // class VI ('subdwarfs')
  246.                 state = SubdwarfPrefixState;
  247.                 i++;
  248.                 break;
  249.             case '?':
  250.                 state = EndState;
  251.                 break;
  252.             default:
  253.                 state = NormalStarClassState;
  254.                 break;
  255.             }
  256.             break;
  257.         case WolfRayetTypeState:
  258.             switch (c)
  259.             {
  260.             case 'C':
  261.                 specClass = StellarClass::Spectral_WC;
  262.                 state = NormalStarSubclassState;
  263.                 i++;
  264.                 break;
  265.             case 'N':
  266.                 specClass = StellarClass::Spectral_WN;
  267.                 state = NormalStarSubclassState;
  268.                 i++;
  269.                 break;
  270.             default:
  271.                 specClass = StellarClass::Spectral_WC;
  272.                 state = NormalStarSubclassState;
  273.                 break;
  274.             }
  275.             break;
  276.         case SubdwarfPrefixState:
  277.             if (c == 'd')
  278.             {
  279.                 lumClass = StellarClass::Lum_VI;
  280.                 state = NormalStarClassState;
  281.                 i++;
  282.                 break;
  283.             }
  284.             else
  285.             {
  286.                 state = EndState;
  287.             }
  288.             break;
  289.         case NormalStarClassState:
  290.             switch (c)
  291.             {
  292.             case 'W':
  293.                 state = WolfRayetTypeState;
  294.                 break;
  295.             case 'O':
  296.                 specClass = StellarClass::Spectral_O;
  297.                 state = NormalStarSubclassState;
  298.                 break;
  299.             case 'B':
  300.                 specClass = StellarClass::Spectral_B;
  301.                 state = NormalStarSubclassState;
  302.                 break;
  303.             case 'A':
  304.                 specClass = StellarClass::Spectral_A;
  305.                 state = NormalStarSubclassState;
  306.                 break;
  307.             case 'F':
  308.                 specClass = StellarClass::Spectral_F;
  309.                 state = NormalStarSubclassState;
  310.                 break;
  311.             case 'G':
  312.                 specClass = StellarClass::Spectral_G;
  313.                 state = NormalStarSubclassState;
  314.                 break;
  315.             case 'K':
  316.                 specClass = StellarClass::Spectral_K;
  317.                 state = NormalStarSubclassState;
  318.                 break;
  319.             case 'M':
  320.                 specClass = StellarClass::Spectral_M;
  321.                 state = NormalStarSubclassState;
  322.                 break;
  323.             case 'R':
  324.                 specClass = StellarClass::Spectral_R;
  325.                 state = NormalStarSubclassState;
  326.                 break;
  327.             case 'S':
  328.                 specClass = StellarClass::Spectral_S;
  329.                 state = NormalStarSubclassState;
  330.                 break;
  331.             case 'N':
  332.                 specClass = StellarClass::Spectral_N;
  333.                 state = NormalStarSubclassState;
  334.                 break;
  335.             case 'L':
  336.                 specClass = StellarClass::Spectral_L;
  337.                 state = NormalStarSubclassState;
  338.                 break;
  339.             case 'T':
  340.                 specClass = StellarClass::Spectral_T;
  341.                 state = NormalStarSubclassState;
  342.                 break;
  343.             case 'C':
  344.                 specClass = StellarClass::Spectral_C;
  345.                 state = NormalStarSubclassState;
  346.                 break;
  347.             default:
  348.                 state = EndState;
  349.                 break;
  350.             }
  351.             i++;
  352.             break;
  353.         case NormalStarSubclassState:
  354.             if (isdigit(c))
  355.             {
  356.                 subclass = (unsigned int) c - (unsigned int) '0';
  357.                 state = NormalStarSubclassDecimalState;
  358.                 i++;
  359.             }
  360.             else
  361.             {
  362.                 state = LumClassBeginState;
  363.             }
  364.             break;
  365.         case NormalStarSubclassDecimalState:
  366.             if (c == '.')
  367.             {
  368.                 state = NormalStarSubclassFinalState;
  369.                 i++;
  370.             }
  371.             else
  372.             {
  373.                 state = LumClassBeginState;
  374.             }
  375.             break;
  376.         case NormalStarSubclassFinalState:
  377.             if (isdigit(c))
  378.                 state = LumClassBeginState;
  379.             else
  380.                 state = EndState;
  381.             i++;
  382.             break;
  383.         case LumClassBeginState:
  384.             switch (c)
  385.             {
  386.             case 'I':
  387.                 state = LumClassIState;
  388.                 break;
  389.             case 'V':
  390.                 state = LumClassVState;
  391.                 break;
  392.             default:
  393.                 state = EndState;
  394.                 break;
  395.             }
  396.             i++;
  397.             break;
  398.         case LumClassIState:
  399.             switch (c)
  400.             {
  401.             case 'I':
  402.                 state = LumClassIIState;
  403.                 break;
  404.             case 'V':
  405.                 lumClass = StellarClass::Lum_IV;
  406.                 state = EndState;
  407.                 break;
  408.             case 'a':
  409.                 state = LumClassIaState;
  410.                 break;
  411.             case 'b':
  412.                 lumClass = StellarClass::Lum_Ib;
  413.                 state = EndState;
  414.                 break;
  415.             case '-':
  416.                 state = LumClassIdashState;
  417.                 break;
  418.             default:
  419.                 lumClass = StellarClass::Lum_Ib;
  420.                 state = EndState;
  421.                 break;
  422.             }
  423.             i++;
  424.             break;
  425.         case LumClassIIState:
  426.             switch (c)
  427.             {
  428.             case 'I':
  429.                 lumClass = StellarClass::Lum_III;
  430.                 state = EndState;
  431.                 break;
  432.             default:
  433.                 lumClass = StellarClass::Lum_II;
  434.                 state = EndState;
  435.                 break;
  436.             }
  437.             break;
  438.         case LumClassIdashState:
  439.             switch (c)
  440.             {
  441.             case 'a':
  442.                 state = LumClassIaState;
  443.                 break;
  444.             case 'b':
  445.                 lumClass = StellarClass::Lum_Ib;
  446.                 state = EndState;
  447.                 break;
  448.             default:
  449.                 lumClass = StellarClass::Lum_Ib;
  450.                 state = EndState;
  451.                 break;
  452.             }
  453.             break;
  454.         case LumClassIaState:
  455.             switch (c)
  456.             {
  457.             case '0':
  458.                 lumClass = StellarClass::Lum_Ia0;
  459.                 state = EndState;
  460.                 break;
  461.             default:
  462.                 lumClass = StellarClass::Lum_Ia;
  463.                 state = EndState;
  464.                 break;
  465.             }
  466.             break;
  467.         case LumClassVState:
  468.             switch (c)
  469.             {
  470.             case 'I':
  471.                 lumClass = StellarClass::Lum_VI;
  472.                 state = EndState;
  473.                 break;
  474.             default:
  475.                 lumClass = StellarClass::Lum_V;
  476.                 state = EndState;
  477.                 break;
  478.             }
  479.             break;
  480.         case WDTypeState:
  481.             switch (c)
  482.             {
  483.             case 'A':
  484.                 specClass = StellarClass::Spectral_DA;
  485.                 i++;
  486.                 break;
  487.             case 'B':
  488.                 specClass = StellarClass::Spectral_DB;
  489.                 i++;
  490.                 break;
  491.             case 'C':
  492.                 specClass = StellarClass::Spectral_DC;
  493.                 i++;
  494.                 break;
  495.             case 'O':
  496.                 specClass = StellarClass::Spectral_DO;
  497.                 i++;
  498.                 break;
  499.             case 'Q':
  500.                 specClass = StellarClass::Spectral_DQ;
  501.                 i++;
  502.                 break;
  503.             case 'X':
  504.                 specClass = StellarClass::Spectral_DX;
  505.                 i++;
  506.                 break;
  507.             case 'Z':
  508.                 specClass = StellarClass::Spectral_DZ;
  509.                 i++;
  510.                 break;
  511.             default:
  512.                 specClass = StellarClass::Spectral_D;
  513.                 break;
  514.             }
  515.             state = WDExtendedTypeState;
  516.             break;
  517.         case WDExtendedTypeState:
  518.             switch (c)
  519.             {
  520.             case 'A':
  521.             case 'B':
  522.             case 'C':
  523.             case 'O':
  524.             case 'Q':
  525.             case 'Z':
  526.             case 'X':
  527.             case 'V': // variable
  528.             case 'P': // magnetic stars with polarized light
  529.             case 'H': // magnetic stars without polarized light
  530.             case 'E': // emission lines
  531.                 i++;
  532.                 break;
  533.             default:
  534.                 state = WDSubclassState;
  535.                 break;
  536.             }
  537.             break;
  538.         case WDSubclassState:
  539.             if (isdigit(c))
  540.             {
  541.                 subclass = (unsigned int) c - (unsigned int) '0';
  542.                 i++;
  543.             }
  544.             state = EndState;
  545.             break;
  546.         default:
  547.             assert(0);
  548.             state = EndState;
  549.             break;
  550.         }
  551.     }
  552.     return StellarClass(starType, specClass, subclass, lumClass);
  553. }