File indexing completed on 2023-05-30 10:49:16
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 0003 // SPDX-FileCopyrightText: 2010 Matias Kallio <matias.kallio@gmail.com> 0004 // SPDX-FileCopyrightText: 2011 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 // SPDX-FileCopyrightText: 2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de> 0006 0007 #include "MarbleGlobal.h" 0008 #include "MarbleWidget.h" 0009 #include "GeoDataCoordinates.h" 0010 #include "TestUtils.h" 0011 0012 #include <QLocale> 0013 #include <QDebug> 0014 #include <QTranslator> 0015 #include <QTemporaryFile> 0016 0017 using namespace Marble; 0018 0019 0020 class TestGeoDataCoordinates : public QObject 0021 { 0022 Q_OBJECT 0023 0024 private Q_SLOTS: 0025 void initTestCase(); 0026 0027 void testConstruction(); 0028 void testSet_Degree(); 0029 void testSet_Radian(); 0030 void testSetLongitude_Degree(); 0031 void testSetLongitude_Radian(); 0032 void testSetLatitude_Degree(); 0033 void testSetLatitude_Radian(); 0034 void testAltitude(); 0035 void testOperatorAssignment(); 0036 void testDetail(); 0037 void testIsPole_data(); 0038 void testIsPole(); 0039 void testNotation(); 0040 void testNormalizeLat_data(); 0041 void testNormalizeLat(); 0042 void testNormalizeLon_data(); 0043 void testNormalizeLon(); 0044 void testNormalizeDegree_data(); 0045 void testNormalizeDegree(); 0046 void testNormalizeRadian_data(); 0047 void testNormalizeRadian(); 0048 void testFromStringDMS_data(); 0049 void testFromStringDMS(); 0050 void testFromStringDM_data(); 0051 void testFromStringDM(); 0052 void testFromStringD_data(); 0053 void testFromStringD(); 0054 void testFromLocaleString_data(); 0055 void testFromLocaleString(); 0056 void testToString_Decimal_data(); 0057 void testToString_Decimal(); 0058 void testToString_DMS_data(); 0059 void testToString_DMS(); 0060 void testToString_DM_data(); 0061 void testToString_DM(); 0062 void testPack_data(); 0063 void testPack(); 0064 void testUTM_data(); 0065 void testUTM(); 0066 }; 0067 0068 void TestGeoDataCoordinates::initTestCase() 0069 { 0070 QLocale::setDefault( QLocale::c() ); // needed for testing toString* conversions 0071 0072 QTime time = QTime::currentTime(); 0073 qsrand((uint)time.msec()); 0074 } 0075 0076 /* 0077 * test constructors 0078 */ 0079 void TestGeoDataCoordinates::testConstruction() 0080 { 0081 GeoDataCoordinates invalid1; 0082 0083 QVERIFY(!invalid1.isValid()); 0084 0085 GeoDataCoordinates invalid2(invalid1); 0086 0087 QVERIFY(!invalid2.isValid()); 0088 QVERIFY(!invalid1.isValid()); 0089 QCOMPARE(invalid1, invalid2); 0090 0091 const qreal lon = 164.77; 0092 const qreal lat = 55.9; 0093 const qreal alt = 400.003; 0094 0095 GeoDataCoordinates coordinates3(lon, lat, alt, GeoDataCoordinates::Degree); 0096 0097 QVERIFY(coordinates3.isValid()); 0098 QCOMPARE(coordinates3, GeoDataCoordinates(lon, lat, alt, GeoDataCoordinates::Degree)); 0099 QVERIFY(coordinates3 != invalid1); 0100 QVERIFY(coordinates3 != invalid2); 0101 0102 QCOMPARE(coordinates3.longitude(GeoDataCoordinates::Degree), lon); 0103 QCOMPARE(coordinates3.longitude(), lon*DEG2RAD); 0104 0105 QCOMPARE(coordinates3.latitude(GeoDataCoordinates::Degree), lat); 0106 QCOMPARE(coordinates3.latitude(), lat*DEG2RAD); 0107 0108 QCOMPARE(coordinates3.altitude(), alt); 0109 0110 qreal myLongitude = 0; 0111 qreal myLatitude = 0; 0112 0113 coordinates3.geoCoordinates(myLongitude, myLatitude, GeoDataCoordinates::Degree); 0114 0115 QCOMPARE(myLongitude, lon); 0116 QCOMPARE(myLatitude, lat); 0117 0118 myLongitude = 0; 0119 myLatitude = 0; 0120 0121 coordinates3.geoCoordinates(myLongitude, myLatitude); 0122 0123 QCOMPARE(myLongitude, lon*DEG2RAD); 0124 QCOMPARE(myLatitude, lat*DEG2RAD); 0125 0126 GeoDataCoordinates coordinates4(lon*DEG2RAD, lat*DEG2RAD, alt); 0127 0128 QVERIFY(coordinates4.isValid()); 0129 QCOMPARE(coordinates4, GeoDataCoordinates(lon, lat, alt, GeoDataCoordinates::Degree)); 0130 QCOMPARE(coordinates4, coordinates3); 0131 QVERIFY(coordinates4 != invalid1); 0132 QVERIFY(coordinates4 != invalid2); 0133 0134 GeoDataCoordinates coordinates5(coordinates3); 0135 0136 QVERIFY(coordinates5.isValid()); 0137 QCOMPARE(coordinates5, GeoDataCoordinates(lon, lat, alt, GeoDataCoordinates::Degree)); 0138 QCOMPARE(coordinates5, coordinates3); 0139 QCOMPARE(coordinates5, coordinates4); 0140 QVERIFY(coordinates5 != invalid1); 0141 QVERIFY(coordinates5 != invalid2); 0142 0143 GeoDataCoordinates coordinates6(invalid1.longitude(), invalid1.latitude(), invalid1.altitude(), GeoDataCoordinates::Radian, invalid1.detail()); 0144 0145 QVERIFY(coordinates6.isValid()); // it should be valid, even though 0146 QCOMPARE(coordinates6, invalid1); // it is equal to an invalid one 0147 } 0148 0149 /* 0150 * test setting coordinates in degree 0151 */ 0152 void TestGeoDataCoordinates::testSet_Degree() 0153 { 0154 const qreal lon = 345.8; 0155 const qreal lat = 70.3; 0156 const qreal alt = 1000.9; 0157 0158 GeoDataCoordinates coordinates1; // invalid 0159 coordinates1.set(lon, lat, alt, GeoDataCoordinates::Degree); 0160 0161 QVERIFY(coordinates1.isValid()); 0162 0163 GeoDataCoordinates coordinates2(coordinates1); 0164 coordinates2.set(0, 0, 0, GeoDataCoordinates::Degree); 0165 0166 QVERIFY(coordinates2.isValid()); 0167 QCOMPARE(coordinates1, GeoDataCoordinates(lon, lat, alt, GeoDataCoordinates::Degree)); 0168 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0, 0, GeoDataCoordinates::Degree)); 0169 0170 } 0171 0172 /* 0173 * test setting coordinates in radian 0174 */ 0175 void TestGeoDataCoordinates::testSet_Radian() 0176 { 0177 const qreal lon = 1.3; 0178 const qreal lat = 0.7; 0179 const qreal alt = 6886.44; 0180 0181 GeoDataCoordinates coordinates1; // invalid 0182 coordinates1.set(lon, lat, alt); 0183 0184 QVERIFY(coordinates1.isValid()); 0185 0186 GeoDataCoordinates coordinates2(coordinates1); 0187 coordinates2.set(0, 0, 0); 0188 0189 QVERIFY(coordinates2.isValid()); 0190 QCOMPARE(coordinates1, GeoDataCoordinates(lon, lat, alt)); 0191 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0, 0)); 0192 } 0193 0194 /* 0195 * test setLongitude() in degree 0196 */ 0197 void TestGeoDataCoordinates::testSetLongitude_Degree() 0198 { 0199 const qreal lon = 143.8; 0200 0201 GeoDataCoordinates coordinates1; // invalid 0202 coordinates1.setLongitude(lon, GeoDataCoordinates::Degree); 0203 0204 QVERIFY(coordinates1.isValid()); 0205 0206 GeoDataCoordinates coordinates2(coordinates1); 0207 coordinates2.setLongitude(0, GeoDataCoordinates::Degree); 0208 0209 QVERIFY(coordinates2.isValid()); 0210 QCOMPARE(coordinates1, GeoDataCoordinates(lon, 0, 0, GeoDataCoordinates::Degree)); 0211 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0, 0, GeoDataCoordinates::Degree)); 0212 } 0213 0214 /* 0215 * test setLongitude() in radian 0216 */ 0217 void TestGeoDataCoordinates::testSetLongitude_Radian() 0218 { 0219 const qreal lon = 2.5; 0220 0221 GeoDataCoordinates coordinates1; // invalid 0222 coordinates1.setLongitude(lon); 0223 0224 QVERIFY(coordinates1.isValid()); 0225 0226 GeoDataCoordinates coordinates2(coordinates1); 0227 coordinates2.setLongitude(0); 0228 0229 QVERIFY(coordinates2.isValid()); 0230 QCOMPARE(coordinates1, GeoDataCoordinates(lon, 0)); 0231 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0)); 0232 } 0233 0234 /* 0235 * test setLatitude() and latitude() in degree 0236 */ 0237 void TestGeoDataCoordinates::testSetLatitude_Degree() 0238 { 0239 const qreal lat = 75.0; 0240 0241 GeoDataCoordinates coordinates1; // invalid 0242 coordinates1.setLatitude(lat, GeoDataCoordinates::Degree); 0243 0244 QVERIFY(coordinates1.isValid()); 0245 0246 GeoDataCoordinates coordinates2(coordinates1); 0247 coordinates2.setLatitude(0, GeoDataCoordinates::Degree); 0248 0249 QVERIFY(coordinates2.isValid()); 0250 QCOMPARE(coordinates1, GeoDataCoordinates(0, lat, 0, GeoDataCoordinates::Degree)); 0251 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0, 0, GeoDataCoordinates::Degree)); 0252 } 0253 0254 /* 0255 * test setLatitude() in radian 0256 */ 0257 void TestGeoDataCoordinates::testSetLatitude_Radian() 0258 { 0259 const qreal lat = 1.2; 0260 0261 GeoDataCoordinates coordinates1; // invalid 0262 coordinates1.setLatitude(lat); 0263 0264 QVERIFY(coordinates1.isValid()); 0265 0266 GeoDataCoordinates coordinates2(coordinates1); 0267 coordinates2.setLatitude(0); 0268 0269 QVERIFY(coordinates2.isValid()); 0270 QCOMPARE(coordinates1, GeoDataCoordinates(0, lat)); 0271 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0)); 0272 } 0273 0274 /* 0275 * test setAltitude() 0276 */ 0277 void TestGeoDataCoordinates::testAltitude() 0278 { 0279 const qreal alt = 400; 0280 0281 GeoDataCoordinates coordinates1; // invalid 0282 coordinates1.setAltitude(alt); 0283 0284 QVERIFY(coordinates1.isValid()); 0285 0286 GeoDataCoordinates coordinates2(coordinates1); 0287 coordinates2.setAltitude(0); 0288 0289 QVERIFY(coordinates2.isValid()); 0290 QCOMPARE(coordinates1, GeoDataCoordinates(0, 0, alt)); 0291 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0, 0)); 0292 } 0293 0294 void TestGeoDataCoordinates::testOperatorAssignment() 0295 { 0296 const qreal lon = 123.4; 0297 const qreal lat = 56.7; 0298 const qreal alt = 890.1; 0299 0300 const GeoDataCoordinates coordinates1(lon, lat, alt, GeoDataCoordinates::Degree); 0301 const GeoDataCoordinates coordinates2(0, 0, 0); 0302 0303 GeoDataCoordinates coordinates3; // invalid 0304 coordinates3 = coordinates1; 0305 0306 QVERIFY(coordinates3.isValid()); 0307 QCOMPARE(coordinates1, GeoDataCoordinates(lon, lat, alt, GeoDataCoordinates::Degree)); // stays unmodified 0308 QCOMPARE(coordinates3, coordinates1); 0309 0310 coordinates3 = GeoDataCoordinates(); 0311 0312 QVERIFY(!coordinates3.isValid()); 0313 0314 GeoDataCoordinates coordinates4(coordinates1); 0315 coordinates4 = coordinates2; 0316 0317 QVERIFY(coordinates4.isValid()); 0318 QCOMPARE(coordinates1, GeoDataCoordinates(lon, lat, alt, GeoDataCoordinates::Degree)); // stays unmodified 0319 QCOMPARE(coordinates2, GeoDataCoordinates(0, 0, 0)); // stays unmodified 0320 QCOMPARE(coordinates4, coordinates2); 0321 } 0322 0323 /* 0324 * test setDetail() and detail() 0325 */ 0326 void TestGeoDataCoordinates::testDetail() 0327 { 0328 const quint8 detailnumber = 15; 0329 0330 GeoDataCoordinates coordinates1; 0331 coordinates1.setDetail(detailnumber); 0332 0333 GeoDataCoordinates coordinates2(coordinates1); 0334 coordinates2.setDetail(0); 0335 0336 QCOMPARE(coordinates1.detail(), detailnumber); 0337 } 0338 0339 /* 0340 * test setDefaultNotation() and defaultNotation 0341 */ 0342 void TestGeoDataCoordinates::testNotation() 0343 { 0344 GeoDataCoordinates::setDefaultNotation(GeoDataCoordinates::Decimal); 0345 QVERIFY(GeoDataCoordinates::defaultNotation() == GeoDataCoordinates::Decimal); 0346 0347 GeoDataCoordinates::setDefaultNotation(GeoDataCoordinates::DMS); 0348 QVERIFY(GeoDataCoordinates::defaultNotation() == GeoDataCoordinates::DMS); 0349 } 0350 0351 /* 0352 * test data for testIsPole() 0353 */ 0354 void TestGeoDataCoordinates::testIsPole_data() 0355 { 0356 QTest::addColumn<qreal>("lon"); 0357 QTest::addColumn<qreal>("lat"); 0358 QTest::addColumn<qreal>("alt"); 0359 QTest::addColumn<QString>("pole"); 0360 0361 QTest::newRow("false") << qreal(50.0) << qreal(50.0) << qreal(0.0) << "false_pole"; 0362 QTest::newRow("south") << qreal(0.0) << qreal(-90.0) << qreal(0.0) << "south_pole"; 0363 QTest::newRow("north") << qreal(0.0) << qreal(90.0) << qreal(0.0) << "north_pole"; 0364 } 0365 0366 /* 0367 * Test isPole-method 0368 */ 0369 void TestGeoDataCoordinates::testIsPole() 0370 { 0371 QFETCH(qreal, lon); 0372 QFETCH(qreal, lat); 0373 QFETCH(qreal, alt); 0374 QFETCH(QString, pole); 0375 0376 GeoDataCoordinates coordinates1; 0377 0378 if (pole == QLatin1String("false_pole")) { 0379 coordinates1.set(lon, lat, alt, GeoDataCoordinates::Degree); 0380 QVERIFY(coordinates1.isPole() == false); 0381 } else if (pole == QLatin1String("south_pole")) { 0382 coordinates1.set(lon, lat, alt, GeoDataCoordinates::Degree); 0383 QVERIFY(coordinates1.isPole(SouthPole)); 0384 } else if (pole == QLatin1String("north_pole")) { 0385 coordinates1.set(lon, lat, alt, GeoDataCoordinates::Degree); 0386 QVERIFY(coordinates1.isPole(NorthPole)); 0387 } 0388 } 0389 0390 void TestGeoDataCoordinates::testNormalizeLat_data() 0391 { 0392 QTest::addColumn<qreal>( "latRadian" ); 0393 0394 QTest::newRow( "north pole" ) << qreal(M_PI / 2); 0395 QTest::newRow( "south pole" ) << qreal(- M_PI / 2); 0396 QTest::newRow( "somewhere" ) << qreal(1.0); 0397 } 0398 0399 void TestGeoDataCoordinates::testNormalizeLat() 0400 { 0401 QFETCH( qreal, latRadian ); 0402 0403 qreal latDegree = RAD2DEG * latRadian; 0404 for ( int i = 1; i < 10; ++i ) { 0405 if ( ( i % 2 ) == 0 ) { 0406 QCOMPARE( GeoDataCoordinates::normalizeLat( latRadian + i * M_PI, GeoDataCoordinates::Radian ), latRadian ); 0407 QCOMPARE( GeoDataCoordinates::normalizeLat( latRadian + i * M_PI ), latRadian ); 0408 QCOMPARE( GeoDataCoordinates::normalizeLat( latDegree + i * 180, GeoDataCoordinates::Degree ), latDegree ); 0409 } 0410 else { 0411 QCOMPARE( GeoDataCoordinates::normalizeLat( latRadian + i * M_PI, GeoDataCoordinates::Radian ), -latRadian ); 0412 QCOMPARE( GeoDataCoordinates::normalizeLat( latRadian + i * M_PI ), -latRadian ); 0413 QCOMPARE( GeoDataCoordinates::normalizeLat( latDegree + i * 180, GeoDataCoordinates::Degree ), -latDegree ); 0414 } 0415 } 0416 } 0417 0418 void TestGeoDataCoordinates::testNormalizeLon_data() 0419 { 0420 QTest::addColumn<qreal>( "lonRadian" ); 0421 0422 QTest::newRow( "half east" ) << qreal(M_PI / 2); 0423 QTest::newRow( "half west" ) << qreal(- M_PI / 2); 0424 QTest::newRow( "somewhere" ) << qreal(1.0); 0425 QTest::newRow( "date line east" ) << qreal(M_PI); 0426 QTest::newRow( "date line west" ) << - qreal(M_PI); 0427 0428 } 0429 0430 void TestGeoDataCoordinates::testNormalizeLon() 0431 { 0432 QFETCH( qreal, lonRadian ); 0433 0434 qreal lonDegree = RAD2DEG * lonRadian; 0435 for ( int i = 1; i < 10; ++i ) { 0436 if ( lonRadian == qreal(M_PI) || lonRadian == qreal(-M_PI) ) { 0437 int lonRadianLarge = qRound( lonRadian * 1000 ); 0438 int lonDegreeLarge = qRound( lonDegree * 1000 ); 0439 if ( qRound( GeoDataCoordinates::normalizeLon( lonRadian + i * 2 * M_PI ) * 1000 ) != lonRadianLarge 0440 && qRound( GeoDataCoordinates::normalizeLon( lonRadian + i * 2 * M_PI ) * 1000 ) != -lonRadianLarge ) 0441 { 0442 QFAIL( "Error at M_PI/-M_PI" ); 0443 } 0444 if ( qRound( GeoDataCoordinates::normalizeLon( lonRadian + i * 2 * M_PI, GeoDataCoordinates::Radian ) * 1000 ) != lonRadianLarge 0445 && qRound( GeoDataCoordinates::normalizeLon( lonRadian + i * 2 * M_PI, GeoDataCoordinates::Radian ) * 1000 ) != -lonRadianLarge ) 0446 { 0447 QFAIL( "Error at M_PI/-M_PI" ); 0448 } 0449 if ( qRound( GeoDataCoordinates::normalizeLon( lonDegree + i * 360, GeoDataCoordinates::Degree ) * 1000 ) != lonDegreeLarge 0450 && qRound( GeoDataCoordinates::normalizeLon( lonDegree + i * 360, GeoDataCoordinates::Degree ) * 1000 ) != -lonDegreeLarge ) 0451 { 0452 QFAIL( "Error at M_PI/-M_PI" ); 0453 } 0454 } 0455 else { 0456 QCOMPARE( GeoDataCoordinates::normalizeLon( lonRadian + i * 2 * M_PI, GeoDataCoordinates::Radian ), lonRadian ); 0457 QCOMPARE( GeoDataCoordinates::normalizeLon( lonRadian + i * 2 * M_PI ), lonRadian ); 0458 QCOMPARE( GeoDataCoordinates::normalizeLon( lonDegree + i * 360, GeoDataCoordinates::Degree ), lonDegree ); 0459 } 0460 } 0461 } 0462 0463 /* 0464 * test data for testNormalize() 0465 */ 0466 void TestGeoDataCoordinates::testNormalizeDegree_data() 0467 { 0468 QTest::addColumn<qreal>("lon"); 0469 QTest::addColumn<qreal>("lat"); 0470 0471 QTest::newRow("deg") << qreal(200.0) << qreal(130.0); 0472 } 0473 0474 /* 0475 * test normalizeLon(), normalizeLat() and normalizeLonLat() 0476 */ 0477 void TestGeoDataCoordinates::testNormalizeDegree() 0478 { 0479 QFETCH(qreal, lon); 0480 QFETCH(qreal, lat); 0481 0482 QCOMPARE(GeoDataCoordinates::normalizeLon(lon, GeoDataCoordinates::Degree), qreal(-160)); 0483 QCOMPARE(GeoDataCoordinates::normalizeLat(lat, GeoDataCoordinates::Degree), qreal(50)); 0484 0485 qreal normalized_lon = lon; 0486 qreal normalized_lat = lat; 0487 0488 GeoDataCoordinates::normalizeLonLat( normalized_lon, normalized_lat, GeoDataCoordinates::Degree); 0489 QCOMPARE(normalized_lon, qreal(20)); 0490 QCOMPARE(normalized_lat, qreal(50)); 0491 } 0492 0493 /* 0494 * test data for testNormalize() 0495 */ 0496 void TestGeoDataCoordinates::testNormalizeRadian_data() 0497 { 0498 QTest::addColumn<qreal>("lon"); 0499 QTest::addColumn<qreal>("lat"); 0500 0501 QTest::newRow("rad") << qreal(3.6) << qreal(2.7); 0502 } 0503 0504 /* 0505 * test normalizeLon(), normalizeLat() and normalizeLonLat() 0506 */ 0507 void TestGeoDataCoordinates::testNormalizeRadian() 0508 { 0509 QFETCH(qreal, lon); 0510 QFETCH(qreal, lat); 0511 0512 // Compare up to three decimals 0513 qreal value = GeoDataCoordinates::normalizeLon(lon, GeoDataCoordinates::Radian); 0514 QCOMPARE(ceil(value * 1000) / 1000, qreal(-2.683)); 0515 0516 value = GeoDataCoordinates::normalizeLat(lat, GeoDataCoordinates::Radian); 0517 QCOMPARE(ceil(value * 1000) / 1000, qreal(0.442)); 0518 0519 qreal normalized_lon = lon; 0520 qreal normalized_lat = lat; 0521 0522 GeoDataCoordinates::normalizeLonLat( normalized_lon, normalized_lat, GeoDataCoordinates::Radian); 0523 QCOMPARE(ceil(normalized_lon * 1000) / 1000, qreal(0.459)); 0524 QCOMPARE(ceil(normalized_lat * 1000) / 1000, qreal(0.442)); 0525 } 0526 0527 enum SignType {NoSign, PositiveSign, NegativeSign}; 0528 enum SphereType {PosSphere, NegSphere}; 0529 enum UnitsType {NoUnits, WithUnits}; 0530 enum SpacesType {NoSpaces, WithSpaces}; 0531 enum LocaleType {CLocale, SystemLocale}; 0532 0533 static QString 0534 createDegreeString(SignType signType, 0535 int degreeValue, int minutesValue, qreal secondsValue, 0536 LocaleType locale, 0537 UnitsType unitsType, SpacesType spacesType) 0538 { 0539 QString string; 0540 0541 // add degree 0542 if (signType != NoSign) string.append(QLatin1Char(signType==PositiveSign?'+':'-')); 0543 string.append(QString::number(degreeValue)); 0544 if (unitsType == WithUnits) string.append(QChar(0xb0)); 0545 0546 // add minutes 0547 string.append(QLatin1Char(' ') + QString::number(minutesValue)); 0548 if (unitsType == WithUnits) string.append(QLatin1Char('\'')); 0549 0550 // add seconds 0551 if (locale == CLocale) { 0552 string.append(QLatin1Char(' ') + QString::number(secondsValue, 'f', 10)); 0553 } else { 0554 string.append(QLatin1Char(' ') + QLocale::system().toString(secondsValue, 'f', 10)); 0555 } 0556 if (unitsType == WithUnits) string.append(QLatin1Char('"')); 0557 0558 if (spacesType == WithSpaces) string.append(QLatin1Char(' ')); 0559 0560 return string; 0561 } 0562 0563 static QString 0564 createDegreeString(SignType signType, 0565 int degreeValue, qreal minutesValue, 0566 LocaleType locale, 0567 UnitsType unitsType, SpacesType spacesType) 0568 { 0569 QString string; 0570 0571 // add degree 0572 if (signType != NoSign) string.append(QLatin1Char(signType==PositiveSign?'+':'-')); 0573 string.append(QString::number(degreeValue)); 0574 if (unitsType == WithUnits) string.append(QChar(0xb0)); 0575 0576 // add minutes 0577 if (locale == CLocale) { 0578 string.append(QLatin1Char(' ') + QString::number(minutesValue, 'f', 10)); 0579 } else { 0580 string.append(QLatin1Char(' ') + QLocale::system().toString(minutesValue, 'f', 10)); 0581 } 0582 if (unitsType == WithUnits) string.append(QLatin1Char('\'')); 0583 0584 if (spacesType == WithSpaces) string.append(QLatin1Char(' ')); 0585 0586 return string; 0587 } 0588 0589 static QString 0590 createDegreeString(SignType signType, 0591 qreal degreeValue, 0592 LocaleType locale, 0593 UnitsType unitsType, SpacesType spacesType) 0594 { 0595 QString string; 0596 0597 // add degree 0598 if (signType != NoSign) string.append(QLatin1Char(signType==PositiveSign?'+':'-')); 0599 if (locale == CLocale) { 0600 string.append(QString::number(degreeValue, 'f', 10)); 0601 } else { 0602 string.append(QLocale::system().toString(degreeValue, 'f', 10)); 0603 } 0604 if (unitsType == WithUnits) string.append(QChar(0xb0)); 0605 0606 if (spacesType == WithSpaces) string.append(QLatin1Char(' ')); 0607 0608 return string; 0609 } 0610 0611 /* 0612 * test data for testStringDMS() 0613 */ 0614 void TestGeoDataCoordinates::testFromStringDMS_data() 0615 { 0616 QTest::addColumn<QString>("string"); 0617 QTest::addColumn<qreal>("lon"); 0618 QTest::addColumn<qreal>("lat"); 0619 0620 const QVector<SignType> signTypes = QVector<SignType>() 0621 << NoSign << PositiveSign << NegativeSign; 0622 const QVector<SphereType> sphereTypes = QVector<SphereType>() 0623 << PosSphere << NegSphere; 0624 const QVector<UnitsType> unitsTypes = QVector<UnitsType>() 0625 << NoUnits << WithUnits; 0626 const QVector<SpacesType> spacesTypes = QVector<SpacesType>() 0627 << NoSpaces << WithSpaces; 0628 const QVector<LocaleType> localeTypes = QVector<LocaleType>() 0629 << CLocale << SystemLocale; 0630 0631 const QVector<uint> degreeSamples = QVector<uint>() 0632 << 0 << 140 << 180; 0633 const QVector<uint> minutesSamples = QVector<uint>() 0634 << 0 << 23 << 59; 0635 const QVector<qreal> secondsSamples = QVector<qreal>() 0636 << 0.0 << 3.14159 << 59.9999999; 0637 0638 foreach(const UnitsType unitsType, unitsTypes) { 0639 foreach(const SpacesType spacesType, spacesTypes) { 0640 // lon 0641 foreach(const SphereType lonSphere, sphereTypes) { 0642 foreach(const SignType lonSignType, signTypes) { 0643 const bool lonIsPositive = 0644 (lonSphere==PosSphere && lonSignType!=NegativeSign) || 0645 (lonSphere==NegSphere && lonSignType==NegativeSign); 0646 foreach(const uint lonDegree, degreeSamples) { 0647 foreach(const uint lonMinutes, minutesSamples) { 0648 if(lonDegree == 180 && lonMinutes != 0) continue; 0649 foreach(const qreal lonSeconds, secondsSamples) { 0650 if(lonDegree == 180 && lonSeconds != 0.0) continue; 0651 // lat 0652 foreach(const SphereType latSphere, sphereTypes) { 0653 foreach(const SignType latSignType, signTypes) { 0654 const bool latIsPositive = 0655 (latSphere==PosSphere && latSignType!=NegativeSign) || 0656 (latSphere==NegSphere && latSignType==NegativeSign); 0657 foreach(const uint latDegree, degreeSamples) { 0658 foreach(const uint latMinutes, minutesSamples) { 0659 if(latDegree == 180 && latMinutes != 0) continue; 0660 foreach(const qreal latSeconds, secondsSamples) { 0661 if(latDegree == 180 && latSeconds != 0.0) continue; 0662 // locale 0663 foreach(const LocaleType locale, localeTypes) { 0664 0665 // actual construction 0666 // Create lon & lat values 0667 qreal lon = (qreal)lonDegree + lonMinutes*MIN2HOUR + lonSeconds*SEC2HOUR; 0668 if( ! lonIsPositive ) 0669 lon *= -1; 0670 qreal lat = (qreal)latDegree + latMinutes*MIN2HOUR + latSeconds*SEC2HOUR; 0671 if( ! latIsPositive ) 0672 lat *= -1; 0673 0674 // Create string 0675 QString string; 0676 string.append(createDegreeString(latSignType, 0677 latDegree, latMinutes, latSeconds, 0678 locale, 0679 unitsType, spacesType)); 0680 string.append(QLatin1Char(latSphere==PosSphere?'N':'S')); 0681 string.append(QLatin1Char(' ')); 0682 string.append(createDegreeString(lonSignType, 0683 lonDegree, lonMinutes, lonSeconds, 0684 locale, 0685 unitsType, spacesType)); 0686 string.append(QLatin1Char(lonSphere==PosSphere?'E':'W')); 0687 0688 // Create row title 0689 QString rowTitle; 0690 rowTitle.append(QLatin1String(spacesType==WithSpaces?"spaced dir":"unspaced dir")) 0691 .append(QLatin1String(unitsType==WithUnits?"|units":"|no units")) 0692 .append(QLatin1String("|lon:")) 0693 .append(QLatin1Char(lonIsPositive?'+':'-')) 0694 .append(QString::number(lonDegree)+QChar(0xb0)) 0695 .append(QString::number(lonMinutes)+QLatin1Char('\'')) 0696 .append(QString::number(lonSeconds, 'f', 10)+QLatin1Char('"')) 0697 .append(QLatin1Char(lonSphere==PosSphere?'P':'N')) 0698 .append(QLatin1String("|lat:")) 0699 .append(QLatin1Char(latIsPositive?'+':'-')) 0700 .append(QString::number(latDegree)+QChar(0xb0)) 0701 .append(QString::number(latMinutes)+QLatin1Char('\'')) 0702 .append(QString::number(latSeconds, 'f', 10)+QLatin1Char('"')) 0703 .append(QLatin1Char(latSphere==PosSphere?'P':'N')) 0704 .append(QLatin1Char('|')).append(QLatin1Char(locale==CLocale?'C':'L')) 0705 .append(QLatin1Char('|')).append(string).append(QLatin1Char('|')); 0706 QTest::newRow(rowTitle.toLatin1().constData()) 0707 << string 0708 << lon 0709 << lat; 0710 } 0711 } 0712 } 0713 } 0714 } 0715 } 0716 } 0717 } 0718 } 0719 } 0720 } 0721 } 0722 } 0723 } 0724 0725 /* 0726 * test fromString() with DMS notation 0727 */ 0728 void TestGeoDataCoordinates::testFromStringDMS() 0729 { 0730 // only run random 5% of all possible permutations 0731 if ((qreal(qrand()) / RAND_MAX) > 0.05) { 0732 QSKIP("Not picked for this run."); 0733 } 0734 0735 QFETCH(QString, string); 0736 QFETCH(qreal, lon); 0737 QFETCH(qreal, lat); 0738 0739 bool succeeded = false; 0740 const GeoDataCoordinates coords = GeoDataCoordinates::fromString(string, succeeded); 0741 0742 if(! succeeded) 0743 qWarning() << "Could not parse"<<string <<"for"<<lon<<lat; 0744 0745 QVERIFY(succeeded); 0746 QCOMPARE(coords.longitude(GeoDataCoordinates::Degree), lon); 0747 QCOMPARE(coords.latitude(GeoDataCoordinates::Degree), lat); 0748 } 0749 0750 /* 0751 * test data for testStringDM() 0752 */ 0753 void TestGeoDataCoordinates::testFromStringDM_data() 0754 { 0755 QTest::addColumn<QString>("string"); 0756 QTest::addColumn<qreal>("lon"); 0757 QTest::addColumn<qreal>("lat"); 0758 0759 const QVector<SignType> signTypes = QVector<SignType>() 0760 << NoSign << PositiveSign << NegativeSign; 0761 const QVector<SphereType> sphereTypes = QVector<SphereType>() 0762 << PosSphere << NegSphere; 0763 const QVector<UnitsType> unitsTypes = QVector<UnitsType>() 0764 << NoUnits << WithUnits; 0765 const QVector<SpacesType> spacesTypes = QVector<SpacesType>() 0766 << NoSpaces << WithSpaces; 0767 const QVector<LocaleType> localeTypes = QVector<LocaleType>() 0768 << CLocale << SystemLocale; 0769 0770 const QVector<uint> degreeSamples = QVector<uint>() 0771 << 0 << 140 << 180; 0772 const QVector<qreal> minutesSamples = QVector<qreal>() 0773 << 0.0 << 3.14159 << 59.9999999; 0774 0775 foreach(const UnitsType unitsType, unitsTypes) { 0776 foreach(const SpacesType spacesType, spacesTypes) { 0777 // lon 0778 foreach(const SphereType lonSphere, sphereTypes) { 0779 foreach(const SignType lonSignType, signTypes) { 0780 const bool lonIsPositive = 0781 (lonSphere==PosSphere && lonSignType!=NegativeSign) || 0782 (lonSphere==NegSphere && lonSignType==NegativeSign); 0783 foreach(const uint lonDegree, degreeSamples) { 0784 foreach(const qreal lonMinutes, minutesSamples) { 0785 if(lonDegree == 180 && lonMinutes != 0.0) continue; 0786 // lat 0787 foreach(const SphereType latSphere, sphereTypes) { 0788 foreach(const SignType latSignType, signTypes) { 0789 const bool latIsPositive = 0790 (latSphere==PosSphere && latSignType!=NegativeSign) || 0791 (latSphere==NegSphere && latSignType==NegativeSign); 0792 foreach(const uint latDegree, degreeSamples) { 0793 foreach(const qreal latMinutes, minutesSamples) { 0794 if(latDegree == 180 && latMinutes != 0.0) continue; 0795 // locale 0796 foreach(const LocaleType locale, localeTypes) { 0797 0798 // actual construction 0799 // Create lon & lat values 0800 qreal lon = (qreal)lonDegree + lonMinutes*MIN2HOUR; 0801 if( ! lonIsPositive ) 0802 lon *= -1; 0803 qreal lat = (qreal)latDegree + latMinutes*MIN2HOUR; 0804 if( ! latIsPositive ) 0805 lat *= -1; 0806 0807 // Create string 0808 QString string; 0809 string.append(createDegreeString(latSignType, 0810 latDegree, latMinutes, 0811 locale, 0812 unitsType, spacesType)); 0813 string.append(QLatin1Char(latSphere==PosSphere?'N':'S')); 0814 string.append(QLatin1Char(' ')); 0815 string.append(createDegreeString(lonSignType, 0816 lonDegree, lonMinutes, 0817 locale, 0818 unitsType, spacesType)); 0819 string.append(QLatin1Char(lonSphere==PosSphere?'E':'W')); 0820 0821 // Create row title 0822 QString rowTitle; 0823 rowTitle.append(QLatin1String(spacesType==WithSpaces?"spaced dir":"unspaced dir")) 0824 .append(QLatin1String(unitsType==WithUnits?"|units":"|no units")) 0825 .append(QLatin1String("|lon:")) 0826 .append(QLatin1Char(lonIsPositive?'+':'-')) 0827 .append(QString::number(lonDegree)+QChar(0xb0)) 0828 .append(QString::number(lonMinutes, 'f', 10)+QLatin1Char('\'')) 0829 .append(QLatin1Char(lonSphere==PosSphere?'P':'N')) 0830 .append(QLatin1String("|lat:")) 0831 .append(QLatin1Char(latIsPositive?'+':'-')) 0832 .append(QString::number(latDegree)+QChar(0xb0)) 0833 .append(QString::number(latMinutes, 'f', 10)+QLatin1Char('\'')) 0834 .append(QLatin1Char(latSphere==PosSphere?'P':'N')) 0835 .append(QLatin1Char('|')).append(QLatin1Char(locale==CLocale?'C':'L')) 0836 .append(QLatin1Char('|')).append(string).append(QLatin1Char('|')); 0837 QTest::newRow(rowTitle.toLatin1().constData()) 0838 << string 0839 << lon 0840 << lat; 0841 } 0842 } 0843 } 0844 } 0845 } 0846 } 0847 } 0848 } 0849 } 0850 } 0851 } 0852 } 0853 0854 /* 0855 * test fromString() with DM notation 0856 */ 0857 void TestGeoDataCoordinates::testFromStringDM() 0858 { 0859 // only run random 5% of all possible permutations 0860 if ((qreal(qrand()) / RAND_MAX) > 0.05) { 0861 QSKIP("Not picked for this run."); 0862 } 0863 0864 0865 QFETCH(QString, string); 0866 QFETCH(qreal, lon); 0867 QFETCH(qreal, lat); 0868 0869 bool succeeded = false; 0870 const GeoDataCoordinates coords = GeoDataCoordinates::fromString(string, succeeded); 0871 0872 if(! succeeded) 0873 qWarning() << "Could not parse"<<string <<"for"<<lon<<lat; 0874 0875 QVERIFY(succeeded); 0876 QCOMPARE(coords.longitude(GeoDataCoordinates::Degree), lon); 0877 QCOMPARE(coords.latitude(GeoDataCoordinates::Degree), lat); 0878 } 0879 0880 /* 0881 * test data for testStringDM() 0882 */ 0883 void TestGeoDataCoordinates::testFromStringD_data() 0884 { 0885 QTest::addColumn<QString>("string"); 0886 QTest::addColumn<qreal>("lon"); 0887 QTest::addColumn<qreal>("lat"); 0888 0889 const QVector<SignType> signTypes = QVector<SignType>() 0890 << NoSign << PositiveSign << NegativeSign; 0891 const QVector<SphereType> sphereTypes = QVector<SphereType>() 0892 << PosSphere << NegSphere; 0893 const QVector<UnitsType> unitsTypes = QVector<UnitsType>() 0894 << NoUnits << WithUnits; 0895 const QVector<SpacesType> spacesTypes = QVector<SpacesType>() 0896 << NoSpaces << WithSpaces; 0897 const QVector<LocaleType> localeTypes = QVector<LocaleType>() 0898 << CLocale << SystemLocale; 0899 0900 const QVector<qreal> degreeSamples = QVector<qreal>() 0901 << qreal(0.0) << qreal(3.14159) << qreal(180.0); 0902 0903 foreach(const UnitsType unitsType, unitsTypes) { 0904 foreach(const SpacesType spacesType, spacesTypes) { 0905 // lon 0906 foreach(const SphereType lonSphere, sphereTypes) { 0907 foreach(const SignType lonSignType, signTypes) { 0908 const bool lonIsPositive = 0909 (lonSphere==PosSphere && lonSignType!=NegativeSign) || 0910 (lonSphere==NegSphere && lonSignType==NegativeSign); 0911 foreach(const qreal lonDegree, degreeSamples) { 0912 // lat 0913 foreach(const SphereType latSphere, sphereTypes) { 0914 foreach(const SignType latSignType, signTypes) { 0915 const bool latIsPositive = 0916 (latSphere==PosSphere && latSignType!=NegativeSign) || 0917 (latSphere==NegSphere && latSignType==NegativeSign); 0918 foreach(const qreal latDegree, degreeSamples) { 0919 // locale 0920 foreach(const LocaleType locale, localeTypes) { 0921 0922 // actual construction 0923 // Create lon & lat values 0924 qreal lon = lonDegree; 0925 if (! lonIsPositive) 0926 lon *= -1; 0927 qreal lat = latDegree; 0928 if (! latIsPositive) 0929 lat *= -1; 0930 0931 // Create string 0932 QString string; 0933 string.append(createDegreeString(latSignType, 0934 latDegree, 0935 locale, 0936 unitsType, spacesType)); 0937 string.append(QLatin1Char(latSphere==PosSphere?'N':'S')); 0938 string.append(QLatin1Char(' ')); 0939 string.append(createDegreeString(lonSignType, 0940 lonDegree, 0941 locale, 0942 unitsType, spacesType)); 0943 string.append(QLatin1Char(lonSphere==PosSphere?'E':'W')); 0944 0945 // Create row title 0946 QString rowTitle; 0947 rowTitle.append(QLatin1String(spacesType==WithSpaces?"spaced dir":"unspaced dir")) 0948 .append(QLatin1String(unitsType==WithUnits?"|units":"|no units")) 0949 .append(QLatin1String("|lon:")) 0950 .append(QLatin1Char(lonIsPositive?'+':'-')) 0951 .append(QString::number(lonDegree, 'f', 10)+QChar(0xb0)) 0952 .append(QLatin1Char(lonSphere==PosSphere?'P':'N')) 0953 .append(QLatin1String("|lat:")) 0954 .append(QLatin1Char(latIsPositive?'+':'-')) 0955 .append(QString::number(latDegree, 'f', 10)+QChar(0xb0)) 0956 .append(QLatin1Char(latSphere==PosSphere?'P':'N')) 0957 .append(QLatin1Char('|')).append(QLatin1Char(locale==CLocale?'C':'L')) 0958 .append(QLatin1Char('|')).append(string).append(QLatin1Char('|')); 0959 QTest::newRow(rowTitle.toLatin1().constData()) 0960 << string 0961 << lon 0962 << lat; 0963 } 0964 } 0965 } 0966 } 0967 } 0968 } 0969 } 0970 } 0971 } 0972 0973 QTest::newRow("scientific notation") << "0.0,1.0e-2" << qreal(1.0e-2) << qreal(0.0); 0974 QTest::newRow("scientific notation") << "-2.4E0 1.0e-18" << qreal(1e-18) << qreal(-2.4e0); 0975 QTest::newRow("scientific notation") << "1.14e-02;1.33e+01" << qreal(1.33e1) << qreal(1.14e-2); 0976 } 0977 0978 /* 0979 * test fromString() with DM notation 0980 */ 0981 void TestGeoDataCoordinates::testFromStringD() 0982 { 0983 QFETCH(QString, string); 0984 QFETCH(qreal, lon); 0985 QFETCH(qreal, lat); 0986 0987 bool succeeded = false; 0988 const GeoDataCoordinates coords = GeoDataCoordinates::fromString(string, succeeded); 0989 0990 if(! succeeded) 0991 qWarning() << "Could not parse"<<string <<"for"<<lon<<lat; 0992 0993 QVERIFY(succeeded); 0994 QCOMPARE(coords.longitude(GeoDataCoordinates::Degree), lon); 0995 QCOMPARE(coords.latitude(GeoDataCoordinates::Degree), lat); 0996 } 0997 0998 class FromStringRegExpTranslator : public QTranslator 0999 { 1000 public: 1001 FromStringRegExpTranslator(const QString& _degree, const QString& _minutes, const QString& _seconds, 1002 const QString& _north, const QString& _south, 1003 const QString& _east, const QString& _west) 1004 : QTranslator((QObject*)nullptr) 1005 , degree( _degree ) 1006 , minutes( _minutes ) 1007 , seconds( _seconds ) 1008 , north( _north ) 1009 , south( _south ) 1010 , east( _east ) 1011 , west( _west ) 1012 {} 1013 1014 public: // QTranslator API 1015 bool isEmpty() const override { return false; } 1016 QString translate( const char* context, const char* sourceText, 1017 const char* disambiguation = nullptr, int n = -1 ) const override; 1018 private: 1019 const QString degree; 1020 const QString minutes; 1021 const QString seconds; 1022 const QString north; 1023 const QString south; 1024 const QString east; 1025 const QString west; 1026 }; 1027 1028 QString FromStringRegExpTranslator::translate(const char* context, const char* sourceText, 1029 const char* disambiguation , int n) const 1030 { 1031 Q_UNUSED(n); 1032 if (qstrcmp(context, "GeoDataCoordinates") != 0 ) 1033 return QString(); 1034 1035 if (qstrcmp(sourceText, "*") != 0 ) 1036 return QString(); 1037 1038 if (qstrcmp(disambiguation, "North direction terms") == 0 ) 1039 return north; 1040 if (qstrcmp(disambiguation, "South direction terms") == 0 ) 1041 return south; 1042 if (qstrcmp(disambiguation, "East direction terms") == 0 ) 1043 return east; 1044 if (qstrcmp(disambiguation, "West direction terms") == 0 ) 1045 return west; 1046 if (qstrcmp(disambiguation, "Degree symbol terms") == 0 ) 1047 return degree; 1048 if (qstrcmp(disambiguation, "Minutes symbol terms") == 0 ) 1049 return minutes; 1050 if (qstrcmp(disambiguation, "Seconds symbol terms") == 0 ) 1051 return seconds; 1052 1053 return QString(); 1054 } 1055 1056 class Sample 1057 { 1058 public: 1059 Sample() {} 1060 Sample(const char* _name, const char* _string, qreal _lon, qreal _lat) 1061 : name(QString::fromUtf8(_name)) 1062 , string(QString::fromUtf8(_string)) 1063 , lon(_lon) 1064 , lat(_lat) 1065 {} 1066 QString name; 1067 QString string; 1068 qreal lon; 1069 qreal lat; 1070 }; 1071 1072 class Language { 1073 public: 1074 Language() {} 1075 Language(const char* _name, 1076 const char* _degree, const char* _minutes, const char* _seconds, 1077 const char* _north, const char* _south, const char* _east, const char* _west, 1078 const QVector<Sample>& _samples) 1079 : name(QString::fromUtf8(_name)) 1080 , degree(QString::fromUtf8(_degree)) 1081 , minutes(QString::fromUtf8(_minutes)) 1082 , seconds(QString::fromUtf8(_seconds)) 1083 , north(QString::fromUtf8(_north)) 1084 , south(QString::fromUtf8(_south)) 1085 , east(QString::fromUtf8(_east)) 1086 , west(QString::fromUtf8(_west)) 1087 , samples(_samples) 1088 {} 1089 QString name; 1090 QString degree; 1091 QString minutes; 1092 QString seconds; 1093 QString north; 1094 QString south; 1095 QString east; 1096 QString west; 1097 QVector<Sample> samples; 1098 }; 1099 1100 void TestGeoDataCoordinates::testFromLocaleString_data() 1101 { 1102 QTest::addColumn<QString>("degree"); 1103 QTest::addColumn<QString>("minutes"); 1104 QTest::addColumn<QString>("seconds"); 1105 QTest::addColumn<QString>("north"); 1106 QTest::addColumn<QString>("south"); 1107 QTest::addColumn<QString>("east"); 1108 QTest::addColumn<QString>("west"); 1109 1110 QTest::addColumn<QString>("string"); 1111 QTest::addColumn<qreal>("lon"); 1112 QTest::addColumn<qreal>("lat"); 1113 1114 const QVector<Language> languages = QVector<Language>() 1115 << Language( 1116 "English", 1117 "*", // degree 1118 "*", // minutes 1119 "*", // seconds 1120 "*", // north 1121 "*", // south 1122 "*", // east 1123 "*", // west 1124 QVector<Sample>() 1125 << Sample( 1126 "London", 1127 "N051 30.150′ W000 07.234′", 1128 -0.12056666666666666921, 51.50249999999999772626) 1129 << Sample( 1130 "Ålgård", 1131 "N58.764828 E5.855483", 1132 5.85548300000000043752, 58.76482800000000139562)) 1133 1134 << Language( 1135 "Japanese", 1136 "度", // degree 1137 "分", // minutes 1138 "秒", // seconds 1139 "北緯", // north 1140 "南緯", // south 1141 "東経", // east 1142 "西経", // west 1143 QVector<Sample>() 1144 << Sample( 1145 "London", 1146 "北緯51度30分28秒 西経0度07分41秒", 1147 -0.12805555555555556135, 51.50777777777777544088) 1148 << Sample( 1149 "Sydney", 1150 "南緯33度52分06秒 東経151度12分31秒", 1151 151.20861111111111085847, -33.86833333333333229120)) 1152 << Language( 1153 "Korean", 1154 "도", // degree 1155 "분", // minutes 1156 "초", // seconds 1157 "북위", // north 1158 "남위", // south 1159 "동경", // east 1160 "서경", // west 1161 QVector<Sample>() 1162 << Sample( 1163 "London", 1164 "북위 51도 30분 26초, 서경 0도 7분 39초", 1165 -0.12750000000000000222, 51.50722222222222512755) 1166 << Sample( 1167 "Sydney", 1168 "남위 33도 31분 56초, 동경 151도 12분 40초", 1169 151.21111111111110858474, -33.53222222222222370647)) 1170 1171 // TODO: allow test control for parsing float in given locale 1172 #if 0 1173 << Language( 1174 "Galician", 1175 "", // degree 1176 "", // minutes 1177 "", // seconds 1178 "N", //north 1179 "S", // south 1180 "L|E", // east 1181 "O|W", // west 1182 QVector<Sample>() 1183 << Sample( 1184 "Campamento", 1185 "36º10,67´N 5º24,29´W", 1186 -5.40483333333333337833, 36.17783333333333217752)) 1187 #endif 1188 1189 << Language( 1190 "German", 1191 "*", // degree 1192 "*", // minutes 1193 "*", // seconds 1194 "N", //north 1195 "S", // south 1196 "O", // east 1197 "W", // west 1198 QVector<Sample>() 1199 << Sample( 1200 "London", 1201 "51° 31′ N, 0° 7′ W", 1202 -0.11666666666666666852, 51.51666666666666571928)) 1203 1204 << Language( 1205 "Greek", 1206 "", // degree 1207 "", // minutes 1208 "", // seconds 1209 "Β", // north 1210 "Ν", // south 1211 "Α", // east 1212 "Δ", // west 1213 QVector<Sample>() 1214 << Sample( 1215 "Χαλκίδα", 1216 "38° 28′ Β 23° 36′ Α", 1217 23.6, 38.46666666666666856)) 1218 1219 << Language( 1220 "Dutch", 1221 "", // degree 1222 "", // minutes 1223 "", // seconds 1224 "N|NB", // north 1225 "Z|ZB", // south 1226 "O|OL", // east 1227 "W|WL", // west 1228 QVector<Sample>() 1229 << Sample( 1230 "Amersfoort", 1231 "N 52° 8′ 32.14″ , E 5° 24′ 56.09″", 1232 5.41558055555555561966, 52.14226111111111094942) 1233 // TODO: allow test control for parsing float in given locale 1234 #if 0 1235 << Sample( 1236 "London", 1237 "51°30'00,55\" NB 0°07'34,45\" WL", 1238 -0.12623611111111110450, 51.50015277777777811252) 1239 << Sample( 1240 "Amsterdam", 1241 "52°22'12,78\" NB 4°53'42,60\" OL", 1242 4.89516666666666644403, 52.37021666666666419587) 1243 << Sample( 1244 "Capetown", 1245 "33°55'29,52\" ZB 18°25'26,60\" OL", 1246 18.42405555555555451974, -33.92486666666666650372) 1247 #endif 1248 ) 1249 1250 << Language( 1251 "Polish", 1252 "", // degree 1253 "", // minutes 1254 "", // seconds 1255 "Pn.|Pn", // north 1256 "Płd.|Płd", // south 1257 "Wschod.|Wschod|Wsch.|Wsch|Ws.|Ws", // east 1258 "Zach.|Zach|Z", // west 1259 QVector<Sample>() 1260 << Sample( 1261 "Warsaw", 1262 "52°13′56″Pn. 21°00′30″Ws.", 1263 21.00833333333333285964, 52.23222222222221944321)) 1264 1265 // TODO: allow test control for parsing float in given locale 1266 #if 0 1267 << Language( 1268 "Esperanto", 1269 "", // degree 1270 "", // minutes 1271 "", // seconds 1272 "N", // north 1273 "S", // south 1274 "Or", // east 1275 "Ok", // west 1276 QVector<Sample>() 1277 << Sample( 1278 "London", 1279 "52° 8′ 32,14″ N; 5° 24′ 56,09″ Or", 1280 5.41558055555555561966, 52.14226111111111094942)) 1281 #endif 1282 1283 << Language( 1284 "Norwegian", 1285 "", // degree 1286 "", // minutes 1287 "", // seconds 1288 "N", // north 1289 "S", // south 1290 "Ø", // east 1291 "V", // west 1292 QVector<Sample>() 1293 << Sample( 1294 "London", 1295 "51° 30′ 25” N 0° 7′ 39” V", 1296 -0.12750000000000000222, 51.50694444444444286546) 1297 << Sample( 1298 "Ålgård", 1299 "58° 45′ 53.38″ N 5° 51′ 19.74″ Ø", 1300 5.85548333333333292927, 58.76482777777777499750)) 1301 1302 << Language( 1303 "Swedish", 1304 "", // degree 1305 "", // minutes 1306 "", // seconds 1307 "N", // north 1308 "S", // south 1309 "O", // east 1310 "V", // west 1311 QVector<Sample>() 1312 << Sample( 1313 "London", 1314 "51°30′29″N 0°7′29″V", 1315 -0.12472222222222222043, 51.50805555555555770297) 1316 << Sample( 1317 "Sydney", 1318 "33°31′56″S 151°12′40″O", 1319 151.21111111111110858474, -33.53222222222222370647)) 1320 1321 << Language( 1322 "Icelandic", 1323 "", // degree 1324 "", // minutes 1325 "", // seconds 1326 "N", //north 1327 "S", // south 1328 "A", // east 1329 "V", // west 1330 //TODO: "breidd 51°30'26\" N, lengd 0°7'39\" V" // London 1331 QVector<Sample>() 1332 << Sample( 1333 "Sydney", 1334 "33°31'56\" S, 151°12'40\" A", 1335 151.21111111111110858474, -33.53222222222222370647)) 1336 1337 << Language( 1338 "Turkish", 1339 "", // degree 1340 "", // minutes 1341 "", // seconds 1342 "K", // north 1343 "G", // south 1344 "D", // east 1345 "B", // west 1346 QVector<Sample>() 1347 << Sample( 1348 "London", 1349 "51° 30′ 28″ K, 0° 7′ 41″ B", 1350 -0.12805555555555556135, 51.50777777777777544088)) 1351 1352 << Language( 1353 "Spanish", // (incl. Latin America) 1354 "", // degree 1355 "", // minutes 1356 "", // seconds 1357 "N", // north 1358 "S", // south 1359 "E", // east 1360 "O|W", // west 1361 QVector<Sample>() 1362 << Sample( 1363 "London", 1364 "51°30′25″N 00°07′39″O", 1365 -0.12750000000000000222, 51.50694444444444286546) 1366 << Sample( 1367 "Else", 1368 "52° 8′ 32.14″ N, 5° 24′ 56.09″ W", 1369 -5.41558055555555561966, 52.14226111111111094942) 1370 << Sample( 1371 "Bogotá", 1372 "4°35’53″N 74°4’33″O", 1373 -74.07583333333333541759, 4.59805555555555667269)) 1374 1375 << Language( 1376 "French", 1377 "", // degree 1378 "", // minutes 1379 "", // seconds 1380 "N", // north 1381 "S", // south 1382 "E", // east 1383 "O", // west 1384 QVector<Sample>() 1385 << Sample( 1386 "London", 1387 "51° 30′ 18″ N 0° 04′ 43″ O", 1388 -0.07861111111111110383, 51.50500000000000255795)) 1389 1390 << Language( 1391 "Portuguese", // incl. Brazilian Portuguese 1392 "", // degree 1393 "", // minutes 1394 "", // seconds 1395 "N", // north 1396 "S", // south 1397 "E|L", // east 1398 "O", // west 1399 QVector<Sample>() 1400 << Sample( 1401 "London", 1402 "52° 8′ 32.14″ N, 5° 24′ 56.09″ E", 1403 5.41558055555555561966, 52.14226111111111094942)) 1404 1405 << Language( 1406 "Arabic", 1407 "", // degree 1408 "", // minutes 1409 "", // seconds 1410 "شمال", // north 1411 "جنوب", // south 1412 "شرق", // east 1413 "غرب", // west 1414 QVector<Sample>() 1415 << Sample( 1416 "Warsaw", 1417 "52°13′56″ شمال 21°00′30″ شرق", 1418 21.00833333333333285964, 52.23222222222221944321)) 1419 1420 << Language( 1421 "Russian", 1422 "", //"град", "градусов" // degree 1423 "", //"мин", "минут" // minutes 1424 "", //"сек", "секунд" // seconds 1425 "с. ш.", // north 1426 "ю. ш.", // south 1427 "в. д.", // east 1428 "з. д.", // west 1429 QVector<Sample>() 1430 << Sample( 1431 "London", 1432 "51°30′26″ с. ш. 0°07′39″ з. д.", 1433 -0.12750000000000000222, 51.50722222222222512755)) 1434 1435 << Language( 1436 "Ukrainian", 1437 "", // degree 1438 "", // minutes 1439 "", // seconds 1440 "пн. ш.", // north 1441 "пд. ш.", // south 1442 "сх. д.", // east 1443 "зх. д.", // west 1444 QVector<Sample>() 1445 << Sample( 1446 "London", 1447 "51°30' пн. ш. 0°07' сх. д.", 1448 0.11666666666666666852, 51.50000000000000000000) 1449 << Sample( 1450 "Sydney", 1451 "33°52'10'' пд. ш. 151°12'30'' сх. д.", 1452 151.20833333333334280724, -33.86944444444444712872) 1453 << Sample( 1454 "Rio de Janeiro", 1455 "22°54'30'' пд. ш. 43°11'47'' зх. д.", 1456 -43.19638888888889027839, -22.90833333333333499127)) 1457 1458 << Language( 1459 "Bulgarian", 1460 "", // degree 1461 "", // minutes 1462 "", // seconds 1463 "с. ш.", // north 1464 "ю. ш.", // south 1465 "и. д.", // east 1466 "и. д.", // west 1467 QVector<Sample>() 1468 << Sample( 1469 "London", 1470 "51°30′26″ с. ш. 0°07′39″ и. д.", 1471 0.12750000000000000222, 51.50722222222222512755)) 1472 1473 << Language( 1474 "Czech", 1475 "", // degree 1476 "", // minutes 1477 "", // seconds 1478 "s. š.", // north 1479 "j. š.", // south 1480 "z. d.", // east 1481 "v. d.", // west 1482 QVector<Sample>() 1483 << Sample( 1484 "London", 1485 "51°30′42″ s. š., 0°02′56″ z. d.", 1486 0.04888888888888889145, 51.51166666666666316132) 1487 << Sample( 1488 "Sydney", 1489 "33° 52′ j. š., 151° 13′ v. d.", 1490 -151.21666666666669698316, -33.86666666666666714036)) 1491 1492 1493 << Language( 1494 "Hindi", 1495 "", // degree 1496 "", // minutes 1497 "", // seconds 1498 "उ", // north 1499 "द", // south 1500 "पू", // east 1501 "प", // west 1502 QVector<Sample>() 1503 << Sample( 1504 "London", 1505 "51°30′25″उ 00°07′39″पू", 1506 0.12750000000000000222, 51.50694444444444286546)) 1507 1508 << Language( 1509 "Tamil", 1510 "", // degree 1511 "", // minutes 1512 "", // seconds 1513 "வ", // north 1514 "தெ", // south 1515 "கி", // east 1516 "மே", // west 1517 QVector<Sample>() 1518 << Sample( 1519 "London", 1520 "51°30′25″ வ 00°07′39″ கி", 1521 0.12750000000000000222, 51.50694444444444286546)) 1522 ; 1523 1524 foreach( const Language& language, languages ) { 1525 foreach( const Sample& sample, language.samples ) { 1526 const QString rowTitle = 1527 language.name + 1528 QLatin1String("|") + sample.name + 1529 QLatin1String("|lon:") + 1530 QString::number(sample.lon, 'f', 10) + 1531 QLatin1String("|lat:") + 1532 QString::number(sample.lat, 'f', 10); 1533 1534 QTest::newRow(rowTitle.toLatin1().constData()) 1535 << language.degree 1536 << language.minutes 1537 << language.seconds 1538 << language.north 1539 << language.south 1540 << language.east 1541 << language.west 1542 << sample.string 1543 << sample.lon 1544 << sample.lat; 1545 } 1546 } 1547 } 1548 1549 1550 void TestGeoDataCoordinates::testFromLocaleString() 1551 { 1552 QFETCH(QString, degree); 1553 QFETCH(QString, minutes); 1554 QFETCH(QString, seconds); 1555 QFETCH(QString, north); 1556 QFETCH(QString, south); 1557 QFETCH(QString, east); 1558 QFETCH(QString, west); 1559 1560 QFETCH(QString, string); 1561 QFETCH(qreal, lon); 1562 QFETCH(qreal, lat); 1563 1564 FromStringRegExpTranslator translator(degree, minutes, seconds, north, south, east, west); 1565 QCoreApplication::installTranslator(&translator); 1566 1567 bool succeeded = false; 1568 const GeoDataCoordinates coords = GeoDataCoordinates::fromString(string, succeeded); 1569 1570 if(! succeeded) 1571 qWarning() << "Could not parse"<<string <<"for"<<lon<<lat; 1572 1573 QVERIFY(succeeded); 1574 1575 // Uncomment to get the lon and lat values with more precision 1576 // qWarning() << "lon"<<QString::number(coords.longitude(GeoDataCoordinates::Degree), 'f', 20) 1577 // << "lat"<<QString::number(coords.latitude(GeoDataCoordinates::Degree), 'f', 20); 1578 1579 QCOMPARE(coords.longitude(GeoDataCoordinates::Degree), lon); 1580 QCOMPARE(coords.latitude(GeoDataCoordinates::Degree), lat); 1581 1582 QCoreApplication::removeTranslator(&translator); 1583 } 1584 1585 /* 1586 * test data for toString() 1587 */ 1588 void TestGeoDataCoordinates::testToString_Decimal_data() 1589 { 1590 QTest::addColumn<qreal>("lon"); 1591 QTest::addColumn<qreal>("lat"); 1592 QTest::addColumn<int>("precision"); 1593 QTest::addColumn<QString>("expected"); 1594 1595 addRow() << qreal(150.0) << qreal(80.0) << 0 << QString::fromUtf8( " 150°E, 80°N" ); 1596 addRow() << qreal(150.0) << qreal(80.0) << 1 << QString::fromUtf8( "150.0°E, 80.0°N" ); 1597 addRow() << qreal(150.0) << qreal(80.0) << 2 << QString::fromUtf8( "150.00°E, 80.00°N" ); 1598 addRow() << qreal(150.0) << qreal(80.0) << 3 << QString::fromUtf8( "150.000°E, 80.000°N" ); 1599 addRow() << qreal(150.0) << qreal(80.0) << 4 << QString::fromUtf8( "150.0000°E, 80.0000°N" ); 1600 addRow() << qreal(150.0) << qreal(80.0) << 5 << QString::fromUtf8( "150.00000°E, 80.00000°N" ); 1601 1602 addRow() << qreal(149.6) << qreal(79.6) << 0 << QString::fromUtf8( " 150°E, 80°N" ); 1603 addRow() << qreal(149.96) << qreal(79.96) << 0 << QString::fromUtf8( " 150°E, 80°N" ); 1604 1605 addRow() << qreal(149.6) << qreal(79.6) << 1 << QString::fromUtf8( "149.6°E, 79.6°N" ); 1606 addRow() << qreal(149.96) << qreal(79.96) << 1 << QString::fromUtf8( "150.0°E, 80.0°N" ); 1607 addRow() << qreal(149.996) << qreal(79.996) << 1 << QString::fromUtf8( "150.0°E, 80.0°N" ); 1608 1609 addRow() << qreal(149.96) << qreal(79.96) << 2 << QString::fromUtf8( "149.96°E, 79.96°N" ); 1610 addRow() << qreal(149.996) << qreal(79.996) << 2 << QString::fromUtf8( "150.00°E, 80.00°N" ); 1611 addRow() << qreal(149.9996) << qreal(79.9996) << 2 << QString::fromUtf8( "150.00°E, 80.00°N" ); 1612 1613 addRow() << qreal(149.996) << qreal(79.996) << 3 << QString::fromUtf8( "149.996°E, 79.996°N" ); 1614 addRow() << qreal(149.9996) << qreal(79.9996) << 3 << QString::fromUtf8( "150.000°E, 80.000°N" ); 1615 addRow() << qreal(149.99996) << qreal(79.99996) << 3 << QString::fromUtf8( "150.000°E, 80.000°N" ); 1616 1617 addRow() << qreal(149.9996) << qreal(79.9996) << 4 << QString::fromUtf8( "149.9996°E, 79.9996°N" ); 1618 addRow() << qreal(149.99996) << qreal(79.99996) << 4 << QString::fromUtf8( "150.0000°E, 80.0000°N" ); 1619 addRow() << qreal(149.999996) << qreal(79.999996) << 4 << QString::fromUtf8( "150.0000°E, 80.0000°N" ); 1620 1621 addRow() << qreal(149.99996) << qreal(79.99996) << 5 << QString::fromUtf8( "149.99996°E, 79.99996°N" ); 1622 addRow() << qreal(149.999996) << qreal(79.999996) << 5 << QString::fromUtf8( "150.00000°E, 80.00000°N" ); 1623 addRow() << qreal(149.9999996) << qreal(79.9999996) << 5 << QString::fromUtf8( "150.00000°E, 80.00000°N" ); 1624 1625 addRow() << qreal(149.999996) << qreal(79.999996) << 6 << QString::fromUtf8( "149.999996°E, 79.999996°N" ); 1626 addRow() << qreal(149.9999996) << qreal(79.9999996) << 6 << QString::fromUtf8( "150.000000°E, 80.000000°N" ); 1627 1628 1629 addRow() << qreal(150.1) << qreal(80.1) << 0 << QString::fromUtf8( " 150°E, 80°N" ); 1630 addRow() << qreal(150.01) << qreal(80.01) << 0 << QString::fromUtf8( " 150°E, 80°N" ); 1631 1632 addRow() << qreal(150.1) << qreal(80.1) << 1 << QString::fromUtf8( "150.1°E, 80.1°N" ); 1633 addRow() << qreal(150.01) << qreal(80.01) << 1 << QString::fromUtf8( "150.0°E, 80.0°N" ); 1634 addRow() << qreal(150.001) << qreal(80.001) << 1 << QString::fromUtf8( "150.0°E, 80.0°N" ); 1635 1636 addRow() << qreal(150.01) << qreal(80.01) << 2 << QString::fromUtf8( "150.01°E, 80.01°N" ); 1637 addRow() << qreal(150.001) << qreal(80.001) << 2 << QString::fromUtf8( "150.00°E, 80.00°N" ); 1638 addRow() << qreal(150.0001) << qreal(80.0001) << 2 << QString::fromUtf8( "150.00°E, 80.00°N" ); 1639 1640 addRow() << qreal(150.001) << qreal(80.001) << 3 << QString::fromUtf8( "150.001°E, 80.001°N" ); 1641 addRow() << qreal(150.0001) << qreal(80.0001) << 3 << QString::fromUtf8( "150.000°E, 80.000°N" ); 1642 addRow() << qreal(150.00001) << qreal(80.00001) << 3 << QString::fromUtf8( "150.000°E, 80.000°N" ); 1643 1644 addRow() << qreal(150.0001) << qreal(80.0001) << 4 << QString::fromUtf8( "150.0001°E, 80.0001°N" ); 1645 addRow() << qreal(150.00001) << qreal(80.00001) << 4 << QString::fromUtf8( "150.0000°E, 80.0000°N" ); 1646 addRow() << qreal(150.000001) << qreal(80.000001) << 4 << QString::fromUtf8( "150.0000°E, 80.0000°N" ); 1647 1648 addRow() << qreal(150.00001) << qreal(80.00001) << 5 << QString::fromUtf8( "150.00001°E, 80.00001°N" ); 1649 addRow() << qreal(150.000001) << qreal(80.000001) << 5 << QString::fromUtf8( "150.00000°E, 80.00000°N" ); 1650 addRow() << qreal(150.0000001) << qreal(80.0000001) << 5 << QString::fromUtf8( "150.00000°E, 80.00000°N" ); 1651 1652 addRow() << qreal(150.000001) << qreal(80.000001) << 6 << QString::fromUtf8( "150.000001°E, 80.000001°N" ); 1653 addRow() << qreal(150.0000001) << qreal(80.0000001) << 6 << QString::fromUtf8( "150.000000°E, 80.000000°N" ); 1654 } 1655 1656 /* 1657 * test toString() 1658 */ 1659 void TestGeoDataCoordinates::testToString_Decimal() 1660 { 1661 QFETCH( qreal, lon ); 1662 QFETCH( qreal, lat ); 1663 QFETCH( int, precision ); 1664 QFETCH( QString, expected ); 1665 1666 const GeoDataCoordinates coordinates( lon, lat, 0, GeoDataCoordinates::Degree ); 1667 1668 const QString result = coordinates.toString( GeoDataCoordinates::Decimal, precision ); 1669 QCOMPARE( result, expected ); 1670 } 1671 1672 /* 1673 * test data for toString() 1674 */ 1675 void TestGeoDataCoordinates::testToString_DMS_data() 1676 { 1677 QTest::addColumn<qreal>("lon"); 1678 QTest::addColumn<qreal>("lat"); 1679 QTest::addColumn<int>("precision"); 1680 QTest::addColumn<QString>("expected"); 1681 1682 addRow() << qreal(0.) << qreal(0.) << 0 << QString::fromUtf8( " 0°E, 0°S" ); 1683 addRow() << qreal(150.) << qreal(80.) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1684 addRow() << qreal(149. + 31./60) << qreal(79. + 31./60) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1685 addRow() << qreal(149. + 30./60 + 31./3600) << qreal(79. + 30./60 + 31./3600) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1686 addRow() << qreal(149. + 30./60 + 30.51/3600) << qreal(79. + 30./60 + 30.51/3600) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1687 addRow() << qreal(150. + 29./60) << qreal(80. + 29./60) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1688 addRow() << qreal(150. + 29./60 + 29./3600) << qreal(80. + 29./60 + 29./3600) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1689 addRow() << qreal(150. + 29./60 + 29.49/3600) << qreal(80. + 29./60 + 29.49/3600) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1690 1691 addRow() << qreal(0.) << qreal(0.) << 1 << QString::fromUtf8( " 0° 00'E, 0° 00'S" ); 1692 addRow() << qreal(150.) << qreal(80.) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1693 addRow() << qreal(149. + 59./60 + 31./3600) << qreal(79. + 59./60 + 31./3600) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1694 addRow() << qreal(149. + 59./60 + 30.51/3600) << qreal(79. + 59./60 + 30.51/3600) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1695 addRow() << qreal(150. + 29./3600) << qreal(80. + 29./3600) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1696 addRow() << qreal(150. + 29.49/3600) << qreal(80. + 29.49/3600) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1697 1698 addRow() << qreal(0.) << qreal(0.) << 2 << QString::fromUtf8( " 0° 00'E, 0° 00'S" ); 1699 addRow() << qreal(150.) << qreal(80.) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1700 addRow() << qreal(149. + 59./60 + 31./3600) << qreal(79. + 59./60 + 31./3600) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1701 addRow() << qreal(149. + 59./60 + 30.51/3600) << qreal(79. + 59./60 + 30.51/3600) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1702 addRow() << qreal(150. + 29./3600) << qreal(80. + 29./3600) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1703 addRow() << qreal(150. + 29.49/3600) << qreal(80. + 29.49/3600) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1704 1705 addRow() << qreal(0.) << qreal(0.) << 3 << QString::fromUtf8( " 0° 00' 00\"E, 0° 00' 00\"S" ); 1706 addRow() << qreal(150.) << qreal(80.) << 3 << QString::fromUtf8( "150° 00' 00\"E, 80° 00' 00\"N" ); 1707 addRow() << qreal(149. + 59./60 + 59.51/3600) << qreal(79. + 59./60 + 59.51/3600) << 3 << QString::fromUtf8( "150° 00' 00\"E, 80° 00' 00\"N" ); 1708 addRow() << qreal(150. + 0.49/3600) << qreal(80. + 0.49/3600) << 3 << QString::fromUtf8( "150° 00' 00\"E, 80° 00' 00\"N" ); 1709 1710 addRow() << qreal(0.) << qreal(0.) << 4 << QString::fromUtf8( " 0° 00' 00\"E, 0° 00' 00\"S" ); 1711 addRow() << qreal(150.) << qreal(80.) << 4 << QString::fromUtf8( "150° 00' 00\"E, 80° 00' 00\"N" ); 1712 addRow() << qreal(149. + 59./60 + 59.51/3600) << qreal(79. + 59./60 + 59.51/3600) << 4 << QString::fromUtf8( "150° 00' 00\"E, 80° 00' 00\"N" ); 1713 addRow() << qreal(150. + 0.49/3600) << qreal(80. + 0.49/3600) << 4 << QString::fromUtf8( "150° 00' 00\"E, 80° 00' 00\"N" ); 1714 1715 addRow() << qreal(0.) << qreal(0.) << 5 << QString::fromUtf8( " 0° 00' 00.0\"E, 0° 00' 00.0\"S" ); 1716 addRow() << qreal(150.) << qreal(80.) << 5 << QString::fromUtf8( "150° 00' 00.0\"E, 80° 00' 00.0\"N" ); 1717 addRow() << qreal(149. + 59./60 + 59.951/3600) << qreal(79. + 59./60 + 59.951/3600) << 5 << QString::fromUtf8( "150° 00' 00.0\"E, 80° 00' 00.0\"N" ); 1718 addRow() << qreal(150. + 0.049/3600) << qreal(80. + 0.049/3600) << 5 << QString::fromUtf8( "150° 00' 00.0\"E, 80° 00' 00.0\"N" ); 1719 1720 addRow() << qreal(0.) << qreal(0.) << 6 << QString::fromUtf8( " 0° 00' 00.00\"E, 0° 00' 00.00\"S" ); 1721 addRow() << qreal(150.) << qreal(80.) << 6 << QString::fromUtf8( "150° 00' 00.00\"E, 80° 00' 00.00\"N" ); 1722 addRow() << qreal(149. + 59./60 + 59.9951/3600) << qreal(79. + 59./60 + 59.9951/3600) << 6 << QString::fromUtf8( "150° 00' 00.00\"E, 80° 00' 00.00\"N" ); 1723 addRow() << qreal(150. + 0.0049/3600) << qreal(80. + 0.0049/3600) << 6 << QString::fromUtf8( "150° 00' 00.00\"E, 80° 00' 00.00\"N" ); 1724 } 1725 1726 /* 1727 * test toString() 1728 */ 1729 void TestGeoDataCoordinates::testToString_DMS() 1730 { 1731 QFETCH( qreal, lon ); 1732 QFETCH( qreal, lat ); 1733 QFETCH( int, precision ); 1734 QFETCH( QString, expected ); 1735 1736 const GeoDataCoordinates coordinates( lon, lat, 0, GeoDataCoordinates::Degree ); 1737 1738 const QString result = coordinates.toString( GeoDataCoordinates::DMS, precision ); 1739 QCOMPARE( result, expected ); 1740 } 1741 1742 /* 1743 * test data for toString() 1744 */ 1745 void TestGeoDataCoordinates::testToString_DM_data() 1746 { 1747 QTest::addColumn<qreal>("lon"); 1748 QTest::addColumn<qreal>("lat"); 1749 QTest::addColumn<int>("precision"); 1750 QTest::addColumn<QString>("expected"); 1751 1752 addRow() << qreal(0.) << qreal(0.) << 0 << QString::fromUtf8( " 0°E, 0°S" ); 1753 addRow() << qreal(150.) << qreal(80.) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1754 addRow() << qreal(149. + 31./60) << qreal(79. + 31./60) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1755 addRow() << qreal(149. + 30.51/60) << qreal(79. + 30.51/60) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1756 addRow() << qreal(150. + 29./60) << qreal(80. + 29./60) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1757 addRow() << qreal(150. + 29.49/60) << qreal(80. + 29.49/60) << 0 << QString::fromUtf8( "150°E, 80°N" ); 1758 1759 addRow() << qreal(0.) << qreal(0.) << 1 << QString::fromUtf8( " 0° 00'E, 0° 00'S" ); 1760 addRow() << qreal(150.) << qreal(80.) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1761 addRow() << qreal(149. + 59.51/60) << qreal(79. + 59.51/60) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1762 addRow() << qreal(150. + 0.49/60) << qreal(80. + 0.49/60) << 1 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1763 1764 addRow() << qreal(0.) << qreal(0.) << 2 << QString::fromUtf8( " 0° 00'E, 0° 00'S" ); 1765 addRow() << qreal(150.) << qreal(80.) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1766 addRow() << qreal(149. + 59.51/60) << qreal(79. + 59.51/60) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1767 addRow() << qreal(150. + 0.49/60) << qreal(80. + 0.49/60) << 2 << QString::fromUtf8( "150° 00'E, 80° 00'N" ); 1768 1769 addRow() << qreal(0.) << qreal(0.) << 3 << QString::fromUtf8( " 0° 00.0'E, 0° 00.0'S" ); 1770 addRow() << qreal(150.) << qreal(80.) << 3 << QString::fromUtf8( "150° 00.0'E, 80° 00.0'N" ); 1771 addRow() << qreal(149. + 59.951/60) << qreal(79. + 59.951/60) << 3 << QString::fromUtf8( "150° 00.0'E, 80° 00.0'N" ); 1772 addRow() << qreal(150. + 0.049/60) << qreal(80. + 0.049/60) << 3 << QString::fromUtf8( "150° 00.0'E, 80° 00.0'N" ); 1773 1774 addRow() << qreal(0.) << qreal(0.) << 4 << QString::fromUtf8( " 0° 00.00'E, 0° 00.00'S" ); 1775 addRow() << qreal(150.) << qreal(80.) << 4 << QString::fromUtf8( "150° 00.00'E, 80° 00.00'N" ); 1776 addRow() << qreal(149. + 59.9951/60) << qreal(79. + 59.9951/60) << 4 << QString::fromUtf8( "150° 00.00'E, 80° 00.00'N" ); 1777 addRow() << qreal(150. + 0.0049/60) << qreal(80. + 0.0049/60) << 4 << QString::fromUtf8( "150° 00.00'E, 80° 00.00'N" ); 1778 } 1779 1780 /* 1781 * test toString() 1782 */ 1783 void TestGeoDataCoordinates::testToString_DM() 1784 { 1785 QFETCH( qreal, lon ); 1786 QFETCH( qreal, lat ); 1787 QFETCH( int, precision ); 1788 QFETCH( QString, expected ); 1789 1790 const GeoDataCoordinates coordinates( lon, lat, 0, GeoDataCoordinates::Degree ); 1791 1792 const QString result = coordinates.toString( GeoDataCoordinates::DM, precision ); 1793 QCOMPARE( result, expected ); 1794 } 1795 1796 /* 1797 * test data for testPack() 1798 */ 1799 void TestGeoDataCoordinates::testPack_data() 1800 { 1801 QTest::addColumn<qreal>("lon"); 1802 QTest::addColumn<qreal>("lat"); 1803 QTest::addColumn<qreal>("alt"); 1804 1805 QTest::newRow("deg") << qreal(180.0) << qreal(90.0) << qreal(400.0); 1806 } 1807 1808 /* 1809 * test pack() and unPack() 1810 */ 1811 void TestGeoDataCoordinates::testPack() 1812 { 1813 QFETCH(qreal, lon); 1814 QFETCH(qreal, lat); 1815 QFETCH(qreal, alt); 1816 1817 GeoDataCoordinates coordinates1,coordinates2; 1818 coordinates1.set(lon, lat, alt, GeoDataCoordinates::Degree); 1819 1820 QTemporaryFile file; 1821 if(file.open()) { 1822 QDataStream out(&file); 1823 coordinates1.pack(out); 1824 } 1825 file.close(); 1826 1827 if(file.open()) { 1828 QDataStream in(&file); 1829 coordinates2.unpack(in); 1830 } 1831 file.close(); 1832 1833 QCOMPARE(coordinates1.longitude(GeoDataCoordinates::Degree), coordinates2.longitude(GeoDataCoordinates::Degree)); 1834 QCOMPARE(coordinates1.latitude(GeoDataCoordinates::Degree), coordinates2.latitude(GeoDataCoordinates::Degree)); 1835 QCOMPARE(coordinates1.altitude(), coordinates2.altitude()); 1836 } 1837 1838 /* 1839 * test data for testUTM() 1840 */ 1841 void TestGeoDataCoordinates::testUTM_data() 1842 { 1843 QTest::addColumn<qreal>("lon"); 1844 QTest::addColumn<qreal>("lat"); 1845 QTest::addColumn<int>("zone"); 1846 QTest::addColumn<QString>("latitudeBand"); 1847 QTest::addColumn<int>("easting"); 1848 QTest::addColumn<int>("northing"); 1849 1850 /* Randomly selected locations, converted to UTM with the following 1851 * tools to check their correctness: 1852 * http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html 1853 * http://www.earthpoint.us/Convert.aspx 1854 * http://www.synnatschke.de/geo-tools/coordinate-converter.php 1855 * http://www.latlong.net/lat-long-utm.html 1856 * http://leware.net/geo/utmgoogle.htm 1857 * http://geographiclib.sourceforge.net/cgi-bin/GeoConvert 1858 */ 1859 1860 // Equator 1861 addRow() << qreal(-180.0) << qreal(0.0) << 1 << "N" << 16602144 << 0; 1862 addRow() << qreal(0) << qreal(0.0) << 31 << "N" << 16602144 << 0; 1863 addRow() << qreal(150.567) << qreal(0.0) << 56 << "N" << 22918607 << 0; 1864 1865 // Zone borders 1866 int zoneNumber = 1; 1867 for ( int i = -180; i <= 180; i += 6 ){ 1868 addRow() << qreal(i) << qreal(0.0) << zoneNumber << "N" << 16602144 << 0; 1869 zoneNumber++; 1870 } 1871 1872 // Northern hemisphere 1873 addRow() << qreal(-180.0) << qreal(15) << 1 << "P" << 17734904 << 166051369; 1874 addRow() << qreal(0) << qreal(60.5) << 31 << "V" << 33523714 << 671085271; 1875 addRow() << qreal(150.567) << qreal(75.123) << 56 << "X" << 43029080 << 833876115; 1876 1877 // Southern hemisphere 1878 addRow() << qreal(-3.5) << qreal(-50) << 30 << "F" << 46416654 << 446124952; 1879 addRow() << qreal(22.56) << qreal(-62.456) << 34 << "E" << 58047905 << 307404780; 1880 1881 // Exceptions 1882 1883 // North pole (no zone associated, so it returns 0) 1884 addRow() << qreal(-100.0) << qreal(85.0) << 0 << "Y" << 49026986 << 943981733; 1885 addRow() << qreal(100.0) << qreal(85.0) << 0 << "Z" << 50973014 << 943981733; 1886 1887 // South pole (no zone associated, so it returns 0) 1888 addRow() << qreal(-100.0) << qreal(-85.0) << 0 << "A" << 49026986 << 56018267; 1889 addRow() << qreal(100.0) << qreal(-85.0) << 0 << "B" << 50973014 << 56018267; 1890 1891 // Stavanger, in southwestern Norway, is in zone 32 1892 addRow() << qreal(5.73) << qreal(58.97) << 32 << "V" << 31201538 << 654131013; 1893 // Same longitude, at the equator, is in zone 31 1894 addRow() << qreal(5.73) << qreal(0.0) << 31 << "N" << 80389643 << 0; 1895 1896 // Svalbard is in zone 33 1897 addRow() << qreal(10.55) << qreal(78.88) << 33 << "X" << 40427848 << 876023047; 1898 // Same longitude, at the equator, is in zone 32 1899 addRow() << qreal(10.55) << qreal(0.0) << 32 << "N" << 67249738 << 0; 1900 } 1901 1902 /* 1903 * test UTM-related functions: 1904 * - utmZone() 1905 * - utmLatitudeBand() 1906 * - utmEasting() 1907 * - utmNorthing() 1908 */ 1909 void TestGeoDataCoordinates::testUTM(){ 1910 QFETCH(qreal, lon); 1911 QFETCH(qreal, lat); 1912 QFETCH(int, zone); 1913 QFETCH(QString, latitudeBand); 1914 QFETCH(int, easting); 1915 QFETCH(int, northing); 1916 1917 GeoDataCoordinates coordinates; 1918 coordinates.set(lon, lat, 0, GeoDataCoordinates::Degree); 1919 1920 QCOMPARE(coordinates.utmZone(), zone); 1921 QCOMPARE(coordinates.utmLatitudeBand(), latitudeBand); 1922 1923 /* Comparing integers is safer than comparing qreals. As the expected 1924 * values are expressed in centimeters, the actual values are converted 1925 * to this unit. 1926 */ 1927 int actualEasting = qRound( 100.0 * coordinates.utmEasting() ); 1928 int actualNorthing = qRound( 100.0 * coordinates.utmNorthing() ); 1929 1930 QCOMPARE( actualEasting, easting ); 1931 QCOMPARE( actualNorthing, northing ); 1932 } 1933 1934 QTEST_MAIN(TestGeoDataCoordinates) 1935 #include "TestGeoDataCoordinates.moc" 1936 1937 1938