Support decimal degrees with [N,S,W,E] suffixes in the goto locator filter

This commit is contained in:
webmaster 2022-03-05 17:02:48 +07:00 committed by Mathieu Pellerin
parent 67e1987fb7
commit 218c124e9d
6 changed files with 139 additions and 3 deletions

View File

@ -45,7 +45,7 @@ void QgsGotoLocatorFilter::fetchResults( const QString &string, const QgsLocator
bool okY = false;
double posX = 0.0;
double posY = 0.0;
bool posIsDms = false;
bool posIsWgs84 = false;
const QLocale locale;
// Coordinates such as 106.8468,-6.3804
@ -71,6 +71,22 @@ void QgsGotoLocatorFilter::fetchResults( const QString &string, const QgsLocator
}
}
if ( !match.hasMatch() )
{
// Check if the string is a pair of decimal degrees with [N,S,E,W] suffixes
separatorRx = QRegularExpression( QStringLiteral( "^\\s*([0-9\\-\\.]*\\s*[NSEWnsew])[\\s\\,]*([0-9\\-\\.]*\\s*[NSEWnsew])\\s*$" ) );
match = separatorRx.match( string.trimmed() );
if ( match.hasMatch() )
{
posIsWgs84 = true;
bool isEasting = false;
posX = QgsCoordinateUtils::degreeToDecimal( match.captured( 1 ), &okX, &isEasting );
posY = QgsCoordinateUtils::degreeToDecimal( match.captured( 2 ), &okY );
if ( !isEasting )
std::swap( posX, posY );
}
}
if ( !match.hasMatch() )
{
// Check if the string is a pair of degree minute second
@ -78,7 +94,7 @@ void QgsGotoLocatorFilter::fetchResults( const QString &string, const QgsLocator
match = separatorRx.match( string.trimmed() );
if ( match.hasMatch() )
{
posIsDms = true;
posIsWgs84 = true;
bool isEasting = false;
posX = QgsCoordinateUtils::dmsToDecimal( match.captured( 1 ), &okX, &isEasting );
posY = QgsCoordinateUtils::dmsToDecimal( match.captured( 3 ), &okY );
@ -94,7 +110,7 @@ void QgsGotoLocatorFilter::fetchResults( const QString &string, const QgsLocator
data.insert( QStringLiteral( "point" ), point );
const bool withinWgs84 = wgs84Crs.bounds().contains( point );
if ( !posIsDms && currentCrs != wgs84Crs )
if ( !posIsWgs84 && currentCrs != wgs84Crs )
{
QgsLocatorResult result;
result.filter = this;

View File

@ -142,6 +142,40 @@ QString QgsCoordinateUtils::formatExtentForProject( QgsProject *project, const Q
QgsCoordinateUtils::formatCoordinateForProject( project, p2, destCrs, precision ) );
}
double QgsCoordinateUtils::degreeToDecimal( const QString &string, bool *ok, bool *isEasting )
{
const QString negative( QStringLiteral( "swSW" ) );
const QString easting( QStringLiteral( "eEwW" ) );
double value = 0.0;
bool okValue = false;
if ( ok )
{
*ok = false;
}
else
{
ok = &okValue;
}
QRegularExpression degreeWithSuffix( QStringLiteral( "^\\s*([0-9\\-\\.]*)\\s*([NSEWnsew])\\s*$" ) );
QRegularExpressionMatch match = degreeWithSuffix.match( string );
if ( match.hasMatch() )
{
const QString suffix = match.captured( 2 );
value = std::abs( match.captured( 1 ).toDouble( ok ) );
if ( ok )
{
value *= ( negative.contains( suffix ) ? -1 : 1 );
if ( isEasting )
{
*isEasting = easting.contains( suffix );
}
}
}
return value;
}
double QgsCoordinateUtils::dmsToDecimal( const QString &string, bool *ok, bool *isEasting )
{
const QString negative( QStringLiteral( "swSW-" ) );

View File

@ -92,6 +92,14 @@ class CORE_EXPORT QgsCoordinateUtils
*/
Q_INVOKABLE static double dmsToDecimal( const QString &string, bool *ok = nullptr, bool *isEasting = nullptr );
/**
* Converts a decimal degree with suffix string to its raw decimal equivalent.
* \param string decimal degree to convert (must include a [N,S,E,W] suffix)
* \returns Double decimal value
* \since QGIS 3.26
*/
Q_INVOKABLE static double degreeToDecimal( const QString &string, bool *ok = nullptr, bool *isEasting = nullptr );
};

View File

@ -374,6 +374,17 @@ void TestQgsAppLocatorFilters::testGoto()
QCOMPARE( results.at( 0 ).displayString, QObject::tr( "Go to 1,234.56 789.012 (Map CRS, )" ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "point" )].value<QgsPointXY>(), QgsPointXY( 1234.56, 789.012 ) );
// decimal degree with suffixes
results = gatherResults( &filter, QStringLiteral( "12.345N, 67.890W" ), QgsLocatorContext() );
QCOMPARE( results.count(), 1 );
QCOMPARE( results.at( 0 ).displayString, QObject::tr( "Go to -67.89° 12.345° (EPSG:4326 - WGS 84)" ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "point" )].value<QgsPointXY>(), QgsPointXY( -67.890, 12.345 ) );
results = gatherResults( &filter, QStringLiteral( "12.345 e, 67.890 s" ), QgsLocatorContext() );
QCOMPARE( results.count(), 1 );
QCOMPARE( results.at( 0 ).displayString, QObject::tr( "Go to 12.345° -67.89° (EPSG:4326 - WGS 84)" ) );
QCOMPARE( results.at( 0 ).userData.toMap()[QStringLiteral( "point" )].value<QgsPointXY>(), QgsPointXY( 12.345, -67.890 ) );
// degree/minuste/second coordinates goto
// easting northing
results = gatherResults( &filter, QStringLiteral( "40deg 1' 0\" E 11deg 55' 0\" S" ), QgsLocatorContext() );

View File

@ -40,6 +40,7 @@ set(TESTS
testqgsconnectionpool.cpp
testqgscoordinatereferencesystemregistry.cpp
testqgscoordinatetransform.cpp
testqgscoordinateutils.cpp
testqgscopyfiletask.cpp
testqgscredentials.cpp
testqgscurve.cpp

View File

@ -0,0 +1,66 @@
/***************************************************************************
testqgscoordinateutils.cpp
--------------------------------------
Date : March 2022
Copyright : (C) 2022 Mathieu Pellerin
Email : nirvn dot asia at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QString>
#include "qgstest.h"
#include "qgscoordinateutils.h"
class TestQgsCoordinateUtils : public QObject
{
Q_OBJECT
private slots:
void testDegreeWithSuffix();
};
void TestQgsCoordinateUtils::testDegreeWithSuffix()
{
bool ok = false ;
bool isEasting = false;
double value = 0.0;
value = QgsCoordinateUtils::degreeToDecimal( QStringLiteral( "1.234W" ), &ok, &isEasting );
QCOMPARE( ok, true );
QCOMPARE( isEasting, true );
QCOMPARE( value, -1.234 );
value = QgsCoordinateUtils::degreeToDecimal( QStringLiteral( "-1.234 w" ), &ok, &isEasting );
QCOMPARE( ok, true );
QCOMPARE( isEasting, true );
QCOMPARE( value, -1.234 );
value = QgsCoordinateUtils::degreeToDecimal( QStringLiteral( "1.234s" ), &ok, &isEasting );
QCOMPARE( ok, true );
QCOMPARE( isEasting, false );
QCOMPARE( value, -1.234 );
value = QgsCoordinateUtils::degreeToDecimal( QStringLiteral( "1.234N" ), &ok, &isEasting );
QCOMPARE( ok, true );
QCOMPARE( isEasting, false );
QCOMPARE( value, 1.234 );
value = QgsCoordinateUtils::degreeToDecimal( QStringLiteral( "1.234 e" ), &ok, &isEasting );
QCOMPARE( ok, true );
QCOMPARE( isEasting, true );
QCOMPARE( value, 1.234 );
value = QgsCoordinateUtils::degreeToDecimal( QStringLiteral( "bad string" ), &ok, &isEasting );
QCOMPARE( ok, false );
QCOMPARE( value, 0.0 );
}
QGSTEST_MAIN( TestQgsCoordinateUtils )
#include "testqgscoordinateutils.moc"