File indexing completed on 2024-04-21 14:44:04
0001 /* 0002 SPDX-FileCopyrightText: 2002 Mark Hollomon <mhh@mindspring.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /** @class KSUtils 0008 *@short KStars utility functions 0009 *@author Mark Hollomon 0010 *@version 1.0 0011 *Static functions for various purposes. 0012 *The openDataFile() function searches the standard KDE directories 0013 *for the data filename given as an argument. 0014 *(it is impossible to instantiate a KSUtils object; just use the static functions). 0015 */ 0016 0017 #pragma once 0018 0019 #include "dms.h" 0020 0021 #include <QPointF> 0022 #include <QSharedPointer> 0023 #include <QJsonDocument> 0024 #include <QJsonArray> 0025 #include <QJsonObject> 0026 #include <unordered_map> 0027 0028 #include "config-kstars.h" 0029 // N.B. DO not remove, it is required for compilation. 0030 #include "polyfills/qstring_hash.h" 0031 0032 #if __GNUC__ > 5 0033 #pragma GCC diagnostic push 0034 #pragma GCC diagnostic ignored "-Wignored-attributes" 0035 #endif 0036 #if __GNUC__ > 6 0037 #pragma GCC diagnostic ignored "-Wint-in-bool-context" 0038 #endif 0039 #include <Eigen/Core> 0040 #if __GNUC__ > 5 0041 #pragma GCC diagnostic pop 0042 #endif 0043 0044 #include <cstddef> 0045 0046 class QFile; 0047 class QString; 0048 class QTextStream; 0049 class SkyPoint; 0050 class SkyObject; 0051 class StarObject; 0052 0053 namespace KSUtils 0054 { 0055 // Quick checks whether hardware is limited or not 0056 // right now the only check is architecture. arm processors are limited while x86 are sufficient 0057 bool isHardwareLimited(); 0058 0059 /** Attempt to open the data file named filename, using the QFile object "file". 0060 *First look in the standard KDE directories, then look in a local "data" 0061 *subdirectory. If the data file cannot be found or opened, display a warning 0062 *messagebox. 0063 *@short Open a data file. 0064 *@param file The QFile object to be opened 0065 *@param s The name of the data file. 0066 *@returns bool Returns true if data file was opened successfully. 0067 *@returns a reference to the opened file. 0068 */ 0069 bool openDataFile(QFile &file, const QString &s); 0070 0071 /** Clamp value into range. 0072 * @p x value to clamp. 0073 * @p min minimal allowed value. 0074 * @p max maximum allowed value. 0075 */ 0076 template <typename T> 0077 inline T clamp(T x, T min, T max) 0078 { 0079 if (x < min) 0080 return min; 0081 if (x > max) 0082 return max; 0083 return x; 0084 } 0085 0086 /** Put angle into range. Period is equal to max-min. 0087 * 0088 * @p x angle value 0089 * @p min minimal angle 0090 * @p max maximal angle 0091 */ 0092 template <typename T> 0093 inline T reduceAngle(T x, T min, T max) 0094 { 0095 T delta = max - min; 0096 return x - delta * floor((x - min) / delta); 0097 } 0098 0099 /** Convert from spherical to cartesian coordinate system. 0100 * Resulting vector have unit length 0101 */ 0102 inline Eigen::Vector3d fromSperical(const dms &longitude, const dms &latitude) 0103 { 0104 double sinL, sinB; 0105 double cosL, cosB; 0106 0107 longitude.SinCos(sinL, cosL); 0108 latitude.SinCos(sinB, cosB); 0109 return Eigen::Vector3d(cosB * cosL, cosB * sinL, sinB); 0110 } 0111 0112 /** Convert a vector to a point */ 0113 inline QPointF vecToPoint(const Eigen::Vector2f &vec) 0114 { 0115 return QPointF(vec[0], vec[1]); 0116 } 0117 0118 /** Convert a point to a vector */ 0119 inline Eigen::Vector2f pointToVec(const QPointF &p) 0120 { 0121 return Eigen::Vector2f(p.x(), p.y()); 0122 } 0123 0124 /** 0125 *@short Create a URL to obtain a DSS image for a given SkyPoint 0126 *@note If SkyPoint is a DeepSkyObject, this method automatically 0127 *decides the image size required to fit the object. 0128 */ 0129 QString getDSSURL(const SkyPoint *const p); 0130 0131 /** 0132 *@short Create a URL to obtain a DSS image for a given RA, Dec 0133 *@param ra The J2000.0 Right Ascension of the point 0134 *@param dec The J2000.0 Declination of the point 0135 *@param width The width of the image in arcminutes 0136 *@param height The height of the image in arcminutes 0137 *@param type The image type, either gif or fits. 0138 *@note This method resets height and width to fall within the range accepted by DSS 0139 */ 0140 QString getDSSURL(const dms &ra, const dms &dec, float width = 0, float height = 0, 0141 const QString &type = "gif"); 0142 0143 /** 0144 *@short Return a string corresponding to an angle specifying direction 0145 * 0146 * The angle must measure direction from North, towards East. Both 0147 * the azimuth and position angle follow this convention, so this 0148 * method can be used to return a string corresponding to the 0149 * general heading of a given azimuth / position angle. 0150 * 0151 *@param angle angle as dms (measured from North, towards East) 0152 *@return A localized string corresponding to the approximate direction (eg: NNW) 0153 */ 0154 QString toDirectionString(dms angle); 0155 /** 0156 *@short Converts StarObject list into SkyObject list 0157 *@param starObjList QList of StarObject pointers 0158 *@return Returns a pointer to QList of SkyObject pointers 0159 *@note Used for Star-Hopper 0160 */ 0161 QList<SkyObject *> *castStarObjListToSkyObjList(QList<StarObject *> *starObjList); 0162 0163 /** 0164 *@note Avoid using this method for the same reasons as QSharedPointer::data() 0165 */ 0166 template <typename T> 0167 QList<T *> makeVanillaPointerList(const QList<QSharedPointer<T>> &spList) 0168 { 0169 QList<T *> vpList; 0170 foreach (QSharedPointer<T> sp, spList) 0171 vpList.append(sp.data()); 0172 return vpList; 0173 } 0174 0175 /** 0176 *@short Return the genetive form of constellation name, given the abbreviation 0177 *@param code Three-letter IAU abbreviation of the constellation 0178 *@return the genetive form of the constellation name 0179 */ 0180 QString constGenetiveFromAbbrev(const QString &code); 0181 0182 /** 0183 *@short Return the name of the constellation, given the abbreviation 0184 *@param code Three-letter IAU abbreviation of the constellation 0185 *@return the nominative form of the constellation name 0186 */ 0187 QString constNameFromAbbrev(const QString &code); 0188 0189 /** 0190 *@short Return the abbreviation of the constellation, given the full name 0191 *@param fullName_ Full name of the constellation 0192 *@return the three-letter IAU standard abbreviation of the constellation 0193 */ 0194 QString constNameToAbbrev(const QString &fullName_); 0195 0196 /** 0197 *@short Return the abbreviation of the constellation, given the genetive form 0198 *@param genetive_ the genetive form of the constellation's name 0199 *@return the three-letter IAU standard abbreviation of the constellation 0200 */ 0201 QString constGenetiveToAbbrev(const QString &genetive_); 0202 0203 /** 0204 * Interface into Qt's logging system 0205 * @author: Yale Dedis 2011 0206 * Adapted from DeDiS project. 0207 */ 0208 class Logging 0209 { 0210 public: 0211 /** 0212 * Store all logs into the specified file 0213 */ 0214 static void UseFile(); 0215 0216 /** 0217 * Output logs to stdout 0218 */ 0219 static void UseStdout(); 0220 0221 /** 0222 * Output logs to stderr 0223 */ 0224 static void UseStderr(); 0225 0226 /** 0227 * Use the default logging mechanism 0228 */ 0229 static void UseDefault(); 0230 0231 /** 0232 * Disable logging 0233 */ 0234 static void Disable(); 0235 0236 /** 0237 * @brief SyncFilterRules Sync QtLogging filter rules from Options 0238 */ 0239 static void SyncFilterRules(); 0240 0241 private: 0242 static QString _filename; 0243 0244 static void Disabled(QtMsgType type, const QMessageLogContext &context, 0245 const QString &msg); 0246 static void File(QtMsgType type, const QMessageLogContext &context, 0247 const QString &msg); 0248 static void Stdout(QtMsgType type, const QMessageLogContext &context, 0249 const QString &msg); 0250 static void Stderr(QtMsgType type, const QMessageLogContext &context, 0251 const QString &msg); 0252 static void Write(QTextStream &stream, QtMsgType type, 0253 const QMessageLogContext &context, const QString &msg); 0254 }; 0255 0256 QString getDefaultPath(const QString &option); 0257 0258 #ifdef Q_OS_OSX 0259 void copyResourcesFolderFromAppBundle(QString folder); 0260 bool setupMacKStarsIfNeeded(); //The boolean returns true if the data folders are good to go. 0261 bool configureAstrometry(); 0262 bool replaceIndexFileNotYetSet(); 0263 bool copyRecursively(QString sourceFolder, QString destFolder); 0264 #endif 0265 0266 // Astrometry Related functions 0267 QStringList getAstrometryDefaultIndexFolderPaths(); 0268 QString getAstrometryConfFilePath(); 0269 QStringList getAstrometryDataDirs(); 0270 bool addAstrometryDataDir(const QString &dataDir); 0271 bool removeAstrometryDataDir(const QString &dataDir); 0272 0273 struct JPLFilter 0274 { 0275 QByteArray item; 0276 QByteArray op; 0277 QByteArray value; 0278 }; 0279 0280 class JPLParser 0281 { 0282 public: 0283 JPLParser(const QString &path); 0284 0285 const QJsonArray &data() const 0286 { 0287 return m_data; 0288 } 0289 const std::unordered_map<QString, int> &fieldMap() const 0290 { 0291 return m_field_map; 0292 } 0293 0294 template <typename Lambda> 0295 void for_each(const Lambda &fct) 0296 { 0297 for (const auto &item : m_data) 0298 { 0299 fct([ &, this](const QString & key) 0300 { 0301 return item.toArray().at(m_field_map.at(key)); 0302 }); 0303 } 0304 }; 0305 0306 private: 0307 QJsonDocument m_doc; 0308 QJsonArray m_data; 0309 std::unordered_map<QString, int> m_field_map; 0310 }; 0311 // TODO: Implement Datatypes//Maps for kind, datafields, filters... 0312 0313 class MPCParser 0314 { 0315 public: 0316 MPCParser(const QString &path); 0317 0318 template <typename Lambda> 0319 void for_each(const Lambda &fct) 0320 { 0321 for (const auto &item : m_data) 0322 { 0323 fct([ &, this](const QString & key) 0324 { 0325 return item.toObject().value(key); 0326 }); 0327 } 0328 }; 0329 0330 private: 0331 QJsonDocument m_doc; 0332 QJsonArray m_data; 0333 }; 0334 0335 /** 0336 *@short Generate a query string for downloading comet/asteroid data from JPL. 0337 *@param kind The kind of object we want: ast, com. 0338 *@param dataFields The columns we want to download. 0339 *@param filters Filters for the Data. 0340 *@return The query string. 0341 */ 0342 QByteArray getJPLQueryString(const QByteArray &kind, const QByteArray &dataFields, 0343 const QVector<JPLFilter> &filters); 0344 0345 /** 0346 * @brief RAWToJPEG Convert raw image (e.g. CR2) using libraw to a JPEG image 0347 * @param rawImage full path to raw image 0348 * @param output full path to jpeg image to write to 0349 * @return True if conversion is successful, false otherwise. 0350 */ 0351 bool RAWToJPEG(const QString &rawImage, const QString &output, QString &errorMessage); 0352 0353 /** 0354 * @brief getAvailableRAM Try to get available and total RAM on system 0355 * @return availableRAM Available (free and unclaimed) system RAM in bytes. 0 if failed to determine RAM 0356 */ 0357 double getAvailableRAM(); 0358 0359 void setGlobalSettings(const QVariantMap &settings); 0360 0361 /** 0362 * @brief sanitize Remove all illegal characters and spaces that can be problematic in file paths across all OSes. 0363 * @param text String to sanitize 0364 * @return Sanitized text 0365 */ 0366 QString sanitize(const QString &text); 0367 0368 /** 0369 * @brief rangePA Limit position angle to -180 to +180 range 0370 * @param pa Position angle 0371 * @return limited position angle 0372 */ 0373 double rangePA(double pa); 0374 0375 /** 0376 * @brief range360 Limit angle to be in 0 to 360 range 0377 * @param r angle in degrees 0378 * @return Limited angle in degrees 0379 */ 0380 double range360(double r); 0381 0382 /** 0383 * @brief rotationToPositionAngle Convert from astrometry.net rotation to PA 0384 * @param value rotation in degrees (-180 to +180) 0385 * @return Position angle in degrees (-180 to +180) 0386 */ 0387 double rotationToPositionAngle(double value); 0388 0389 /** @brief rotationToPositionAngle Convert from position angle to astrometry.net rotation 0390 * @param value Position angle in degrees (-180 to +180) 0391 * @return rotation in degrees (-180 to +180) 0392 */ 0393 double positionAngleToRotation(double value); 0394 0395 } // namespace KSUtils