1 /*
2  * Stellarium
3  * Copyright (C) 2002 Fabien Chereau
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  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #ifndef STELOBJECT_HPP
21 #define STELOBJECT_HPP
22 
23 #include "VecMath.hpp"
24 #include "StelObjectType.hpp"
25 #include "StelRegionObject.hpp"
26 
27 #include <QFlags>
28 #include <QString>
29 
30 class StelCore;
31 
32 //! The base abstract class for sky objects used in Stellarium like Stars, Planets, Constellations etc...
33 //! Normally you should use StelObjectP instead of StelObject* which have by default the same behaviour,
34 //! but which can be added reference counting if needed.
35 //! @sa StelObjectP
36 class StelObject : public StelRegionObject
37 {
38 	//Required for Q_FLAGS macro, this requires this header to be MOC'ed
39 	Q_GADGET
40 	Q_FLAGS(InfoStringGroupFlags InfoStringGroup)
41 public:
42 	//! Used as named bitfield flags as specifiers to
43 	//! filter results of getInfoString. The precise definition of these should
44 	//! be documented in the getInfoString documentation for the derived classes
45 	//! for all specifiers which are defined in that derivative.
46 	//! Use InfoStringGroup instead.
47 	enum InfoStringGroupFlags
48 	{
49 		None			= 0x00000000, //!< Show Nothing
50 		Name			= 0x00000001, //!< An object's name
51 		CatalogNumber		= 0x00000002, //!< Catalog numbers
52 		Magnitude		= 0x00000004, //!< Magnitude related data
53 		RaDecJ2000		= 0x00000008, //!< The equatorial position (J2000 ref)
54 		RaDecOfDate		= 0x00000010, //!< The equatorial position (of date)
55 		AltAzi			= 0x00000020, //!< The position (Altitude/Azimuth)
56 		Distance		= 0x00000040, //!< Info about an object's distance
57 		Elongation		= 0x00000080, //!< Info about elongation, phase angle etc. Most useful for Planets, but possible for all objects.
58 		Size			= 0x00000100, //!< Info about an object's size
59 		Velocity		= 0x00000200, //!< Info about object's velocity
60 		ProperMotion		= 0x00000400, //!< Annual proper motion (for stars) or hourly motion (for Planets)
61 		Extra			= 0x00000800, //!< Derived class-specific extra fields
62 		HourAngle		= 0x00001000, //!< The hour angle + DE (of date)
63 		AbsoluteMagnitude	= 0x00002000, //!< The absolute magnitude
64 		GalacticCoord		= 0x00004000, //!< The galactic position
65 		SupergalacticCoord	= 0x00008000, //!< The supergalactic position
66 		OtherCoord		= 0x00010000, //!< Unspecified additional coordinates. These can be "injected" into the extraInfoStrings by plugins.
67 		ObjectType		= 0x00020000, //!< The type of the object (star, planet, etc.)
68 		EclipticCoordJ2000	= 0x00040000, //!< The ecliptic position (J2000.0 ref) [+ XYZ of VSOP87A (used mainly for debugging, not public)]
69 		EclipticCoordOfDate	= 0x00080000, //!< The ecliptic position (of date)
70 		IAUConstellation        = 0x00100000, //!< Three-letter constellation code (And, Boo, Cas, ...)
71 		SiderealTime		= 0x00200000, //!< Mean and Apparent Sidereal Time
72 		RTSTime			= 0x00400000, //!< Time of rise, transit and set of celestial object
73 		SolarLunarPosition      = 0x00800000, //!< Show Solar and Lunar horizontal position (on Earth location only)
74 		Script                  = 0x01000000, //!< Should be used by Scripts only which can inject extraInfoStrings.
75 		DebugAid                = 0x02000000, //!< Can be used for development only, place messages into extraInfoStrings. Comment them away or delete for releases.
76 		NoFont			= 0x04000000,
77 		PlainText		= 0x08000000  //!< Strip HTML tags from output
78 	};
79 	Q_DECLARE_FLAGS(InfoStringGroup, InfoStringGroupFlags)
80 
81 	//! A pre-defined "all available" set of specifiers for the getInfoString flags argument to getInfoString
82 	static const InfoStringGroupFlags AllInfo = static_cast<InfoStringGroupFlags>(Name|CatalogNumber|Magnitude|RaDecJ2000|RaDecOfDate|AltAzi|
83 									   Distance|Elongation|Size|Velocity|ProperMotion|Extra|HourAngle|AbsoluteMagnitude|
84 									   GalacticCoord|SupergalacticCoord|OtherCoord|ObjectType|EclipticCoordJ2000|
85 									   EclipticCoordOfDate|IAUConstellation|SiderealTime|RTSTime|SolarLunarPosition);
86 	//! A pre-defined "default" set of specifiers for the getInfoString flags argument to getInfoString
87 	//! It appears useful to propose this set as post-install settings and let users configure more on demand.
88 	static const InfoStringGroupFlags DefaultInfo = static_cast<InfoStringGroupFlags>(Name|CatalogNumber|Magnitude|RaDecOfDate|HourAngle|AltAzi|OtherCoord|
89 											  Distance|Elongation|Size|Velocity|Extra|IAUConstellation|SiderealTime|RTSTime);
90 	//! A pre-defined "shortest useful" set of specifiers for the getInfoString flags argument to getInfoString
91 	static const InfoStringGroupFlags ShortInfo = static_cast<InfoStringGroupFlags>(Name|CatalogNumber|Magnitude|RaDecJ2000);
92 
~StelObject()93 	virtual ~StelObject() Q_DECL_OVERRIDE {}
94 
95 	//! Default implementation of the getRegion method.
96 	//! Return the spatial region of the object.
getRegion() const97 	virtual SphericalRegionP getRegion() const Q_DECL_OVERRIDE {return SphericalRegionP(new SphericalPoint(getJ2000EquatorialPos(Q_NULLPTR)));}
98 
99 	//! Default implementation of the getPointInRegion method.
100 	//! Return the J2000 Equatorial Position of the object.
getPointInRegion() const101 	virtual Vec3d getPointInRegion() const Q_DECL_OVERRIDE {return getJ2000EquatorialPos(Q_NULLPTR);}
102 
103 	//! Write I18n information about the object in QString.
104 	//! @param core the StelCore object to use
105 	//! @param flags a set of InfoStringGroup flags which are used to
106 	//! filter the return value - including specified types of information
107 	//! and altering the output format.
108 	//! @return an HTML string containing information about the StelObject.
109 	virtual QString getInfoString(const StelCore *core, const InfoStringGroup& flags=StelObject::AllInfo) const = 0;
110 
111 	//! Return a key/value map with data about an object's position, magnitude and so on. Useful in a context like scripting.
112 	//! Derived objects can add their own special information tags.
113 	//! @param core the current StelCore
114 	//! @return a map of object data.  Keys:
115 	//! - above-horizon : true, if celestial body is above horizon
116 	//! - altitude : apparent altitude angle in decimal degrees
117 	//! - azimuth : apparent azimuth angle in decimal degrees
118 	//! - altitude-geometric : geometric altitude angle in decimal degrees
119 	//! - azimuth-geometric : geometric azimuth angle in decimal degrees
120 	//! - airmass : number of airmasses the object's light had to pass through the atmosphere. For negative altitudes this number may be meaningless.
121 	//! - ra : right ascension angle (current date frame) in decimal degrees
122 	//! - dec : declination angle (current date frame) in decimal degrees
123 	//! - raJ2000 : right ascension angle (J2000 frame) in decimal degrees
124 	//! - decJ2000 : declination angle (J2000 frame) in decimal degrees
125 	//! - parallacticAngle : parallactic angle in decimal degrees (for non-star objects only)
126 	//! - hourAngle-dd : hour angle in decimal degrees
127 	//! - hourAngle-hms : hour angle in HMS format (formatted string)
128 	//! - iauConstellation : 3-letter abbreviation of IAU constellation (string)
129 	//! - meanSidTm : mean sidereal time, in decimal degrees (on Earth only!)
130 	//! - appSidTm : mean sidereal time, in decimal degrees (on Earth only!)
131 	//! - glong : galactic longitude in decimal degrees
132 	//! - glat : galactic latitude in decimal degrees
133 	//! - sglong : supergalactic longitude in decimal degrees
134 	//! - sglat : supergalactic latitude in decimal degrees
135 	//! - elong : ecliptic longitude in decimal degrees (on Earth only!)
136 	//! - elat : ecliptic latitude in decimal degrees (on Earth only!)
137 	//! - elongJ2000 : ecliptic longitude (Earth's J2000 frame) in decimal degrees
138 	//! - elatJ2000 : ecliptic latitude (Earth's J2000 frame) in decimal degrees
139 	//! - vmag : visual magnitude
140 	//! - vmage : visual magnitude (after atmospheric extinction)
141 	//! - size: angular size in radians
142 	//! - size-dd : angular size in decimal degrees
143 	//! - size-deg : angular size in decimal degrees (formatted string)
144 	//! - size-dms : angular size in DMS format
145 	//! - rise : time of rise in HM format
146 	//! - rise-dhr : time of rise in decimal hours
147 	//! - transit : time of transit in HM format
148 	//! - transit-dhr : time of transit in decimal hours
149 	//! - set : time of set in HM format
150 	//! - set-dhr : time of set in decimal hours
151 	//! - name : english name of the object
152 	//! - localized-name : localized name
153 	//! @note Coordinate values may need modulo operation to bring them into ranges [0..360].
154 	virtual QVariantMap getInfoMap(const StelCore *core) const;
155 
156 	//! Return object's type. It should be the name of the class.
157 	virtual QString getType() const = 0;
158 
159 	//! Returns a unique identifier for this object.
160 	//! The ID should be unique for all objects of the same type,
161 	//! but may freely conflict with IDs of other types, so getType() must also be tested.
162 	//!
163 	//! With this it should be possible to at least identify the same object
164 	//! in a different instance of Stellarium running the same version, but
165 	//! it would even be better if the ID provides some degree of forward-compatibility.
166 	//! For some object types (e.g. planets) this may simply return getEnglishName(),
167 	//! but better candidates may be official designations or at least (stable) internal IDs.
168 	//!
169 	//! An object may have multiple IDs (different catalog numbers, etc). StelObjectMgr::searchByID()
170 	//! should search through all ID variants, but this method only returns one of them.
171 	virtual QString getID() const = 0;
172 
173 	//! Return object's name in english
174 	virtual QString getEnglishName() const = 0;
175 
176 	//! Return translated object's name
177 	virtual QString getNameI18n() const = 0;
178 
179 	//! Get observer-centered equatorial coordinates at equinox J2000
180 	virtual Vec3d getJ2000EquatorialPos(const StelCore* core) const = 0;
181 
182 	//! Get observer-centered equatorial coordinate at the current equinox
183 	//! The frame has its Z axis at the planet's current rotation axis
184 	//! At time 2000-01-01 this frame is almost the same as J2000, but ONLY if the observer is on earth
185 	Vec3d getEquinoxEquatorialPos(const StelCore* core) const;
186 	//! Like getEquinoxEquatorialPos(core), but always adds refraction correction to the position.
187 	Vec3d getEquinoxEquatorialPosApparent(const StelCore* core) const;
188 	//! Like getEquinoxEquatorialPos(core), but adds refraction correction to the position if atmosphere is active.
189 	Vec3d getEquinoxEquatorialPosAuto(const StelCore* core) const;
190 
191 	//! Get observer-centered galactic coordinates
192 	Vec3d getGalacticPos(const StelCore* core) const;
193 
194 	//! Get observer-centered supergalactic coordinates
195 	Vec3d getSupergalacticPos(const StelCore* core) const;
196 
197 	//! Get observer-centered hour angle + declination (at current equinox)
198 	//! It is the geometric position, i.e. without taking refraction effect into account.
199 	//! The frame has its Z axis at the planet's current rotation axis
200 	Vec3d getSiderealPosGeometric(const StelCore* core) const;
201 
202 	//! Get observer-centered hour angle + declination (at current equinox)
203 	//! It is the apparent position, i.e. taking the refraction effect into account.
204 	//! The frame has its Z axis at the planet's current rotation axis
205 	Vec3d getSiderealPosApparent(const StelCore* core) const;
206 
207 	//! Get observer-centered alt/az position
208 	//! It is the geometric position, i.e. without taking refraction effect into account.
209 	//! The frame has its Z axis at the zenith
210 	Vec3d getAltAzPosGeometric(const StelCore* core) const;
211 
212 	//! Get observer-centered alt/az position
213 	//! It is the apparent position, i.e. taking the refraction effect into account.
214 	//! The frame has its Z axis at the zenith
215 	Vec3d getAltAzPosApparent(const StelCore* core) const;
216 
217 	//! Get observer-centered alt/az position
218 	//! It is the automatic position, i.e. taking the refraction effect into account if atmosphere is on.
219 	//! The frame has its Z axis at the zenith
220 	Vec3d getAltAzPosAuto(const StelCore* core) const;
221 
222 	//! Get parallactic angle, which is the deviation between zenith angle and north angle. [radians]
223 	float getParallacticAngle(const StelCore* core) const;
224 
225 	//! Checking position an object above mathematical horizon for current location.
226 	//! @return true if object an above mathematical horizon
227 	bool isAboveHorizon(const StelCore* core) const;
228 
229 	//! Checking position an object above real horizon for current location.
230 	//! @return true if object an above real horizon (uses test for landscapes)
231 	bool isAboveRealHorizon(const StelCore* core) const;
232 
233 	//! Compute time of rise, transit and set for celestial object for current location.
234 	//! @param core the currently active StelCore object
235 	//! @param altitude (optional; default=0) altitude of the object, degrees.
236 	//!        Setting this to -6. for the Sun will find begin and end for civil twilight.
237 	//! @return Vec4d - time of rise, transit and set closest to current time; JD.
238 	//! @note The fourth element flags particular conditions:
239 	//!       *  +100. for circumpolar objects. Rise and set give lower culmination times.
240 	//!       *  -100. for objects never rising. Rise and set give transit times.
241 	//!       * -1000. is used as "invalid" value. The result should then not be used.
242 	//! @note This is an abbreviated version of the method implemented in the Planet class.
243 	virtual Vec4d getRTSTime(const StelCore* core, const double altitude=0.) const;
244 
245 	//! Return object's apparent V magnitude as seen from observer, without including extinction.
246 	virtual float getVMagnitude(const StelCore* core) const;
247 
248 	//! Return object's apparent V magnitude as seen from observer including extinction.
249 	//! Extinction obviously only if atmosphere=on.
250 	float getVMagnitudeWithExtinction(const StelCore* core) const;
251 
252 	//! Return a priority value which is used to discriminate objects by priority
253 	//! As for magnitudes, the lower is the higher priority
254 	virtual float getSelectPriority(const StelCore*) const;
255 
256 	//! Get a color used to display info about the object
getInfoColor() const257 	virtual Vec3f getInfoColor() const {return Vec3f(1.f,1.f,1.f);}
258 
259 	//! Return the best FOV in degree to use for a close view of the object
getCloseViewFov(const StelCore *) const260 	virtual double getCloseViewFov(const StelCore*) const {return 10.;}
261 
262 	//! Return the best FOV in degree to use for a global view of the object satellite system (if there are satellites)
getSatellitesFov(const StelCore *) const263 	virtual double getSatellitesFov(const StelCore*) const {return -1.;}
getParentSatellitesFov(const StelCore *) const264 	virtual double getParentSatellitesFov(const StelCore*) const {return -1.;}
265 
266 	//! Return the angular radius of a circle containing the object as seen from the observer
267 	//! with the circle center assumed to be at getJ2000EquatorialPos().
268 	//! @return radius in degree. This value is the apparent angular size of the object, and is independent of the current FOV.
269 	virtual double getAngularSize(const StelCore* core) const = 0;
270 
271 	//! Return airmass value for the object (for atmosphere-dependent calculations)
272 	//! @param core
273 	//! @return airmass value or -1.f if calculations are not applicable or meaningless
274 	virtual float getAirmass(const StelCore *core) const;
275 
276 public slots:
277 	//! Allow additions to the Info String. Can be used by plugins to show extra info for the selected object, or for debugging.
278 	//! Hard-set this string group to a single str, or delete all messages when str==""
279 	//! @note This should be used with caution. Usually you want to use addToExtraInfoString().
280 	//! @note: If this breaks some const declaration, you can use StelObjectMgr::setExtraInfoString() instead.
281 	virtual void setExtraInfoString(const InfoStringGroup& flags, const QString &str);
282 	//! Add str to the extra string. This should be preferrable over hard setting.
283 	//! Can be used by plugins to show extra info for the selected object, or for debugging.
284 	//! The strings will be shown in the InfoString for the selected object, below the default fields per-flag.
285 	//! Additional coordinates not fitting into one of the predefined coordinate sets should be flagged with OtherCoords,
286 	//! and must be adapted to table or non-table layout as required.
287 	//! The line ending must be given explicitly, usually just end a line with "<br/>", except when it may end up in a Table or appended to a line.
288 	//! See getCommonInfoString() or the respective getInfoString() in the subclasses for details of use.
289 	//! @note: If this breaks some const declaration, you can use StelObjectMgr::addToExtraInfoString() instead.
290 	virtual void addToExtraInfoString(const StelObject::InfoStringGroup& flags, const QString &str);
291 	//! Retrieve an (unsorted) QStringList of all extra info strings that match flags.
292 	//! Normally the order matches the order of addition, but this cannot be guaranteed.
293 	//! @note: Usually objects should keep their extraInfoStrings to themselves. But there are cases where StelObjectMgr::setExtraInfoString() has been set.
294 	QStringList getExtraInfoStrings(const InfoStringGroup& flags) const;
295 	//! Remove the extraInfoStrings with the given flags.
296 	//! This is a finer-grained removal than just extraInfoStrings.remove(flags), as it allows a combination of flags.
297 	//! After display, InfoPanel::setTextFromObjects() auto-clears the strings of the selected object using the AllInfo constant.
298 	//! extraInfoStrings having been set with the DebugAid and Script flags have to be removed by separate calls of this method.
299 	//! Those which have been set by scripts have to persist at least as long as the selection remains active.
300 	//! The behaviour of DebugAid texts depends on the use case.
301 	//! @note: Usually objects should keep their extraInfoStrings to themselves. But there are cases where StelObjectMgr::setExtraInfoString() has been set.
302 	void removeExtraInfoStrings(const InfoStringGroup& flags);
303 
304 protected:
305 	//! Format the positional info string containing J2000/of date/altaz/hour angle positions and constellation, sidereal time, etc. for the object
306 	//! FIXME: We should split this and provide shorter virtual methods for various parts of the InfoString.
307 	//! The ExtraInfoStrings should be placed per flag, where they best fit.
308 	QString getCommonInfoString(const StelCore *core, const InfoStringGroup& flags) const;
309 
310 	//! Format the magnitude info string for the object
311 	//! @param core
312 	//! @param flags
313 	//! @param decimals significant digits after the comma.
314 	virtual QString getMagnitudeInfoString(const StelCore *core, const InfoStringGroup& flags, const int decimals=1) const;
315 
316 	//! Add a section to the InfoString with just horizontal data for the Sun and Moon, when observed from Earth.
317 	//! The application of this is to have quick info while observing other objects.
318 	QString getSolarLunarInfoString(const StelCore *core, const InfoStringGroup& flags) const;
319 
320 	//! Apply post processing on the info string.
321 	//! This also removes all extraInfoStrings possibly injected by modules (plugins) etc., except for Script and DebugAid types.
322 	void postProcessInfoString(QString& str, const InfoStringGroup& flags) const;
323 
324 private:
325 	//! Location for additional object info that can be set for special purposes (at least for debugging, but maybe others), even via scripting.
326 	//! Modules are allowed to add new strings to be displayed in the various getInfoString() methods of subclasses.
327 	//! This helps avoiding screen collisions if a plugin wants to display some additional object information.
328 	//! This string map gets cleared by InfoPanel::setTextFromObjects(), with the exception of strings with Script or DebugAid flags,
329 	//! which have been injected by scripts or for debugging (take care of those yourself!).
330 	QMultiMap<InfoStringGroup, QString> extraInfoStrings;
331 
332 	static int stelObjectPMetaTypeID;
333 };
334 
335 Q_DECLARE_OPERATORS_FOR_FLAGS(StelObject::InfoStringGroup)
336 
337 #endif // STELOBJECT_HPP
338