File indexing completed on 2024-09-08 09:27:40
0001 /* 0002 SPDX-FileCopyrightText: 2005 Thomas Kabelmann <thomas.kabelmann@gmx.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "skypoint.h" 0010 #include "typedef.h" 0011 0012 class QString; 0013 0014 class SkyObject; 0015 class SkyPoint; 0016 class SkyComposite; 0017 class SkyPainter; 0018 0019 /** 0020 * @class SkyComponent 0021 * SkyComponent represents an object on the sky map. This may be a star, a planet or an imaginary 0022 * line like the equator. 0023 * The SkyComponent uses the composite design pattern. So if a new object type is needed, it has to 0024 * be derived from this class and must be added into the hierarchy of components. 0025 * 0026 * \section Overview Overview 0027 * KStars utilizes the Composite/Component design pattern to store all elements that must be 0028 * drawn on the SkyMap. In this design pattern, elements to be drawn in the map are called 0029 * "Components", and they are hierarchically organized into groups called "Composites". 0030 * A Composite can contain other Composites, as well as Components. From an organizational 0031 * point of view, you can think of Composites and Components as being analogous to 0032 * "Directories" and "Files" in a computer filesystem. 0033 * 0034 * The advantage of this design pattern is that it minimizes code duplication and maximizes 0035 * modularity. There is a set of operations which all Components must perform periodically 0036 * (such as drawing on screen, or updating position), but each Component may perform its task 0037 * slightly differently. Thus, each Component can implement its own version of the functions, 0038 * and each Composite calls on its child Components to execute the desired function. For 0039 * example, if we wanted to draw all Components in the SkyMap, we would simply need to call 0040 * "skyComposite()->draw()". SkyComposite is the "top-level" Composite; its "draw()" function 0041 * simply calls draw() on each of its children. Its child Components will draw themselves, 0042 * while its child Composites will call "draw()" for each of *their* children. Note that 0043 * we don't need to know *any* implementation details; when we need to draw the 0044 * elements, we just tell the top-level Composite to spread the word. 0045 * 0046 * \section ClassInheritance Class Inheritance 0047 * The base class in this directory is SkyComponent; all other classes are derived from it 0048 * (directly or indirectly). Its most important derivative is SkyComposite, the base classes 0049 * for all Composites. 0050 * 0051 * FIXME: There is no SingleComponent 0052 * From SkyComponent, we derive three important subclasses: SingleComponent, ListComponent, 0053 * and PointListComponent. SingleComponent represents a sky element consisting of a single 0054 * SkyObject, such as the Sun. ListComponent represents a list of SkyObjects, such as the 0055 * Asteroids. PointListComponent represents a list of SkyPoints (not SkyObjects), such as 0056 * the Ecliptic. Almost all other Components are derived from one of these three classes 0057 * (two Components are derived directly from SkyComponent). 0058 * 0059 * The Solar System bodies require some special treatment. For example, only solar system 0060 * bodies may have attached trails, and they move across the sky, so their positions must 0061 * be updated frequently. To handle these features, we derive SolarSystemComposite from 0062 * SkyComposite to be the container for all solar system Components. In addition, we derive 0063 * SolarSystemSingleComponent from SingleComponent, and SolarSystemListComponent from 0064 * ListComponent. These classes simply add functions to handle Trails, and to update the 0065 * positions of the bodies. Also, they contain KSPlanetBase objects, instead of SkyObjects. 0066 * 0067 * The Sun, Moon and Pluto each get a unique Component class, derived from 0068 * SolarSystemSingleComponent (this is needed because each of these bodies uses a unique 0069 * class derived from KSPlanetBase: KSSun, KSMoon, and KSPluto). The remaining major 0070 * planets are each represented with a PlanetComponent object, which is also derived from 0071 * SolarSystemSingleComponent. Finally, we have AsteroidsComponent and CometsComponent, 0072 * each of which is derived from SolarSystemListComponent. 0073 * 0074 * Next, we have the Components derived from PointListComponent. These Components represent 0075 * imaginary guide lines in the sky, such as constellation boundaries or the coordinate grid. 0076 * They are listed above, and most of them don't require further comment. The GuidesComposite 0077 * contains two sub-Composites: CoordinateGridComposite, and ConstellationLinesComposite. 0078 * Both of these contain a number of PointListComponents: CoordinateGridComposite contains one 0079 * PointsListComponent for each circle in the grid, and ConstellationLineComposite contains 0080 * one PointsListComponent for each constellation (representing the "stick figure" of the 0081 * constellation). 0082 * 0083 * Finally, we have the Components which don't inherit from either SingleComponent, 0084 * ListComponent, or PointListComponent: PlanetMoonsComponent inherits from SkyComponent 0085 * directly, because the planet moons have their own class (PlanetMoons) not derived 0086 * directly from a SkyPoint. 0087 * 0088 * \section StarComponent DeepStarComponent and StarComponent 0089 * StarComponent and DeepStarComponent manage stars in KStars. StarComponent maintains a 0090 * QVector of instances of DeepStarComponents and takes care of calling their draw routines 0091 * etc. The machinery for handling stars is documented in great detail in \ref Stars 0092 * 0093 * @author Thomas Kabelmann 0094 */ 0095 class SkyComponent 0096 { 0097 public: 0098 /** 0099 * @short Constructor 0100 * @p parent pointer to the parent SkyComposite 0101 */ 0102 explicit SkyComponent(SkyComposite *parent = nullptr); 0103 0104 virtual ~SkyComponent() = default; 0105 0106 /** 0107 * @short Draw the object on the SkyMap 0108 * @p skyp a pointer to the SkyPainter to use 0109 */ 0110 virtual void draw(SkyPainter *skyp) = 0; 0111 0112 /** @short Draw trails for objects. */ 0113 virtual void drawTrails(SkyPainter *skyp); 0114 0115 /** 0116 * @short Update the sky position(s) of this component. 0117 * 0118 * This function usually just updates the Horizontal (Azimuth/Altitude) 0119 * coordinates of its member object(s). However, the precession and 0120 * nutation must also be recomputed periodically. 0121 * @p num Pointer to the KSNumbers object 0122 * @sa SingleComponent::update() 0123 * @sa ListComponent::update() 0124 * @sa ConstellationBoundaryComponent::update() 0125 */ 0126 virtual void update(KSNumbers *) {} 0127 virtual void updateSolarSystemBodies(KSNumbers *) {} 0128 virtual void updateMoons(KSNumbers *) {} 0129 0130 /** @return true if component is to be drawn on the map. */ 0131 virtual bool selected() 0132 { 0133 return true; 0134 } 0135 0136 /** @return Parent of component. If there is no parent returns nullptr. */ 0137 SkyComposite *parent() 0138 { 0139 return m_parent; 0140 } 0141 0142 /** 0143 * @short Search the children of this SkyComponent for 0144 * a SkyObject whose name matches the argument 0145 * @p name the name to be matched 0146 * @p exact If true, it will return an exact match, otherwise it can return 0147 * a partial match. 0148 * @return a pointer to the SkyObject whose name matches 0149 * the argument, or a nullptr pointer if no match was found. 0150 * @note This function simply returns the nullptr pointer; it 0151 * is reimplemented in various sub-classes 0152 */ 0153 virtual SkyObject *findByName(const QString &name, bool exact = true); 0154 0155 /** 0156 * @short Searches the region(s) and appends the SkyObjects found to the list of sky objects 0157 * 0158 * Look for a SkyObject that is in one of the regions 0159 * If found, then append to the list of sky objects 0160 * @p list list of SkyObject to which matching list has to be appended to 0161 * @p region defines the regions in which the search for SkyObject should be done within 0162 * @return void 0163 * @note This function simply returns; it is 0164 * reimplemented in various sub-classes. 0165 */ 0166 virtual void objectsInArea(QList<SkyObject *> &list, const SkyRegion ®ion); 0167 0168 /** 0169 * @short Find the SkyObject nearest the given SkyPoint 0170 * 0171 * Look for a SkyObject that is nearer to point p than maxrad. 0172 * If one is found, then maxrad is reset to the separation of the new nearest object. 0173 * @p p pointer to the SkyPoint to search around 0174 * @p maxrad reference to current search radius in degrees 0175 * @return a pointer to the nearest SkyObject 0176 * @note This function simply returns a nullptr pointer; it is 0177 * reimplemented in various sub-classes. 0178 */ 0179 virtual SkyObject *objectNearest(SkyPoint *p, double &maxrad); 0180 0181 /** 0182 * @short Emit signal about progress. 0183 * 0184 * @sa SkyMapComposite::emitProgressText 0185 */ 0186 virtual void emitProgressText(const QString &message); 0187 0188 inline QHash<int, QStringList> &objectNames() 0189 { 0190 return getObjectNames(); 0191 } 0192 0193 inline QStringList &objectNames(int type) 0194 { 0195 return getObjectNames()[type]; 0196 } 0197 0198 inline QHash<int, QVector<QPair<QString, const SkyObject *>>> &objectLists() 0199 { 0200 return getObjectLists(); 0201 } 0202 0203 inline QVector<QPair<QString, const SkyObject *>> &objectLists(int type) 0204 { 0205 return getObjectLists()[type]; 0206 } 0207 0208 void removeFromNames(const SkyObject *obj); 0209 void removeFromLists(const SkyObject *obj); 0210 0211 private: 0212 virtual QHash<int, QStringList> &getObjectNames(); 0213 virtual QHash<int, QVector<QPair<QString, const SkyObject *>>> &getObjectLists(); 0214 0215 // Disallow copying and assignment 0216 SkyComponent(const SkyComponent &); 0217 SkyComponent &operator=(const SkyComponent &); 0218 0219 /// Parent of sky component. 0220 SkyComposite *m_parent; 0221 };