File indexing completed on 2025-01-19 09:45:57
0001 /* 0002 SPDX-FileCopyrightText: 2001 Jason Harris <jharris@30doradus.org> 0003 SPDX-FileCopyrightText: 2021 Valentin Boettcher <hiro at protagon.space; @hiro98:tchncs.de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include "skycomponent.h" 0011 #include "catalogsdb.h" 0012 #include "catalogobject.h" 0013 #include "skymesh.h" 0014 #include "trixelcache.h" 0015 #include "Options.h" 0016 0017 #include "polyfills/qstring_hash.h" 0018 #include <unordered_map> 0019 0020 class SkyMesh; 0021 class SkyMap; 0022 0023 /** 0024 * \brief Represents objects loaded from an sqlite backed, trixel 0025 * indexed catalog. 0026 * 0027 * The component doesn't follow the traditional list approach and 0028 * loads it's skyobjects into an LRU cache (`TrixelCache`). For 0029 * puproses of compatiblility with object search etc. some of the 0030 * brightest objects are loaded into `m_static_objects` and registered 0031 * within the component system. Furthermore, if some part of the code 0032 * demands a pointer to a CatalogObject, it will be allocated into 0033 * `m_static_objects` on demand. 0034 * 0035 * If you want to access DSOs in _new_ code you should use a local 0036 * instance of `CatalogsDB::DBManager` instead and call `dropCache` if 0037 * necessary. 0038 * 0039 * \sa CatalogsDB::DBManager 0040 */ 0041 class CatalogsComponent : public SkyComponent 0042 { 0043 public: 0044 using ObjectList = std::vector<CatalogObject>; 0045 0046 /** 0047 * Constructs the Catalogscomponent with a \p parent and a 0048 * database file under the path \p db_filename. If \p load_ngc is 0049 * specified, an attempt is made to load the default catalog from 0050 * the default location into the db. 0051 * 0052 * The lru cache for the objects will be initialized to a capacity 0053 * configurable by Options::dSOCachePercentage. 0054 */ 0055 explicit CatalogsComponent(SkyComposite *parent, const QString &db_filename, 0056 bool load_default = false); 0057 0058 ~CatalogsComponent() override = default; 0059 0060 /** 0061 * Draws the objects in the currently visible trixels by 0062 * dynamically loading them from the database. 0063 */ 0064 void draw(SkyPainter *skyp) override; 0065 0066 /** 0067 * Set the cache size to the new \p percentage. 0068 * 0069 * The cache stores the objects of a certain \p percentage of all 0070 * trixels. Setting `percentage = 100` short circuits the cache and loads 0071 * all the objects into memory. This is reasonable for catalog sizes up 0072 * to `10_000` objects. 0073 */ 0074 void resizeCache(const int percentage) 0075 { 0076 m_mainCache.set_size(calculateCacheSize(percentage)); 0077 m_unknownMagCache.set_size(calculateCacheSize(percentage)); 0078 }; 0079 0080 /** 0081 * \short Search the underlying database for an object with the \p 0082 * name. \sa `CatalogsDB::DBManager::find_object_by_name` for 0083 * details. 0084 * 0085 * If multiple objects match, the one with the hightest magnitude is 0086 * returned. 0087 * 0088 * \return a pointer to the SkyObject whose name matches the argument, or 0089 * a nullptr pointer if no match was found. (Due to way KStars works) 0090 */ 0091 SkyObject *findByName(const QString &name, bool exact = true) override; 0092 0093 void objectsInArea(QList<SkyObject *> &list, const SkyRegion ®ion) override; 0094 0095 SkyObject *objectNearest(SkyPoint *p, double &maxrad) override; 0096 0097 /** 0098 * Insert an object \p obj into `m_static_objects` and return a 0099 * reference to the newly inserted object. If the object is 0100 * already present in the list, return a reference to 0101 * that. Furthermore the object will be updated 0102 * (`CatalogObject::JITupdate`) and inserted into the parent's 0103 * `objectLists`. 0104 */ 0105 CatalogObject &insertStaticObject(const CatalogObject &obj); 0106 0107 /** 0108 * Clear the internal cache and effectively reload all objects 0109 * from the database. 0110 */ 0111 void dropCache() 0112 { 0113 m_mainCache.clear(); 0114 m_unknownMagCache.clear(); 0115 m_catalog_colors = m_db_manager.get_catalog_colors(); 0116 }; 0117 0118 /** 0119 * Wether to show the DSOs. 0120 */ 0121 bool selected() override 0122 { 0123 return Options::showDeepSky(); 0124 }; 0125 0126 private: 0127 /** 0128 * The database interface for the catalog. 0129 */ 0130 CatalogsDB::DBManager m_db_manager; 0131 0132 /** 0133 * A pointer to a SkyMesh of the appropriate level. 0134 * 0135 * @note The use of a pointer here is a legacy from the 0136 * SkyComponent implementation. 0137 */ 0138 SkyMesh *m_skyMesh; 0139 0140 /** 0141 * The main container for the currently loaded objects. 0142 */ 0143 ObjectList m_objects; 0144 0145 /** 0146 * The cache holding the DSOs of known magnitude 0147 */ 0148 TrixelCache<ObjectList> m_mainCache; 0149 0150 /** 0151 * The cache holding the DSOs of unknown magnitude 0152 */ 0153 TrixelCache<ObjectList> m_unknownMagCache; 0154 0155 /** 0156 * A trixel indexed map of lists containing manually loaded 0157 * `CatalogObject`s. 0158 * 0159 * Because some `KStars` internal code requires pointers to SkyObjects 0160 * and this component doesn't hold its objects, we have create a space to 0161 * to own the objets that we create in methods like `findByName`. Thus it 0162 * is expected that this list won't hold many objects and doesn't have to 0163 * be emptied at runtime. The objects in this map are not drawn and have 0164 * to be updated manually. 0165 * 0166 * __No objects should ever be removed from this list, as references and 0167 * pointers to list members are required to remain valid.__ 0168 * 0169 * __In new code, a local instance of `CatalogsDB::DBManager` should be 0170 * used when access to CatalogObjects is required. Call `dropCache` if 0171 * required.__ 0172 */ 0173 std::unordered_map<Trixel, CatalogsDB::CatalogObjectList> m_static_objects; 0174 0175 /** 0176 * A cache for catalog colors. 0177 */ 0178 CatalogsDB::ColorMap m_catalog_colors; 0179 0180 //@{ 0181 /** Helpers */ 0182 0183 void updateSkyMesh(SkyMap &map, MeshBufNum_t buf = DRAW_BUF); 0184 size_t calculateCacheSize(const unsigned int percentage) 0185 { 0186 return m_skyMesh->size() * percentage / 100.f; 0187 } 0188 0189 /** 0190 * Try importing the old skycomponents database. 0191 */ 0192 void tryImportSkyComponents(); 0193 0194 //@} 0195 };