File indexing completed on 2024-04-14 03:43:17

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 #include "approachsolver.h"
0009 #include <kstars_debug.h>
0010 
0011 ApproachSolver::ApproachSolver(QObject *parent) : QObject(parent)
0012 {
0013     m_geoPlace = KStarsData::Instance()->geo();
0014     m_Earth = KSPlanet(i18n("Earth"), QString(), QColor("white"), 12756.28 /*diameter in km*/);
0015 }
0016 
0017 void ApproachSolver::setGeoLocation(GeoLocation *geo)
0018 {
0019     if (geo != nullptr)
0020         m_geoPlace = geo;
0021     else
0022         m_geoPlace = KStarsData::Instance()->geo();
0023 }
0024 
0025 // FIXME: We need a better algo for finding approaches!
0026 QMap<long double, dms> ApproachSolver::findClosestApproach(long double startJD,
0027         long double stopJD, std::function<void (long double, dms)> const &callback)
0028 {
0029     QMap<long double, dms> Separations;
0030     QPair<long double, dms> extremum;
0031     dms Dist;
0032     dms prevDist;
0033 
0034     double step, step0;
0035     int Sign, prevSign;
0036 
0037     //  qCDebug(KSTARS) << "Entered KSConjunct::findClosestApproach() with startJD = " << (double)startJD;
0038     //  qCDebug(KSTARS) << "Initial Positional Information: \n";
0039     //  qCDebug(KSTARS) << m_object1->name() << ": RA = " << m_object1->ra() -> toHMSString() << "; Dec = " << m_object1->dec() -> toDMSString() << "\n";
0040     //  qCDebug(KSTARS) << m_object2->name() << ": RA = " << m_object2->ra() -> toHMSString() << "; Dec = " << m_object2->dec() -> toDMSString() << "\n";
0041     prevSign = 0;
0042 
0043     step0 = findInitialStep(startJD, stopJD);
0044     step = step0;
0045     //  qCDebug(KSTARS) << "Initial Separation between " << m_object1->name() << " and " << m_object2->name() << " = " << (prevDist.toDMSString());
0046 
0047     long double jd = startJD;
0048     prevDist       = updateAndFindDistance(jd);
0049     jd += step;
0050     while (jd <= stopJD)
0051     {
0052         int progress = int(100.0 * (jd - startJD) / (stopJD - startJD));
0053         emit solverMadeProgress(progress);
0054 
0055         Dist = updateAndFindDistance(jd);
0056         Sign = sgn(Dist - prevDist);
0057         //  qCDebug(KSTARS) << "Dist = " << Dist.toDMSString() << "; prevDist = " << prevDist.toDMSString() << "; Difference = " << (Dist.Degrees() - prevDist.Degrees()) << "; Step = " << step;
0058 
0059         //How close are we to a conjunction, and how fast are we approaching one?
0060         double factor = fabs((Dist.Degrees() - prevDist.Degrees()) / Dist.Degrees());
0061         if (factor > 10.0) //let's go faster!
0062         {
0063             step = step0 * factor / 10.0;
0064         }
0065         else //slow down, we're getting close!
0066         {
0067             step = step0;
0068         }
0069 
0070         if (Sign != prevSign && prevSign == -1) //all right, we may have just passed a conjunction
0071         {
0072             if (step > step0) //mini-loop to back up and make sure we're close enough
0073             {
0074                 //            qCDebug(KSTARS) << "Entering slow loop: ";
0075                 jd -= step;
0076                 step = step0;
0077                 Sign = prevSign;
0078                 while (jd <= stopJD)
0079                 {
0080                     Dist = updateAndFindDistance(jd);
0081                     Sign = sgn(Dist - prevDist);
0082                     //  qCDebug(KSTARS) << "Dist=" << Dist.toDMSString() << "; prevDist=" << prevDist.toDMSString() << "; Diff=" << (Dist.Degrees() - prevDist.Degrees()) << "djd=" << (int)(jd - startJD);
0083                     if (Sign != prevSign)
0084                         break;
0085 
0086                     prevDist = Dist;
0087                     prevSign = Sign;
0088                     jd += step;
0089                 }
0090             }
0091 
0092             //  qCDebug(KSTARS) << "Sign = " << Sign << " and " << "prevSign = " << prevSign << ": Entering findPrecise()\n";
0093             if (findPrecise(&extremum, jd, step, Sign))
0094             {
0095                 if (extremum.second.radians() < getMaxSeparation())
0096                 {
0097                     Separations.insert(extremum.first, extremum.second);
0098 
0099                     if(callback)
0100                         callback(extremum.first, extremum.second);
0101                 }
0102             }
0103         }
0104 
0105         prevDist = Dist;
0106         prevSign = Sign;
0107         jd += step;
0108     }
0109 
0110     return Separations;
0111 }
0112 
0113 bool ApproachSolver::findPrecise(QPair<long double, dms> *out, long double jd,
0114                                  double step, int prevSign)
0115 {
0116     dms prevDist;
0117     int Sign;
0118     dms Dist;
0119 
0120     if (out == nullptr)
0121     {
0122         qCDebug(KSTARS) << "ERROR: Argument out to KSConjunct::findPrecise(...) was nullptr!";
0123         return false;
0124     }
0125 
0126     prevDist = updateAndFindDistance(jd);
0127 
0128     step     = -step / 2.0;
0129     prevSign = -prevSign;
0130 
0131     while (true)
0132     {
0133         jd += step;
0134         Dist = updateAndFindDistance(jd);
0135         //    qCDebug(KSTARS) << "Dist=" << Dist.toDMSString() << "; prevDist=" << prevDist.toDMSString() << "; Diff=" << (Dist.Degrees() - prevDist.Degrees()) << "step=" << step;
0136 
0137         if (fabs(step) < 1.0 / (24.0 * 60.0))
0138         {
0139             out->first  = jd - step / 2.0;
0140             out->second = updateAndFindDistance(jd - step / 2.0);
0141             if (out->second.radians() < updateAndFindDistance(jd - 5.0).radians())
0142                 return true;
0143             else
0144                 return false;
0145         }
0146         Sign = sgn(Dist - prevDist);
0147         if (Sign != prevSign)
0148         {
0149             step = -step / 2.0;
0150             Sign = -Sign;
0151         }
0152         prevSign = Sign;
0153         prevDist = Dist;
0154     }
0155 }
0156 
0157 dms ApproachSolver::findSkyPointDistance(SkyPoint * obj1, SkyPoint * obj2)
0158 {
0159     dms dist;
0160     dist.setRadians(obj1->angularDistanceTo(obj2).radians());
0161     return dist;
0162 }
0163 
0164 int ApproachSolver::sgn(dms a)
0165 {
0166     // Auxiliary function used by the KSConjunct::findClosestApproach(...)
0167     // method and the KSConjunct::findPrecise(...) method
0168 
0169     return ((a.radians() > 0) ? 1 : ((a.radians() < 0) ? -1 : 0));
0170 }
0171