File indexing completed on 2024-04-28 11:25:23
0001 /* 0002 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "dms.h" 0010 #include "skypoint.h" 0011 0012 #include <KLocalizedString> 0013 0014 #include <QSharedDataPointer> 0015 #include <QString> 0016 #include <QStringList> 0017 0018 class QPoint; 0019 class GeoLocation; 0020 class KSPopupMenu; 0021 0022 namespace { 0023 constexpr const char *emptyString = ""; 0024 constexpr const char *unnamedString = I18N_NOOP("unnamed"); 0025 constexpr const char *unnamedObjectString = I18N_NOOP("unnamed object"); 0026 constexpr const char *starString = I18N_NOOP("star"); 0027 } 0028 0029 // Set the faintest sane magnitude to 36.0 (faintest visual magnitude visible with E-ELT, acc. to Wikipedia on Apparent Magnitude.) 0030 constexpr const float FAINTEST_MAGNITUDE = 36.0; 0031 0032 /** 0033 * @class SkyObject 0034 * Provides all necessary information about an object in the sky: 0035 * its coordinates, name(s), type, magnitude, and QStringLists of 0036 * URLs for images and webpages regarding the object. 0037 * @short Information about an object in the sky. 0038 * @author Jason Harris 0039 * @version 1.0 0040 */ 0041 class SkyObject : public SkyPoint 0042 { 0043 public: 0044 /** 0045 * @short Type for Unique object IDenticator. 0046 * 0047 * Each object has unique ID (UID). For different objects UIDs must be different. 0048 */ 0049 typedef qint64 UID; 0050 0051 /** @short Kind of UID */ 0052 static const UID UID_STAR; 0053 static const UID UID_GALAXY; 0054 static const UID UID_DEEPSKY; 0055 static const UID UID_SOLARSYS; 0056 0057 /** Invalid UID. Real sky object could not have such UID */ 0058 static const UID invalidUID; 0059 0060 /** 0061 * Constructor. Set SkyObject data according to arguments. 0062 * @param t Type of object 0063 * @param r catalog Right Ascension 0064 * @param d catalog Declination 0065 * @param m magnitude (brightness) 0066 * @param n Primary name 0067 * @param n2 Secondary name 0068 * @param lname Long name (common name) 0069 */ 0070 explicit SkyObject(int t = TYPE_UNKNOWN, dms r = dms(0.0), dms d = dms(0.0), float m = 0.0, 0071 const QString &n = QString(), const QString &n2 = QString(), const QString &lname = QString()); 0072 /** 0073 * Constructor. Set SkyObject data according to arguments. Differs from 0074 * above function only in data type of RA and Dec. 0075 * @param t Type of object 0076 * @param r catalog Right Ascension 0077 * @param d catalog Declination 0078 * @param m magnitude (brightness) 0079 * @param n Primary name 0080 * @param n2 Secondary name 0081 * @param lname Long name (common name) 0082 */ 0083 SkyObject(int t, double r, double d, float m = 0.0, const QString &n = QString(), const QString &n2 = QString(), 0084 const QString &lname = QString()); 0085 0086 /** Destructor (empty) */ 0087 virtual ~SkyObject() override = default; 0088 0089 /** 0090 * @short Create copy of object. 0091 * This method is virtual copy constructor. It allows for safe 0092 * copying of objects. In other words, KSPlanet object stored in 0093 * SkyObject pointer will be copied as KSPlanet. 0094 * 0095 * Each subclass of SkyObject MUST implement clone method. There 0096 * is no checking to ensure this, though. 0097 * 0098 * @return pointer to newly allocated object. Caller takes full responsibility 0099 * for deallocating it. 0100 */ 0101 virtual SkyObject *clone() const; 0102 0103 /** 0104 * @enum TYPE 0105 * The type classification of the SkyObject. 0106 * @note Keep TYPE_UNKNOWN at 255. To find out how many known 0107 * types exist, keep the NUMBER_OF_KNOWN_TYPES at the highest 0108 * non-Unknown value. This is a fake type that can be used in 0109 * comparisons and for loops. 0110 */ 0111 enum TYPE 0112 { 0113 STAR = 0, 0114 CATALOG_STAR = 1, 0115 PLANET = 2, 0116 OPEN_CLUSTER = 3, 0117 GLOBULAR_CLUSTER = 4, 0118 GASEOUS_NEBULA = 5, 0119 PLANETARY_NEBULA = 6, 0120 SUPERNOVA_REMNANT = 7, 0121 GALAXY = 8, 0122 COMET = 9, 0123 ASTEROID = 10, 0124 CONSTELLATION = 11, 0125 MOON = 12, 0126 ASTERISM = 13, 0127 GALAXY_CLUSTER = 14, 0128 DARK_NEBULA = 15, 0129 QUASAR = 16, 0130 MULT_STAR = 17, 0131 RADIO_SOURCE = 18, 0132 SATELLITE = 19, 0133 SUPERNOVA = 20, 0134 NUMBER_OF_KNOWN_TYPES = 21, 0135 TYPE_UNKNOWN = 255 0136 }; 0137 /** 0138 * @return A translated string indicating the type name for a given type number 0139 * @param t The type number 0140 * @note Note the existence of a SkyObject::typeName( void ) method that is not static and returns the type of this object. 0141 */ 0142 static QString typeName(const int t); 0143 0144 /** @return object's primary name. */ 0145 inline virtual QString name(void) const { return hasName() ? Name : unnamedString; } 0146 0147 /** @return object's primary name, translated to local language. */ 0148 inline QString translatedName() const 0149 { 0150 return i18n( 0151 name() 0152 .toUtf8()); // FIXME: Hmm... that's funny. How does the string extraction work, if we are UTF8-ing the name first? Does the string extraction change to UTF8? 0153 } 0154 0155 /** @return object's secondary name */ 0156 inline QString name2(void) const { return (hasName2() ? Name2 : emptyString); } 0157 0158 /** @return object's secondary name, translated to local language. */ 0159 inline QString translatedName2() const { return (hasName2() ? i18n(Name2.toUtf8()) : emptyString); } 0160 0161 /** 0162 * @return object's common (long) name 0163 */ 0164 virtual QString longname(void) const { return hasLongName() ? LongName : unnamedObjectString; } 0165 0166 /** 0167 * @return object's common (long) name, translated to local language. 0168 */ 0169 QString translatedLongName() const { return i18n(longname().toUtf8()); } 0170 0171 /** 0172 * Set the object's long name. 0173 * @param longname the object's long name. 0174 */ 0175 void setLongName(const QString &longname = QString()); 0176 0177 /** 0178 * @return the string used to label the object on the map 0179 * In the default implementation, this just returns translatedName() 0180 * Overridden by StarObject. 0181 */ 0182 virtual QString labelString() const; 0183 0184 /** 0185 * @return object's type identifier (int) 0186 * @see enum TYPE 0187 */ 0188 inline int type(void) const { return (int)Type; } 0189 0190 /** 0191 * Set the object's type identifier to the argument. 0192 * @param t the object's type identifier (e.g., "SkyObject::PLANETARY_NEBULA") 0193 * @see enum TYPE 0194 */ 0195 inline void setType(int t) { Type = (unsigned char)t; } 0196 0197 /** 0198 * @return the type name for this object 0199 * @note This just calls the static method by the same name, with the appropriate type number. See SkyObject::typeName( const int ) 0200 */ 0201 QString typeName() const; 0202 0203 /** 0204 * @return object's magnitude 0205 */ 0206 inline float mag() const { return sortMagnitude; } 0207 0208 /** 0209 * @return the object's position angle. This is overridden in KSPlanetBase 0210 * and DeepSkyObject; for all other SkyObjects, this returns 0.0. 0211 */ 0212 inline virtual double pa() const { return 0.0; } 0213 0214 /** 0215 * @return true if the object is a solar system body. 0216 */ 0217 inline bool isSolarSystem() const { return (type() == 2 || type() == 9 || type() == 10 || type() == 12); } 0218 0219 /** 0220 * Initialize the popup menut. This function should call correct 0221 * initialization function in KSPopupMenu. By overloading the 0222 * function, we don't have to check the object type when we need 0223 * the menu. 0224 */ 0225 virtual void initPopupMenu(KSPopupMenu *pmenu); 0226 0227 /** Show Type-specific popup menu. Overloading is done in the function initPopupMenu */ 0228 void showPopupMenu(KSPopupMenu *pmenu, const QPoint &pos); 0229 0230 /** 0231 * Determine the time at which the point will rise or set. Because solar system 0232 * objects move across the sky, it is necessary to iterate on the solution. 0233 * We compute the rise/set time for the object's current position, then 0234 * compute the object's position at that time. Finally, we recompute then 0235 * rise/set time for the new coordinates. Further iteration is not necessary, 0236 * even for the most swiftly-moving object (the Moon). 0237 * @return the local time that the object will rise 0238 * @param dt current UT date/time 0239 * @param geo current geographic location 0240 * @param rst If true, compute rise time. If false, compute set time. 0241 * @param exact If true, use a second iteration for more accurate time 0242 */ 0243 QTime riseSetTime(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact = true) const; 0244 0245 /** 0246 * @return the UT time when the object will rise or set 0247 * @param dt target date/time 0248 * @param geo pointer to Geographic location 0249 * @param rst Boolean. If true will compute rise time. If false 0250 * will compute set time. 0251 * @param exact If true, use a second iteration for more accurate time 0252 */ 0253 QTime riseSetTimeUT(const KStarsDateTime &dt, const GeoLocation *geo, bool rst, bool exact = true) const; 0254 0255 /** 0256 * @return the Azimuth time when the object will rise or set. This function 0257 * recomputes set or rise UT times. 0258 * @param dt target date/time 0259 * @param geo GeoLocation object 0260 * @param rst Boolen. If true will compute rise time. If false 0261 * will compute set time. 0262 */ 0263 dms riseSetTimeAz(const KStarsDateTime &dt, const GeoLocation *geo, bool rst) const; 0264 0265 /** 0266 * The same iteration technique described in riseSetTime() is used here. 0267 * @return the local time that the object will transit the meridian. 0268 * @param dt target date/time 0269 * @param geo pointer to the geographic location 0270 */ 0271 QTime transitTime(const KStarsDateTime &dt, const GeoLocation *geo) const; 0272 0273 /** 0274 * @return the universal time that the object will transit the meridian. 0275 * @param dt target date/time 0276 * @param geo pointer to the geographic location 0277 */ 0278 QTime transitTimeUT(const KStarsDateTime &dt, const GeoLocation *geo) const; 0279 0280 /** 0281 * @return the altitude of the object at the moment it transits the meridian. 0282 * @param dt target date/time 0283 * @param geo pointer to the geographic location 0284 */ 0285 dms transitAltitude(const KStarsDateTime &dt, const GeoLocation *geo) const; 0286 0287 /** 0288 * The equatorial coordinates for the object on date dt are computed and returned, 0289 * but the object's internal coordinates are not modified. 0290 * @return the coordinates of the selected object for the time given by jd 0291 * @param dt date/time for which the coords will be computed. 0292 * @param geo pointer to geographic location (used for solar system only) 0293 * @note Does not update the horizontal coordinates. Call EquatorialToHorizontal for that. 0294 */ 0295 SkyPoint recomputeCoords(const KStarsDateTime &dt, const GeoLocation *geo = nullptr) const; 0296 0297 /** 0298 * @short Like recomputeCoords, but also calls EquatorialToHorizontal before returning 0299 */ 0300 SkyPoint recomputeHorizontalCoords(const KStarsDateTime &dt, const GeoLocation *geo) const; 0301 0302 inline bool hasName() const { return !Name.isEmpty(); } 0303 0304 inline bool hasName2() const { return !Name2.isEmpty(); } 0305 0306 inline bool hasLongName() const { return !LongName.isEmpty(); } 0307 0308 /** 0309 * @short Given the Image title from a URL file, try to convert it to an image credit string. 0310 */ 0311 QString messageFromTitle(const QString &imageTitle) const; 0312 0313 /** 0314 * @return the pixel distance for offseting the object's name label 0315 * @note overridden in StarObject, DeepSkyObject, KSPlanetBase 0316 */ 0317 virtual double labelOffset() const; 0318 0319 /** 0320 * @short Return UID for object. 0321 * This method should be reimplemented in all concrete 0322 * subclasses. Implementation for SkyObject just returns 0323 * invalidUID. It's required SkyObject is not an abstract class. 0324 */ 0325 virtual UID getUID() const; 0326 0327 // TODO: (Valentin) have another think about onFocus handlers :) 0328 0329 /** 0330 * @brief hashBeenUpdated 0331 * @return whether the coordinates of the object have been updated 0332 * 0333 * This is used for faster filtering. 0334 */ 0335 bool hashBeenUpdated() { return has_been_updated; } 0336 0337 private: 0338 /** 0339 * Compute the UT time when the object will rise or set. It is an auxiliary 0340 * procedure because it does not use the RA and DEC of the object but values 0341 * given as parameters. You may want to use riseSetTimeUT() which is 0342 * public. riseSetTimeUT() calls this function iteratively. 0343 * @param dt target date/time 0344 * @param geo pointer to Geographic location 0345 * @param righta pointer to Right ascention of the object 0346 * @param decl pointer to Declination of the object 0347 * @param rst Boolean. If true will compute rise time. If false 0348 * will compute set time. 0349 * @return the time at which the given position will rise or set. 0350 */ 0351 QTime auxRiseSetTimeUT(const KStarsDateTime &dt, const GeoLocation *geo, const dms *righta, const dms *decl, 0352 bool riseT) const; 0353 0354 /** 0355 * Compute the LST time when the object will rise or set. It is an auxiliary 0356 * procedure because it does not use the RA and DEC of the object but values 0357 * given as parameters. You may want to use riseSetTimeLST() which is 0358 * public. riseSetTimeLST() calls this function iteratively. 0359 * @param gLt Geographic latitude 0360 * @param rga Right ascention of the object 0361 * @param decl Declination of the object 0362 * @param rst Boolean. If true will compute rise time. If false 0363 * will compute set time. 0364 */ 0365 dms auxRiseSetTimeLST(const dms *gLt, const dms *rga, const dms *decl, bool rst) const; 0366 0367 /** 0368 * Compute the approximate hour angle that an object with declination d will have 0369 * when its altitude is h (as seen from geographic latitude gLat). 0370 * This function is only used by auxRiseSetTimeLST(). 0371 * @param h pointer to the altitude of the object 0372 * @param gLat pointer to the geographic latitude 0373 * @param d pointer to the declination of the object. 0374 * @return the Hour Angle, in degrees. 0375 */ 0376 double approxHourAngle(const dms *h, const dms *gLat, const dms *d) const; 0377 0378 /** 0379 * Correct for the geometric altitude of the center of the body at the 0380 * time of rising or setting. This is due to refraction at the horizon 0381 * and to the size of the body. The moon correction has also to take into 0382 * account parallax. The value we use here is a rough approximation 0383 * suggested by J. Meeus. 0384 * 0385 * Weather status (temperature and pressure basically) is not taken 0386 * into account although change of conditions between summer and 0387 * winter could shift the times of sunrise and sunset by 20 seconds. 0388 * 0389 * This function is only used by auxRiseSetTimeLST(). 0390 * @return dms object with the correction. 0391 */ 0392 dms elevationCorrection(void) const; 0393 0394 unsigned char Type; 0395 float 0396 sortMagnitude; // This magnitude is used for sorting / making decisions about the visibility of an object. Should not be NaN. 0397 0398 protected: 0399 /** 0400 * Set the object's sorting magnitude. 0401 * @param m the object's magnitude. 0402 */ 0403 inline void setMag(float m) 0404 { 0405 sortMagnitude = 0406 m < FAINTEST_MAGNITUDE ? 0407 m : 0408 NaN:: 0409 f; 0410 } 0411 // FIXME: We claim sortMagnitude should not be NaN, but we are setting it to NaN above!! ^ 0412 0413 /** 0414 * Set the object's primary name. 0415 * @param name the object's primary name 0416 */ 0417 inline void setName(const QString &name) { Name = name; } 0418 0419 /** 0420 * Set the object's secondary name. 0421 * @param name2 the object's secondary name. 0422 */ 0423 inline void setName2(const QString &name2 = QString()) { Name2 = name2; } 0424 0425 QString Name, Name2, LongName; 0426 0427 // Whether the coordinates of the object have been updated. 0428 // The default value is chose for compatibility reasons. 0429 // It primarily matters for objects which are filtered. 0430 // See `KSAsteroid` for an example. 0431 bool has_been_updated = true; 0432 };