diff --git a/include/proj/coordinateoperation.hpp b/include/proj/coordinateoperation.hpp index d4b666e207..5608022146 100644 --- a/include/proj/coordinateoperation.hpp +++ b/include/proj/coordinateoperation.hpp @@ -1704,8 +1704,8 @@ class PROJ_GCC_DLL Transformation : public SingleOperation { PROJ_INTERNAL const std::string & getPROJ4NadgridsCompatibleFilename() const; - PROJ_FOR_TEST std::vector - getTOWGS84Parameters() const; // throw(io::FormattingException) + PROJ_FOR_TEST std::vector getTOWGS84Parameters( + bool canThrowException) const; // throw(io::FormattingException) PROJ_INTERNAL const std::string &getHeightToGeographic3DFilename() const; diff --git a/scripts/reference_exported_symbols.txt b/scripts/reference_exported_symbols.txt index 9035283b5b..c71a34a8e8 100644 --- a/scripts/reference_exported_symbols.txt +++ b/scripts/reference_exported_symbols.txt @@ -758,7 +758,7 @@ osgeo::proj::operation::Transformation::createTimeDependentPositionVector(osgeo: osgeo::proj::operation::Transformation::createTOWGS84(dropbox::oxygen::nn > const&, std::vector > const&) osgeo::proj::operation::Transformation::createVERTCON(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn > const&, dropbox::oxygen::nn > const&, std::string const&, std::vector >, std::allocator > > > const&) osgeo::proj::operation::Transformation::createVerticalOffset(osgeo::proj::util::PropertyMap const&, dropbox::oxygen::nn > const&, dropbox::oxygen::nn > const&, osgeo::proj::common::Length const&, std::vector >, std::allocator > > > const&) -osgeo::proj::operation::Transformation::getTOWGS84Parameters() const +osgeo::proj::operation::Transformation::getTOWGS84Parameters(bool) const osgeo::proj::operation::Transformation::inverse() const osgeo::proj::operation::Transformation::sourceCRS() const osgeo::proj::operation::Transformation::targetCRS() const diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp index 7b683c2260..3d8459b170 100644 --- a/src/iso19111/c_api.cpp +++ b/src/iso19111/c_api.cpp @@ -7761,16 +7761,19 @@ int proj_coordoperation_get_towgs84_values(PJ_CONTEXT *ctx, } return FALSE; } - try { - auto values = transf->getTOWGS84Parameters(); + + const auto values = transf->getTOWGS84Parameters(false); + if (!values.empty()) { for (int i = 0; i < value_count && static_cast(i) < values.size(); i++) { out_values[i] = values[i]; } return TRUE; - } catch (const std::exception &e) { + } else { if (emit_error_if_incompatible) { - proj_log_error(ctx, __FUNCTION__, e.what()); + proj_log_error(ctx, __FUNCTION__, + "Transformation cannot be formatted as WKT1 TOWGS84 " + "parameters"); } return FALSE; } diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index d858f7778d..c7014f97b1 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -696,11 +696,10 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( const auto takeIntoAccountCandidate = [&](const operation::TransformationNNPtr &transf) { - try { - transf->getTOWGS84Parameters(); - } catch (const std::exception &) { + if (transf->getTOWGS84Parameters(false).empty()) { return; } + candidateCount++; if (candidateBoundCRS == nullptr) { candidateCount = 1; @@ -1426,13 +1425,12 @@ CRSNNPtr CRS::promoteTo3D(const std::string &newName, auto base3DCRS = boundCRS->baseCRS()->promoteTo3D( newName, dbContext, verticalAxisIfNotAlreadyPresent); auto transf = boundCRS->transformation(); - try { - transf->getTOWGS84Parameters(); + if (!transf->getTOWGS84Parameters(false).empty()) { return BoundCRS::create( createProperties(), base3DCRS, boundCRS->hubCRS()->promoteTo3D(std::string(), dbContext), transf->promoteTo3D(std::string(), dbContext)); - } catch (const io::FormattingException &) { + } else { return BoundCRS::create(base3DCRS, boundCRS->hubCRS(), std::move(transf)); } @@ -1481,13 +1479,12 @@ CRSNNPtr CRS::demoteTo2D(const std::string &newName, else if (auto boundCRS = dynamic_cast(this)) { auto base2DCRS = boundCRS->baseCRS()->demoteTo2D(newName, dbContext); auto transf = boundCRS->transformation(); - try { - transf->getTOWGS84Parameters(); + if (!transf->getTOWGS84Parameters(false).empty()) { return BoundCRS::create( base2DCRS, boundCRS->hubCRS()->demoteTo2D(std::string(), dbContext), transf->demoteTo2D(std::string(), dbContext)); - } catch (const io::FormattingException &) { + } else { return BoundCRS::create(base2DCRS, boundCRS->hubCRS(), transf); } } @@ -5985,7 +5982,7 @@ void BoundCRS::_exportToWKT(io::WKTFormatter *formatter) const { io::FormattingException::Throw( "Cannot export BoundCRS with non-WGS 84 hub CRS in WKT1"); } - auto params = d->transformation()->getTOWGS84Parameters(); + auto params = d->transformation()->getTOWGS84Parameters(true); if (!formatter->useESRIDialect()) { formatter->setTOWGS84Parameters(params); } @@ -6075,7 +6072,7 @@ void BoundCRS::_exportToPROJString( formatter->setHDatumExtension(std::string()); } else { if (isTOWGS84Compatible()) { - auto params = transformation()->getTOWGS84Parameters(); + auto params = transformation()->getTOWGS84Parameters(true); formatter->setTOWGS84Parameters(params); } crs_exportable->_exportToPROJString(formatter); @@ -6137,7 +6134,7 @@ BoundCRS::_identify(const io::AuthorityFactoryPtr &authorityFactory) const { } bool refIsNullTransform = false; if (isTOWGS84Compatible()) { - auto params = transformation()->getTOWGS84Parameters(); + auto params = transformation()->getTOWGS84Parameters(true); if (params == std::vector{0, 0, 0, 0, 0, 0, 0}) { refIsNullTransform = true; } diff --git a/src/iso19111/operation/singleoperation.cpp b/src/iso19111/operation/singleoperation.cpp index 72f10173fd..4778966c79 100644 --- a/src/iso19111/operation/singleoperation.cpp +++ b/src/iso19111/operation/singleoperation.cpp @@ -1443,8 +1443,8 @@ bool SingleOperation::_isEquivalentTo(const util::IComparable *other, isTOWGS84Transf(otherMethodEPSGCode)) { auto transf = static_cast(this); auto otherTransf = static_cast(otherSO); - auto params = transf->getTOWGS84Parameters(); - auto otherParams = otherTransf->getTOWGS84Parameters(); + auto params = transf->getTOWGS84Parameters(true); + auto otherParams = otherTransf->getTOWGS84Parameters(true); assert(params.size() == 7); assert(otherParams.size() == 7); for (size_t i = 0; i < 7; i++) { diff --git a/src/iso19111/operation/transformation.cpp b/src/iso19111/operation/transformation.cpp index 3d25f54c30..5dd77282b9 100644 --- a/src/iso19111/operation/transformation.cpp +++ b/src/iso19111/operation/transformation.cpp @@ -184,12 +184,14 @@ Transformation::demoteTo2D(const std::string &, * can be used as the value of the WKT1 TOWGS84 parameter or * PROJ +towgs84 parameter. * + * @param canThrowException if true, an exception is thrown if the method fails, + * otherwise an empty vector is returned in case of failure. * @return a vector of 7 values if valid, otherwise a io::FormattingException * is thrown. * @throws io::FormattingException */ -std::vector -Transformation::getTOWGS84Parameters() const // throw(io::FormattingException) +std::vector Transformation::getTOWGS84Parameters( + bool canThrowException) const // throw(io::FormattingException) { // GDAL WKT1 assumes EPSG:9606 / Position Vector convention @@ -297,6 +299,8 @@ Transformation::getTOWGS84Parameters() const // throw(io::FormattingException) (foundRotX && foundRotY && foundRotZ && foundScale))) { return params; } else { + if (!canThrowException) + return {}; throw io::FormattingException( "Missing required parameter values in transformation"); } @@ -321,6 +325,8 @@ Transformation::getTOWGS84Parameters() const // throw(io::FormattingException) } #endif + if (!canThrowException) + return {}; throw io::FormattingException( "Transformation cannot be formatted as WKT1 TOWGS84 parameters"); } diff --git a/test/unit/gie_self_tests.cpp b/test/unit/gie_self_tests.cpp index 8165b18670..3807b452a4 100644 --- a/test/unit/gie_self_tests.cpp +++ b/test/unit/gie_self_tests.cpp @@ -302,8 +302,8 @@ TEST_F(gieTest, proj_create_crs_to_crs) { TEST_F(gieTest, proj_create_crs_to_crs_EPSG_4326) { - auto P = - proj_create_crs_to_crs(PJ_DEFAULT_CTX, "EPSG:4326", "EPSG:32631", nullptr); + auto P = proj_create_crs_to_crs(PJ_DEFAULT_CTX, "EPSG:4326", "EPSG:32631", + nullptr); ASSERT_TRUE(P != nullptr); PJ_COORD a, b; diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp index cc0cbcaecf..0786ad76c2 100644 --- a/test/unit/test_io.cpp +++ b/test/unit/test_io.cpp @@ -5033,7 +5033,7 @@ TEST(wkt_parse, BOUNDCRS_transformation_from_names) { EXPECT_EQ(crs->transformation()->sourceCRS()->nameStr(), projcrs->baseCRS()->nameStr()); - auto params = crs->transformation()->getTOWGS84Parameters(); + auto params = crs->transformation()->getTOWGS84Parameters(true); auto expected = std::vector{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; ASSERT_EQ(params.size(), expected.size()); for (int i = 0; i < 7; i++) { @@ -5082,7 +5082,7 @@ TEST(wkt_parse, BOUNDCRS_transformation_from_codes) { EXPECT_EQ(crs->transformation()->sourceCRS()->nameStr(), projcrs->baseCRS()->nameStr()); - auto params = crs->transformation()->getTOWGS84Parameters(); + auto params = crs->transformation()->getTOWGS84Parameters(true); auto expected = std::vector{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; ASSERT_EQ(params.size(), expected.size()); for (int i = 0; i < 7; i++) { @@ -5224,7 +5224,7 @@ TEST(wkt_parse, geogcs_TOWGS84_3terms) { ASSERT_TRUE(crs->transformation()->sourceCRS() != nullptr); EXPECT_EQ(crs->transformation()->sourceCRS()->nameStr(), "my GEOGCRS"); - auto params = crs->transformation()->getTOWGS84Parameters(); + auto params = crs->transformation()->getTOWGS84Parameters(true); auto expected = std::vector{1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0}; ASSERT_EQ(params.size(), expected.size()); for (int i = 0; i < 7; i++) { @@ -5270,7 +5270,7 @@ TEST(wkt_parse, projcs_TOWGS84_7terms) { ASSERT_TRUE(crs->transformation()->sourceCRS() != nullptr); EXPECT_EQ(crs->transformation()->sourceCRS()->nameStr(), "my GEOGCRS"); - auto params = crs->transformation()->getTOWGS84Parameters(); + auto params = crs->transformation()->getTOWGS84Parameters(true); auto expected = std::vector{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; ASSERT_EQ(params.size(), expected.size()); for (int i = 0; i < 7; i++) { @@ -5313,7 +5313,7 @@ TEST(io, projcs_TOWGS84_7terms_autocorrect) { auto crs = nn_dynamic_pointer_cast(obj); ASSERT_TRUE(crs != nullptr); - auto params = crs->transformation()->getTOWGS84Parameters(); + auto params = crs->transformation()->getTOWGS84Parameters(true); auto expected = std::vector{-106.8686, 52.2978, -103.7239, 0.3366, -0.457, 1.8422, -1.2747}; ASSERT_EQ(params.size(), expected.size()); diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp index ed8f247efe..41c93ad3c0 100644 --- a/test/unit/test_operation.cpp +++ b/test/unit/test_operation.cpp @@ -555,7 +555,7 @@ TEST(operation, transformation_createGeocentricTranslations) { 2.0, 3.0, std::vector()); EXPECT_TRUE(transf->validateParameters().empty()); - auto params = transf->getTOWGS84Parameters(); + auto params = transf->getTOWGS84Parameters(true); auto expected = std::vector{1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0}; EXPECT_EQ(params, expected); @@ -570,7 +570,7 @@ TEST(operation, transformation_createGeocentricTranslations) { inv_transf_as_transf->sourceCRS()->nameStr()); auto expected_inv = std::vector{-1.0, -2.0, -3.0, 0.0, 0.0, 0.0, 0.0}; - EXPECT_EQ(inv_transf_as_transf->getTOWGS84Parameters(), expected_inv); + EXPECT_EQ(inv_transf_as_transf->getTOWGS84Parameters(true), expected_inv); EXPECT_EQ(transf->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline +step +proj=axisswap +order=2,1 +step " @@ -677,7 +677,7 @@ TEST(operation, transformation_createPositionVector) { ASSERT_EQ(transf->coordinateOperationAccuracies().size(), 1U); auto expected = std::vector{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; - EXPECT_EQ(transf->getTOWGS84Parameters(), expected); + EXPECT_EQ(transf->getTOWGS84Parameters(true), expected); EXPECT_EQ(transf->exportToPROJString(PROJStringFormatter::create().get()), "+proj=pipeline +step +proj=axisswap +order=2,1 +step " @@ -744,7 +744,7 @@ TEST(operation, transformation_createCoordinateFrameRotation) { std::vector()); EXPECT_TRUE(transf->validateParameters().empty()); - auto params = transf->getTOWGS84Parameters(); + auto params = transf->getTOWGS84Parameters(true); auto expected = std::vector{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; EXPECT_EQ(params, expected);