File indexing completed on 2024-04-21 03:44:48

0001 /*
0002     SPDX-FileCopyrightText: 2008 Akarsh Simha <akarsh.simha@kdemail.net>
0003     SPDX-FileCopyrightText: 2018 Valentin Boettcher <valentin@boettcher.cf>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 #include "dms.h"
0010 #include "skyobjects/ksplanet.h"
0011 #include "skycomponents/typedef.h"
0012 
0013 #include <QObject>
0014 #include <QMap>
0015 #include <memory>
0016 
0017 /**
0018  * @class ApproachSolver
0019  * @short Implements algorithms to find close approaches of two objects on the sky.
0020  * A class that implements a method to compute close approaches between any two solar system
0021  * objects excluding planetary moons. Given two such objects, this class has implementations of
0022  * algorithms required to find the time of closest approach in a given range of time. It is meant
0023  * to be subclassed and provides the boilerplate (+ common interface) for classes like KSKonjunct
0024  * and EclipseHandler.
0025  *
0026  * @author Akarsh Simha
0027  * @version 2.0
0028  */
0029 class ApproachSolver : public QObject
0030 {
0031     Q_OBJECT
0032 public:
0033     explicit ApproachSolver(QObject *parent = nullptr);
0034 
0035     /**
0036      * @short Sets the geographic location to compute conjunctions at
0037      *
0038      * @param geo  Pointer to the GeoLocation object
0039      */
0040     void setGeoLocation(GeoLocation *geo);
0041 
0042     /**
0043      * @short Compute the closest approach of two planets in the given range
0044      *
0045      * @param startJD  Julian Day corresponding to start of the calculation period
0046      * @param stopJD   Julian Day corresponding to end of the calculation period
0047      * @param callback A callback function
0048      * @return Hash containing julian days of close conjunctions against separation
0049      */
0050     QMap<long double, dms> findClosestApproach(long double startJD,
0051                                                long double stopJD,
0052                                                const std::function<void (long double, dms)> &callback = {}); // FIXME: QMap is awkward!
0053 
0054     /**
0055      * @brief getGeoLocation
0056      * @return the currently set GeoLocation
0057      */
0058     GeoLocation * getGeoLocation() { return m_geoPlace; }
0059 
0060 
0061     /**
0062      * @brief setMaxSeparation
0063      * @param sep - maximum allowed anglar separation
0064      */
0065     void setMaxSeparation(double sep) { m_maxSeparation = sep; }
0066     void setMaxSeparation(dms sep) { m_maxSeparation = sep.radians(); }
0067 
0068 signals:
0069     /**
0070      * @brief solverMadeProgress
0071      * @param progress - progress in percent
0072      */
0073     void solverMadeProgress(int progress);
0074 
0075 protected:
0076     // TODO: This one may be moved to KSConjunct
0077 
0078     /**
0079      * @brief getMaxSeparation
0080      * @return the maximum separation allowed, based on the (guaranteed to be up-to-date)
0081      * parameters of the objects if overwritten. Here it's just a constant.
0082      */
0083     virtual double getMaxSeparation() { return m_maxSeparation; }
0084 
0085     /**
0086      * @brief findSkyPointDistance
0087      * @param obj1
0088      * @param obj2
0089      * @return the angular distance between two SkyPoints in arcminutes
0090      */
0091     dms findSkyPointDistance(SkyPoint * obj1, SkyPoint * obj2);
0092 
0093     /**
0094      * @short Finds the angular distance between two solar system objects.
0095      * @return The angular distance between the two bodies.
0096      */
0097     virtual dms findDistance() = 0;
0098 
0099     /**
0100      * @brief updatePositions
0101      * @short Update the positions of the objects involved.
0102      * @param jd  Julian Day corresponding to the time of computation
0103      */
0104     virtual void updatePositions(long double jd) = 0;
0105 
0106     /**
0107      * @brief findStep
0108      * @return the step size used by findClosestApproach (in Julian Days)
0109      *
0110      * @short Make this as big as possible. The bigger it is, the more likely is a skip over...
0111      */
0112     virtual double findInitialStep(long double startJD, long double stopJD) = 0;
0113 
0114     /**
0115      * @short Compute the precise value of the extremum once the extremum has been detected.
0116      *
0117      * @param out  A pointer to a QPair that stores the Julian Day and Separation corresponding to the extremum
0118      * @param jd  Julian day corresponding to the endpoint of the interval where extremum was detected.
0119      * @param step  The step in jd taken during computation earlier. (Defines the interval size)
0120      * @param prevSign The previous sign of increment in moving from jd - step to jd
0121      *
0122      * @return true if the extremum is a minimum
0123      */
0124     bool findPrecise(QPair<long double, dms> *out, long double jd,
0125                      double step, int prevSign);
0126 
0127     KSPlanet m_Earth;
0128 
0129 private:
0130     /**
0131      * @brief updateAndFindDistance
0132      * @param jd Julian Date for which to calculate
0133      * @return output of ApproachSolver::findDistance
0134      */
0135     dms updateAndFindDistance(long double jd) {
0136         updatePositions(jd);
0137         return findDistance();
0138     }
0139 
0140     /**
0141      * @short Return the sign of an angle
0142      *
0143      * @param a  The angle whose sign has to be returned
0144      *
0145      * @return (-1, 0, 1) if a.radians() is (-ve, zero, +ve)
0146      */
0147     int sgn(dms a);
0148 
0149     GeoLocation * m_geoPlace { nullptr };
0150     double m_maxSeparation;
0151 };