diff options
| -rw-r--r-- | include/proj/crs.hpp | 5 | ||||
| -rw-r--r-- | src/c_api.cpp | 26 | ||||
| -rw-r--r-- | src/crs.cpp | 6 | ||||
| -rw-r--r-- | src/proj_experimental.h | 3 | ||||
| -rw-r--r-- | src/projinfo.cpp | 26 | ||||
| -rw-r--r-- | test/unit/test_c_api.cpp | 4 | ||||
| -rw-r--r-- | test/unit/test_crs.cpp | 43 |
7 files changed, 74 insertions, 39 deletions
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp index 10d1f07e..1066f886 100644 --- a/include/proj/crs.hpp +++ b/include/proj/crs.hpp @@ -92,8 +92,9 @@ class PROJ_GCC_DLL CRS : public common::ObjectUsage { PROJ_DLL GeodeticCRSPtr extractGeodeticCRS() const; PROJ_DLL GeographicCRSPtr extractGeographicCRS() const; PROJ_DLL VerticalCRSPtr extractVerticalCRS() const; - PROJ_DLL CRSNNPtr createBoundCRSToWGS84IfPossible( - const io::DatabaseContextPtr &dbContext) const; + PROJ_DLL CRSNNPtr + createBoundCRSToWGS84IfPossible(const io::DatabaseContextPtr &dbContext, + bool allowIntermediateCRS) const; PROJ_DLL CRSNNPtr stripVerticalComponent() const; PROJ_DLL const BoundCRSPtr &canonicalBoundCRS() PROJ_CONST_DECL; diff --git a/src/c_api.cpp b/src/c_api.cpp index 78ca1c24..03a0c0bd 100644 --- a/src/c_api.cpp +++ b/src/c_api.cpp @@ -1319,11 +1319,19 @@ PJ_OBJ *proj_obj_crs_create_bound_crs(PJ_CONTEXT *ctx, const PJ_OBJ *base_crs, * * @param ctx PROJ context, or NULL for default context * @param crs Objet of type CRS (must not be NULL) + * @param options null-terminated list of options, or NULL. Currently + * supported options are: + * <ul> + * <li>ALLOW_INTERMEDIATE_CRS=YES/NO. Defaults to NO. When set to YES, + * intermediate CRS may be considered when computing the possible + * tranformations. Slower.</li> + * </ul> * @return Object that must be unreferenced with proj_obj_unref(), or NULL * in case of error. */ PJ_OBJ *proj_obj_crs_create_bound_crs_to_WGS84(PJ_CONTEXT *ctx, - const PJ_OBJ *crs) { + const PJ_OBJ *crs, + const char *const *options) { SANITIZE_CTX(ctx); assert(crs); auto l_crs = dynamic_cast<const CRS *>(crs->obj.get()); @@ -1333,8 +1341,20 @@ PJ_OBJ *proj_obj_crs_create_bound_crs_to_WGS84(PJ_CONTEXT *ctx, } auto dbContext = getDBcontextNoException(ctx, __FUNCTION__); try { - return PJ_OBJ::create( - l_crs->createBoundCRSToWGS84IfPossible(dbContext)); + bool allowIntermediateCRS = false; + for (auto iter = options; iter && iter[0]; ++iter) { + const char *value; + if ((value = getOptionValue(*iter, "ALLOW_INTERMEDIATE_CRS="))) { + allowIntermediateCRS = ci_equal(value, "YES"); + } else { + std::string msg("Unknown option :"); + msg += *iter; + proj_log_error(ctx, __FUNCTION__, msg.c_str()); + return nullptr; + } + } + return PJ_OBJ::create(l_crs->createBoundCRSToWGS84IfPossible( + dbContext, allowIntermediateCRS)); } catch (const std::exception &e) { proj_log_error(ctx, __FUNCTION__, e.what()); return nullptr; diff --git a/src/crs.cpp b/src/crs.cpp index 81e9a300..639fc3a9 100644 --- a/src/crs.cpp +++ b/src/crs.cpp @@ -375,8 +375,9 @@ VerticalCRSPtr CRS::extractVerticalCRS() const { * * @return a CRS. */ -CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( - const io::DatabaseContextPtr &dbContext) const { +CRSNNPtr +CRS::createBoundCRSToWGS84IfPossible(const io::DatabaseContextPtr &dbContext, + bool allowIntermediateCRS) const { auto thisAsCRS = NN_NO_CHECK( std::static_pointer_cast<CRS>(shared_from_this().as_nullable())); auto boundCRS = util::nn_dynamic_pointer_cast<BoundCRS>(thisAsCRS); @@ -441,6 +442,7 @@ CRSNNPtr CRS::createBoundCRSToWGS84IfPossible( authority == "any" ? std::string() : authority); auto ctxt = operation::CoordinateOperationContext::create( authFactory, extent, 0.0); + ctxt->setAllowUseIntermediateCRS(allowIntermediateCRS); // ctxt->setSpatialCriterion( // operation::CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION); auto list = diff --git a/src/proj_experimental.h b/src/proj_experimental.h index b8c37054..9af7c389 100644 --- a/src/proj_experimental.h +++ b/src/proj_experimental.h @@ -244,7 +244,8 @@ PJ_OBJ PROJ_DLL *proj_obj_crs_create_bound_crs(PJ_CONTEXT *ctx, const PJ_OBJ *transformation); PJ_OBJ PROJ_DLL *proj_obj_crs_create_bound_crs_to_WGS84(PJ_CONTEXT *ctx, - const PJ_OBJ *crs); + const PJ_OBJ *crs, + const char *const *options); /* BEGIN: Generated by scripts/create_c_api_projections.py*/ PJ_OBJ PROJ_DLL *proj_obj_create_conversion_utm( diff --git a/src/projinfo.cpp b/src/projinfo.cpp index ba19b8d2..d6fa37bc 100644 --- a/src/projinfo.cpp +++ b/src/projinfo.cpp @@ -136,7 +136,8 @@ static std::string c_ify_string(const std::string &str) { static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext, const std::string &user_string, bool kindIsCRS, const std::string &context, - bool buildBoundCRSToWGS84) { + bool buildBoundCRSToWGS84, + bool allowPivots) { BaseObjectPtr obj; std::string l_user_string(user_string); @@ -192,7 +193,8 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext, if (buildBoundCRSToWGS84) { auto crs = std::dynamic_pointer_cast<CRS>(obj); if (crs) { - obj = crs->createBoundCRSToWGS84IfPossible(dbContext).as_nullable(); + obj = crs->createBoundCRSToWGS84IfPossible(dbContext, allowPivots) + .as_nullable(); } } @@ -202,7 +204,7 @@ static BaseObjectNNPtr buildObject(DatabaseContextPtr dbContext, // --------------------------------------------------------------------------- static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, - const OutputOptions &outputOpt) { + bool allowPivots, const OutputOptions &outputOpt) { auto identified = dynamic_cast<const IdentifiedObject *>(obj.get()); if (!outputOpt.quiet && identified && identified->isDeprecated()) { @@ -263,7 +265,8 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, if (crs) { objToExport = nn_dynamic_pointer_cast<IPROJStringExportable>( - crs->createBoundCRSToWGS84IfPossible(dbContext)); + crs->createBoundCRSToWGS84IfPossible(dbContext, + allowPivots)); } if (!objToExport) { objToExport = projStringExportable; @@ -398,7 +401,8 @@ static void outputObject(DatabaseContextPtr dbContext, BaseObjectNNPtr obj, std::shared_ptr<IWKTExportable> objToExport; if (crs) { objToExport = nn_dynamic_pointer_cast<IWKTExportable>( - crs->createBoundCRSToWGS84IfPossible(dbContext)); + crs->createBoundCRSToWGS84IfPossible(dbContext, + allowPivots)); } if (!objToExport) { objToExport = wktExportable; @@ -506,7 +510,7 @@ static void outputOperations( const std::string &authority, bool usePROJGridAlternatives, bool showSuperseded, const OutputOptions &outputOpt, bool summary) { auto sourceObj = - buildObject(dbContext, sourceCRSStr, true, "source CRS", false); + buildObject(dbContext, sourceCRSStr, true, "source CRS", false, false); auto sourceCRS = nn_dynamic_pointer_cast<CRS>(sourceObj); if (!sourceCRS) { std::cerr << "source CRS string is not a CRS" << std::endl; @@ -514,7 +518,7 @@ static void outputOperations( } auto targetObj = - buildObject(dbContext, targetCRSStr, true, "target CRS", false); + buildObject(dbContext, targetCRSStr, true, "target CRS", false, false); auto targetCRS = nn_dynamic_pointer_cast<CRS>(targetObj); if (!targetCRS) { std::cerr << "target CRS string is not a CRS" << std::endl; @@ -545,7 +549,7 @@ static void outputOperations( std::exit(1); } if (outputOpt.quiet && !list.empty()) { - outputObject(dbContext, list[0], outputOpt); + outputObject(dbContext, list[0], allowPivots, outputOpt); return; } if (summary) { @@ -571,7 +575,7 @@ static void outputOperations( } outputOperationSummary(op); std::cout << std::endl; - outputObject(dbContext, op, outputOpt); + outputObject(dbContext, op, allowPivots, outputOpt); } } } @@ -906,7 +910,7 @@ int main(int argc, char **argv) { if (!user_string.empty()) { auto obj(buildObject(dbContext, user_string, kindIsCRS, "input string", - buildBoundCRSToWGS84)); + buildBoundCRSToWGS84, allowPivots)); if (guessDialect) { auto dialect = WKTParser().guessDialect(user_string); std::cout << "Guessed WKT dialect: "; @@ -923,7 +927,7 @@ int main(int argc, char **argv) { } std::cout << std::endl; } - outputObject(dbContext, obj, outputOpt); + outputObject(dbContext, obj, allowPivots, outputOpt); if (identify) { auto crs = dynamic_cast<CRS *>(obj.get()); if (crs) { diff --git a/test/unit/test_c_api.cpp b/test/unit/test_c_api.cpp index b119d914..f3ba66df 100644 --- a/test/unit/test_c_api.cpp +++ b/test/unit/test_c_api.cpp @@ -402,7 +402,7 @@ TEST_F(CApi, proj_obj_crs_create_bound_crs_to_WGS84) { ObjectKeeper keeper(crs); ASSERT_NE(crs, nullptr); - auto res = proj_obj_crs_create_bound_crs_to_WGS84(m_ctxt, crs); + auto res = proj_obj_crs_create_bound_crs_to_WGS84(m_ctxt, crs, nullptr); ObjectKeeper keeper_res(res); ASSERT_NE(res, nullptr); @@ -447,7 +447,7 @@ TEST_F(CApi, proj_obj_crs_create_bound_crs_to_WGS84_on_invalid_type) { ObjectKeeper keeper(obj); ASSERT_NE(obj, nullptr); - auto res = proj_obj_crs_create_bound_crs_to_WGS84(m_ctxt, obj); + auto res = proj_obj_crs_create_bound_crs_to_WGS84(m_ctxt, obj, nullptr); ASSERT_EQ(res, nullptr); } diff --git a/test/unit/test_crs.cpp b/test/unit/test_crs.cpp index 7918ab0b..6ed002a9 100644 --- a/test/unit/test_crs.cpp +++ b/test/unit/test_crs.cpp @@ -3479,9 +3479,8 @@ TEST(crs, boundCRS_crs_link) { EXPECT_TRUE(baseCRS->isEquivalentTo(GeographicCRS::EPSG_4267.get())); EXPECT_TRUE(baseCRS->canonicalBoundCRS() != nullptr); - EXPECT_TRUE( - baseCRS->createBoundCRSToWGS84IfPossible(nullptr)->isEquivalentTo( - baseCRS->canonicalBoundCRS().get())); + EXPECT_TRUE(baseCRS->createBoundCRSToWGS84IfPossible(nullptr, false) + ->isEquivalentTo(baseCRS->canonicalBoundCRS().get())); } { @@ -4780,26 +4779,28 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { auto factory = AuthorityFactory::create(dbContext, "EPSG"); { auto crs_4326 = factory->createCoordinateReferenceSystem("4326"); - EXPECT_EQ(crs_4326->createBoundCRSToWGS84IfPossible(dbContext), + EXPECT_EQ(crs_4326->createBoundCRSToWGS84IfPossible(dbContext, false), crs_4326); } { auto crs_32631 = factory->createCoordinateReferenceSystem("32631"); - EXPECT_EQ(crs_32631->createBoundCRSToWGS84IfPossible(dbContext), + EXPECT_EQ(crs_32631->createBoundCRSToWGS84IfPossible(dbContext, false), crs_32631); } { // Pulkovo 42 East Germany auto crs_5670 = factory->createCoordinateReferenceSystem("5670"); - EXPECT_EQ(crs_5670->createBoundCRSToWGS84IfPossible(dbContext), + EXPECT_EQ(crs_5670->createBoundCRSToWGS84IfPossible(dbContext, false), crs_5670); } { // Pulkovo 42 Romania auto crs_3844 = factory->createCoordinateReferenceSystem("3844"); - auto bound = crs_3844->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = + crs_3844->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_NE(bound, crs_3844); - EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext), bound); + EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext, false), + bound); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(bound); ASSERT_TRUE(boundCRS != nullptr); EXPECT_EQ(boundCRS->exportToPROJString( @@ -4814,9 +4815,11 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { { // Pulkovo 42 Poland auto crs_2171 = factory->createCoordinateReferenceSystem("2171"); - auto bound = crs_2171->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = + crs_2171->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_NE(bound, crs_2171); - EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext), bound); + EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext, false), + bound); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(bound); ASSERT_TRUE(boundCRS != nullptr); EXPECT_EQ(boundCRS->exportToPROJString( @@ -4831,9 +4834,11 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { { // NTF (Paris) auto crs_4807 = factory->createCoordinateReferenceSystem("4807"); - auto bound = crs_4807->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = + crs_4807->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_NE(bound, crs_4807); - EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext), bound); + EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext, false), + bound); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(bound); ASSERT_TRUE(boundCRS != nullptr); EXPECT_EQ(boundCRS->exportToPROJString( @@ -4846,9 +4851,11 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { { // NTF (Paris) / Lambert zone II + NGF-IGN69 height auto crs_7421 = factory->createCoordinateReferenceSystem("7421"); - auto bound = crs_7421->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = + crs_7421->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_NE(bound, crs_7421); - EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext), bound); + EXPECT_EQ(bound->createBoundCRSToWGS84IfPossible(dbContext, false), + bound); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(bound); ASSERT_TRUE(boundCRS != nullptr); EXPECT_EQ(boundCRS->exportToPROJString( @@ -4862,13 +4869,13 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { } { auto crs = createVerticalCRS(); - EXPECT_EQ(crs->createBoundCRSToWGS84IfPossible(dbContext), crs); + EXPECT_EQ(crs->createBoundCRSToWGS84IfPossible(dbContext, false), crs); } { auto factoryIGNF = AuthorityFactory::create(DatabaseContext::create(), "IGNF"); auto crs = factoryIGNF->createCoordinateReferenceSystem("TERA50STEREO"); - auto bound = crs->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = crs->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_NE(bound, crs); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(bound); ASSERT_TRUE(boundCRS != nullptr); @@ -4884,7 +4891,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { auto factoryIGNF = AuthorityFactory::create(DatabaseContext::create(), "IGNF"); auto crs = factoryIGNF->createCoordinateReferenceSystem("PGP50"); - auto bound = crs->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = crs->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_NE(bound, crs); auto boundCRS = nn_dynamic_pointer_cast<BoundCRS>(bound); ASSERT_TRUE(boundCRS != nullptr); @@ -4897,7 +4904,7 @@ TEST(crs, crs_createBoundCRSToWGS84IfPossible) { } { auto crs = factory->createCoordinateReferenceSystem("4269"); // NAD83 - auto bound = crs->createBoundCRSToWGS84IfPossible(dbContext); + auto bound = crs->createBoundCRSToWGS84IfPossible(dbContext, false); EXPECT_EQ(bound, crs); } } |
