File indexing completed on 2024-04-14 14:12:12
0001 /* 0002 SPDX-FileCopyrightText: 2021 Hy Murveit <hy@murveit.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /* 0008 * This file contains unit tests for the ArtificialHorizon class. 0009 */ 0010 0011 #include <QObject> 0012 #include <QTest> 0013 #include <memory> 0014 0015 #include "artificialhorizoncomponent.h" 0016 #include "linelist.h" 0017 #include "Options.h" 0018 0019 class TestArtificialHorizon : public QObject 0020 { 0021 Q_OBJECT 0022 0023 public: 0024 /** @short Constructor */ 0025 TestArtificialHorizon(); 0026 0027 /** @short Destructor */ 0028 ~TestArtificialHorizon() override = default; 0029 0030 private slots: 0031 void artificialHorizonTest(); 0032 void artificialCeilingTest(); 0033 0034 private: 0035 }; 0036 0037 // This include must go after the class declaration. 0038 #include "testartificialhorizon.moc" 0039 0040 TestArtificialHorizon::TestArtificialHorizon() : QObject() 0041 { 0042 } 0043 0044 namespace 0045 { 0046 0047 // Pass in two lists with azimuth and altitude values to set up an artificial horizon LineList. 0048 std::shared_ptr<LineList> setupHorizonEntities(const QList<double> &az, const QList<double> alt) 0049 { 0050 std::shared_ptr<LineList> list(new LineList()); 0051 std::shared_ptr<SkyPoint> p; 0052 0053 for (int i = 0; i < az.size(); ++i) 0054 { 0055 p.reset(new SkyPoint()); 0056 p->setAz(dms(az[i])); 0057 p->setAlt(dms(alt[i])); 0058 list->append(p); 0059 } 0060 return list; 0061 } 0062 0063 // Checks both that horizon.isVisible(az, alt) == visibility, as well as making sure that the 0064 // given az,alt is contained in one of the polygons (if visibility is false) or not contained 0065 // if visibility is true. Those polygons should be those generated to render the red 0066 // artificial-horizon area on the SkyMap. 0067 bool checkHorizon(const ArtificialHorizon &horizon, double az, double alt, 0068 bool visibility, QList<LineList> &polygons) 0069 { 0070 bool azAltInPolygon = false; 0071 for (int i = 0; i < polygons.size(); ++i) 0072 { 0073 const SkyList &points = *(polygons[i].points()); 0074 if (points.size() < 3) 0075 return false; 0076 0077 QPolygonF polygon; 0078 for (int j = 0; j < points.size(); ++j) 0079 polygon << QPointF(points[j]->az().Degrees(), points[j]->alt().Degrees()); 0080 polygon << QPointF(points[0]->az().Degrees(), points[0]->alt().Degrees()); 0081 0082 if (polygon.containsPoint(QPointF(az, alt), Qt::OddEvenFill)) 0083 { 0084 azAltInPolygon = true; 0085 break; 0086 } 0087 } 0088 if (horizon.isVisible(az, alt) != visibility) 0089 qInfo() << QString("isVisible test failed for az %1 alt %2 vis %3").arg(az, 0, 'f', 1).arg(alt, 0, 'f', 1).arg(visibility); 0090 if (azAltInPolygon == visibility) 0091 qInfo() << QString("inPolygon test failed for az %1 alt %2 vis %3\n").arg(az, 0, 'f', 1).arg(alt, 0, 'f', 0092 1).arg(visibility); 0093 return (horizon.isVisible(az, alt) == visibility) && (azAltInPolygon != visibility); 0094 } 0095 0096 } // namespace 0097 0098 void TestArtificialHorizon::artificialHorizonTest() 0099 { 0100 ArtificialHorizon horizon; 0101 0102 // This removes a call to KStars::Instance() that's not needed in testing. 0103 horizon.setTesting(); 0104 0105 // Setup a simple 3-point horizon. 0106 QList<double> az1 = {10.0, 20.0, 30.0}; 0107 QList<double> alt1 = {20.0, 40.0, 26.0}; 0108 auto list1 = setupHorizonEntities(az1, alt1); 0109 horizon.addRegion("R1", true, list1, false); 0110 0111 QVERIFY(horizon.altitudeConstraintsExist()); 0112 QList<LineList> polygons; 0113 horizon.drawPolygons(nullptr, &polygons); 0114 0115 // Check points above and below the first horizon line. 0116 QVERIFY(checkHorizon(horizon, 20, 41, true, polygons)); 0117 QVERIFY(checkHorizon(horizon, 20, 39, false, polygons)); 0118 QVERIFY(checkHorizon(horizon, 20.0, 51, true, polygons)); 0119 QVERIFY(checkHorizon(horizon, 25.0, 34, true, polygons)); 0120 QVERIFY(checkHorizon(horizon, 25.0, 32, false, polygons)); 0121 QVERIFY(checkHorizon(horizon, 15.0, 31, true, polygons)); 0122 QVERIFY(checkHorizon(horizon, 15.0, 29, false, polygons)); 0123 QVERIFY(checkHorizon(horizon, 35.0, -90 + 1, true, polygons)); 0124 QVERIFY(checkHorizon(horizon, 5.0, -90 + 1, true, polygons)); 0125 0126 // Try adding and subtracting 360-degrees from the azimuth for 0127 // the same tests. Shouldn't matter. 0128 // Graphics test doesn't make sense for >360-degrees so just test isVisible(). 0129 QVERIFY(horizon.isVisible(360.0 + 20.0, 41)); 0130 QVERIFY(!horizon.isVisible(360.0 + 20.0, 39)); 0131 QVERIFY(horizon.isVisible(-360.0 + 20.0, 41)); 0132 QVERIFY(!horizon.isVisible(-360.0 + 20.0, 39)); 0133 QVERIFY(horizon.isVisible(360.0 + 25.0, 34)); 0134 QVERIFY(!horizon.isVisible(360.0 + 25.0, 32)); 0135 QVERIFY(horizon.isVisible(-360.0 + 25.0, 34)); 0136 QVERIFY(!horizon.isVisible(-360.0 + 25.0, 32)); 0137 QVERIFY(horizon.isVisible(360.0 + 15.0, 31)); 0138 QVERIFY(!horizon.isVisible(360.0 + 15.0, 29)); 0139 QVERIFY(horizon.isVisible(-360.0 + 15.0, 31)); 0140 QVERIFY(!horizon.isVisible(-360.0 + 15.0, 29)); 0141 QVERIFY(horizon.isVisible(360.0 + 35.0, -90 + 1)); 0142 QVERIFY(horizon.isVisible(360.0 + 5.0, -90 + 1)); 0143 QVERIFY(horizon.isVisible(-360.0 + 35.0, -90 + 1)); 0144 QVERIFY(horizon.isVisible(-360.0 + 5.0, -90 + 1)); 0145 0146 // Disable that horizon. All tests above shoud be visible. 0147 horizon.findRegion("R1")->setEnabled(false); 0148 polygons.clear(); 0149 horizon.drawPolygons(nullptr, &polygons); 0150 0151 QVERIFY(!horizon.altitudeConstraintsExist()); 0152 QVERIFY(checkHorizon(horizon, 20, 41, true, polygons)); 0153 QVERIFY(checkHorizon(horizon, 20, 39, true, polygons)); 0154 QVERIFY(checkHorizon(horizon, 25.0, 34, true, polygons)); 0155 QVERIFY(checkHorizon(horizon, 25.0, 32, true, polygons)); 0156 QVERIFY(checkHorizon(horizon, 15.0, 31, true, polygons)); 0157 QVERIFY(checkHorizon(horizon, 15.0, 29, true, polygons)); 0158 QVERIFY(checkHorizon(horizon, 35.0, -90 + 1, true, polygons)); 0159 QVERIFY(checkHorizon(horizon, 5.0, -90 + 1, true, polygons)); 0160 0161 // Re-enable it 0162 horizon.findRegion("R1")->setEnabled(true); 0163 QVERIFY(horizon.altitudeConstraintsExist()); 0164 0165 // Now add a ceiling above the first horizon line. 0166 // Above the ceiling should not be visible 0167 QList<double> az2 = {14.0, 20.0, 24.0}; 0168 QList<double> alt2 = {40.0, 46.0, 50.0}; 0169 auto list2 = setupHorizonEntities(az2, alt2); 0170 horizon.addRegion("R2", true, list2, true); 0171 polygons.clear(); 0172 horizon.drawPolygons(nullptr, &polygons); 0173 0174 QVERIFY(checkHorizon(horizon, 18, 51, false, polygons)); 0175 QVERIFY(checkHorizon(horizon, 18, 60, false, polygons)); 0176 QVERIFY(checkHorizon(horizon, 22, 51, false, polygons)); 0177 QVERIFY(checkHorizon(horizon, 22, 60, false, polygons)); 0178 QVERIFY(checkHorizon(horizon, 18, 42, true, polygons)); 0179 // but it doesn't affect things to its side 0180 QVERIFY(checkHorizon(horizon, 13, 51, true, polygons)); 0181 QVERIFY(checkHorizon(horizon, 13, 49, true, polygons)); 0182 QVERIFY(checkHorizon(horizon, 25, 51, true, polygons)); 0183 QVERIFY(checkHorizon(horizon, 25, 49, true, polygons)); 0184 0185 // Disable the ceiling. Those points become visible again. 0186 horizon.findRegion("R2")->setEnabled(false); 0187 polygons.clear(); 0188 horizon.drawPolygons(nullptr, &polygons); 0189 0190 QVERIFY(checkHorizon(horizon, 18, 51, true, polygons)); 0191 QVERIFY(checkHorizon(horizon, 18, 60, true, polygons)); 0192 QVERIFY(checkHorizon(horizon, 22, 51, true, polygons)); 0193 QVERIFY(checkHorizon(horizon, 22, 60, true, polygons)); 0194 0195 // Re-enable the ceiling. 0196 horizon.findRegion("R2")->setEnabled(true); 0197 polygons.clear(); 0198 horizon.drawPolygons(nullptr, &polygons); 0199 QVERIFY(checkHorizon(horizon, 18, 51, false, polygons)); 0200 QVERIFY(checkHorizon(horizon, 18, 60, false, polygons)); 0201 QVERIFY(checkHorizon(horizon, 22.5, 51, false, polygons)); 0202 QVERIFY(checkHorizon(horizon, 22.5, 60, false, polygons)); 0203 0204 // Add another horizon line above the ceiling again makes that visible. 0205 QList<double> az3 = {10.0, 19.0}; 0206 QList<double> alt3 = {50.5, 50.2}; 0207 auto list3 = setupHorizonEntities(az3, alt3); 0208 horizon.addRegion("R3", true, list3, false); 0209 polygons.clear(); 0210 horizon.drawPolygons(nullptr, &polygons); 0211 0212 QVERIFY(checkHorizon(horizon, 18, 51, true, polygons)); 0213 QVERIFY(checkHorizon(horizon, 18, 60, true, polygons)); 0214 // but it shouldn't affect other az values 0215 QVERIFY(checkHorizon(horizon, 22.5, 51, false, polygons)); 0216 QVERIFY(checkHorizon(horizon, 22.5, 60, false, polygons)); 0217 0218 } 0219 0220 void TestArtificialHorizon::artificialCeilingTest() 0221 { 0222 ArtificialHorizon horizon; 0223 0224 // This removes a call to KStars::Instance() that's not needed in testing. 0225 horizon.setTesting(); 0226 0227 QList<double> az1 = {259.0, 260.0, 299.0, 300.0, 330.0, 0.0, 30.0, 60.0, 61.0, 90.0, 120.0, 150.0, 180.0, 210.0, 240.0, 259.99}; 0228 QList<double> alt1 = { 90.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 90.0, 90.0, 90.0, 90.0, 90.0, 90.0, 90.0, 90.0}; 0229 auto list1 = setupHorizonEntities(az1, alt1); 0230 horizon.addRegion("horizon", true, list1, false); 0231 0232 QList<double> az2 = {260.0, 300.0, 330.0, 0.0, 30.0, 60.0}; 0233 QList<double> alt2 = { 66.0, 66.0, 66.0, 66.0, 66.0, 66.0}; 0234 auto list2 = setupHorizonEntities(az2, alt2); 0235 horizon.addRegion("ceiling", true, list2, true); 0236 0237 QVERIFY(horizon.altitudeConstraintsExist()); 0238 QList<LineList> polygons; 0239 horizon.drawPolygons(nullptr, &polygons); 0240 0241 // Check points above and below the first horizon line. 0242 QVERIFY(checkHorizon(horizon, 54, 50, true, polygons)); 0243 QVERIFY(checkHorizon(horizon, 54, 60, true, polygons)); 0244 QVERIFY(checkHorizon(horizon, 49, 68, false, polygons)); 0245 QVERIFY(checkHorizon(horizon, 21, 77, false, polygons)); 0246 QVERIFY(checkHorizon(horizon, 321, 74, false, polygons)); 0247 QVERIFY(checkHorizon(horizon, 310, 68, false, polygons)); 0248 QVERIFY(checkHorizon(horizon, 305, 60, true, polygons)); 0249 QVERIFY(checkHorizon(horizon, 306, 48, true, polygons)); 0250 QVERIFY(checkHorizon(horizon, 328, 14, false, polygons)); 0251 QVERIFY(checkHorizon(horizon, 351, 3, false, polygons)); 0252 } 0253 0254 QTEST_GUILESS_MAIN(TestArtificialHorizon)