Skip to content

Commit 458185a

Browse files
authored
Merge pull request qgis#59484 from nyalldawson/cs_error
Fix QgsCsException messages
2 parents 25c4a83 + 5733e3d commit 458185a

4 files changed

+54
-12
lines changed

src/core/proj/qgscoordinatereferencesystem.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1688,7 +1688,11 @@ void QgsCoordinateReferenceSystem::setProjString( const QString &proj4String )
16881688
{
16891689
#ifdef QGISDEBUG
16901690
const int errNo = proj_context_errno( ctx );
1691+
#if PROJ_VERSION_MAJOR>=8
1692+
QgsDebugError( QStringLiteral( "proj string rejected: %1" ).arg( proj_context_errno_string( ctx, errNo ) ) );
1693+
#else
16911694
QgsDebugError( QStringLiteral( "proj string rejected: %1" ).arg( proj_errno_string( errNo ) ) );
1695+
#endif
16921696
#endif
16931697
d->mIsValid = false;
16941698
}

src/core/proj/qgscoordinatetransform.cpp

+20-10
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
830830
}
831831

832832
mFallbackOperationOccurred = false;
833+
bool errorOccurredDuringFallbackOperation = false;
833834
if ( actualRes != 0
834835
&& ( d->mAvailableOpCount > 1 || d->mAvailableOpCount == -1 ) // only use fallbacks if more than one operation is possible -- otherwise we've already tried it and it failed
835836
&& ( d->mAllowFallbackTransforms || mBallparkTransformsAreAppropriate ) )
@@ -854,13 +855,14 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
854855
// So here just check proj_errno() for single point transform
855856
if ( numPoints == 1 )
856857
{
858+
projResult = proj_errno( transform );
857859
// hmm - something very odd here. We can't trust proj_errno( transform ), as that's giving us incorrect error numbers
858860
// (such as "failed to load datum shift file", which is definitely incorrect for a default proj created operation!)
859861
// so we resort to testing values ourselves...
860-
projResult = std::isinf( xprev[0] ) || std::isinf( yprev[0] ) || std::isinf( zprev[0] ) ? 1 : 0;
862+
errorOccurredDuringFallbackOperation = std::isinf( xprev[0] ) || std::isinf( yprev[0] ) || std::isinf( zprev[0] );
861863
}
862864

863-
if ( projResult == 0 )
865+
if ( !errorOccurredDuringFallbackOperation )
864866
{
865867
memcpy( x, xprev.data(), sizeof( double ) * numPoints );
866868
memcpy( y, yprev.data(), sizeof( double ) * numPoints );
@@ -885,25 +887,33 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
885887
z[pos] = std::numeric_limits<double>::quiet_NaN();
886888
}
887889

888-
if ( projResult != 0 )
890+
if ( projResult != 0 || errorOccurredDuringFallbackOperation )
889891
{
890892
//something bad happened....
891893
QString points;
892894

895+
const QChar delim = numPoints > 1 ? '\n' : ' ';
893896
for ( int i = 0; i < numPoints; ++i )
894897
{
895-
points += QStringLiteral( "(%1, %2)\n" ).arg( x[i], 0, 'f' ).arg( y[i], 0, 'f' );
898+
points += QStringLiteral( "(%1, %2)" ).arg( xprev[i], 0, 'f' ).arg( yprev[i], 0, 'f' ) + delim;
896899
}
897900

898-
const QString dir = ( direction == Qgis::TransformDirection::Forward ) ? QObject::tr( "forward transform" ) : QObject::tr( "inverse transform" );
901+
const QString dir = ( direction == Qgis::TransformDirection::Forward ) ? QObject::tr( "Forward transform" ) : QObject::tr( "Inverse transform" );
899902

900-
const QString msg = QObject::tr( "%1 of\n"
901-
"%2"
902-
"Error: %3" )
903+
#if PROJ_VERSION_MAJOR>=8
904+
PJ_CONTEXT *projContext = QgsProjContext::get();
905+
const QString projError = !errorOccurredDuringFallbackOperation ? QString::fromUtf8( proj_context_errno_string( projContext, projResult ) ) : QObject::tr( "Fallback transform failed" );
906+
#else
907+
const QString projError = !errorOccurredDuringFallbackOperation ? QString::fromUtf8( proj_errno_string( projResult ) ) : QObject::tr( "Fallback transform failed" );
908+
#endif
909+
910+
const QString msg = QObject::tr( "%1 (%2 to %3) of%4%5Error: %6" )
903911
.arg( dir,
912+
( direction == Qgis::TransformDirection::Forward ) ? d->mSourceCRS.authid() : d->mDestCRS.authid(),
913+
( direction == Qgis::TransformDirection::Forward ) ? d->mDestCRS.authid() : d->mSourceCRS.authid(),
914+
QString( delim ),
904915
points,
905-
projResult < 0 ? QString::fromUtf8( proj_errno_string( projResult ) ) : QObject::tr( "Fallback transform failed" ) );
906-
916+
projError );
907917

