Kstars

skyobject.cpp
1/*
2 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "skyobject.h"
8
9#include "geolocation.h"
10#include "ksnumbers.h"
11#include "kspaths.h"
12#ifdef KSTARS_LITE
13#include "skymaplite.h"
14#else
15#include "kspopupmenu.h"
16#include "skymap.h"
17#endif
18#include "kstarsdata.h"
19#include "Options.h"
20#include "starobject.h"
21#include "skycomponents/skylabeler.h"
22
23
26const SkyObject::UID SkyObject::UID_GALAXY = 1;
27const SkyObject::UID SkyObject::UID_DEEPSKY = 2;
28const SkyObject::UID SkyObject::UID_SOLARSYS = 3;
29
30SkyObject::SkyObject(int t, dms r, dms d, float m, const QString &n, const QString &n2, const QString &lname)
31 : SkyPoint(r, d)
32{
33 setType(t);
34 sortMagnitude = m;
35 setName(n);
36 setName2(n2);
37 setLongName(lname);
38}
39
40SkyObject::SkyObject(int t, double r, double d, float m, const QString &n, const QString &n2, const QString &lname)
41 : SkyPoint(r, d)
42{
43 setType(t);
44 sortMagnitude = m;
45 setName(n);
46 setName2(n2);
47 setLongName(lname);
48}
49
51{
52 Q_ASSERT(typeid(this) == typeid(static_cast<const SkyObject *>(this))); // Ensure we are not slicing a derived class
53 return new SkyObject(*this);
54}
55
57{
58#if defined(KSTARS_LITE)
59 Q_UNUSED(pos)
60 Q_UNUSED(pmenu);
61#else
62 initPopupMenu(pmenu);
63 pmenu->popup(pos);
64#endif
65}
66
68{
69#ifdef KSTARS_LITE
70 Q_UNUSED(pmenu)
71#else
72 pmenu->createEmptyMenu(this);
73#endif
74}
75
76void SkyObject::setLongName(const QString &longname)
77{
78 if (longname.isEmpty())
79 {
80 if (hasName())
81 LongName = name();
82 else if (hasName2())
83 LongName = name2();
84 else
85 LongName.clear();
86 }
87 else
88 {
89 LongName = longname;
90 }
91}
92
93QTime SkyObject::riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact) const
94{
95 // If this object does not rise or set, return an invalid time
96 SkyPoint p = recomputeCoords(dt, geo);
97 if (p.checkCircumpolar(geo->lat()))
98 return QTime();
99
100 //First of all, if the object is below the horizon at date/time dt, adjust the time
101 //to bring it above the horizon
102 KStarsDateTime dt2 = dt;
103 dms lst(geo->GSTtoLST(dt.gst()));
104 p.EquatorialToHorizontal(&lst, geo->lat());
105 if (p.alt().Degrees() < 0.0)
106 {
107 if (p.az().Degrees() < 180.0) //object has not risen yet
108 {
109 dt2 = dt.addSecs(12. * 3600.); // Move forward 12 hours, to a time when it has already risen
110 }
111 else //object has already set
112 {
113 dt2 = dt.addSecs(-12. * 3600.); // Move backward 12 hours, to a time when it has not yet set
114 }
115 }
116 // The addition / subtraction of 12 hours ensures that we always
117 // compute the _closest_ rise time and the _closest_ set time to
118 // the current time.
119
120 QTime rstUt = riseSetTimeUT(dt2, geo, rst, exact);
121 if (!rstUt.isValid())
122 return QTime();
123
124 return geo->UTtoLT(KStarsDateTime(dt2.date(), rstUt)).time();
125}
126
127QTime SkyObject::riseSetTimeUT(const KStarsDateTime &dt, const GeoLocation *geo, bool riseT, bool exact) const
128{
129 // First trial to calculate UT
130 QTime UT = auxRiseSetTimeUT(dt, geo, &ra(), &dec(), riseT);
131
132 // We iterate once more using the calculated UT to compute again
133 // the ra and dec for that time and hence the rise/set time.
134 // Also, adjust the date by +/- 1 day, if necessary
135
136 // By adding this +/- 1 day, we are double-checking that the
137 // reported rise-time is the _already_ (last) risen time, and that
138 // the reported set-time is the _future_ (next) set time
139 //
140 // However, issues with this are taken care of in
141 // SkyObject::riseSetTime()
142
143 KStarsDateTime dt0 = dt;
144 dt0.setTime(UT);
145 if (riseT && dt0 > dt)
146 {
147 dt0 = dt0.addDays(-1);
148 }
149 else if (!riseT && dt0 < dt)
150 {
151 dt0 = dt0.addDays(1);
152 }
153
154 SkyPoint sp = recomputeCoords(dt0, geo);
155 UT = auxRiseSetTimeUT(dt0, geo, &sp.ra(), &sp.dec(), riseT);
156
157 if (exact)
158 {
159 // We iterate a second time (For the Moon the second iteration changes
160 // aprox. 1.5 arcmin the coordinates).
161 dt0.setTime(UT);
162 sp = recomputeCoords(dt0, geo);
163 UT = auxRiseSetTimeUT(dt0, geo, &sp.ra(), &sp.dec(), riseT);
164 }
165
166 return UT;
167}
168
169QTime SkyObject::auxRiseSetTimeUT(const KStarsDateTime &dt, const GeoLocation *geo, const dms *righta, const dms *decl,
170 bool riseT) const
171{
172 dms LST = auxRiseSetTimeLST(geo->lat(), righta, decl, riseT);
173 return dt.GSTtoUT(geo->LSTtoGST(LST));
174}
175
176dms SkyObject::auxRiseSetTimeLST(const dms *gLat, const dms *righta, const dms *decl, bool riseT) const
177{
178 dms h0 = elevationCorrection();
179 double H = approxHourAngle(&h0, gLat, decl);
180 dms LST;
181
182 if (riseT)
183 LST.setH(24.0 + righta->Hours() - H / 15.0);
184 else
185 LST.setH(righta->Hours() + H / 15.0);
186
187 return LST.reduce();
188}
189
190dms SkyObject::riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool riseT) const
191{
192 dms Azimuth;
193 double AltRad, AzRad;
194 double sindec, cosdec, sinlat, coslat, sinHA, cosHA;
195 double sinAlt, cosAlt;
196
197 QTime UT = riseSetTimeUT(dt, geo, riseT);
198 KStarsDateTime dt0 = dt;
199 dt0.setTime(UT);
200 SkyPoint sp = recomputeCoords(dt0, geo);
201
202 dms LST = auxRiseSetTimeLST(geo->lat(), &sp.ra0(), &sp.dec0(), riseT);
203 dms HourAngle = dms(LST.Degrees() - sp.ra0().Degrees());
204
205 geo->lat()->SinCos(sinlat, coslat);
206 dec().SinCos(sindec, cosdec);
207 HourAngle.SinCos(sinHA, cosHA);
208
209 sinAlt = sindec * sinlat + cosdec * coslat * cosHA;
210 AltRad = asin(sinAlt);
211 cosAlt = cos(AltRad);
212
213 AzRad = acos((sindec - sinlat * sinAlt) / (coslat * cosAlt));
214 if (sinHA > 0.0)
215 AzRad = 2.0 * dms::PI - AzRad; // resolve acos() ambiguity
216 Azimuth.setRadians(AzRad);
217
218 return Azimuth;
219}
220
222{
223 dms LST = geo->GSTtoLST(dt.gst());
224
225 //dSec is the number of seconds until the object transits.
226 dms HourAngle = dms(LST.Degrees() - ra().Degrees());
227 int dSec = static_cast<int>(-3600. * HourAngle.Degrees() / 15.0);
228
229 //dt0 is the first guess at the transit time.
230 KStarsDateTime dt0 = dt.addSecs(dSec);
231 //recompute object's position at UT0 and then find transit time of this refined position
232 SkyPoint sp = recomputeCoords(dt0, geo);
233 HourAngle = dms(LST.Degrees() - sp.ra().Degrees());
234 dSec = static_cast<int>(-3600. * HourAngle.Degrees() / 15.0);
235
236 return dt.addSecs(dSec).time();
237}
238
240{
241 return geo->UTtoLT(KStarsDateTime(dt.date(), transitTimeUT(dt, geo))).time();
242}
243
245{
246 KStarsDateTime dt0 = dt;
247 dt0.setTime(transitTimeUT(dt, geo));
248 SkyPoint sp = recomputeCoords(dt0, geo);
249
250 double delta = 90 - geo->lat()->Degrees() + sp.dec().Degrees();
251 if (delta > 90)
252 delta = 180 - delta;
253 return dms(delta);
254}
255
256double SkyObject::approxHourAngle(const dms *h0, const dms *gLat, const dms *dec) const
257{
258 double sh0 = sin(h0->radians());
259 double r = (sh0 - sin(gLat->radians()) * sin(dec->radians())) / (cos(gLat->radians()) * cos(dec->radians()));
260
261 double H = acos(r) / dms::DegToRad;
262
263 return H;
264}
265
266dms SkyObject::elevationCorrection(void) const
267{
268 /* The atmospheric refraction at the horizon shifts altitude by
269 * - 34 arcmin = 0.5667 degrees. This value changes if the observer
270 * is above the horizon, or if the weather conditions change much.
271 *
272 * For the sun we have to add half the angular sie of the body, since
273 * the sunset is the time the upper limb of the sun disappears below
274 * the horizon, and dawn, when the upper part of the limb appears
275 * over the horizon. The angular size of the sun = angular size of the
276 * moon = 31' 59''.
277 *
278 * So for the sun the correction is = -34 - 16 = 50 arcmin = -0.8333
279 *
280 * This same correction should be applied to the moon however parallax
281 * is important here. Meeus states that the correction should be
282 * 0.7275 P - 34 arcmin, where P is the moon's horizontal parallax.
283 * He proposes a mean value of 0.125 degrees if no great accuracy
284 * is needed.
285 */
286
287 if (name() == i18n("Sun") || name() == i18n("Moon") || name() == i18n("Earth Shadow"))
288 return dms(-0.8333);
289 // else if ( name() == "Moon" )
290 // return dms(0.125);
291 else // All sources point-like.
292 return dms(-0.5667);
293}
294
296{
297 // Create a clone
298 SkyObject *c = this->clone();
299
300 // compute coords of the copy for new time jd
301 KSNumbers num(dt.djd());
302
303 // Note: isSolarSystem() below should give the same result on this
304 // and c. The only very minor reason to prefer this is so that we
305 // have an additional layer of warnings about subclasses of
306 // KSPlanetBase that do not implement SkyObject::clone() due to
307 // the passing of lat and LST
308
309 if (isSolarSystem() && geo)
310 {
311 CachingDms LST = geo->GSTtoLST(dt.gst());
312 c->updateCoords(&num, true, geo->lat(), &LST);
313 }
314 else
315 {
316 c->updateCoords(&num);
317 }
318
319 // Transfer the coordinates into a SkyPoint
320 SkyPoint p = *c;
321
322 // Delete the clone
323 delete c;
324
325 // Return the SkyPoint
326 return p;
327}
328
330{
331 Q_ASSERT(geo);
332 SkyPoint ret = recomputeCoords(dt, geo);
333 CachingDms LST = geo->GSTtoLST(dt.gst());
334 ret.EquatorialToHorizontal(&LST, geo->lat());
335 return ret;
336}
337
339{
340 switch (t)
341 {
342 case STAR:
343 return i18n("Star");
344 case CATALOG_STAR:
345 return i18n("Catalog Star");
346 case PLANET:
347 return i18n("Planet");
348 case OPEN_CLUSTER:
349 return i18n("Open Cluster");
350 case GLOBULAR_CLUSTER:
351 return i18n("Globular Cluster");
352 case GASEOUS_NEBULA:
353 return i18n("Gaseous Nebula");
354 case PLANETARY_NEBULA:
355 return i18n("Planetary Nebula");
356 case SUPERNOVA_REMNANT:
357 return i18n("Supernova Remnant");
358 case GALAXY:
359 return i18n("Galaxy");
360 case COMET:
361 return i18n("Comet");
362 case ASTEROID:
363 return i18n("Asteroid");
364 case CONSTELLATION:
365 return i18n("Constellation");
366 case MOON:
367 return i18n("Moon");
368 case GALAXY_CLUSTER:
369 return i18n("Galaxy Cluster");
370 case SATELLITE:
371 return i18n("Satellite");
372 case SUPERNOVA:
373 return i18n("Supernova");
374 case RADIO_SOURCE:
375 return i18n("Radio Source");
376 case ASTERISM:
377 return i18n("Asterism");
378 case DARK_NEBULA:
379 return i18n("Dark Nebula");
380 case QUASAR:
381 return i18n("Quasar");
382 case MULT_STAR:
383 return i18n("Multiple Star");
384 default:
385 return i18n("Unknown Type");
386 }
387}
388
390{
391 return typeName(Type);
392}
393
395{
396 QString message = imageTitle;
397
398 //HST Image
399 if (imageTitle == i18n("Show HST Image") || imageTitle.contains("HST"))
400 {
401 message = i18n("%1: Hubble Space Telescope, operated by STScI for NASA [public domain]", longname());
402
403 //Spitzer Image
404 }
405 else if (imageTitle.contains(i18n("Show Spitzer Image")))
406 {
407 message = i18n("%1: Spitzer Space Telescope, courtesy NASA/JPL-Caltech [public domain]", longname());
408
409 //SEDS Image
410 }
411 else if (imageTitle == i18n("Show SEDS Image"))
412 {
413 message = i18n("%1: SEDS, http://www.seds.org [free for non-commercial use]", longname());
414
415 //Kitt Peak AOP Image
416 }
417 else if (imageTitle == i18n("Show KPNO AOP Image"))
418 {
419 message = i18n("%1: Advanced Observing Program at Kitt Peak National Observatory [free for non-commercial use; "
420 "no physical reproductions]",
421 longname());
422
423 //NOAO Image
424 }
425 else if (imageTitle.contains(i18n("Show NOAO Image")))
426 {
427 message =
428 i18n("%1: National Optical Astronomy Observatories and AURA [free for non-commercial use]", longname());
429
430 //VLT Image
431 }
432 else if (imageTitle.contains("VLT"))
433 {
434 message = i18n("%1: Very Large Telescope, operated by the European Southern Observatory [free for "
435 "non-commercial use; no reproductions]",
436 longname());
437
438 //All others
439 }
440 else if (imageTitle.startsWith(i18n("Show")))
441 {
442 message = imageTitle.mid(imageTitle.indexOf(" ") + 1); //eat first word, "Show"
443 message = longname() + ": " + message;
444 }
445
446 return message;
447}
448
450{
451 return translatedName();
452}
453
455{
456 return SkyLabeler::ZoomOffset();
457}
458
460{
461 return invalidUID;
462}
a dms subclass that caches its sine and cosine values every time the angle is changed.
Definition cachingdms.h:19
void SinCos(double &s, double &c) const
Get the sine and cosine together.
Definition cachingdms.h:175
Contains all relevant information for specifying a location on Earth: City Name, State/Province name,...
Definition geolocation.h:28
There are several time-dependent values used in position calculations, that are not specific to an ob...
Definition ksnumbers.h:43
The KStars Popup Menu.
Definition kspopupmenu.h:35
void createEmptyMenu(SkyPoint *nullObj)
Create a popup menu for empty sky.
Extension of QDateTime for KStars KStarsDateTime can represent the date/time as a Julian Day,...
KStarsDateTime addDays(int nd) const
Modify the Date/Time by adding a number of days.
QTime GSTtoUT(dms GST) const
Convert a given Greenwich Sidereal Time to Universal Time (=Greenwich Mean Time).
KStarsDateTime addSecs(double s) const
long double djd() const
void setTime(const QTime &t)
Assign the Time according to a QTime object.
static double ZoomOffset()
returns the zoom dependent label offset.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
Definition skyobject.h:42
void setName2(const QString &name2=QString())
Set the object's secondary name.
Definition skyobject.h:423
virtual void initPopupMenu(KSPopupMenu *pmenu)
Initialize the popup menut.
Definition skyobject.cpp:67
void setLongName(const QString &longname=QString())
Set the object's long name.
Definition skyobject.cpp:76
static const UID invalidUID
Invalid UID.
Definition skyobject.h:58
SkyPoint recomputeHorizontalCoords(const KStarsDateTime &dt, const GeoLocation *geo) const
Like recomputeCoords, but also calls EquatorialToHorizontal before returning.
virtual SkyObject * clone() const
Create copy of object.
Definition skyobject.cpp:50
SkyObject(int t=TYPE_UNKNOWN, dms r=dms(0.0), dms d=dms(0.0), float m=0.0, const QString &n=QString(), const QString &n2=QString(), const QString &lname=QString())
Constructor.
Definition skyobject.cpp:30
QString translatedName() const
Definition skyobject.h:148
void showPopupMenu(KSPopupMenu *pmenu, const QPoint &pos)
Show Type-specific popup menu.
Definition skyobject.cpp:56
dms riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool rst) const
static const UID UID_STAR
Kind of UID.
Definition skyobject.h:52
virtual QString labelString() const
QTime transitTimeUT(const KStarsDateTime &dt, const GeoLocation *geo) const
virtual QString name(void) const
Definition skyobject.h:145
dms transitAltitude(const KStarsDateTime &dt, const GeoLocation *geo) const
QString messageFromTitle(const QString &imageTitle) const
Given the Image title from a URL file, try to convert it to an image credit string.
bool isSolarSystem() const
Definition skyobject.h:217
void setName(const QString &name)
Set the object's primary name.
Definition skyobject.h:417
virtual QString longname(void) const
Definition skyobject.h:164
QString name2(void) const
Definition skyobject.h:156
qint64 UID
Type for Unique object IDenticator.
Definition skyobject.h:49
QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const
The same iteration technique described in riseSetTime() is used here.
virtual UID getUID() const
Return UID for object.
QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
Determine the time at which the point will rise or set.
Definition skyobject.cpp:93
QString typeName() const
void setType(int t)
Set the object's type identifier to the argument.
Definition skyobject.h:195
QTime riseSetTimeUT(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact=true) const
virtual double labelOffset() const
SkyPoint recomputeCoords(const KStarsDateTime &dt, const GeoLocation *geo=nullptr) const
The equatorial coordinates for the object on date dt are computed and returned, but the object's inte...
The sky coordinates of a point in the sky.
Definition skypoint.h:45
const CachingDms & dec() const
Definition skypoint.h:269
const CachingDms & ra0() const
Definition skypoint.h:251
bool checkCircumpolar(const dms *gLat) const
Check if this point is circumpolar at the given geographic latitude.
const CachingDms & ra() const
Definition skypoint.h:263
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
const dms & az() const
Definition skypoint.h:275
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
const dms & alt() const
Definition skypoint.h:281
const CachingDms & dec0() const
Definition skypoint.h:257
An angle, stored as degrees, but expressible in many ways.
Definition dms.h:38
double Hours() const
Definition dms.h:168
virtual void setH(const double &x)
Sets floating-point value of angle, in hours.
Definition dms.h:210
const dms reduce() const
return the equivalent angle between 0 and 360 degrees.
Definition dms.cpp:251
void SinCos(double &s, double &c) const
Compute Sine and Cosine of the angle simultaneously.
Definition dms.h:447
static constexpr double PI
PI is a const static member; it's public so that it can be used anywhere, as long as dms....
Definition dms.h:385
double radians() const
Express the angle in radians.
Definition dms.h:325
virtual void setRadians(const double &Rad)
Set angle according to the argument, in radians.
Definition dms.h:333
const double & Degrees() const
Definition dms.h:141
static constexpr double DegToRad
DegToRad is a const static member equal to the number of radians in one degree (dms::PI/180....
Definition dms.h:390
QString i18n(const char *text, const TYPE &arg...)
QDate date() const const
QTime time() const const
void popup(const QPoint &p, QAction *atAction)
void clear()
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString mid(qsizetype position, qsizetype n) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isValid(int h, int m, int s, int ms)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:38:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.