aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/proj/crs.hpp3
-rw-r--r--include/proj/io.hpp3
-rw-r--r--src/iso19111/c_api.cpp2
-rw-r--r--src/iso19111/common.cpp3
-rw-r--r--src/iso19111/coordinateoperation.cpp1
-rw-r--r--src/iso19111/crs.cpp8
-rw-r--r--src/iso19111/io.cpp49
-rw-r--r--test/unit/test_io.cpp11
-rw-r--r--test/unit/test_operation.cpp26
9 files changed, 83 insertions, 23 deletions
diff --git a/include/proj/crs.hpp b/include/proj/crs.hpp
index 1c012666..6a09ea78 100644
--- a/include/proj/crs.hpp
+++ b/include/proj/crs.hpp
@@ -158,8 +158,7 @@ class PROJ_GCC_DLL SingleCRS : public CRS {
PROJ_DLL const datum::DatumPtr &datum() PROJ_PURE_DECL;
PROJ_DLL const datum::DatumEnsemblePtr &datumEnsemble() PROJ_PURE_DECL;
- PROJ_DLL const cs::CoordinateSystemNNPtr &
- coordinateSystem() PROJ_PURE_DECL;
+ PROJ_DLL const cs::CoordinateSystemNNPtr &coordinateSystem() PROJ_PURE_DECL;
PROJ_PRIVATE :
//! @cond Doxygen_Suppress
diff --git a/include/proj/io.hpp b/include/proj/io.hpp
index 825e8e44..4120d707 100644
--- a/include/proj/io.hpp
+++ b/include/proj/io.hpp
@@ -422,6 +422,9 @@ class PROJ_GCC_DLL PROJStringFormatter {
PROJ_INTERNAL void setOmitZUnitConversion(bool omit);
PROJ_INTERNAL bool omitZUnitConversion() const;
+ PROJ_INTERNAL void setDropEarlyBindingsTerms(bool drop);
+ PROJ_INTERNAL bool getDropEarlyBindingsTerms() const;
+
PROJ_INTERNAL const DatabaseContextPtr &databaseContext() const;
PROJ_INTERNAL Convention convention() const;
diff --git a/src/iso19111/c_api.cpp b/src/iso19111/c_api.cpp
index 06a3c02e..de11f181 100644
--- a/src/iso19111/c_api.cpp
+++ b/src/iso19111/c_api.cpp
@@ -337,7 +337,7 @@ PJ *proj_create(PJ_CONTEXT *ctx, const char *text) {
assert(text);
// Only connect to proj.db if needed
- if( strstr(text, "proj=") == nullptr || strstr(text, "init=") != nullptr ) {
+ if (strstr(text, "proj=") == nullptr || strstr(text, "init=") != nullptr) {
getDBcontextNoException(ctx, __FUNCTION__);
}
try {
diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp
index ca9d3b3e..57654d84 100644
--- a/src/iso19111/common.cpp
+++ b/src/iso19111/common.cpp
@@ -1122,8 +1122,7 @@ struct DataEpoch::Private {
// ---------------------------------------------------------------------------
-DataEpoch::DataEpoch()
- : d(internal::make_unique<Private>(Measure())) {}
+DataEpoch::DataEpoch() : d(internal::make_unique<Private>(Measure())) {}
// ---------------------------------------------------------------------------
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 723fddec..6f9b6283 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -11100,6 +11100,7 @@ CoordinateOperationFactory::Private::createOperations(
}
auto projFormatter = io::PROJStringFormatter::create();
projFormatter->setCRSExport(true);
+ projFormatter->setDropEarlyBindingsTerms(true);
projFormatter->startInversion();
sourceProjExportable->_exportToPROJString(projFormatter.get());
auto geogSrc =
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index 74b94a1f..adb441cd 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -1653,8 +1653,7 @@ CRSNNPtr GeographicCRS::_shallowClone() const {
*
* @return a EllipsoidalCS.
*/
-const cs::EllipsoidalCSNNPtr &
-GeographicCRS::coordinateSystem() PROJ_PURE_DEFN {
+const cs::EllipsoidalCSNNPtr &GeographicCRS::coordinateSystem() PROJ_PURE_DEFN {
return d->coordinateSystem_;
}
@@ -3767,6 +3766,11 @@ void BoundCRS::_exportToPROJString(
"baseCRS of BoundCRS cannot be exported as a PROJ string");
}
+ if (formatter->getDropEarlyBindingsTerms()) {
+ crs_exportable->_exportToPROJString(formatter);
+ return;
+ }
+
auto vdatumProj4GridName = getVDatumPROJ4GRIDS();
if (!vdatumProj4GridName.empty()) {
formatter->setVDatumExtension(vdatumProj4GridName);
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 4c417585..0722c22a 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -4745,6 +4745,7 @@ struct PROJStringFormatter::Private {
bool addNoDefs_ = true;
bool coordOperationOptimizations_ = false;
bool crsExport_ = false;
+ bool dropEarlyBindingsTerms_ = false;
std::string result_{};
@@ -5274,7 +5275,7 @@ void PROJStringFormatter::Private::appendToResult(const char *str) {
static void
PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
std::vector<Step::KeyValue> &globalParamValues,
- std::string &title) {
+ std::string &title, bool dropEarlyBindingsTerms) {
const char *c_str = projString.c_str();
std::vector<std::string> tokens;
@@ -5352,13 +5353,17 @@ PROJStringSyntaxParser(const std::string &projString, std::vector<Step> &steps,
} else if (word != "step") {
const auto pos = word.find('=');
auto key = word.substr(0, pos);
- auto pair = (pos != std::string::npos)
- ? Step::KeyValue(key, word.substr(pos + 1))
- : Step::KeyValue(key);
- if (steps.empty()) {
- globalParamValues.push_back(pair);
- } else {
- steps.back().paramValues.push_back(pair);
+ if (!(dropEarlyBindingsTerms &&
+ (key == "towgs84" || key == "nadgrids" ||
+ key == "geoidgrids" || key == "wktext"))) {
+ auto pair = (pos != std::string::npos)
+ ? Step::KeyValue(key, word.substr(pos + 1))
+ : Step::KeyValue(key);
+ if (steps.empty()) {
+ globalParamValues.push_back(pair);
+ } else {
+ steps.back().paramValues.push_back(pair);
+ }
}
}
}
@@ -5433,7 +5438,8 @@ void PROJStringFormatter::ingestPROJString(
{
std::vector<Step> steps;
std::string title;
- PROJStringSyntaxParser(str, steps, d->globalParamValues_, title);
+ PROJStringSyntaxParser(str, steps, d->globalParamValues_, title,
+ d->dropEarlyBindingsTerms_);
d->steps_.insert(d->steps_.end(), steps.begin(), steps.end());
}
@@ -5695,6 +5701,18 @@ bool PROJStringFormatter::omitZUnitConversion() const {
// ---------------------------------------------------------------------------
+void PROJStringFormatter::setDropEarlyBindingsTerms(bool drop) {
+ d->dropEarlyBindingsTerms_ = drop;
+}
+
+// ---------------------------------------------------------------------------
+
+bool PROJStringFormatter::getDropEarlyBindingsTerms() const {
+ return d->dropEarlyBindingsTerms_;
+}
+
+// ---------------------------------------------------------------------------
+
const DatabaseContextPtr &PROJStringFormatter::databaseContext() const {
return d->dbContext_;
}
@@ -6673,8 +6691,12 @@ CRSNNPtr
PROJStringParser::Private::buildBoundOrCompoundCRSIfNeeded(int iStep,
CRSNNPtr crs) {
const auto &step = steps_[iStep];
+ const auto &nadgrids = getParamValue(step, "nadgrids");
const auto &towgs84 = getParamValue(step, "towgs84");
- if (!towgs84.empty()) {
+ // nadgrids has the priority over towgs84
+ if (!nadgrids.empty()) {
+ crs = BoundCRS::createFromNadgrids(crs, nadgrids);
+ } else if (!towgs84.empty()) {
std::vector<double> towgs84Values;
const auto tokens = split(towgs84, ',');
for (const auto &str : tokens) {
@@ -6687,11 +6709,6 @@ PROJStringParser::Private::buildBoundOrCompoundCRSIfNeeded(int iStep,
crs = BoundCRS::createFromTOWGS84(crs, towgs84Values);
}
- const auto &nadgrids = getParamValue(step, "nadgrids");
- if (!nadgrids.empty()) {
- crs = BoundCRS::createFromNadgrids(crs, nadgrids);
- }
-
const auto &geoidgrids = getParamValue(step, "geoidgrids");
if (!geoidgrids.empty()) {
auto vdatum =
@@ -7397,7 +7414,7 @@ PROJStringParser::createFromPROJString(const std::string &projString) {
d->globalParamValues_.clear();
d->projString_ = projString;
PROJStringSyntaxParser(projString, d->steps_, d->globalParamValues_,
- d->title_);
+ d->title_, false);
if (d->steps_.empty()) {
const auto &vunits = d->getGlobalParamValue("vunits");
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 15ba30f1..9bd3d70f 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -7024,6 +7024,17 @@ TEST(io, projparse_longlat_nadgrids) {
// ---------------------------------------------------------------------------
+TEST(io, projparse_longlat_nadgrids_towgs84_ignored) {
+ auto obj = PROJStringParser().createFromPROJString(
+ "+proj=longlat +ellps=GRS80 +towgs84=1,2,3 +nadgrids=foo.gsb "
+ "+type=crs");
+ auto crs = nn_dynamic_pointer_cast<BoundCRS>(obj);
+ ASSERT_TRUE(crs != nullptr);
+ EXPECT_TRUE(dynamic_cast<GeographicCRS *>(crs->baseCRS().get()) != nullptr);
+}
+
+// ---------------------------------------------------------------------------
+
TEST(io, projparse_longlat_geoidgrids) {
auto obj = PROJStringParser().createFromPROJString(
"+proj=longlat +ellps=GRS80 +geoidgrids=foo.gtx +type=crs");
diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp
index d134f086..ed31f155 100644
--- a/test/unit/test_operation.cpp
+++ b/test/unit/test_operation.cpp
@@ -6320,6 +6320,32 @@ TEST(operation, createOperation_fallback_to_proj4_strings) {
// ---------------------------------------------------------------------------
+TEST(operation, createOperation_on_crs_with_bound_crs_and_wktext) {
+ auto objSrc = PROJStringParser().createFromPROJString(
+ "+proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 "
+ "+units=m +no_defs +nadgrids=GDA94_GDA2020_conformal.gsb "
+ "+type=crs");
+ auto src = nn_dynamic_pointer_cast<CRS>(objSrc);
+ ASSERT_TRUE(src != nullptr);
+
+ auto objDst = PROJStringParser().createFromPROJString(
+ "+proj=utm +zone=55 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 "
+ "+units=m +no_defs +type=crs");
+ auto dst = nn_dynamic_pointer_cast<CRS>(objDst);
+ ASSERT_TRUE(dst != nullptr);
+
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ NN_CHECK_ASSERT(src), NN_CHECK_ASSERT(dst));
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline +step +inv +proj=utm +zone=55 +south "
+ "+ellps=GRS80 +step +proj=hgridshift "
+ "+grids=GDA94_GDA2020_conformal.gsb +step +proj=utm +zone=55 "
+ "+south +ellps=GRS80");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, mercator_variant_A_to_variant_B) {
auto projCRS = ProjectedCRS::create(
PropertyMap(), GeographicCRS::EPSG_4326,