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