Kstars

starobject.cpp
1 /*
2  SPDX-FileCopyrightText: 2001 Jason Harris <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "starobject.h"
8 
9 #include "deepstardata.h"
10 #include "ksnumbers.h"
11 #ifndef KSTARS_LITE
12 #include "kspopupmenu.h"
13 #endif
14 #include "kstarsdata.h"
15 #include "ksutils.h"
16 #include "Options.h"
17 #include "skymap.h"
18 #include "stardata.h"
19 
20 #include <typeinfo>
21 
22 #ifdef PROFILE_UPDATECOORDS
23 double StarObject::updateCoordsCpuTime = 0.;
24 unsigned int StarObject::starsUpdated = 0;
25 #include <cstdlib>
26 #include <ctime>
27 #endif
28 
29 // DEBUG EDIT. Uncomment for testing Proper Motion
30 //#include "skycomponents/skymesh.h"
31 // END DEBUG
32 
33 #include "skycomponents/skylabeler.h"
34 
35 // DEBUG EDIT. Uncomment for testing Proper Motion
36 // You will also need to uncomment all related blocks
37 // from this file, starobject.h and also the trixel-boundaries
38 // block from lines 253 - 257 of skymapcomposite.cpp
39 //QVector<SkyPoint *> StarObject::Trail;
40 // END DEBUG
41 
42 #include <KLocalizedString>
43 
44 //----- Static Methods -----
45 //
46 double StarObject::reindexInterval(double pm)
47 {
48  if (pm < 1.0e-6)
49  return 1.0e6;
50 
51  // arcminutes * sec/min * milliarcsec/sec centuries/year
52  // / [milliarcsec/year] = centuries
53 
54  return 25.0 * 60.0 * 10.0 / pm;
55 }
56 
57 StarObject::StarObject(dms r, dms d, float m, const QString &n, const QString &n2, const QString &sptype, double pmra,
58  double pmdec, double par, bool mult, bool var, int hd)
59  : SkyObject(SkyObject::STAR, r, d, m, n, n2, QString()), PM_RA(pmra), PM_Dec(pmdec), Parallax(par),
60  Multiplicity(mult), Variability(var), HD(hd)
61 {
62  QByteArray spt = sptype.toLatin1();
63  SpType[0] = spt[0];
64  SpType[1] = spt[1];
65 
66  QString lname;
67  if (hasName())
68  {
69  lname = n;
70  if (hasName2())
71  lname += " (" + gname() + ')';
72  }
73  else if (hasName2())
74  {
75  lname = gname();
76  //If genetive name exists, but no primary name, set primary name = genetive name.
77  setName(gname());
78  }
79  else if (HD > 0)
80  {
81  lname = QLatin1String("HD ") + QString::number(HD);
82  }
83  setLongName(lname);
84  updateID = updateNumID = 0;
85 }
86 
87 StarObject::StarObject(double r, double d, float m, const QString &n, const QString &n2, const QString &sptype,
88  double pmra, double pmdec, double par, bool mult, bool var, int hd)
89  : SkyObject(SkyObject::STAR, r, d, m, n, n2, QString()), PM_RA(pmra), PM_Dec(pmdec), Parallax(par),
90  Multiplicity(mult), Variability(var), HD(hd)
91 {
92  QByteArray spt = sptype.toLatin1();
93  SpType[0] = spt[0];
94  SpType[1] = spt[1];
95 
96  QString lname;
97  if (hasName())
98  {
99  lname = n;
100  if (hasName2())
101  lname += " (" + gname() + ')';
102  }
103  else if (hasName2())
104  {
105  lname = gname();
106  //If genetive name exists, but no primary name, set primary name = genetive name.
107  setName(gname());
108  }
109  else if (HD > 0)
110  {
111  lname = QLatin1String("HD ") + QString::number(HD);
112  }
113  setLongName(lname);
114  updateID = updateNumID = 0;
115 }
116 
118  : SkyObject(o), PM_RA(o.PM_RA), PM_Dec(o.PM_Dec), Parallax(o.Parallax), Multiplicity(o.Multiplicity),
119  Variability(o.Variability), HD(o.HD)
120 {
121  SpType[0] = o.SpType[0];
122  SpType[1] = o.SpType[1];
123  updateID = updateNumID = 0;
124 }
125 
127 {
128  Q_ASSERT(typeid(this) ==
129  typeid(static_cast<const StarObject *>(this))); // Ensure we are not slicing a derived class
130  return new StarObject(*this);
131 }
132 
133 void StarObject::init(const StarData *stardata)
134 {
135  double ra, dec;
136  ra = stardata->RA / 1000000.0;
137  dec = stardata->Dec / 100000.0;
138  setType(SkyObject::STAR);
139  setMag(stardata->mag / 100.0);
140  setRA0(ra);
141  setDec0(dec);
142  setRA(ra0());
143  setDec(dec0());
144  SpType[0] = stardata->spec_type[0];
145  SpType[1] = stardata->spec_type[1];
146  PM_RA = stardata->dRA / 10.0;
147  PM_Dec = stardata->dDec / 10.0;
148  Parallax = stardata->parallax / 10.0;
149  Multiplicity = stardata->flags & 0x02;
150  Variability = stardata->flags & 0x04;
151  updateID = updateNumID = 0;
152  HD = stardata->HD;
153  if (HD > 0)
155  B = V = 99.9;
156 
157  // DEBUG Edit. For testing proper motion. Uncomment all related blocks to test.
158  // WARNING: You can debug only ONE STAR AT A TIME, because
159  // the StarObject::Trail is static. It has to be
160  // static, because otherwise, we can run into segfaults
161  // due to the memcpy() that we do to create stars
162  /*
163  testStar = false;
164  if( stardata->HD == 103095 && Trail.size() == 0 ) {
165  // Populate Trail with various positions
166  qDebug() << Q_FUNC_INFO << "TEST STAR FOUND!";
167  testStar = true;
168  KSNumbers num( J2000 ); // Some estimate, doesn't matter.
169  long double jy;
170  for( jy = -10000.0; jy <= 10000.0; jy += 500.0 ) {
171  num.updateValues( J2000 + jy * 365.238 );
172  double ra, dec;
173  getIndexCoords( &num, &ra, &dec );
174  Trail.append( new SkyPoint( ra / 15.0, dec ) );
175  }
176  qDebug() << Q_FUNC_INFO << "Populated the star's trail with " << Trail.size() << " entries.";
177  }
178  */
179  // END DEBUG.
180 
181  lastPrecessJD = J2000;
182 }
183 
184 void StarObject::init(const DeepStarData *stardata)
185 {
186  double ra, dec, BV_Index;
187 
188  ra = stardata->RA / 1000000.0;
189  dec = stardata->Dec / 100000.0;
190  setType(SkyObject::STAR);
191 
192  if (stardata->V == 30000 && stardata->B != 30000)
193  setMag((stardata->B - 1600) / 1000.0); // FIXME: Is it okay to make up stuff like this?
194  else
195  setMag(stardata->V / 1000.0);
196 
197  setRA0(ra);
198  setDec0(dec);
199  setRA(ra);
200  setDec(dec);
201 
202  SpType[1] = '?';
203  SpType[0] = 'B';
204  if (stardata->B == 30000 || stardata->V == 30000)
205  {
206  // Unused value
207 // BV_Index = -100;
208  SpType[0] = '?';
209  }
210  else
211  {
212  BV_Index = (stardata->B - stardata->V) / 1000.0;
213  if (BV_Index > 0.0) SpType[0] = 'A';
214  if (BV_Index > 0.325) SpType[0] = 'F';
215  if (BV_Index > 0.575) SpType[0] = 'G';
216  if (BV_Index > 0.975) SpType[0] = 'K';
217  if (BV_Index > 1.6) SpType[0] = 'M';
218  }
219 
220  PM_RA = stardata->dRA / 100.0;
221  PM_Dec = stardata->dDec / 100.0;
222  Parallax = 0.0;
223  Multiplicity = 0;
224  Variability = 0;
225  updateID = updateNumID = 0;
226  B = stardata->B / 1000.0;
227  V = stardata->V / 1000.0;
228  lastPrecessJD = J2000;
229 }
230 
231 void StarObject::setNames(const QString &name, const QString &name2)
232 {
233  QString lname;
234 
235  setName(name);
236 
237  setName2(name2);
238 
239  if (hasName() && name.startsWith(QLatin1String("HD")) == false)
240  {
241  lname = name;
242  if (hasName2())
243  lname += " (" + gname() + ')';
244  }
245  else if (hasName2())
246  lname = gname();
247  setLongName(lname);
248 }
250 {
251 #ifdef KSTARS_LITE
252  Q_UNUSED(pmenu)
253 #else
254  pmenu->createStarMenu(this);
255 #endif
256 }
257 
258 void StarObject::updateCoords(const KSNumbers *num, bool, const CachingDms *, const CachingDms *, bool)
259 {
260 //Correct for proper motion of stars. Determine RA and Dec offsets.
261 //Proper motion is given im milliarcsec per year by the pmRA() and pmDec() functions.
262 //That is numerically identical to the number of arcsec per millenium, so multiply by
263 //KSNumbers::julianMillenia() to find the offsets in arcsec.
264 
265 // Correction: The method below computes the proper motion before the
266 // precession. If we precessed first then the direction of the proper
267 // motion correction would depend on how far we've precessed. -jbb
268 #ifdef PROFILE_UPDATECOORDS
269  std::clock_t start, stop;
270  start = std::clock();
271 #endif
272  CachingDms saveRA = ra0(), saveDec = dec0();
273  CachingDms newRA, newDec;
274 
275  getIndexCoords(num, newRA, newDec);
276 
277  setRA0(newRA);
278  setDec0(newDec);
280  setRA0(saveRA);
281  setDec0(saveDec);
282 
283 #ifdef PROFILE_UPDATECOORDS
284  stop = std::clock();
285  updateCoordsCpuTime += double(stop - start) / double(CLOCKS_PER_SEC);
286  ++starsUpdated;
287 #endif
288 }
289 
291 {
292  static double pmms;
293 
294  // =================== NOTE: CODE DUPLICATION ====================
295  // If you modify this, please also modify the other getIndexCoords
296  // ===============================================================
297  //
298  // Reason for code duplication is as follows:
299  //
300  // This method is designed to use CachingDms, i.e. we know we are
301  // going to use the sine and cosine of the returned values.
302  //
303  // The other method is designed to avoid CachingDms and try to
304  // compute as little trigonometry as possible when the ra/dec has
305  // to be returned in double (used in SkyMesh::indexStar() for
306  // example)
307  //
308  // Thus, the philosophy of writing code is different. Granted, we
309  // don't need to optimize for the smaller star catalogs (which use
310  // SkyMesh::indexStar()), but it is nevertheless a good idea,
311  // given that getIndexCoords() shows up in callgrind as one of the
312  // slightly more expensive operations.
313 
314  // Old, Incorrect Proper motion Computation. We retain this in a
315  // comment because we might want to use it to come up with a
316  // linear approximation that's faster.
317  // double dra = pmRA() * num->julianMillenia() / ( cos( dec0().radians() ) * 3600.0 );
318  // double ddec = pmDec() * num->julianMillenia() / 3600.0;
319 
320 
321  pmms = pmMagnitudeSquared();
322 
323  if (std::isnan(pmms) || pmms * num->julianMillenia() * num->julianMillenia() < .01)
324  {
325  // Ignore corrections
326  ra = ra0();
327  dec = dec0();
328  return false;
329  }
330 
331  /*
332 
333  // Proper Motion Correction should be implemented as motion along a great
334  // circle passing through the given (ra0, dec0) in a direction of
335  // atan2( pmRA(), pmDec() ) to an angular distance given by the Magnitude of
336  // PM times the number of Julian millenia since J2000.0
337 
338  double pm = pmMagnitude() * num->julianMillenia(); // Proper Motion in arcseconds
339 
340  double dir0 = ((pm > 0) ? atan2(pmRA(), pmDec()) : atan2(-pmRA(), -pmDec())); // Bearing, in radian
341 
342  if (pm < 0)
343  pm = -pm;
344 
345  double dst = (pm * M_PI / (180.0 * 3600.0));
346  // double phi = M_PI / 2.0 - dec0().radians();
347 
348  // Note: According to callgrind, dms::dms() + dms::setRadians()
349  // takes ~ 40 CPU cycles, whereas, the advantage afforded by using
350  // sincos() instead of sin() and cos() calls seems to be about 30
351  // CPU cycles.
352 
353  // So it seems like it is not worth turning dir0 and dst into dms
354  // objects and using SinCos(). However, caching the values of sin
355  // and cos if we are going to reuse them avoids expensive (~120
356  // CPU cycle) recomputation!
357  CachingDms lat1, dtheta;
358  double sinDst = sin(dst), cosDst = cos(dst);
359  lat1.setUsing_asin(dec0().sin() * cosDst + dec0().cos() * sinDst * cos(dir0));
360  dtheta.setUsing_atan2(sin(dir0) * sinDst * dec0().cos(), cosDst - dec0().sin() * lat1.sin());
361 
362  ra = ra0() + dtheta; // Use operator + to avoid trigonometry
363  dec = lat1; // Need variable lat1 because dec may refer to dec0, so cannot construct result in-place
364 
365  */
366 
367  // Use the formula given in Seidelmann (Explanatory Supplement to
368  // the Astronomical Almanac) instead. The formulas used here are
369  // the combination of (3.23-1), (3.23-3), (3.23-5). Not only does
370  // it reduce trigonometry use, it is more likely to be correct
371  // than the stuff we came up with on our own above
372 
373  // Although it is not explained in the above reference, a formula
374  // that reduces to α' = α + μ_α * t must have μ_α be the rate of
375  // change of the angle at the center of the declination circle,
376  // and not the rate of change of arclength, i.e. μ_α must _not_
377  // include the cos(δ) factor. I have checked that the formulas
378  // used here do reduce to the above, and therefore expect μ_α =
379  // pmRa / cos(δ)
380 
381  double cosDec, sinDec, cosRa, sinRa;
382  double scale = num->julianMillenia() * (M_PI / (180.0 * 3600.0));
383  dec0().SinCos(sinDec, cosDec);
384  ra0().SinCos(sinRa, cosRa);
385 
386  // Note: Below assumes that pmRA is already pre-scaled by cos(delta), as it is for Hipparcos
387  double net_pmRA = pmRA() * scale, net_pmDec = pmDec() * scale;
388 
389  double x0 = cosDec * cosRa, y0 = cosDec * sinRa, z0 = sinDec;
390  double dX = - net_pmRA * sinRa - net_pmDec * sinDec * cosRa;
391  double dY = net_pmRA * cosRa - net_pmDec * sinDec * sinRa;
392  double dZ = net_pmDec * cosDec;
393  double x = x0 + dX, y = y0 + dY, z = z0 + dZ;
394 
395  ra.setUsing_atan2(y, x);
396 
397  // Note: dec = asin(z) is a poor choice, because we aren't
398  // guaranteed that (x, y, z) lies on the unit sphere due to the
399  // first-order approximation. Therefore, we must "project" out any
400  // change in the length of the vector to get our best estimate,
401  // and this is achieved by using atan. In fact atan gives the
402  // least-squares estimate for an angle given both its sin and
403  // cosine components.
404  dec.setUsing_atan2(z, sqrt(x * x + y * y));
405 
406  return true;
407 }
408 
409 bool StarObject::getIndexCoords(const KSNumbers *num, double *ra, double *dec)
410 {
411  static double pmms;
412 
413  // =================== NOTE: CODE DUPLICATION ====================
414  // If you modify this, please also modify the other getIndexCoords
415  // ===============================================================
416  //
417  // Reason for code duplication is as follows:
418  //
419  // This method is designed to avoid CachingDms and try to compute
420  // as little trigonometry as possible when the ra/dec has to be
421  // returned in double (used in SkyMesh::indexStar() for example)
422  //
423  // The other method is designed to use CachingDms, i.e. we know we
424  // are going to use the sine and cosine of the returned values.
425  //
426  // Thus, the philosophy of writing code is different. Granted, we
427  // don't need to optimize for the smaller star catalogs (which use
428  // SkyMesh::indexStar()), but it is nevertheless a good idea,
429  // given that getIndexCoords() shows up in callgrind as one of the
430  // slightly more expensive operations.
431 
432  // Old, Incorrect Proper motion Computation. We retain this in a
433  // comment because we might want to use it to come up with a
434  // linear approximation that's faster.
435  // double dra = pmRA() * num->julianMillenia() / ( cos( dec0().radians() ) * 3600.0 );
436  // double ddec = pmDec() * num->julianMillenia() / 3600.0;
437 
438  // Proper Motion Correction should be implemented as motion along a great
439  // circle passing through the given (ra0, dec0) in a direction of
440  // atan2( pmRA(), pmDec() ) to an angular distance given by the Magnitude of
441  // PM times the number of Julian millenia since J2000.0
442 
443  pmms = pmMagnitudeSquared();
444 
445  if (std::isnan(pmms) || pmms * num->julianMillenia() * num->julianMillenia() < .01)
446  {
447  // Ignore corrections
448  *ra = ra0().Degrees();
449  *dec = dec0().Degrees();
450  return false;
451  }
452 
453  /*
454  double pm = pmMagnitude() * num->julianMillenia(); // Proper Motion in arcseconds
455 
456  double dir0 = ((pm > 0) ? atan2(pmRA(), pmDec()) : atan2(-pmRA(), -pmDec())); // Bearing, in radian
457 
458  (pm < 0) && (pm = -pm);
459 
460  double dst = (pm * M_PI / (180.0 * 3600.0));
461  // double phi = M_PI / 2.0 - dec0().radians();
462 
463  // Note: According to callgrind, dms::dms() + dms::setRadians()
464  // takes ~ 40 CPU cycles, whereas, the advantage afforded by using
465  // sincos() instead of sin() and cos() calls seems to be about 30
466  // CPU cycles.
467 
468  // So it seems like it is not worth turning dir0 and dst into dms
469  // objects and using SinCos(). However, caching the values of sin
470  // and cos if we are going to reuse them avoids expensive (~120
471  // CPU cycle) recomputation!
472  dms lat1, dtheta;
473  double sinDst = sin(dst), cosDst = cos(dst);
474  double sinLat1 = dec0().sin() * cosDst + dec0().cos() * sinDst * cos(dir0);
475  lat1.setRadians(asin(sinLat1));
476  dtheta.setRadians(atan2(sin(dir0) * sinDst * dec0().cos(), cosDst - dec0().sin() * sinLat1));
477 
478  // Using dms instead, to ensure that the numbers are in the right range.
479  dms finalRA(ra0().Degrees() + dtheta.Degrees());
480 
481  *ra = finalRA.Degrees();
482  *dec = lat1.Degrees();
483  */
484 
485 
486  // Although it is not explained in the above reference, a formula
487  // that reduces to α' = α + μ_α * t must have μ_α be the rate of
488  // change of the angle at the center of the declination circle,
489  // and not the rate of change of arclength, i.e. μ_α must _not_
490  // include the cos(δ) factor. I have checked that the formulas
491  // used in Seidelmann do reduce to the above, and therefore expect
492  // μ_α = pmRa / cos(δ). Therefore, I'm absorbing the factor in the
493  // implementation here.
494 
495  double cosDec, sinDec, cosRa, sinRa;
496  double scale = num->julianMillenia() * (M_PI / (180.0 * 3600.0));
497  dec0().SinCos(sinDec, cosDec);
498  ra0().SinCos(sinRa, cosRa);
499 
500  // Note: Below assumes that pmRA is already pre-scaled by cos(delta), as it is for Hipparcos
501  double net_pmRA = pmRA() * scale, net_pmDec = pmDec() * scale;
502 
503  double x0 = cosDec * cosRa, y0 = cosDec * sinRa, z0 = sinDec;
504  double dX = - net_pmRA * sinRa - net_pmDec * sinDec * cosRa;
505  double dY = net_pmRA * cosRa - net_pmDec * sinDec * sinRa;
506  double dZ = net_pmDec * cosDec;
507  double x = x0 + dX, y = y0 + dY, z = z0 + dZ;
508 
509  dms alpha, delta;
510  alpha.setRadians(atan2(y, x));
511 
512  // Note: dec = asin(z) is a poor choice, because we aren't
513  // guaranteed that (x, y, z) lies on the unit sphere due to the
514  // first-order approximation. Therefore, we must "project" out any
515  // change in the length of the vector to get our best estimate,
516  // and this is achieved by using atan. In fact atan gives the
517  // least-squares estimate for an angle given both its sin and
518  // cosine components.
519  delta.setRadians(atan2(z, sqrt(x * x + y * y)));
520  *ra = alpha.reduce().Degrees();
521  *dec = delta.Degrees();
522 
523  return true;
524 }
525 
527 {
528  static KStarsData *data = KStarsData::Instance();
529 
530  if (updateNumID != data->updateNumID())
531  {
532  // TODO: This can be optimized and reorganized further in a better manner.
533  // Maybe we should do this only for stars, since this is really a slow step only for stars
534  Q_ASSERT(std::isfinite(lastPrecessJD));
535 
536  if (Options::alwaysRecomputeCoordinates() || (Options::useRelativistic() && checkBendLight()) ||
537  std::abs(lastPrecessJD - data->updateNum()->getJD()) >= 0.00069444) // Update is once per solar minute
538  {
539  // Short circuit right here, if recomputing coordinates is not required. NOTE: POTENTIALLY DANGEROUS
540  updateCoords(data->updateNum());
541  }
542 
543  updateNumID = data->updateNumID();
544  }
545  EquatorialToHorizontal(data->lst(), data->geo()->lat());
546  updateID = data->updateID();
547 }
548 
550 {
551  return QString(QByteArray(SpType, 2));
552 }
553 
554 char StarObject::spchar() const
555 {
556  return SpType[0];
557 }
558 
559 QString StarObject::gname(bool useGreekChars) const
560 {
561  if (!name2().isEmpty())
562  return greekLetter(useGreekChars) + ' ' + constell();
563  else
564  return QString();
565 }
566 
568 {
569  QString code = name2().left(3);
570  QString letter = code; //in case genitive name is *not* a Greek letter
571  int alpha = 0x03B1;
572 
573  auto checkAndGreekify = [&code, gchar, alpha, &letter](const QString &abbrev, int unicodeOffset,
574  const QString &expansion) {
575  if (code == abbrev)
576  gchar ? letter = QString(QChar(alpha + unicodeOffset)) : letter = expansion;
577  };
578 
579  checkAndGreekify("alp", 0, i18n("alpha"));
580  checkAndGreekify("bet", 1, i18n("beta"));
581  checkAndGreekify("gam", 2, i18n("gamma"));
582  checkAndGreekify("del", 3, i18n("delta"));
583  checkAndGreekify("eps", 4, i18n("epsilon"));
584  checkAndGreekify("zet", 5, i18n("zeta"));
585  checkAndGreekify("eta", 6, i18n("eta"));
586  checkAndGreekify("the", 7, i18n("theta"));
587  checkAndGreekify("iot", 8, i18n("iota"));
588  checkAndGreekify("kap", 9, i18n("kappa"));
589  checkAndGreekify("lam", 10, i18n("lambda"));
590  checkAndGreekify("mu ", 11, i18n("mu"));
591  checkAndGreekify("nu ", 12, i18n("nu"));
592  checkAndGreekify("xi ", 13, i18n("xi"));
593  checkAndGreekify("omi", 14, i18n("omicron"));
594  checkAndGreekify("pi ", 15, i18n("pi"));
595  checkAndGreekify("rho", 16, i18n("rho"));
596  //there are two unicode symbols for sigma;
597  //skip the first one, the second is more widely used
598  checkAndGreekify("sig", 18, i18n("sigma"));
599  checkAndGreekify("tau", 19, i18n("tau"));
600  checkAndGreekify("ups", 20, i18n("upsilon"));
601  checkAndGreekify("phi", 21, i18n("phi"));
602  checkAndGreekify("chi", 22, i18n("chi"));
603  checkAndGreekify("psi", 23, i18n("psi"));
604  checkAndGreekify("ome", 24, i18n("omega"));
605 
606  if (name2().length() && name2().mid(3, 1) != " ")
607  letter += '[' + name2().mid(3, 1) + ']';
608 
609  return letter;
610 }
611 
612 // FIXME: Move this somewhere else, make this static, and give it a better name.
613 // Mostly for code cleanliness. Also, try to put it in a DB.
615 {
616  QString code = name2().mid(4, 3);
617 
618  return KSUtils::constGenetiveFromAbbrev(code);
619 }
620 
621 // The two routines below seem overly complicated but at least they are doing
622 // the right thing now. Please resist the temptation to simplify them unless
623 // you are prepared to ensure there is no ugly label overlap for all 8 cases
624 // they deal with ( drawName x DrawMag x star-has-name). -jbb
625 
626 QString StarObject::nameLabel(bool drawName, bool drawMag) const
627 {
628  QString sName;
629 
630  if (drawName)
631  {
632  QString translation = translatedName();
633  if (translation != i18n("star") && !translation.startsWith("HD"))
634  sName = translation;
635  else if (!gname().trimmed().isEmpty())
636  sName = gname(true);
637  else
638  {
639  if (drawMag)
640  return ('[' + QLocale().toString(mag(), 'f', 1) + "m]");
641  }
642  if (!drawMag)
643  return sName;
644  else
645  return sName + " [" + QLocale().toString(mag(), 'f', 1) + "m]";
646  }
647  return ('[' + QLocale().toString(mag(), 'f', 1) + "m]");
648 }
649 
650 //If this works, we can maybe get rid of customLabel() and nameLabel()??
652 {
653  return nameLabel(Options::showStarNames(), Options::showStarMagnitudes());
654 }
655 
657 {
658  return (6. + 0.5 * (5.0 - mag()) + 0.01 * (Options::zoomFactor() / 500.));
659 }
660 
662 {
663  // mag takes 10 bit
664  SkyObject::UID m = mag() * 10;
665  if (m < 0)
666  m = 0;
667 
668  // Both RA & dec fits in 24-bits
669  SkyObject::UID ra = ra0().Degrees() * 36000;
670  SkyObject::UID dec = (ra0().Degrees() + 91) * 36000;
671 
672  Q_ASSERT("Magnitude is expected to fit into 10bits" && m >= 0 && m < (1 << 10));
673  Q_ASSERT("RA should fit into 24bits" && ra >= 0 && ra < (1 << 24));
674  Q_ASSERT("Dec should fit into 24bits" && dec >= 0 && dec < (1 << 24));
675 
676  return (SkyObject::UID_STAR << 60) | (m << 48) | (ra << 24) | dec;
677 }
static const UID UID_STAR
Kind of UID.
Definition: skyobject.h:52
QString greekLetter(bool useGreekChars=true) const
Returns the greek letter portion of the star's genetive name.
Definition: starobject.cpp:567
double julianMillenia() const
Definition: ksnumbers.h:94
QString number(int n, int base)
QString name(void) const override
If star is unnamed return "star" otherwise return the name.
Definition: starobject.h:130
QString nameLabel(bool drawName, bool drawMag) const
returns the name, the magnitude or both.
Definition: starobject.cpp:626
A 32-byte Structure that holds star data.
Definition: stardata.h:17
void setUsing_atan2(const double &y, const double &x)
Sets the angle using atan2()
Definition: cachingdms.cpp:62
a dms subclass that caches its sine and cosine values every time the angle is changed.
Definition: cachingdms.h:18
void setDec0(dms d)
Sets Dec0, the catalog Declination.
Definition: skypoint.h:119
QString labelString() const override
Definition: starobject.cpp:651
bool getIndexCoords(const KSNumbers *num, CachingDms &ra, CachingDms &dec)
Fills ra and dec with the coordinates of the star with the proper motion correction but without preci...
Definition: starobject.cpp:290
void SinCos(double &s, double &c) const
Get the sine and cosine together.
Definition: cachingdms.h:175
CachingDms * lst()
Definition: kstarsdata.h:224
void setNames(const QString &name, const QString &name2)
Sets the name, genetive name, and long name.
Definition: starobject.cpp:231
QString translatedName() const
Definition: skyobject.h:148
float mag() const
Definition: skyobject.h:206
QByteArray toLatin1() const const
void setRA0(dms r)
Sets RA0, the catalog Right Ascension.
Definition: skypoint.h:94
void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat)
Determine the (Altitude, Azimuth) coordinates of the SkyPoint from its (RA, Dec) coordinates,...
Definition: skypoint.cpp:77
qint32 RA
Raw signed 32-bit RA value.
Definition: stardata.h:19
qint64 UID
Type for Unique object IDenticator.
Definition: skyobject.h:49
long double getJD() const
Definition: ksnumbers.h:128
void updateCoords(const KSNumbers *num, bool includePlanets=true, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, bool forceRecompute=false) override
Determine the current coordinates (RA, Dec) from the catalog coordinates (RA0, Dec0),...
Definition: starobject.cpp:258
QString gname(bool useGreekChars=true) const
Returns the genetive name of the star.
Definition: starobject.cpp:559
virtual void updateCoords(const KSNumbers *num, bool includePlanets=true, const CachingDms *lat=nullptr, const CachingDms *LST=nullptr, bool forceRecompute=false)
Determine the current coordinates (RA, Dec) from the catalog coordinates (RA0, Dec0),...
Definition: skypoint.cpp:582
QString i18n(const char *text, const TYPE &arg...)
Store several time-dependent astronomical quantities.
Definition: ksnumbers.h:42
const CachingDms & dec() const
Definition: skypoint.h:269
const CachingDms * lat() const
Definition: geolocation.h:70
void setMag(float m)
Set the object's sorting magnitude.
Definition: skyobject.h:403
subclass of SkyObject specialized for stars.
Definition: starobject.h:32
GeoLocation * geo()
Definition: kstarsdata.h:230
QString sptype(void) const
Returns entire spectral type string.
Definition: starobject.cpp:549
void initPopupMenu(KSPopupMenu *pmenu) override
Initialize the popup menut.
Definition: starobject.cpp:249
QString toString(qlonglong i) const const
double pmRA() const
Definition: starobject.h:224
StarObject(dms r=dms(0.0), dms d=dms(0.0), float m=0.0, const QString &n=QString(), const QString &n2=QString(), const QString &sptype="--", double pmra=0.0, double pmdec=0.0, double par=0.0, bool mult=false, bool var=false, int hd=0)
Constructor.
Definition: starobject.cpp:57
void setName(const QString &name)
Set the object's primary name.
Definition: skyobject.h:417
void init(const StarData *stardata)
Initializes a StarObject to given data.
Definition: starobject.cpp:133
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
An angle, stored as degrees, but expressible in many ways.
Definition: dms.h:37
virtual void setRadians(const double &Rad)
Set angle according to the argument, in radians.
Definition: dms.h:333
char spchar() const
Returns just the first character of the spectral type string.
Definition: starobject.cpp:554
double labelOffset() const override
Definition: starobject.cpp:656
qint32 HD
unsigned 32-bit Henry Draper Index.
Definition: stardata.h:24
QString constell(void) const
Definition: starobject.cpp:614
const CachingDms & ra() const
Definition: skypoint.h:263
StarObject * clone() const override
Create copy of object.
Definition: starobject.cpp:126
const CachingDms & dec0() const
Definition: skypoint.h:257
QString left(int n) const const
const double & Degrees() const
Definition: dms.h:141
qint16 mag
signed 16-bit raw magnitude.
Definition: stardata.h:25
bool checkBendLight()
Check if this sky point is close enough to the sun for gravitational lensing to be significant.
Definition: skypoint.cpp:399
A 16-byte structure that holds star data for really faint stars.
bool hasName() const
Definition: starobject.h:120
double pmMagnitudeSquared() const
returns the square of the magnitude of the proper motion correction in (milliarcsec/year)^2
Definition: starobject.h:206
const CachingDms & ra0() const
Definition: skypoint.h:251
void setDec(dms d)
Sets Dec, the current Declination.
Definition: skypoint.h:169
void JITupdate()
added for JIT updates from both StarComponent and ConstellationLines
Definition: starobject.cpp:526
qint32 Dec
Raw signed 32-bit DE value.
Definition: stardata.h:20
void setRA(dms &r)
Sets RA, the current Right Ascension.
Definition: skypoint.h:144
const dms reduce() const
return the equivalent angle between 0 and 360 degrees.
Definition: dms.cpp:251
QString name2(void) const
Definition: skyobject.h:156
void createStarMenu(StarObject *star)
Create a popup menu for a star.
QString mid(int position, int n) const const
void setName2(const QString &name2=QString())
Set the object's secondary name.
Definition: skyobject.h:423
UID getUID() const override
Return UID for object.
Definition: starobject.cpp:661
double pmDec() const
Definition: starobject.h:227
Information about an object in the sky.
Definition: skyobject.h:41
void setType(int t)
Set the object's type identifier to the argument.
Definition: skyobject.h:195
static double reindexInterval(double pm)
returns the reindex interval (in centuries!) for the given magnitude of proper motion (in milliarcsec...
Definition: starobject.cpp:46
void setLongName(const QString &longname=QString())
Set the object's long name.
Definition: skyobject.cpp:76
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Fri Sep 29 2023 03:56:59 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.