File indexing completed on 2024-04-14 14:12:12
0001 /* 0002 SPDX-FileCopyrightText: 2016 Akarsh Simha <akarsh.simha@kdemail.net> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /* Project Includes */ 0008 #include "test_skypoint.h" 0009 #include "ksnumbers.h" 0010 #include "time/kstarsdatetime.h" 0011 #include "auxiliary/dms.h" 0012 #include "Options.h" 0013 #include <libnova/libnova.h> 0014 TestSkyPoint::TestSkyPoint() : QObject() 0015 { 0016 useRelativistic = Options::useRelativistic(); 0017 } 0018 0019 TestSkyPoint::~TestSkyPoint() 0020 { 0021 Options::setUseRelativistic(useRelativistic); 0022 } 0023 0024 void TestSkyPoint::testPrecession() 0025 { 0026 /* 0027 * NOTE: These test cases were picked randomly and generated using 0028 * https://ned.ipac.caltech.edu/forms/calculator.html 0029 */ 0030 0031 auto verify = [](const SkyPoint & p, const double targetRA, const double targetDec, const double tolerance) 0032 { 0033 qDebug() << p.ra().toHMSString() << " " << p.dec().toDMSString(); 0034 QVERIFY(fabs(p.ra().Degrees() - targetRA) < tolerance * 15.); 0035 QVERIFY(fabs(p.dec().Degrees() - targetDec) < tolerance); 0036 }; 0037 0038 /* Precession of equinoxes within FK5 system */ 0039 0040 // Check precession from J2000.0 to J1992.5 0041 0042 // NOTE: (FIXME?) I set 1950.0 as the observation epoch in the 0043 // calculator. Changing it to 1992.5 made no difference; probably 0044 // required only for FK5 to FK4 conversion. The help is not 0045 // extremely clear on this. -- asimha 0046 0047 constexpr double arcsecPrecision = 3.e-4; 0048 0049 long double jd = KStarsDateTime::epochToJd(1992.5, KStarsDateTime::JULIAN); 0050 KSNumbers num(jd); 0051 SkyPoint p(dms("18:22:54", false), dms("34:23:19", true)); // J2000.0 coordinates 0052 p.precess(&num); 0053 verify(p, 275.65734620, 34.38447020, arcsecPrecision); 0054 0055 // Check precession from J2000.0 to J2016.8 0056 jd = KStarsDateTime::epochToJd(2016.8); 0057 num.updateValues(jd); 0058 p.set(dms("23:24:25", false), dms("-08:07:06", true)); 0059 p.precess(&num); 0060 verify(p, 351.32145112, (-8.02590004), arcsecPrecision); 0061 0062 // Check precession from J2000.0 to J2109.8 0063 jd = KStarsDateTime::epochToJd(2109.8); 0064 num.updateValues(jd); 0065 p.precess(&num); 0066 verify(p, 352.52338626, (-7.51340424), arcsecPrecision); 0067 0068 /* Precession of equinoxes + conversion from FK4 to FK5 */ 0069 0070 // Conversion from B1950.0 to J2000.0 0071 p.set(dms("11:22:33", false), dms("44:55:66", true)); // Sets all of RA0,Dec0,RA,Dec 0072 p.B1950ToJ2000(); // Assumes (RA, Dec) are referenced to FK4 @ B1950 and stores the FK5 @ J2000 result in (RA, Dec) 0073 verify(p, 171.32145647, 44.66010982, arcsecPrecision); 0074 0075 // Conversion from B1950.0 to J2016.8 0076 // Current of B1950ToJ2000 is to NOT alter (RA0,Dec0), so we shouldn't have to reset it 0077 jd = KStarsDateTime::epochToJd(2016.8); 0078 p.precessFromAnyEpoch( 0079 B1950, jd); // Takes (RA0, Dec0) and precesses to (RA, Dec) applying FK4 <--> FK5 conversions as necessary 0080 verify(p, 171.55045618, 44.56762158, arcsecPrecision); 0081 0082 /* Precession of equinoxes + conversion from FK5 to FK4 */ 0083 p.set(dms("11:22:33", false), dms("44:55:66", true)); // Sets all of RA0,Dec0,RA,Dec 0084 p.J2000ToB1950(); // Assumes (RA, Dec) are referenced to FK5 @ J2000 and stores the FK4 @ B1950 result in (RA, Dec) 0085 // NOTE: I set observation epoch = 2000.0 in NED's calculator. This time, it made a difference whether I set 2000.0 or 1950.0, but the difference was very small. 0086 verify(p, 169.94978888, 45.20928652, arcsecPrecision); 0087 0088 // Conversion from J2016.8 to B1950.0 0089 // Current behavior of J2000ToB1950 is to NOT alter (RA0,Dec0), so we shouldn't have to reset it 0090 jd = KStarsDateTime::epochToJd(2016.8); 0091 p.precessFromAnyEpoch( 0092 jd, B1950); // Takes (RA0, Dec0) and precesses to (RA, Dec) applying FK4 <--> FK5 conversions as necessary 0093 // NOTE: I set observation epoch = 2016.8 in NED's calculator. It made a difference whether I set 2000.0 or 2016.8, but the difference was very small. 0094 verify(p, 169.71785991, 45.30132855, arcsecPrecision); 0095 } 0096 0097 void TestSkyPoint::compareNovas() 0098 { 0099 Options::setUseRelativistic(false); 0100 0101 KStarsDateTime kdt = KStarsDateTime::currentDateTimeUtc(); 0102 long double jd = kdt.djd(); 0103 0104 double lnJd = ln_get_julian_from_sys(); 0105 // compare JD provided by KStarsDateTime and libnova 0106 qDebug() << "KDT JD " << static_cast<double>(jd) << " LN JD " << lnJd << " Diff " << (static_cast<double> 0107 (jd) - lnJd) * 86400 << "secs"; 0108 QVERIFY(fabs(static_cast<double>(jd) - lnJd) * 86400 < 1); 0109 0110 qDebug() << "Check conversion in Align"; 0111 // the align process is a bit like this: 0112 // Catalogue position 0113 SkyPoint target(4, 20); // ra in hours, dec in degrees 0114 0115 // transform to JNow in EKOS 0116 // this is wrong because aberration and nutation are handled incorrectly 0117 target.apparentCoord(static_cast<long double>(J2000), jd); 0118 double raN = target.ra().Degrees(); 0119 double decN = target.dec().Degrees(); 0120 qDebug() << "SkyPoint J2000 to JNow " << raN << ", " << decN; 0121 0122 // should be: 0123 // remove aberration 0124 0125 // remove nutation 0126 0127 // this is passed to the CCD simulator where it is transformed to J2K using libnova 0128 ln_equ_posn JnowPos { 0, 0 }, J2kPos { 0, 0 }; 0129 JnowPos.ra = raN; 0130 JnowPos.dec = decN; 0131 ln_get_equ_prec2(&JnowPos, lnJd, JD2000, &J2kPos); 0132 double ra0 = J2kPos.ra; 0133 double dec0 = J2kPos.dec; 0134 qDebug() << "Libnova JNow to J2000" << ra0 << ", " << dec0; 0135 0136 // this is used to generate a star image which is solved 0137 // assume this solve is perfect 0138 0139 // Align converts this J2000 position back to JNow: 0140 SkyPoint ac(ra0 / 15., dec0); 0141 ac.apparentCoord(static_cast<long double>(J2000), jd); 0142 double ran2 = ac.ra().Degrees(); 0143 double decn2 = ac.dec().Degrees(); 0144 qDebug() << "SkyPoint J2000 to JNow" << ran2 << ", " << decn2; 0145 // get the error, this appears as the align error 0146 qDebug() << "Error (arcsec)" << (raN - ran2) * 3600 << ", " << (decN - decn2) * 3600; 0147 0148 // check the difference 0149 //QVERIFY(fabs(decN - decn2) * 3600. < 1); 0150 //QVERIFY(fabs(raN - ran2) * 3600. < 1); 0151 0152 qDebug(); 0153 qDebug() << "Using libnova throughout"; 0154 J2kPos.ra = 60; 0155 J2kPos.dec = 20; 0156 // convert to JNow 0157 ln_get_equ_prec2(&J2kPos, JD2000, lnJd, &JnowPos); 0158 qDebug() << "libnova J2000 to JNow " << JnowPos.ra << ", " << JnowPos.dec; 0159 // convert to J2000 0160 ln_get_equ_prec2(&JnowPos, lnJd, JD2000, &J2kPos); 0161 qDebug() << " libnova JNow to J2000" << J2kPos.ra << ", " << J2kPos.dec; 0162 0163 // 'solve' 0164 0165 // convert back to Jnow 0166 ln_equ_posn Jnow2Pos { 0, 0 }; 0167 ln_get_equ_prec2(&J2kPos, JD2000, lnJd, &Jnow2Pos); 0168 qDebug() << "libnova J2000 to JNow " << Jnow2Pos.ra << ", " << Jnow2Pos.dec; 0169 0170 qDebug() << "Error (arcsec)" << (JnowPos.ra - Jnow2Pos.ra) * 3600 << ", " << (JnowPos.dec - Jnow2Pos.dec) * 3600; 0171 0172 // Using SkyPoint won't help: 0173 qDebug(); 0174 qDebug() << "using SkyPoint both ways"; 0175 // do the conversion from the previously computed JNow position 0176 SkyPoint ccd; 0177 ccd.setRA(raN / 15.); 0178 ccd.setDec(decN); 0179 KSNumbers num(jd); 0180 ccd.deprecess(&num); 0181 qDebug() << "SkyPoint Jnow to J2000 " << ccd.ra0().Degrees() << ", " << ccd.dec0().Degrees(); 0182 // and to Jnow 0183 ccd.apparentCoord(static_cast<long double>(J2000), jd); 0184 qDebug() << "SkyPoint J2000 to JNow " << ccd.ra().Degrees() << ", " << ccd.dec().Degrees(); 0185 0186 qDebug() << "Error " << (raN - ccd.ra().Degrees()) * 3600 << ", " << (decN - ccd.dec().Degrees()) * 3600; 0187 0188 //QVERIFY(fabs(p.ra().Degrees() - targetRA) < tolerance * 15.); 0189 //QVERIFY(fabs(p.dec().Degrees() - targetDec) < tolerance); 0190 0191 //qCDebug(KSTARS_EKOS_ALIGN) << "libnova errors " << 0192 // (epochPos.ra - targetCoord.ra().Degrees()) * 3600. << "as, " << (epochPos.dec - targetCoord.dec().Degrees()) * 3600. << "as"; 0193 0194 0195 Options::setUseRelativistic(useRelativistic); 0196 } 0197 0198 void TestSkyPoint::testPrecess_data() 0199 { 0200 QTest::addColumn<double>("Ra"); 0201 QTest::addColumn<double>("Dec"); 0202 0203 QTest::newRow("normal") << 4.0 << 20.0; 0204 QTest::newRow("south") << 15.0 << -35.0; 0205 QTest::newRow("near Pole") << 22.0 << 85.0; 0206 QTest::newRow("near S Pole") << 22.0 << -85.0; 0207 } 0208 0209 void TestSkyPoint::testPrecess() 0210 { 0211 auto jd = KStarsDateTime::currentDateTimeUtc().djd(); 0212 KSNumbers now(jd); 0213 SkyPoint sp; 0214 QFETCH(double, Ra); 0215 QFETCH(double, Dec); 0216 0217 sp = SkyPoint(Ra, Dec); 0218 0219 sp.precess(&now); 0220 0221 qDebug() << "precess dRa " << sp.ra0().Degrees() - sp.ra().Degrees() << ", dDec " << sp.dec0().Degrees() - 0222 sp.dec().Degrees(); 0223 0224 SkyPoint spn = sp.deprecess(&now); 0225 0226 compare("precess-deprecess ", sp.ra0().Degrees(), sp.dec0().Degrees(), spn.ra().Degrees(), spn.dec().Degrees()); 0227 } 0228 0229 void TestSkyPoint::testPrecessFromAnyEpoch_data() 0230 { 0231 QTest::addColumn<double>("Ra"); 0232 QTest::addColumn<double>("Dec"); 0233 0234 QTest::newRow("normal") << 4.0 << 20.0; 0235 QTest::newRow("south") << 15.0 << -35.0; 0236 QTest::newRow("near Pole") << 22.0 << 85.0; 0237 QTest::newRow("near S Pole") << 22.0 << -85.0; 0238 } 0239 0240 void TestSkyPoint::testPrecessFromAnyEpoch() 0241 { 0242 auto jd = KStarsDateTime::currentDateTimeUtc().djd(); 0243 KSNumbers now(jd); 0244 0245 SkyPoint sp; 0246 QFETCH(double, Ra); 0247 QFETCH(double, Dec); 0248 sp = SkyPoint(Ra, Dec); 0249 0250 sp.precessFromAnyEpoch(J2000L, jd); 0251 0252 qDebug() << "PFAE dRa " << sp.ra0().Degrees() - sp.ra().Degrees() << ", dDec " << sp.dec0().Degrees() - sp.dec().Degrees(); 0253 0254 SkyPoint spn = SkyPoint(sp.ra(), sp.dec()); 0255 spn.precessFromAnyEpoch(jd, J2000L); 0256 0257 compare("dePFAE ", sp.ra0().Degrees(), sp.dec0().Degrees(), spn.ra().Degrees(), spn.dec().Degrees()); 0258 } 0259 0260 void TestSkyPoint::testNutate_data() 0261 { 0262 QTest::addColumn<double>("Ra"); 0263 QTest::addColumn<double>("Dec"); 0264 0265 QTest::newRow("normal") << 4.0 << 20.0; 0266 QTest::newRow("south") << 15.0 << -35.0; 0267 QTest::newRow("near Pole") << 22.0 << 85.0; 0268 QTest::newRow("near S Pole") << 22.0 << -85.0; 0269 } 0270 0271 void TestSkyPoint::testNutate() 0272 { 0273 long double jd = KStarsDateTime::currentDateTimeUtc().djd(); 0274 KSNumbers now(jd); 0275 0276 SkyPoint sp; 0277 QFETCH(double, Ra); 0278 QFETCH(double, Dec); 0279 sp = SkyPoint(Ra, Dec); 0280 0281 sp.nutate(&now); 0282 0283 qDebug() << "nutate dRa " << sp.ra0().Degrees() - sp.ra().Degrees() << ", dDec " << sp.dec0().Degrees() - 0284 sp.dec().Degrees(); 0285 0286 sp.nutate(&now, true); 0287 0288 compare("nutate-denutate", &sp); 0289 } 0290 0291 void TestSkyPoint::testAberrate_data() 0292 { 0293 QTest::addColumn<double>("Ra"); 0294 QTest::addColumn<double>("Dec"); 0295 0296 QTest::newRow("normal") << 4.0 << 20.0; 0297 QTest::newRow("south") << 15.0 << -35.0; 0298 QTest::newRow("near Pole") << 22.0 << 85.0; 0299 QTest::newRow("near S Pole") << 22.0 << -85.0; 0300 } 0301 0302 void TestSkyPoint::testAberrate() 0303 { 0304 long double jd = KStarsDateTime::epochToJd(2028.3); 0305 KSNumbers now(jd); 0306 0307 SkyPoint sp; 0308 QFETCH(double, Ra); 0309 QFETCH(double, Dec); 0310 sp = SkyPoint(Ra, Dec); 0311 0312 sp.aberrate(&now); 0313 0314 // deaberrate 0315 sp.aberrate(&now, true); 0316 0317 compare("aberrate-deaberrate", &sp); 0318 } 0319 0320 // test results obtained using the ASCOM Transform component 0321 // to convert from J2000 to Apparent 0322 // this uses SOFA so should be fairly good 0323 void TestSkyPoint::testApparentCatalogue_data() 0324 { 0325 QTest::addColumn<double>("Ra"); 0326 QTest::addColumn<double>("Dec"); 0327 QTest::addColumn<double>("RaOut"); 0328 QTest::addColumn<double>("DecOut"); 0329 0330 QTest::newRow("Apparent") << 4.0 << 20.0 << 4.0274 << 20.0791; 0331 QTest::newRow("south") << 10.0 << -35.0 << 10.0208 << -35.1418; 0332 QTest::newRow("south") << 10.0 << -55.0 << 10.01698 << -55.14256; 0333 QTest::newRow("near Pole") << 22.0 << 85.0 << 21.9601 << 85.1317; 0334 QTest::newRow("near S Pole") << 15.0 << -85.0 << 15.1159 << -85.1112; 0335 } 0336 0337 void TestSkyPoint::testApparentCatalogue() 0338 { 0339 Options::setUseRelativistic(false); 0340 0341 //long double jd = KStarsDateTime::currentDateTimeUtc().djd(); 0342 auto dt = KStarsDateTime::fromString("2028-04-27T06:30"); 0343 long double jd = dt.djd(); 0344 0345 double rjd = static_cast<double>(jd - J2000L); 0346 //qDebug() << "DT " << dt.toString() << " JD " << static_cast<double>(jd) << " RJD " << rjd; 0347 0348 QVERIFY(fabs(rjd - 10343.771) < 0.1); 0349 0350 SkyPoint sp; 0351 QFETCH(double, Ra); 0352 QFETCH(double, Dec); 0353 sp = SkyPoint(Ra, Dec); 0354 0355 // J2000 catalogue to Apparent 0356 sp.apparentCoord(J2000L, jd); 0357 // qDebug() << "apparent ra0 " << sp.ra0().Hours() << ", dec0 " << sp.dec0().Degrees() << 0358 // " ra " << sp.ra().Hours() << ", dec " << sp.dec().Degrees(); 0359 QFETCH(double, RaOut); 0360 QFETCH(double, DecOut); 0361 0362 compare("J2000 to aparrent", RaOut, DecOut, sp.ra().Hours(), sp.dec().Degrees()); 0363 0364 SkyPoint spn = SkyPoint(sp.ra(), sp.dec()); 0365 qDebug() << "spn ra0 " << spn.ra0().Degrees() << ", dec0 " << spn.dec0().Degrees() << 0366 " ra " << spn.ra().Degrees() << ", dec " << spn.dec().Degrees(); 0367 0368 // apparent on jd to J2000Catalogue 0369 spn.catalogueCoord(jd); 0370 0371 compare("J2K to app to catalogue", sp.ra0().Degrees(), sp.dec0().Degrees(), spn.ra0().Degrees(), spn.dec0().Degrees()); 0372 } 0373 0374 void TestSkyPoint::testApparentCatalogueInversion_data() 0375 { 0376 QTest::addColumn<double>("Ra"); 0377 QTest::addColumn<double>("Dec"); 0378 QTest::addColumn<double>("Epoch"); 0379 0380 QTest::newRow("Random1") << 15.32 << 34.50 << 2012.34; 0381 QTest::newRow("Random2") << 72.96 << 24.10 << 2022.39; 0382 QTest::newRow("Random3") << 188.52 << -36.58 << 2042.86; 0383 QTest::newRow("Random4") << 239.22 << -47.32 << 2139.23; 0384 QTest::newRow("Random5") << 278.78 << 01.68 << 2058.62; 0385 QTest::newRow("Near J2000 NCP") << 172.59 << 88.95 << 2029.88; 0386 QTest::newRow("Near J2000 SCP") << 145.22 << -88.86 << 2034.72; 0387 QTest::newRow("Near Current NEP") << 280.74 << 70.81 << 2021.23; 0388 } 0389 0390 void TestSkyPoint::testApparentCatalogueInversion() 0391 { 0392 Options::setUseRelativistic(false); 0393 0394 // This test tests the conversion of J2000 -> arbitrary ICRS epoch -> back to J2000 by inversion 0395 constexpr double sub_arcsecond_tolerance = 0.1 / 3600.0; 0396 SkyPoint sp_forward; 0397 QFETCH(double, Ra); 0398 QFETCH(double, Dec); 0399 QFETCH(double, Epoch); 0400 long double targetJd = KStarsDateTime::epochToJd(Epoch); 0401 dms dms_ra {Ra}; 0402 KSNumbers num(targetJd); 0403 sp_forward.setRA0(dms_ra); 0404 sp_forward.setDec0(Dec); 0405 sp_forward.updateCoordsNow(&num); 0406 SkyPoint sp_backward {sp_forward.catalogueCoord(targetJd)}; 0407 compare( 0408 QString("Apparent to Catalogue Inversion Check for epoch %1").arg(Epoch, 7, 'f', 2), 0409 sp_backward.ra0().reduce().Degrees(), sp_backward.dec0().Degrees(), 0410 dms_ra.reduce().Degrees(), Dec, 0411 sub_arcsecond_tolerance 0412 ); 0413 } 0414 0415 void TestSkyPoint::compareSkyPointLibNova_data() 0416 { 0417 QTest::addColumn<double>("Ra"); 0418 QTest::addColumn<double>("Dec"); 0419 QTest::addColumn<double>("RaOut"); 0420 QTest::addColumn<double>("DecOut"); 0421 0422 QTest::newRow("Apparent") << 4.0 << 20.0 << 4.0274 << 20.0791; 0423 QTest::newRow("south") << 10.0 << -35.0 << 10.0208 << -35.1418; 0424 QTest::newRow("south") << 10.0 << -55.0 << 10.01698 << -55.14256; 0425 QTest::newRow("near Pole") << 22.0 << 85.0 << 21.9601 << 85.1317; 0426 QTest::newRow("near S Pole") << 15.0 << -85.0 << 15.1159 << -85.1112; 0427 } 0428 void TestSkyPoint::compareSkyPointLibNova() 0429 { 0430 // skypoint JD 0431 auto dt = KStarsDateTime::fromString("2028-04-27T06:30"); 0432 long double ljd = dt.djd(); 0433 double jd = static_cast<double>(ljd); 0434 0435 SkyPoint sp; 0436 QFETCH(double, Ra); 0437 QFETCH(double, Dec); 0438 sp = SkyPoint(Ra, Dec); 0439 ln_equ_posn LnPos { Ra * 15.0, Dec }, observed { 0, 0 }, J2000Pos { 0, 0 }; 0440 0441 ln_equ_posn tempPosn; 0442 0443 KSNumbers num(ljd); 0444 0445 // apply precession from J2000 to jd 0446 ln_get_equ_prec2(&LnPos, JD2000, jd, &tempPosn); 0447 SkyPoint spp = sp; 0448 spp.precessFromAnyEpoch(J2000L, ljd); 0449 compare("precess", spp.ra().Degrees(), spp.dec().Degrees(), tempPosn.ra, tempPosn.dec); 0450 0451 // apply nutation (needs new function) 0452 ln_get_equ_nut(&tempPosn, jd); 0453 SkyPoint spn = spp; 0454 spn.nutate(&num); 0455 compare("nutate", spn.ra().Degrees(), spn.dec().Degrees(), tempPosn.ra, tempPosn.dec); 0456 0457 // apply aberration 0458 ln_get_equ_aber(&tempPosn, jd, &observed); 0459 SkyPoint spa = spn; 0460 spa.aberrate(&num); 0461 compare("aberrate", spa.ra().Degrees(), spa.dec().Degrees(), observed.ra, observed.dec); 0462 0463 sp.apparentCoord(J2000L, ljd); 0464 0465 // compare sp and observed with each other 0466 compare("sp and LN ", sp.ra().Degrees(), sp.dec().Degrees(), observed.ra, observed.dec); 0467 QFETCH(double, RaOut); 0468 QFETCH(double, DecOut); 0469 // compare sp with expected, use degrees 0470 compare("sp expected ", RaOut * 15., DecOut, sp.ra().Degrees(), sp.Dec.Degrees(), 0.0005); 0471 // compare ln with expected 0472 compare("ln expected ", RaOut * 15, DecOut, observed.ra, observed.dec, 0.0005); 0473 0474 // now to J2000 0475 0476 // remove the aberration 0477 ln_get_equ_aber(&observed, jd, &tempPosn); 0478 // this conversion has added the aberration, we want to subtract it 0479 tempPosn.ra = observed.ra - (tempPosn.ra - observed.ra); 0480 tempPosn.dec = observed.dec * 2 - tempPosn.dec; 0481 //sp.aberrate(&num, true); 0482 0483 0484 // remove the nutation 0485 ln_get_equ_nut(&tempPosn, jd, true); 0486 0487 //sp.nutate(&num, true); 0488 0489 // precess from now to J2000 0490 ln_get_equ_prec2(&tempPosn, jd, JD2000, &J2000Pos); 0491 0492 // the start position needs to be in RA0,Dec0 0493 //sp.RA0 = sp.RA; 0494 //sp.Dec0 = sp.Dec; 0495 // from now to J2000 0496 //sp.precessFromAnyEpoch(jd, J2000L); 0497 // the J2000 position is in RA,Dec, move to RA0, Dec0 0498 //sp.RA0 = sp.RA; 0499 //sp.Dec0 = sp.Dec; 0500 //sp.lastPrecessJD = J2000; 0501 0502 sp.catalogueCoord(ljd); 0503 0504 //compare sp and the j2000Pos with each other and the original 0505 compare("Round trip ", &sp, &J2000Pos); 0506 compare("original", Ra, Dec, sp.RA0.Hours(), sp.Dec0.Degrees()); 0507 } 0508 0509 void TestSkyPoint::compare(QString msg, SkyPoint *sp, SkyPoint *sp1) 0510 { 0511 compare(msg, sp->ra0().Degrees(), sp->dec0().Degrees(), sp1->ra().Degrees(), sp1->dec().Degrees()); 0512 } 0513 0514 void TestSkyPoint::compare(QString msg, SkyPoint *sp, ln_equ_posn *lnp) 0515 { 0516 compare(msg, sp->ra0().Degrees(), sp->dec0().Degrees(), lnp->ra, lnp->dec); 0517 } 0518 0519 void TestSkyPoint::compare(QString msg, SkyPoint *sp) 0520 { 0521 compare(msg, sp->ra0().Degrees(), sp->dec0().Degrees(), sp->ra().Degrees(), sp->dec().Degrees()); 0522 } 0523 0524 void TestSkyPoint::compare(QString msg, double ra1, double dec1, double ra2, double dec2, double err) 0525 { 0526 qDebug() << qPrintable(QString("%1 pos1 %2, %3 pos2 %4, %5 errors %6, %7 secs").arg(msg) 0527 .arg(ra1).arg(dec1).arg(ra2).arg(dec2) 0528 .arg((ra1 - ra2) * 3600.0, 6, 'f', 1).arg((dec1 - dec2) * 3600., 6, 'f', 1)); 0529 //QString str; 0530 //str.sprintf("%s pos1 %f, %f pos2 %f, %f errors %.1f, %.1f sec", msg.data(), ra1, dec1, ra2, dec2, (ra1 - ra2) *3600, (dec1 - dec2) * 3600 ); 0531 //qDebug() << str;// << msg << "SP " << ra1 << ", " << dec1 << " Sp0 " << ra2 << ", " << dec2 0532 //<< " errors " << ((ra1 - ra2) * 3600) << ", " << ((dec1 - dec2) * 3600) << " arcsec"; 0533 0534 double errRa = err / cos(dec1 * M_PI / 180.0); 0535 0536 QVERIFY2(fabs(ra1 - ra2) < errRa, qPrintable(QString("Ra %1, %2 error %3").arg(ra1).arg(ra2).arg(((ra1 - ra2) * 3600.0), 6, 0537 'f', 1))); 0538 QVERIFY2(fabs(dec1 - dec2) < err, qPrintable(QString("Dec %1, %2 error %3").arg(dec1).arg(dec2).arg((dec1 - dec2) * 3600., 0539 6, 'f', 1))); 0540 } 0541 0542 // apply or remove nutation 0543 void TestSkyPoint::ln_get_equ_nut(ln_equ_posn *posn, double jd, bool reverse) 0544 { 0545 // code lifted from libnova ln_get_equ_nut 0546 // with the option to add or remove nutation 0547 struct ln_nutation nut; 0548 ln_get_nutation (jd, &nut); 0549 0550 double mean_ra, mean_dec, delta_ra, delta_dec; 0551 0552 mean_ra = ln_deg_to_rad(posn->ra); 0553 mean_dec = ln_deg_to_rad(posn->dec); 0554 0555 // Equ 22.1 0556 0557 double nut_ecliptic = ln_deg_to_rad(nut.ecliptic + nut.obliquity); 0558 double sin_ecliptic = sin(nut_ecliptic); 0559 0560 double sin_ra = sin(mean_ra); 0561 double cos_ra = cos(mean_ra); 0562 0563 double tan_dec = tan(mean_dec); 0564 0565 delta_ra = (cos (nut_ecliptic) + sin_ecliptic * sin_ra * tan_dec) * nut.longitude - cos_ra * tan_dec * nut.obliquity; 0566 delta_dec = (sin_ecliptic * cos_ra) * nut.longitude + sin_ra * nut.obliquity; 0567 0568 // the sign changed to remove nutation 0569 if (reverse) 0570 { 0571 delta_ra = -delta_ra; 0572 delta_dec = -delta_dec; 0573 } 0574 posn->ra += delta_ra; 0575 posn->dec += delta_dec; 0576 } 0577 0578 void TestSkyPoint::testUpdateCoords() 0579 { 0580 Options::setUseRelativistic(false); 0581 0582 dms ra, dec; 0583 // ra.setH(11, 50, 3, 0); Min RA 0584 ra.setH(11, 55, 28, 0); 0585 // ra.setH(12, 00, 53, 0); Max RA 0586 0587 // dec.setD(-89,52,41,0); Min abs(dec) 0588 dec.setD(-89, 53, 02, 0); 0589 // dec.setD(-89,53,23,0); Max abs(Dec) 0590 0591 auto dt = KStarsDateTime::fromString("2021-01-24T00:00"); 0592 int numtest = 100; 0593 int numdays = 100; 0594 0595 long double jd = dt.djd(); 0596 double jdfrac, jdint; 0597 KSNumbers num(jd); 0598 SkyPoint sp; 0599 sp.setRA0(ra); 0600 sp.setDec0(dec); 0601 for(int i = 0; i < numtest; i++) 0602 { 0603 sp.updateCoordsNow(&num); 0604 jdfrac = modf(static_cast<double>(dt.djd()), &jdint); 0605 if (fabs(sp.dec().Degrees()) > 90.0) 0606 qDebug() << "i" << i << " jdfrac" << jdfrac << ": sp ra0 " << sp.ra0().Degrees() << ", dec " << sp.dec0().Degrees() << 0607 " ra " << sp.ra().Degrees() << ", dec " << sp.dec().Degrees(); 0608 QVERIFY(fabs(sp.dec().Degrees()) <= 90.0); 0609 0610 dt = dt.addSecs(numdays * 86400 / numtest); 0611 jd = dt.djd(); 0612 num.updateValues(jd); 0613 } 0614 0615 } 0616 0617 void TestSkyPoint::testDeltaAngle() 0618 { 0619 SkyPoint p1(dms("00:43:13", false), dms("40:45:42")); 0620 SkyPoint p2(dms("00:43:44", false), dms("41:23:07")); 0621 0622 auto diffRA = p1.ra().deltaAngle(p2.ra()); 0623 auto diffDE = p1.dec().deltaAngle(p2.dec()); 0624 0625 QVERIFY(diffRA.Degrees() < 1); 0626 QVERIFY(diffDE.Degrees() < 1); 0627 } 0628 0629 QTEST_GUILESS_MAIN(TestSkyPoint)