1 /* 2 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 3 SPDX-FileCopyrightText: 2021 Valentin Boettcher <hiro at protagon.space; @hiro98:tchncs.de> 4 5 SPDX-License-Identifier: GPL-2.0-or-later 6 */ 7 8 #pragma once 9 10 #include "dms.h" 11 #include "skyobject.h" 12 #include "nan.h" 13 #include "texturemanager.h" 14 #include <QString> 15 #include <QByteArray> 16 #include <QImage> 17 #include <array> 18 #include <utility> 19 20 class KSPopupMenu; 21 class KStarsData; 22 class CatalogComponent; 23 class CatalogEntryData; 24 namespace CatalogsDB 25 { 26 struct Catalog; 27 } 28 29 /** 30 * A simple container object to hold the minimum information for a Deeb 31 * Sky Object to be drawn on the skymap. Detailed information about the 32 * object (like `Catalog` information) will be loaded from it's birthing 33 * database when needed. Based on the original DeepSkyObject by Jason 34 * Harris. 35 * 36 * You shouldn't create a CatalogObject manually! 37 * 38 * \todo maybe just turn the const members public 39 */ 40 class CatalogObject : public SkyObject 41 { 42 friend class AddCatalogObject; 43 44 public: 45 using oid = QByteArray; 46 47 /** 48 * @param id oid (hash) of the object 49 * @param t Type of object 50 * @param r Right Ascension 51 * @param d Declination 52 * @param m magnitude (brightness) 53 * @param n Primary name 54 * @param lname Long name (common name) 55 * @param catalog_identifier a catalog specific identifier 56 * @param catalog_id catalog id 57 * @param a major axis (arcminutes) 58 * @param b minor axis (arcminutes) 59 * @param pa position angle (degrees) 60 * @param flux integrated flux (optional) 61 * @param database_path the path to the birthing database of this 62 * object, used to load additional information on-demand 63 */ 64 CatalogObject(oid id = {}, const SkyObject::TYPE t = SkyObject::STAR, 65 const dms &r = dms(0.0), const dms &d = dms(0.0), 66 const float m = NaN::f, const QString &n = "unnamed", 67 const QString &lname = QString(), 68 const QString &catalog_identifier = QString(), 69 const int catalog_id = -1, const float a = 0.0, const float b = 0.0, 70 const double pa = 0.0, const float flux = 0, 71 const QString &database_path = "") SkyObject(t,r,d,m,n,catalog_identifier,lname)72 : SkyObject(t, r, d, m, n, catalog_identifier, lname), 73 m_catalog_identifier{ catalog_identifier }, m_catalog_id{ catalog_id }, 74 m_database_path{ database_path }, m_major_axis{ a }, m_minor_axis{ b }, 75 m_position_angle{ pa }, m_flux{ flux } 76 { 77 if (id.length() == 0) 78 m_object_id = getId(); 79 else 80 m_object_id = std::move(id); 81 }; 82 83 ~CatalogObject() override = default; 84 85 /** 86 * @return the string for the skymap label of the object. 87 */ 88 QString labelString() const override; 89 90 /** 91 * Clones the object and returns a pointer to it. This is legacy 92 * code. 93 * 94 * @deprecated do not use in new code 95 */ 96 CatalogObject *clone() const override; 97 98 /** 99 * Generates a KStars internal UID from the object id. 100 */ 101 SkyObject::UID getUID() const override; 102 103 /** 104 * @return the object's integrated flux, unit value is stored in 105 * the custom catalog component. 106 */ flux()107 inline float flux() const { return m_flux; } 108 109 /** 110 * @return the object's major axis length, in arcminutes. 111 */ a()112 inline float a() const { return m_major_axis; } 113 114 /** 115 * @return the object's minor axis length, in arcminutes. 116 */ b()117 inline float b() const { return m_minor_axis; } 118 119 /** 120 * @return the object's aspect ratio (MinorAxis/MajorAxis). Returns 1.0 121 * if the object's MinorAxis=0.0. 122 */ 123 float e() const; 124 125 /** 126 * @return the object's position angle in degrees, measured clockwise from North. 127 */ pa()128 inline double pa() const override { return m_position_angle; } 129 130 /** 131 * Get information about the catalog that this objects stems from. 132 * 133 * The catalog information will be loaded from the catalog 134 * database on demand. 135 */ 136 const CatalogsDB::Catalog getCatalog() const; 137 138 /** 139 * Get the id of the catalog this object belongs to. 140 */ catalogId()141 int catalogId() const { return m_catalog_id; } 142 143 /** 144 * @return the pixel distance for offseting the object's name label 145 */ 146 double labelOffset() const override; 147 148 /** 149 * Update the cooridnates and the horizontal coordinates if 150 * updateID or updateNumID have changed (global). 151 */ 152 void JITupdate(); 153 154 /** 155 * Initialize the popup menu for a `CatalogObject`. 156 */ 157 void initPopupMenu(KSPopupMenu *pmenu) override; 158 159 /** 160 * \return the catalog specific identifier. (For example UGC ...) 161 */ 162 catalogIdentifier()163 const QString &catalogIdentifier() const { return m_catalog_identifier; }; 164 165 friend bool operator==(const CatalogObject &c1, const CatalogObject &c2) 166 { 167 return c1.m_object_id == c2.m_object_id; 168 } 169 170 friend bool operator!=(const CatalogObject &c1, const CatalogObject &c2) 171 { 172 return !(c1 == c2); 173 } 174 175 /** 176 * \returns the unique ID of this object (not the physical ID = 177 * m_object_id) by hashing unique properties of the object. 178 * 179 * This method provides the reference implementation for the oid hash. 180 */ 181 const oid getId() const; 182 static const oid getId(const SkyObject::TYPE type, const double ra, const double dec, 183 const QString &name, const QString &catalog_identifier); 184 185 /** 186 * \returns the physical object id of the catalogobject 187 */ getObjectId()188 const oid getObjectId() const { return m_object_id; }; 189 190 /** 191 * Set the catalog identifier to \p `cat_ident`. 192 */ setCatalogIdentifier(const QString & cat_ident)193 void setCatalogIdentifier(const QString &cat_ident) 194 { 195 m_catalog_identifier = cat_ident; 196 } 197 198 /** 199 * Set the major axis to \p `a`. 200 */ setMaj(const float a)201 void setMaj(const float a) { m_major_axis = a; } 202 203 /** 204 * Set the minor axis to \p `b`. 205 */ setMin(const float b)206 void setMin(const float b) { m_minor_axis = b; } 207 208 /** 209 * Set the flux to \p `flux`. 210 */ setFlux(const float flux)211 void setFlux(const float flux) { m_flux = flux; } 212 213 /** 214 * Set the position angle to \p `pa`. 215 */ setPA(const double pa)216 void setPA(const double pa) { m_position_angle = pa; } 217 218 /** 219 * Set the magnitude of the object. 220 */ setMag(const double mag)221 void setMag(const double mag) { SkyObject::setMag(mag); }; 222 223 /** 224 * Load the image for this object. 225 */ 226 void load_image(); 227 228 /** 229 * Get the image for this object. 230 * 231 * @returns [has image?, the image] 232 */ image()233 inline std::pair<bool, const QImage &> image() const 234 { 235 return { !m_image.isNull(), m_image }; 236 } 237 238 private: 239 /** 240 * The unique physical object identifier (hash). 241 */ 242 oid m_object_id; 243 244 /** 245 * A catalog specific identifier. 246 */ 247 QString m_catalog_identifier; 248 249 /** 250 * The id of the catalog, the object is originating from. 251 * 252 * A value of -1 means that the catalog is unknown. This member is 253 * not exposed publicly because it is only useful along with 254 * `m_database_path`. 255 */ 256 int m_catalog_id; 257 258 /** 259 * The database path which this object was loaded from. 260 */ 261 std::reference_wrapper<const QString> m_database_path; 262 263 /** 264 * Whether the image for this catalog object has been loaded. 265 */ 266 bool m_image_loaded{ false }; 267 268 /** 269 * The image for this object (if any). 270 * 271 * @todo use std::optional 272 */ 273 QImage m_image; 274 275 //@{ 276 /** 277 * Astronical metadata. 278 * 279 * Those values may make sense depending on the type of the 280 * object. A value of `-1` always means: "it doesn't make sense 281 * here". 282 */ 283 float m_major_axis; 284 float m_minor_axis; 285 286 double m_position_angle; 287 float m_flux; 288 //@} 289 290 //@{ 291 /** 292 * Update id counters. 293 */ 294 quint64 m_updateID{ 0 }; 295 quint64 m_updateNumID{ 0 }; 296 //@} 297 }; 298