aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/proj/crs.hpp5
-rw-r--r--src/c_api.cpp26
-rw-r--r--src/crs.cpp6
-rw-r--r--src/proj_experimental.h3
-rw-r--r--src/projinfo.cpp26
-rw-r--r--test/unit/test_c_api.cpp4
-rw-r--r--test/unit/test_crs.cpp43
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);
}
}