00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <cstring>
00011 #include <cstdio>
00012 #include <cassert>
00013 #include "celestia.h"
00014 #include "stellarclass.h"
00015
00016 using namespace std;
00017
00018
00019 Color StellarClass::getApparentColor() const
00020 {
00021 return getApparentColor(getSpectralClass());
00022 }
00023
00024
00025 Color StellarClass::getApparentColor(StellarClass::SpectralClass sc) const
00026 {
00027 switch (sc)
00028 {
00029 case Spectral_O:
00030 return Color(0.7f, 0.8f, 1.0f);
00031 case Spectral_B:
00032 return Color(0.8f, 0.9f, 1.0f);
00033 case Spectral_A:
00034 return Color(1.0f, 1.0f, 1.0f);
00035 case Spectral_F:
00036 return Color(1.0f, 1.0f, 0.88f);
00037 case Spectral_G:
00038 return Color(1.0f, 1.0f, 0.75f);
00039 case StellarClass::Spectral_K:
00040 return Color(1.0f, 0.9f, 0.7f);
00041 case StellarClass::Spectral_M:
00042 return Color(1.0f, 0.7f, 0.7f);
00043 case StellarClass::Spectral_R:
00044 case StellarClass::Spectral_S:
00045 case StellarClass::Spectral_N:
00046 case StellarClass::Spectral_C:
00047 return Color(1.0f, 0.4f, 0.4f);
00048 case StellarClass::Spectral_L:
00049 case StellarClass::Spectral_T:
00050 return Color(0.75f, 0.2f, 0.2f);
00051 default:
00052
00053
00054 return Color(1.0f, 1.0f, 1.0f);
00055 }
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 char* StellarClass::str(char* buf, unsigned int buflen) const
00067 {
00068 StellarClass::StarType st = getStarType();
00069 char s0[3];
00070 char s1[2];
00071 const char* s2 = "";
00072 s0[0] = '\0';
00073 s1[0] = '\0';
00074
00075 if (st == StellarClass::WhiteDwarf)
00076 {
00077 strcpy(s0, "WD");
00078 }
00079 else if (st == StellarClass::NeutronStar)
00080 {
00081 strcpy(s0, "Q");
00082 }
00083 else if (st == StellarClass::BlackHole)
00084 {
00085 strcpy(s0, "X");
00086 }
00087 else if (st == StellarClass::NormalStar)
00088 {
00089 s0[0] = "OBAFGKMRSNWW?LTC"[(unsigned int) getSpectralClass()];
00090 s0[1] = '\0';
00091 s1[0] = "0123456789"[getSubclass()];
00092 s1[1] = '\0';
00093 switch (getLuminosityClass())
00094 {
00095 case StellarClass::Lum_Ia0:
00096 s2 = " I-a0";
00097 break;
00098 case StellarClass::Lum_Ia:
00099 s2 = " I-a";
00100 break;
00101 case StellarClass::Lum_Ib:
00102 s2 = " I-b";
00103 break;
00104 case StellarClass::Lum_II:
00105 s2 = " II";
00106 break;
00107 case StellarClass::Lum_III:
00108 s2 = " III";
00109 break;
00110 case StellarClass::Lum_IV:
00111 s2 = " IV";
00112 break;
00113 case StellarClass::Lum_V:
00114 s2 = " V";
00115 break;
00116 case StellarClass::Lum_VI:
00117 s2 = " VI";
00118 break;
00119 }
00120 }
00121 else
00122 {
00123 strcpy(s0, "?");
00124 }
00125
00126 if (strlen(s0) + strlen(s1) + strlen(s2) >= buflen)
00127 {
00128 return NULL;
00129 }
00130 else
00131 {
00132 sprintf(buf, "%s%s%s", s0, s1, s2);
00133 return buf;
00134 }
00135 }
00136
00137
00138 string StellarClass::str() const
00139 {
00140 char buf[20];
00141 str(buf, sizeof buf);
00142 return string(buf);
00143 }
00144
00145
00146 uint16
00147 StellarClass::pack() const
00148 {
00149 return (((uint16) starType << 12) |
00150 (((uint16) specClass & 0xf) << 8) |
00151 ((uint16) subclass << 4) |
00152 ((uint16) lumClass));
00153 }
00154
00155
00156 bool
00157 StellarClass::unpack(uint16 st)
00158 {
00159 starType = static_cast<StellarClass::StarType>(st >> 12);
00160
00161 switch (starType)
00162 {
00163 case NormalStar:
00164 specClass = static_cast<SpectralClass>(st >> 8 & 0xf);
00165 subclass = st >> 4 & 0xf;
00166 lumClass = static_cast<LuminosityClass>(st & 0xf);
00167 break;
00168 case WhiteDwarf:
00169 if ((st >> 8 & 0xf) >= WDClassCount)
00170 return false;
00171 specClass = static_cast<SpectralClass>((st >> 8 & 0xf) + Spectral_DA);
00172 subclass = st >> 4 & 0xf;
00173 lumClass = Lum_Unknown;
00174 break;
00175 case NeutronStar:
00176 case BlackHole:
00177 specClass = Spectral_Unknown;
00178 subclass = Subclass_Unknown;
00179 lumClass = Lum_Unknown;
00180 break;
00181 default:
00182 return false;
00183 }
00184
00185 return true;
00186 }
00187
00188
00189 ostream& operator<<(ostream& os, const StellarClass& sc)
00190 {
00191 char buf[20];
00192 char *scString = sc.str(buf, sizeof buf);
00193 assert(scString != NULL);
00194
00195 os << scString;
00196
00197 return os;
00198 }
00199
00200
00201 bool operator<(const StellarClass& sc0, const StellarClass& sc1)
00202 {
00203 return sc0.pack() < sc1.pack();
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 enum ParseState
00213 {
00214 BeginState,
00215 EndState,
00216 NormalStarState,
00217 WolfRayetTypeState,
00218 NormalStarClassState,
00219 NormalStarSubclassState,
00220 NormalStarSubclassDecimalState,
00221 NormalStarSubclassFinalState,
00222 LumClassBeginState,
00223 LumClassIState,
00224 LumClassIIState,
00225 LumClassVState,
00226 LumClassIdashState,
00227 LumClassIaState,
00228 WDTypeState,
00229 WDExtendedTypeState,
00230 WDSubclassState,
00231 SubdwarfPrefixState,
00232 };
00233
00234
00235 StellarClass
00236 StellarClass::parse(const string& st)
00237 {
00238 uint32 i = 0;
00239 ParseState state = BeginState;
00240 StellarClass::StarType starType = StellarClass::NormalStar;
00241 StellarClass::SpectralClass specClass = StellarClass::Spectral_Unknown;
00242 StellarClass::LuminosityClass lumClass = StellarClass::Lum_Unknown;
00243 unsigned int subclass = StellarClass::Subclass_Unknown;
00244
00245 while (state != EndState)
00246 {
00247 char c;
00248 if (i < st.length())
00249 c = st[i];
00250 else
00251 c = '\0';
00252
00253 switch (state)
00254 {
00255 case BeginState:
00256 switch (c)
00257 {
00258 case 'Q':
00259 starType = StellarClass::NeutronStar;
00260 state = EndState;
00261 break;
00262 case 'X':
00263 starType = StellarClass::BlackHole;
00264 state = EndState;
00265 break;
00266 case 'D':
00267 starType = StellarClass::WhiteDwarf;
00268 specClass = StellarClass::Spectral_D;
00269 state = WDTypeState;
00270 i++;
00271 break;
00272 case 's':
00273
00274
00275 state = SubdwarfPrefixState;
00276 i++;
00277 break;
00278 case '?':
00279 state = EndState;
00280 break;
00281 default:
00282 state = NormalStarClassState;
00283 break;
00284 }
00285 break;
00286
00287 case WolfRayetTypeState:
00288 switch (c)
00289 {
00290 case 'C':
00291 specClass = StellarClass::Spectral_WC;
00292 state = NormalStarSubclassState;
00293 i++;
00294 break;
00295 case 'N':
00296 specClass = StellarClass::Spectral_WN;
00297 state = NormalStarSubclassState;
00298 i++;
00299 break;
00300 default:
00301 specClass = StellarClass::Spectral_WC;
00302 state = NormalStarSubclassState;
00303 break;
00304 }
00305 break;
00306
00307 case SubdwarfPrefixState:
00308 if (c == 'd')
00309 {
00310 lumClass = StellarClass::Lum_VI;
00311 state = NormalStarClassState;
00312 i++;
00313 break;
00314 }
00315 else
00316 {
00317 state = EndState;
00318 }
00319 break;
00320
00321 case NormalStarClassState:
00322 switch (c)
00323 {
00324 case 'W':
00325 state = WolfRayetTypeState;
00326 break;
00327 case 'O':
00328 specClass = StellarClass::Spectral_O;
00329 state = NormalStarSubclassState;
00330 break;
00331 case 'B':
00332 specClass = StellarClass::Spectral_B;
00333 state = NormalStarSubclassState;
00334 break;
00335 case 'A':
00336 specClass = StellarClass::Spectral_A;
00337 state = NormalStarSubclassState;
00338 break;
00339 case 'F':
00340 specClass = StellarClass::Spectral_F;
00341 state = NormalStarSubclassState;
00342 break;
00343 case 'G':
00344 specClass = StellarClass::Spectral_G;
00345 state = NormalStarSubclassState;
00346 break;
00347 case 'K':
00348 specClass = StellarClass::Spectral_K;
00349 state = NormalStarSubclassState;
00350 break;
00351 case 'M':
00352 specClass = StellarClass::Spectral_M;
00353 state = NormalStarSubclassState;
00354 break;
00355 case 'R':
00356 specClass = StellarClass::Spectral_R;
00357 state = NormalStarSubclassState;
00358 break;
00359 case 'S':
00360 specClass = StellarClass::Spectral_S;
00361 state = NormalStarSubclassState;
00362 break;
00363 case 'N':
00364 specClass = StellarClass::Spectral_N;
00365 state = NormalStarSubclassState;
00366 break;
00367 case 'L':
00368 specClass = StellarClass::Spectral_L;
00369 state = NormalStarSubclassState;
00370 break;
00371 case 'T':
00372 specClass = StellarClass::Spectral_T;
00373 state = NormalStarSubclassState;
00374 break;
00375 case 'C':
00376 specClass = StellarClass::Spectral_C;
00377 state = NormalStarSubclassState;
00378 break;
00379 default:
00380 state = EndState;
00381 break;
00382 }
00383 i++;
00384 break;
00385
00386 case NormalStarSubclassState:
00387 if (isdigit(c))
00388 {
00389 subclass = (unsigned int) c - (unsigned int) '0';
00390 state = NormalStarSubclassDecimalState;
00391 i++;
00392 }
00393 else
00394 {
00395 state = LumClassBeginState;
00396 }
00397 break;
00398
00399 case NormalStarSubclassDecimalState:
00400 if (c == '.')
00401 {
00402 state = NormalStarSubclassFinalState;
00403 i++;
00404 }
00405 else
00406 {
00407 state = LumClassBeginState;
00408 }
00409 break;
00410
00411 case NormalStarSubclassFinalState:
00412 if (isdigit(c))
00413 state = LumClassBeginState;
00414 else
00415 state = EndState;
00416 i++;
00417 break;
00418
00419 case LumClassBeginState:
00420 switch (c)
00421 {
00422 case 'I':
00423 state = LumClassIState;
00424 break;
00425 case 'V':
00426 state = LumClassVState;
00427 break;
00428 default:
00429 state = EndState;
00430 break;
00431 }
00432 i++;
00433 break;
00434
00435 case LumClassIState:
00436 switch (c)
00437 {
00438 case 'I':
00439 state = LumClassIIState;
00440 break;
00441 case 'V':
00442 lumClass = StellarClass::Lum_IV;
00443 state = EndState;
00444 break;
00445 case 'a':
00446 state = LumClassIaState;
00447 break;
00448 case 'b':
00449 lumClass = StellarClass::Lum_Ib;
00450 state = EndState;
00451 break;
00452 case '-':
00453 state = LumClassIdashState;
00454 break;
00455 default:
00456 lumClass = StellarClass::Lum_Ib;
00457 state = EndState;
00458 break;
00459 }
00460 i++;
00461 break;
00462
00463 case LumClassIIState:
00464 switch (c)
00465 {
00466 case 'I':
00467 lumClass = StellarClass::Lum_III;
00468 state = EndState;
00469 break;
00470 default:
00471 lumClass = StellarClass::Lum_II;
00472 state = EndState;
00473 break;
00474 }
00475 break;
00476
00477 case LumClassIdashState:
00478 switch (c)
00479 {
00480 case 'a':
00481 state = LumClassIaState;
00482 break;
00483 case 'b':
00484 lumClass = StellarClass::Lum_Ib;
00485 state = EndState;
00486 break;
00487 default:
00488 lumClass = StellarClass::Lum_Ib;
00489 state = EndState;
00490 break;
00491 }
00492 break;
00493
00494 case LumClassIaState:
00495 switch (c)
00496 {
00497 case '0':
00498 lumClass = StellarClass::Lum_Ia0;
00499 state = EndState;
00500 break;
00501 default:
00502 lumClass = StellarClass::Lum_Ia;
00503 state = EndState;
00504 break;
00505 }
00506 break;
00507
00508 case LumClassVState:
00509 switch (c)
00510 {
00511 case 'I':
00512 lumClass = StellarClass::Lum_VI;
00513 state = EndState;
00514 break;
00515 default:
00516 lumClass = StellarClass::Lum_V;
00517 state = EndState;
00518 break;
00519 }
00520 break;
00521
00522 case WDTypeState:
00523 switch (c)
00524 {
00525 case 'A':
00526 specClass = StellarClass::Spectral_DA;
00527 i++;
00528 break;
00529 case 'B':
00530 specClass = StellarClass::Spectral_DB;
00531 i++;
00532 break;
00533 case 'C':
00534 specClass = StellarClass::Spectral_DC;
00535 i++;
00536 break;
00537 case 'O':
00538 specClass = StellarClass::Spectral_DO;
00539 i++;
00540 break;
00541 case 'Q':
00542 specClass = StellarClass::Spectral_DQ;
00543 i++;
00544 break;
00545 case 'X':
00546 specClass = StellarClass::Spectral_DX;
00547 i++;
00548 break;
00549 case 'Z':
00550 specClass = StellarClass::Spectral_DZ;
00551 i++;
00552 break;
00553 default:
00554 specClass = StellarClass::Spectral_D;
00555 break;
00556 }
00557 state = WDExtendedTypeState;
00558 break;
00559
00560 case WDExtendedTypeState:
00561 switch (c)
00562 {
00563 case 'A':
00564 case 'B':
00565 case 'C':
00566 case 'O':
00567 case 'Q':
00568 case 'Z':
00569 case 'X':
00570 case 'V':
00571 case 'P':
00572 case 'H':
00573 case 'E':
00574 i++;
00575 break;
00576 default:
00577 state = WDSubclassState;
00578 break;
00579 }
00580 break;
00581
00582 case WDSubclassState:
00583 if (isdigit(c))
00584 {
00585 subclass = (unsigned int) c - (unsigned int) '0';
00586 i++;
00587 }
00588 state = EndState;
00589 break;
00590
00591 default:
00592 assert(0);
00593 state = EndState;
00594 break;
00595 }
00596 }
00597
00598 return StellarClass(starType, specClass, subclass, lumClass);
00599 }