File indexing completed on 2024-05-05 15:57:12
0001 /* 0002 SPDX-FileCopyrightText: 2018 Valentin Boettcher <valentin@boettcher.cf> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "lunareclipsehandler.h" 0008 #include "skymapcomposite.h" 0009 #include "solarsystemcomposite.h" 0010 #include "dms.h" 0011 0012 LunarEclipseHandler::LunarEclipseHandler(QObject * parent) : EclipseHandler(parent), 0013 m_sun(), m_moon(), m_shadow(&m_moon, &m_sun, &m_Earth) 0014 { 0015 } 0016 0017 EclipseHandler::EclipseVector LunarEclipseHandler::computeEclipses(long double startJD, long double endJD) 0018 { 0019 m_mode = CLOSEST_APPROACH; 0020 0021 const long double SEARCH_INTERVAL = 5.l; // Days 0022 0023 QVector<EclipseEvent_s> eclipses; 0024 QVector<long double> fullMoons = getFullMoons(startJD, endJD); 0025 0026 int total = fullMoons.length(); 0027 if (total == 0) 0028 return eclipses; 0029 0030 float step = 1 / total; 0031 float progress = 0; 0032 0033 connect(this, &ApproachSolver::solverMadeProgress, this, [ &, this] (int dProgress) 0034 { 0035 float tmpProgress = roundf(progress + step * dProgress); 0036 if (tmpProgress > progress) 0037 { 0038 progress = tmpProgress; 0039 emit signalProgress(static_cast<int>(progress)); 0040 } 0041 }); 0042 0043 for(auto date : fullMoons) 0044 { 0045 findClosestApproach(date, date + SEARCH_INTERVAL, [&eclipses, this] (long double JD, dms) 0046 { 0047 EclipseEvent::ECLIPSE_TYPE type; 0048 updatePositions(JD); 0049 0050 KSEarthShadow::ECLIPSE_TYPE extended_type = m_shadow.getEclipseType(); 0051 switch (extended_type) 0052 { 0053 case KSEarthShadow::FULL_PENUMBRA: 0054 case KSEarthShadow::FULL_UMBRA: 0055 type = EclipseEvent::FULL; 0056 break; 0057 case KSEarthShadow::NONE: 0058 return; 0059 default: 0060 type = EclipseEvent::PARTIAL; 0061 break; 0062 } 0063 0064 EclipseEvent_s event = std::make_shared<LunarEclipseEvent>(JD, *getGeoLocation(), type, extended_type); 0065 emit signalEventFound(event); 0066 eclipses.append(event); 0067 }); 0068 0069 progress++; 0070 emit signalProgress(static_cast<int>(roundf(100 * (progress / total)))); 0071 } 0072 0073 emit signalProgress(100); 0074 emit signalComputationFinished(); 0075 return eclipses; 0076 } 0077 0078 // FIXME: (Valentin) This doesn't work for now. We need another method. 0079 LunarEclipseDetails LunarEclipseHandler::findEclipseDetails(LunarEclipseEvent *event) 0080 { 0081 Q_UNUSED(event); 0082 // const long double INTERVAL = 1.l; 0083 0084 // const long double JD = event->getJD(); 0085 // const long double start = JD - INTERVAL; 0086 // const long double stop = JD + INTERVAL; 0087 0088 LunarEclipseDetails details; 0089 // details.available = true; 0090 // details.eclipseTimes.insert(JD, LunarEclipseDetails::CLOSEST_APPROACH); 0091 0092 // auto type = event->getDetailedType(); 0093 // auto findBoth = [&](LunarEclipseDetails::EVENT ev1 /* first (temporal) */, LunarEclipseDetails::EVENT ev2) { 0094 // QMap<long double, dms> tmpApproaches; 0095 0096 // QPair<long double, dms> out; 0097 // findPrecise(&out, JD, 0.001, -1); 0098 // details.eclipseTimes.insert(out.first, ev1); 0099 0100 // findPrecise(&out, JD, 0.001, 1); 0101 // details.eclipseTimes.insert(out.first, ev2); 0102 // }; 0103 0104 // // waterfall method... 0105 0106 // if(type == KSEarthShadow::NONE) { 0107 // details.available = false; 0108 // return details; 0109 // } 0110 0111 // if(type == KSEarthShadow::FULL_UMBRA) { 0112 // m_mode = UMBRA_IMMERSION; 0113 // findBoth(LunarEclipseDetails::BEGIN_FULL_PENUMRA, LunarEclipseDetails::END_FULL_PENUMRA); 0114 0115 // m_mode = UMBRA_CONTACT; 0116 // findBoth(LunarEclipseDetails::BEGIN_UMBRA_CONTACT, LunarEclipseDetails::END_UMBRA_CONTACT); 0117 // } 0118 0119 //// if(type == KSEarthShadow::FULL_PENUMBRA || type == KSEarthShadow::FULL_UMBRA) { 0120 0121 //// m_mode = UMR 0122 //// }; 0123 return details; 0124 0125 } 0126 0127 LunarEclipseHandler::~LunarEclipseHandler() 0128 { 0129 0130 } 0131 0132 void LunarEclipseHandler::updatePositions(long double jd) 0133 { 0134 KStarsDateTime t(jd); 0135 KSNumbers num(jd); 0136 CachingDms LST(getGeoLocation()->GSTtoLST(t.gst())); 0137 const CachingDms * LAT = getGeoLocation()->lat(); 0138 0139 m_Earth.findPosition(&num); 0140 m_sun.findPosition(&num, LAT, &LST, &m_Earth); 0141 m_moon.findPosition(&num, LAT, &LST, &m_Earth); 0142 m_shadow.findPosition(&num, LAT, &LST, &m_Earth); 0143 } 0144 0145 dms LunarEclipseHandler::findDistance() 0146 { 0147 dms moon_rad = dms(m_moon.angSize() / 120); 0148 dms pen_rad = dms(m_shadow.getPenumbraAngSize() / 60); 0149 dms um_rad = dms(m_shadow.getUmbraAngSize() / 60); 0150 0151 dms dist = findSkyPointDistance(&m_shadow, &m_moon); 0152 switch (m_mode) 0153 { 0154 case CLOSEST_APPROACH: 0155 return dist; 0156 case PENUMBRA_CONTACT: 0157 return dist - (moon_rad + pen_rad); 0158 case PUNUMBRA_IMMERSION: 0159 return dist + moon_rad - pen_rad; 0160 case UMBRA_CONTACT: 0161 return dist - (moon_rad + um_rad); 0162 case UMBRA_IMMERSION: 0163 return dist + moon_rad - um_rad; 0164 } 0165 0166 return dms(); 0167 } 0168 0169 double LunarEclipseHandler::getMaxSeparation() 0170 { 0171 const double SEP_QUALITY = 0.1; 0172 0173 // we use the penumbra as measure :) 0174 if(m_mode == CLOSEST_APPROACH) 0175 return (m_shadow.getPenumbraAngSize() + m_moon.angSize()) / 60; 0176 else 0177 return SEP_QUALITY; 0178 } 0179 0180 QVector<long double> LunarEclipseHandler::getFullMoons(long double startJD, long double endJD) 0181 { 0182 const long double NEXT_STEP = 0.5l; 0183 const long double INTERVAL = 26.5l; 0184 long double ¤tJD = startJD; 0185 0186 QVector<long double> fullMoons; 0187 while(currentJD <= endJD) 0188 { 0189 KStarsDateTime t(currentJD); 0190 KSNumbers num(currentJD); 0191 CachingDms LST = getGeoLocation()->GSTtoLST(t.gst()); 0192 0193 m_sun.updateCoords(&num, true, getGeoLocation()->lat(), &LST, true); 0194 m_moon.updateCoords(&num, true, getGeoLocation()->lat(), &LST, true); 0195 m_moon.findPhase(&m_sun); 0196 0197 if(m_moon.illum() > 0.9) 0198 { 0199 fullMoons.append(currentJD); 0200 currentJD += INTERVAL; 0201 continue; 0202 } 0203 0204 currentJD += NEXT_STEP; 0205 } 0206 0207 return fullMoons; 0208 } 0209 0210 LunarEclipseEvent::LunarEclipseEvent(long double jd, GeoLocation geoPlace, EclipseEvent::ECLIPSE_TYPE type, KSEarthShadow::ECLIPSE_TYPE detailed_type) 0211 : EclipseEvent (jd, geoPlace, type), m_detailedType { detailed_type } 0212 { 0213 m_details.available = false; 0214 } 0215 0216 QString LunarEclipseEvent::getExtraInfo() 0217 { 0218 switch(m_detailedType) 0219 { 0220 case KSEarthShadow::FULL_UMBRA: 0221 return "Full Umbral"; 0222 case KSEarthShadow::FULL_PENUMBRA: 0223 return "Full Penumbral"; 0224 case KSEarthShadow::PARTIAL: 0225 case KSEarthShadow::NONE: 0226 return ""; 0227 } 0228 return ""; 0229 } 0230 0231 SkyObject *LunarEclipseEvent::getEclipsingObjectFromSkyComposite() 0232 { 0233 return KStarsData::Instance()->skyComposite()->solarSystemComposite()->moon(); 0234 } 0235 0236 void LunarEclipseEvent::slotShowDetails() 0237 { 0238 if(!m_details.available) 0239 { 0240 LunarEclipseHandler handler; 0241 GeoLocation loc = getGeolocation(); 0242 handler.setGeoLocation(&loc); 0243 handler.findEclipseDetails(this); 0244 } 0245 }