diff options
| -rw-r--r-- | include/proj/crs.hpp | 3 | ||||
| -rw-r--r-- | include/proj/io.hpp | 3 | ||||
| -rw-r--r-- | src/iso19111/c_api.cpp | 2 | ||||
| -rw-r--r-- | src/iso19111/common.cpp | 3 | ||||
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 1 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 8 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 49 | ||||
| -rw-r--r-- | test/unit/test_io.cpp | 11 | ||||
| -rw-r--r-- | test/unit/test_operation.cpp | 26 |
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, |
