From 4b9e1d665e0fd9e86f0eed7f878df30b2cef76ea Mon Sep 17 00:00:00 2001 From: Patrik Sylve Date: Thu, 13 Feb 2025 17:17:33 +0100 Subject: [PATCH] Handle polar CRS with NE axis order --- src/core/proj/qgsprojutils.cpp | 36 +++++++++++++++++++++++++---- tests/src/core/testqgsprojutils.cpp | 6 +++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/core/proj/qgsprojutils.cpp b/src/core/proj/qgsprojutils.cpp index dc15e1bf7ebb..942f962b4ccc 100644 --- a/src/core/proj/qgsprojutils.cpp +++ b/src/core/proj/qgsprojutils.cpp @@ -113,6 +113,7 @@ bool QgsProjUtils::usesAngularUnit( const QString &projDef ) bool QgsProjUtils::axisOrderIsSwapped( const PJ *crs ) { //ported from https://github.com/pramsey/postgis/blob/7ecf6839c57a838e2c8540001a3cd35b78a730db/liblwgeom/lwgeom_transform.c#L299 + //and GDAL OGRSpatialReference::isNorthEastAxisOrder https://github.com/OSGeo/gdal/blob/release/3.10/ogr/ogrspatialreference.cpp#L419 if ( !crs ) return false; @@ -129,19 +130,46 @@ bool QgsProjUtils::axisOrderIsSwapped( const PJ *crs ) const int axisCount = proj_cs_get_axis_count( context, pjCs.get() ); if ( axisCount > 0 ) { - const char *outDirection = nullptr; - // Read only first axis, see if it is degrees / north + const char *outDirection0 = nullptr; + const char *outDirection1 = nullptr; + const char *outName0 = nullptr; + const char *outName1 = nullptr; proj_cs_get_axis_info( context, pjCs.get(), 0, + &outName0, nullptr, + &outDirection0, nullptr, - &outDirection, + nullptr, + nullptr, + nullptr + ); + + proj_cs_get_axis_info( context, pjCs.get(), 1, + &outName1, + nullptr, + &outDirection1, nullptr, nullptr, nullptr, nullptr ); - return QString( outDirection ).compare( QLatin1String( "north" ), Qt::CaseInsensitive ) == 0; + + if ( QString( outDirection0 ).compare( QLatin1String( "north" ), Qt::CaseInsensitive ) == 0 && + QString( outDirection1 ).compare( QLatin1String( "east" ), Qt::CaseInsensitive ) == 0 ) + { + return true; + } + + // Handle polar projections with NE-order + if ( ( QString( outDirection0 ).compare( QLatin1String( "north" ), Qt::CaseInsensitive ) == 0 && + QString( outDirection1 ).compare( QLatin1String( "north" ), Qt::CaseInsensitive ) == 0 ) || + ( QString( outDirection0 ).compare( QLatin1String( "south" ), Qt::CaseInsensitive ) == 0 && + QString( outDirection1 ).compare( QLatin1String( "south" ), Qt::CaseInsensitive ) == 0 ) ) + { + return QString( outName0 ).startsWith( QLatin1String( "northing" ), Qt::CaseInsensitive ) && + QString( outName1 ).startsWith( QLatin1String( "easting" ), Qt::CaseInsensitive ) ; + } } return false; } diff --git a/tests/src/core/testqgsprojutils.cpp b/tests/src/core/testqgsprojutils.cpp index 86c11203d7e8..0f3903b5d171 100644 --- a/tests/src/core/testqgsprojutils.cpp +++ b/tests/src/core/testqgsprojutils.cpp @@ -95,6 +95,12 @@ void TestQgsProjUtils::axisOrderIsSwapped() QVERIFY( QgsProjUtils::axisOrderIsSwapped( crs.get() ) ); crs.reset( proj_create( context, "urn:ogc:def:crs:EPSG::3903" ) ); QVERIFY( QgsProjUtils::axisOrderIsSwapped( crs.get() ) ); + crs.reset( proj_create( context, "urn:ogc:def:crs:EPSG::32761" ) ); + QVERIFY( QgsProjUtils::axisOrderIsSwapped( crs.get() ) ); + crs.reset( proj_create( context, "urn:ogc:def:crs:EPSG::5482" ) ); + QVERIFY( QgsProjUtils::axisOrderIsSwapped( crs.get() ) ); + crs.reset( proj_create( context, "urn:ogc:def:crs:EPSG::32661" ) ); + QVERIFY( QgsProjUtils::axisOrderIsSwapped( crs.get() ) ); } void TestQgsProjUtils::searchPath()