From 89ababe4075f9e816ecd3c3e569fc6517d5e7244 Mon Sep 17 00:00:00 2001 From: Tarja Sundqvist Date: Mon, 7 Jun 2021 18:01:27 +0300 Subject: Bump version --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 062d6124..0932d882 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -3,7 +3,7 @@ CONFIG += warning_clean DEFINES += QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST -MODULE_VERSION = 5.15.5 +MODULE_VERSION = 5.15.6 # Adds a way to debug location. The define is needed for multiple subprojects as they # include the essential headers. -- cgit v1.2.1 From ade8147da038ebaae230a38a6e0f16364fc0edbe Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Thu, 29 Jul 2021 11:34:16 +0200 Subject: QGeoCoordinate: fix toString() conversion Applying qRound() to check if the minutes/seconds should overflow was not the right solution in some cases. It could lead to incorrect overflows, and so - to wrong conversion results. The actual logic of overflow is related to the behavior of QString::number. This patch fixes the logic and also introduces some minor optimizations. After overflow, the minutes or seconds value is always 0.0, because the actual minutes/seconds value is always in range [0; 60). This allows us to get rid of some checks. Fixes: QTBUG-95221 Change-Id: Ie3dcb6cef226b04c43dd973c09c4ae297c583f3b Reviewed-by: Alex Blasche Reviewed-by: Qt CI Bot (cherry picked from commit 15f06eca6a5085ce14d2eb0b743c5a06365068ea) Reviewed-by: Qt Cherry-pick Bot --- src/positioning/qgeocoordinate.cpp | 47 ++++++++++++------------ tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp | 20 +++++++++- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/positioning/qgeocoordinate.cpp b/src/positioning/qgeocoordinate.cpp index fdc7ae4f..e0b1a0b3 100644 --- a/src/positioning/qgeocoordinate.cpp +++ b/src/positioning/qgeocoordinate.cpp @@ -594,19 +594,18 @@ QString QGeoCoordinate::toString(CoordinateFormat format) const double latMin = (absLat - int(absLat)) * 60; double lngMin = (absLng - int(absLng)) * 60; - if (qRound(latMin) >= 60) { + // We use QString::number(val, 'f', 3) to represent minutes. + // It rounds up to the next integer in case the fraction > 0.9995. + // Such behavior should be handled specifically when the rounded + // value is 60, so that we overflow to degrees correctly. + // If we overflow, the minutes should unconditionally be 0.0. + if (latMin > 59.9995) { absLat++; - latMin = qAbs(latMin - 60.0f); - //avoid invalid latitude due to latMin rounding below - if (qRound(absLat) >= 90) - latMin = 0.0f; + latMin = 0.0f; } - if (qRound(lngMin) >= 60) { + if (lngMin > 59.9995) { absLng++; - lngMin = qAbs(lngMin - 60.0f); - // avoid invalid longitude due to lngMin rounding below - if (qRound(absLng) >= 180) - lngMin = 0.0f; + lngMin = 0.0f; } latStr = QString::fromLatin1("%1%2 %3'") @@ -626,28 +625,28 @@ QString QGeoCoordinate::toString(CoordinateFormat format) const double latSec = (latMin - int(latMin)) * 60; double lngSec = (lngMin - int(lngMin)) * 60; - // overflow to full minutes - if (qRound(latSec) >= 60) { + // We use QString::number(val, 'f', 1) to represent seconds. + // It rounds up to the next integer in case the fraction >= 0.95. + // Such behavior should be handled specifically when the rounded + // value is 60, so that we overflow to minutes correctly. + // If we overflow, the seconds should unconditionally be 0.0. + if (latSec >= 59.95) { latMin++; - latSec = qAbs(latSec - 60.0f); - // overflow to full degrees + latSec = 0.0f; + // We cast to int to represent minutes, so we can use qRound() + // to determine if we need to overflow to full degrees. + // If we overflow, the minutes will unconditionally be 0.0. if (qRound(latMin) >= 60) { absLat++; - latMin = qAbs(latMin - 60.0f); - // avoid invalid latitude due to latSec rounding below - if (qRound(absLat) >= 90) - latSec = 0.0f; + latMin = 0.0f; } } - if (qRound(lngSec) >= 60) { + if (lngSec >= 59.95) { lngMin++; - lngSec = qAbs(lngSec - 60.0f); + lngSec = 0.0f; if (qRound(lngMin) >= 60) { absLng++; - lngMin = qAbs(lngMin - 60.0f); - // avoid invalid longitude due to lngSec rounding below - if (qRound(absLng) >= 180) - lngSec = 0.0f; + lngMin = 0.0f; } } diff --git a/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp b/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp index 1b30f647..28f10aca 100644 --- a/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp +++ b/tests/auto/qgeocoordinate/tst_qgeocoordinate.cpp @@ -843,13 +843,29 @@ private slots: << QString( "2%1 0.000', 2%1 0.000'").arg(DEGREES_SYMB); QTest::newRow("Wrap seconds to minutes to Degrees DM -> above valid long/lat values") - << QGeoCoordinate(89.9999, 179.9999) << QGeoCoordinate::DegreesMinutesSeconds + << QGeoCoordinate(89.999999, 179.999999) << QGeoCoordinate::DegreesMinutesSeconds << QString( "90%1 0' 0.0\", 180%1 0' 0.0\"").arg(DEGREES_SYMB); + QTest::newRow("Seconds and minutes near valid long/lat values border") + << QGeoCoordinate(89.9999, 179.9999) << QGeoCoordinate::DegreesMinutesSeconds + << QString("89%1 59' 59.6\", 179%1 59' 59.6\"").arg(DEGREES_SYMB); + QTest::newRow("Wrap minutes to Degrees DM ->above valid long/lat values") - << QGeoCoordinate(89.9999, 179.9999) << QGeoCoordinate::DegreesMinutes + << QGeoCoordinate(89.999999, 179.999999) << QGeoCoordinate::DegreesMinutes << QString( "90%1 0.000', 180%1 0.000'").arg(DEGREES_SYMB); + QTest::newRow("Minutes near valid long/lat values border") + << QGeoCoordinate(89.9999, 179.9999) << QGeoCoordinate::DegreesMinutes + << QString("89%1 59.994', 179%1 59.994'").arg(DEGREES_SYMB); + + QTest::newRow("Fix incorrect wrap minutes to degrees") + << QGeoCoordinate(0.995833, 0.995833) << QGeoCoordinate::DegreesMinutes + << QString("0%1 59.750', 0%1 59.750'").arg(DEGREES_SYMB); + + QTest::newRow("Fix incorrect wrap seconds to minutes") + << QGeoCoordinate(0.9832222, 0.9832222) << QGeoCoordinate::DegreesMinutesSeconds + << QString("0%1 58' 59.6\", 0%1 58' 59.6\"").arg(DEGREES_SYMB); + } void datastream() -- cgit v1.2.1