908918
// don't flood console with thousands of duplicate transform error messages
909919
if ( msg != mLastError )

src/core/proj/qgscoordinatetransform_p.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -332,12 +332,17 @@ ProjData QgsCoordinateTransformPrivate::threadLocalProjData()
332332
{
333333
// huh?
334334
const int errNo = proj_context_errno( context );
335-
if ( errNo && errNo != -61 )
335+
if ( errNo )
336336
{
337+
#if PROJ_VERSION_MAJOR>=8
338+
nonAvailableError = QString( proj_context_errno_string( context, errNo ) );
339+
#else
337340
nonAvailableError = QString( proj_errno_string( errNo ) );
341+
#endif
338342
}
339343
else
340344
{
345+
// in theory should never be hit!
341346
nonAvailableError = QObject::tr( "No coordinate operations are available between these two reference systems" );
342347
}
343348
}
@@ -466,9 +471,13 @@ ProjData QgsCoordinateTransformPrivate::threadLocalProjData()
466471
{
467472
const int errNo = proj_context_errno( context );
468473
const QStringList projErrors = errorLogger.errors();
469-
if ( errNo && errNo != -61 )
474+
if ( errNo )
470475
{
476+
#if PROJ_VERSION_MAJOR>=8
477+
nonAvailableError = QString( proj_context_errno_string( context, errNo ) );
478+
#else
471479
nonAvailableError = QString( proj_errno_string( errNo ) );
480+
#endif
472481
}
473482
else if ( !projErrors.empty() )
474483
{

tests/src/python/test_qgscoordinatetransform.py

+19
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@
1111

1212

1313
from qgis.core import (
14+
Qgis,
1415
QgsCoordinateReferenceSystem,
1516
QgsCoordinateTransform,
1617
QgsCoordinateTransformContext,
1718
QgsProject,
1819
QgsRectangle,
20+
QgsPointXY,
21+
QgsCsException
1922
)
2023
import unittest
2124
from qgis.testing import start_app, QgisTestCase
@@ -208,6 +211,22 @@ def test_has_vertical_component(self):
208211
)
209212
self.assertTrue(transform.hasVerticalComponent())
210213

214+
def test_cs_exception(self):
215+
ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:4326'),
216+
QgsCoordinateReferenceSystem('EPSG:3857'), QgsProject.instance())
217+
point = QgsPointXY(-7603859, -7324441)
218+
with self.assertRaises(QgsCsException) as e:
219+
ct.transform(point)
220+
self.assertEqual(str(e.exception), 'Forward transform (EPSG:4326 to EPSG:3857) of (-7603859.000000, -7324441.000000) Error: Invalid coordinate')
221+
222+
# reverse transform
223+
ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem('EPSG:3857'),
224+
QgsCoordinateReferenceSystem('EPSG:4326'), QgsProject.instance())
225+
point = QgsPointXY(-7603859, -7324441)
226+
with self.assertRaises(QgsCsException) as e:
227+
ct.transform(point, Qgis.TransformDirection.Reverse)
228+
self.assertEqual(str(e.exception), 'Inverse transform (EPSG:4326 to EPSG:3857) of (-7603859.000000, -7324441.000000) Error: Invalid coordinate')
229+
211230

212231
if __name__ == '__main__':
213232
unittest.main()

0 commit comments

Comments
 (0)