File indexing completed on 2024-04-28 15:11:57

0001 /*
0002     SPDX-FileCopyrightText: 2016 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "testdms.h"
0008 
0009 #include "auxiliary/dms.h"
0010 
0011 #include <QTest>
0012 
0013 TestDMS::TestDMS() : QObject()
0014 {
0015 }
0016 
0017 void TestDMS::defaultCtor()
0018 {
0019     /*
0020      * Test 1: Check Default Constructor
0021     */
0022 
0023     // Check default empty constructor
0024     dms d;
0025     QVERIFY(std::isnan(d.Degrees()));
0026 }
0027 
0028 void TestDMS::explicitSexigesimalCtor()
0029 {
0030     /*
0031      * Test 2: Checks Sexigesimal Ctor
0032     */
0033 
0034     // HH:MM:SS
0035     // 14:55:20
0036 
0037     dms d(14, 55, 20);
0038 
0039     QVERIFY(d.degree() == 14);
0040     QVERIFY(d.arcmin() == 55);
0041     QVERIFY(d.arcsec() == 20);
0042     QVERIFY(qFuzzyCompare(d.Degrees(), (14.0 + 55.0 / 60.0 + 20.0 / 3600.0)));
0043 }
0044 
0045 void TestDMS::angleCtor()
0046 {
0047     /*
0048      * Test 3: Checks Angle Ctor
0049     */
0050 
0051     // Angle = -112.56 Degrees ---> HMS (16:29:45)
0052 
0053     double angle = -112.56;
0054 
0055     dms d(angle);
0056 
0057     QVERIFY(d.degree() == (int)angle);
0058 
0059     QVERIFY(qFuzzyCompare(d.Hours(), (angle + 360) / 15.0));
0060     QVERIFY(d.hour() == 16);
0061     QVERIFY(d.minute() == 29);
0062     QVERIFY(d.second() == 45);
0063 }
0064 
0065 void TestDMS::stringCtor()
0066 {
0067     QString hms("14:55:20");
0068 
0069     // From Degree
0070     dms d(hms);
0071 
0072     QVERIFY(d.degree() == 14);
0073     QVERIFY(d.arcmin() == 55);
0074     QVERIFY(d.arcsec() == 20);
0075     QVERIFY(qFuzzyCompare(d.Degrees(), (14.0 + 55.0 / 60.0 + 20.0 / 3600.0)));
0076 
0077     // From Hours
0078     dms h(hms, false);
0079     QVERIFY(qFuzzyCompare(h.Degrees(), d.Degrees() * 15.0));
0080     QVERIFY(qFuzzyCompare(h.Hours(), d.Degrees()));
0081 }
0082 
0083 void TestDMS::testReduceToRange()
0084 {
0085     double base = 67.8;
0086     double a    = 360.0 * 11. + base;
0087     double b    = -360.0 * 12. + base;
0088 
0089     dms d;
0090     d.setD(a);
0091     d.reduceToRange(dms::ZERO_TO_2PI);
0092     QVERIFY(fabs(d.Degrees() - base) < 1e-9);
0093 
0094     d.setD(b);
0095     d.reduceToRange(dms::ZERO_TO_2PI);
0096     QVERIFY(fabs(d.Degrees() - base) < 1e-9);
0097 
0098     d.setD(360.0);
0099     d.reduceToRange(dms::ZERO_TO_2PI);
0100     QVERIFY(fabs(d.Degrees() - 0.) < 1e-9);
0101 
0102     double c = 180.0 * 13. + base;
0103     double e = 180.0 * 14. + base;
0104     double f = -180.0 * 15. + base;
0105     double g = -180.0 * 16. + base;
0106 
0107     d.setD(c);
0108     d.reduceToRange(dms::MINUSPI_TO_PI);
0109     QVERIFY(fabs(d.Degrees() - (base - 180.0)) < 1e-9);
0110 
0111     d.setD(e);
0112     d.reduceToRange(dms::MINUSPI_TO_PI);
0113     QVERIFY(fabs(d.Degrees() - base) < 1e-9);
0114 
0115     d.setD(f);
0116     d.reduceToRange(dms::MINUSPI_TO_PI);
0117     QVERIFY(fabs(d.Degrees() - (base - 180.0)) < 1e-9);
0118 
0119     d.setD(g);
0120     d.reduceToRange(dms::MINUSPI_TO_PI);
0121     QVERIFY(fabs(d.Degrees() - base) < 1e-9);
0122 }
0123 
0124 void TestDMS::testSubstraction()
0125 {
0126     // Diff 359 and 1
0127     dms sub = dms(359) - dms(1);
0128     QVERIFY(sub.Degrees() == 358.);
0129 
0130     // The reverse is -358
0131     sub = dms(1) - dms(359);
0132     QVERIFY(sub.Degrees() == -358.);
0133 
0134     // Diff 100 and 300
0135     sub = dms(100) - dms(300);
0136     QVERIFY(sub.Degrees() == -200.0);
0137 
0138     // Diff 310 and 110 should be 200
0139     sub = dms(310) - dms(110);
0140     QVERIFY(sub.Degrees() == 200.0);
0141 
0142     // Diff 170 and 130 should be 40
0143     sub = dms(170) - dms(130);
0144     QVERIFY(sub.Degrees() == 40.0);
0145 
0146     // Reverse is -40
0147     sub = dms(130) - dms(170);
0148     QVERIFY(sub.Degrees() == -40.0);
0149 }
0150 
0151 void TestDMS::testDeltaAngle()
0152 {
0153     // Diff 359 and 1 should be 2 (shortest path normalized)
0154     dms sub = dms(359).deltaAngle(dms(1));
0155     QVERIFY(sub.Degrees() == 2.);
0156 
0157     // Diff 1 to 350 is -11
0158     sub = dms(1).deltaAngle(dms(350));
0159     QVERIFY(sub.Degrees() == -11.);
0160 
0161     // Diff 310 and 110 should be 160
0162     sub = dms(310).deltaAngle(dms(110));
0163     QVERIFY(sub.Degrees() == 160.0);
0164 
0165     // Diff 100 and 300 should be -160 (NOT -200) since 160 is the shorest path CCW
0166     sub = dms(100).deltaAngle(dms(300));
0167     QVERIFY(sub.Degrees() == -160.0);
0168 }
0169 
0170 void TestDMS::testUnitTransition()
0171 {
0172     // check for rounding/truncating errors around unit transition
0173     // in DMS and HMS angle representation strings
0174     dms sp; 
0175     sp.setD(10.0 - 1.0E-14);
0176     QVERIFY(sp.degree() == 9);
0177     QVERIFY(sp.arcmin() == 59);
0178     QVERIFY(sp.arcsec() == 59);
0179     QVERIFY(sp.marcsec() == 999);
0180 
0181     sp.setH(10.0 - 1.0E-14);
0182     QVERIFY(sp.hour() == 9);
0183     QVERIFY(sp.minute() == 59);
0184     QVERIFY(sp.second() == 59);
0185     QVERIFY(sp.msecond() == 999);
0186  
0187     sp.setD(10.0);
0188     QVERIFY(sp.degree() == 10);
0189     QVERIFY(sp.arcmin() == 0);
0190     QVERIFY(sp.arcsec() == 0);
0191     QVERIFY(sp.marcsec() == 0);
0192 
0193     sp.setH(10.0);
0194     QVERIFY(sp.hour() == 10);
0195     QVERIFY(sp.minute() == 0);
0196     QVERIFY(sp.second() == 0);
0197     QVERIFY(sp.msecond() == 0);
0198 
0199     sp.setD(10.0 + 1.0E-14);
0200     QVERIFY(sp.degree() == 10);
0201     QVERIFY(sp.arcmin() == 0);
0202     QVERIFY(sp.arcsec() == 0);
0203     QVERIFY(sp.marcsec() == 0);
0204 
0205     sp.setH(10.0 + 1.0E-14);
0206     QVERIFY(sp.hour() == 10);
0207     QVERIFY(sp.minute() == 0);
0208     QVERIFY(sp.second() == 0);
0209     QVERIFY(sp.msecond() == 0);
0210 }
0211 
0212 void TestDMS::testPrecisionTransition()
0213 {
0214     // check for transitions in DMS and HMS angle representation strings
0215     // with respect to DMS and HMS precision around angle units 
0216     dms sp;
0217     double half_precision_DMS = 1.0 / 7200.0;
0218     double half_precision_HMS = 15.0 / 7200.0;
0219     double epsilon = 0.000000001;
0220 
0221     QLocale::setDefault(QLocale::c());
0222 
0223     // toDMSString
0224 
0225     bool forceSign = false;
0226     bool machineReadable = false;
0227     bool highPrecision = false;
0228 
0229     sp.setD(10.0 + half_precision_DMS + epsilon);
0230     QCOMPARE(sp.toDMSString(
0231     forceSign, machineReadable, highPrecision), QString(" 10° 00' 01\""));
0232     sp.setD(10.0 + half_precision_DMS - epsilon);
0233     QCOMPARE(sp.toDMSString(
0234     forceSign, machineReadable, highPrecision), QString(" 10° 00' 00\""));
0235     sp.setD(10.0 - half_precision_DMS + epsilon);
0236     QCOMPARE(sp.toDMSString(
0237     forceSign, machineReadable, highPrecision), QString(" 10° 00' 00\""));
0238     sp.setD(10.0 - half_precision_DMS - epsilon);
0239     QCOMPARE(sp.toDMSString(
0240     forceSign, machineReadable, highPrecision), QString(" 09° 59' 59\""));
0241 
0242     sp.setD(-10.0 + half_precision_DMS + epsilon);
0243     QCOMPARE(sp.toDMSString(
0244     forceSign, machineReadable, highPrecision), QString("-09° 59' 59\""));
0245     sp.setD(-10.0 + half_precision_DMS - epsilon);
0246     QCOMPARE(sp.toDMSString(
0247     forceSign, machineReadable, highPrecision), QString("-10° 00' 00\""));
0248     sp.setD(-10.0 - half_precision_DMS + epsilon);
0249     QCOMPARE(sp.toDMSString(
0250     forceSign, machineReadable, highPrecision), QString("-10° 00' 00\""));
0251     sp.setD(-10.0 - half_precision_DMS - epsilon);
0252     QCOMPARE(sp.toDMSString(
0253     forceSign, machineReadable, highPrecision), QString("-10° 00' 01\""));
0254 
0255     machineReadable = true;
0256 
0257     for (int i=0; i < 2; i++)
0258     {
0259         sp.setD(10.0 + half_precision_DMS + epsilon);
0260         QCOMPARE(sp.toDMSString(
0261         forceSign, machineReadable, highPrecision), QString(" 10:00:01"));
0262         sp.setD(10.0 + half_precision_DMS - epsilon);
0263         QCOMPARE(sp.toDMSString(
0264         forceSign, machineReadable, highPrecision), QString(" 10:00:00"));
0265         sp.setD(10.0 - half_precision_DMS + epsilon);
0266         QCOMPARE(sp.toDMSString(
0267         forceSign, machineReadable, highPrecision), QString(" 10:00:00"));
0268         sp.setD(10.0 - half_precision_DMS - epsilon);
0269         QCOMPARE(sp.toDMSString(
0270         forceSign, machineReadable, highPrecision), QString(" 09:59:59"));
0271 
0272         sp.setD(-10.0 + half_precision_DMS + epsilon);
0273         QCOMPARE(sp.toDMSString(
0274         forceSign, machineReadable, highPrecision), QString("-09:59:59"));
0275         sp.setD(-10.0 + half_precision_DMS - epsilon);
0276         QCOMPARE(sp.toDMSString(
0277         forceSign, machineReadable, highPrecision), QString("-10:00:00"));
0278         sp.setD(-10.0 - half_precision_DMS + epsilon);
0279         QCOMPARE(sp.toDMSString(
0280         forceSign, machineReadable, highPrecision), QString("-10:00:00"));
0281         sp.setD(-10.0 - half_precision_DMS - epsilon);
0282         QCOMPARE(sp.toDMSString(
0283         forceSign, machineReadable, highPrecision), QString("-10:00:01"));
0284 
0285     highPrecision = true;
0286     }
0287 
0288     machineReadable = false;
0289 
0290     sp.setD(10.0 + half_precision_DMS + epsilon);
0291     QCOMPARE(sp.toDMSString(
0292     forceSign, machineReadable, highPrecision), QString(" 10° 00' 0.50\""));
0293     sp.setD(10.0 + half_precision_DMS - epsilon);
0294     QCOMPARE(sp.toDMSString(
0295     forceSign, machineReadable, highPrecision), QString(" 10° 00' 0.50\""));
0296     sp.setD(10.0 - half_precision_DMS + epsilon);
0297     QCOMPARE(sp.toDMSString(
0298     forceSign, machineReadable, highPrecision), QString(" 09° 59' 59.50\""));
0299     sp.setD(10.0 - half_precision_DMS - epsilon);
0300     QCOMPARE(sp.toDMSString(
0301     forceSign, machineReadable, highPrecision), QString(" 09° 59' 59.50\""));
0302 
0303     sp.setD(-10.0 + half_precision_DMS + epsilon);
0304     QCOMPARE(sp.toDMSString(
0305     forceSign, machineReadable, highPrecision), QString("-09° 59' 59.50\""));
0306     sp.setD(-10.0 + half_precision_DMS - epsilon);
0307     QCOMPARE(sp.toDMSString(
0308     forceSign, machineReadable, highPrecision), QString("-09° 59' 59.50\""));
0309     sp.setD(-10.0 - half_precision_DMS + epsilon);
0310     QCOMPARE(sp.toDMSString(
0311     forceSign, machineReadable, highPrecision), QString("-10° 00' 0.50\""));
0312     sp.setD(-10.0 - half_precision_DMS - epsilon);
0313     QCOMPARE(sp.toDMSString(
0314     forceSign, machineReadable, highPrecision), QString("-10° 00' 0.50\""));
0315 
0316     // toHMSString
0317     
0318     highPrecision = false;
0319 
0320     sp.setD(10.0 * 15.0 + half_precision_HMS + epsilon);
0321     QCOMPARE(sp.toHMSString(
0322     machineReadable, highPrecision),QString("10h 00m 01s"));
0323     sp.setD(10.0 * 15.0 + half_precision_HMS - epsilon);
0324     QCOMPARE(sp.toHMSString(
0325     machineReadable, highPrecision),QString("10h 00m 00s"));
0326     sp.setD(10.0 * 15.0 - half_precision_HMS + epsilon);
0327     QCOMPARE(sp.toHMSString(
0328     machineReadable, highPrecision),QString("10h 00m 00s"));
0329     sp.setD(10.0 * 15.0 - half_precision_HMS - epsilon);
0330     QCOMPARE(sp.toHMSString(
0331     machineReadable, highPrecision),QString("09h 59m 59s"));
0332 
0333     sp.setD(-10.0 * 15.0 + half_precision_HMS + epsilon);
0334     QCOMPARE(sp.toHMSString(
0335     machineReadable, highPrecision),QString("14h 00m 01s"));
0336     sp.setD(-10.0 * 15.0 + half_precision_HMS - epsilon);
0337     QCOMPARE(sp.toHMSString(
0338     machineReadable, highPrecision),QString("14h 00m 00s"));
0339     sp.setD(-10.0 * 15.0 - half_precision_HMS + epsilon);
0340     QCOMPARE(sp.toHMSString(
0341     machineReadable, highPrecision),QString("14h 00m 00s"));
0342     sp.setD(-10.0 * 15.0 - half_precision_HMS - epsilon);
0343     QCOMPARE(sp.toHMSString(
0344     machineReadable, highPrecision),QString("13h 59m 59s"));
0345 
0346     machineReadable = true;
0347 
0348     for (int i=0; i < 2; i++)
0349     {
0350         sp.setD(10.0 * 15.0 + half_precision_HMS + epsilon);
0351         QCOMPARE(sp.toHMSString(
0352         machineReadable, highPrecision), QString("10:00:01"));
0353         sp.setD(10.0 * 15.0 + half_precision_HMS - epsilon);
0354         QCOMPARE(sp.toHMSString(
0355         machineReadable, highPrecision), QString("10:00:00"));
0356         sp.setD(10.0 * 15.0 - half_precision_HMS + epsilon);
0357         QCOMPARE(sp.toHMSString(
0358         machineReadable, highPrecision), QString("10:00:00"));
0359         sp.setD(10.0 * 15.0 - half_precision_HMS - epsilon);
0360         QCOMPARE(sp.toHMSString(
0361         machineReadable, highPrecision), QString("09:59:59"));
0362 
0363         sp.setD(-10.0 * 15.0 + half_precision_HMS + epsilon);
0364         QCOMPARE(sp.toHMSString(
0365         machineReadable, highPrecision), QString("14:00:01"));
0366         sp.setD(-10.0 * 15.0 + half_precision_HMS - epsilon);
0367         QCOMPARE(sp.toHMSString(
0368         machineReadable, highPrecision), QString("14:00:00"));
0369         sp.setD(-10.0 * 15.0 - half_precision_HMS + epsilon);
0370         QCOMPARE(sp.toHMSString(
0371         machineReadable, highPrecision), QString("14:00:00"));
0372         sp.setD(-10.0 * 15.0 - half_precision_HMS - epsilon);
0373         QCOMPARE(sp.toHMSString(
0374         machineReadable, highPrecision), QString("13:59:59"));
0375 
0376     highPrecision = true;
0377     }
0378 
0379     machineReadable = false;
0380 
0381     sp.setD(10.0 * 15.0 + half_precision_HMS + epsilon);
0382     QCOMPARE(sp.toHMSString(
0383     machineReadable, highPrecision),QString("10h 00m 0.50s"));
0384     sp.setD(10.0 * 15.0 + half_precision_HMS - epsilon);
0385     QCOMPARE(sp.toHMSString(
0386     machineReadable, highPrecision),QString("10h 00m 0.50s"));
0387     sp.setD(10.0 * 15.0 - half_precision_HMS + epsilon);
0388     QCOMPARE(sp.toHMSString(
0389     machineReadable, highPrecision),QString("09h 59m 59.50s"));
0390     sp.setD(10.0 * 15.0 - half_precision_HMS - epsilon);
0391     QCOMPARE(sp.toHMSString(
0392     machineReadable, highPrecision),QString("09h 59m 59.50s"));
0393 
0394     sp.setD(-10.0 * 15.0 + half_precision_HMS + epsilon);
0395     QCOMPARE(sp.toHMSString(
0396     machineReadable, highPrecision),QString("14h 00m 0.50s"));
0397     sp.setD(-10.0 * 15.0 + half_precision_HMS - epsilon);
0398     QCOMPARE(sp.toHMSString(
0399     machineReadable, highPrecision),QString("14h 00m 0.50s"));
0400     sp.setD(-10.0 * 15.0 - half_precision_HMS + epsilon);
0401     QCOMPARE(sp.toHMSString(
0402     machineReadable, highPrecision),QString("13h 59m 59.50s"));
0403     sp.setD(-10.0 * 15.0 - half_precision_HMS - epsilon);
0404     QCOMPARE(sp.toHMSString(
0405     machineReadable, highPrecision),QString("13h 59m 59.50s"));
0406 
0407     QLocale::setDefault(QLocale::system());
0408 }
0409 
0410 QTEST_GUILESS_MAIN(TestDMS)