From 7898eaba1160631405e8d4eccd73254f453bd3d4 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 24 Apr 2021 15:22:02 +0200 Subject: Improvements related to DerivedVerticalCRS using Change Unit and Height/Depth reversal methods - For instantiation from urn combined references, create a better name, using conventions of EPSG vertical CRS - For exportToWKT(), allow export in WKT < WKT2 for such DerivedVerticalCRS --- src/iso19111/crs.cpp | 27 ++++++++++++++++++++ src/iso19111/io.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 85 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 2d589ad1..51317c18 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -6506,6 +6506,33 @@ DerivedVerticalCRSNNPtr DerivedVerticalCRS::create( void DerivedVerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; if (!isWKT2) { + + bool useBaseMethod = true; + const DerivedVerticalCRS *dvcrs = this; + while (true) { + // If the derived vertical CRS is obtained through simple conversion + // methods that just do unit change or height/depth reversal, export + // it as a regular VerticalCRS + const int methodCode = + dvcrs->derivingConversionRef()->method()->getEPSGCode(); + if (methodCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT || + methodCode == + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR || + methodCode == EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) { + dvcrs = dynamic_cast(baseCRS().get()); + if (dvcrs == nullptr) { + break; + } + } else { + useBaseMethod = false; + break; + } + } + if (useBaseMethod) { + VerticalCRS::_exportToWKT(formatter); + return; + } + io::FormattingException::Throw( "DerivedVerticalCRS can only be exported to WKT2"); } diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index e3da80e0..6ddeed7a 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -6491,12 +6491,13 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, AuthorityFactory::create(NN_NO_CHECK(dbContext), tokensOp[1]); auto op = factoryOp->createCoordinateOperation(tokensOp[3], true); - std::string name(baseCRS->nameStr()); + const auto &baseName = baseCRS->nameStr(); + std::string name(baseName); auto geogCRS = util::nn_dynamic_pointer_cast(baseCRS); if (geogCRS && geogCRS->coordinateSystem()->axisList().size() == 3 && - baseCRS->nameStr().find("3D") == std::string::npos) { + baseName.find("3D") == std::string::npos) { name += " (3D)"; } name += " / "; @@ -6532,15 +6533,61 @@ static BaseObjectNNPtr createFromUserInput(const std::string &text, baseCRS)) { return DerivedProjectedCRS::create(props, NN_NO_CHECK(pcrs), convNN, cs); - } else if (dynamic_cast(baseCRS.get()) && - dynamic_cast(cs.get())) { - return DerivedVerticalCRS::create( - props, - NN_NO_CHECK(util::nn_dynamic_pointer_cast( - baseCRS)), - convNN, - NN_NO_CHECK( - util::nn_dynamic_pointer_cast(cs))); + } else if (auto vertBaseCRS = + util::nn_dynamic_pointer_cast( + baseCRS)) { + if (auto vertCS = + util::nn_dynamic_pointer_cast(cs)) { + const int methodCode = convNN->method()->getEPSGCode(); + std::string newName(baseName); + std::string unitNameSuffix; + for (const char *suffix : {" (ft)", " (ftUS)"}) { + if (ends_with(newName, suffix)) { + unitNameSuffix = suffix; + newName.resize(newName.size() - strlen(suffix)); + break; + } + } + bool newNameOk = false; + if (methodCode == + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR || + methodCode == + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT) { + const auto &unitName = + vertCS->axisList()[0]->unit().name(); + if (unitName == UnitOfMeasure::METRE.name()) { + newNameOk = true; + } else if (unitName == UnitOfMeasure::FOOT.name()) { + newName += " (ft)"; + newNameOk = true; + } else if (unitName == + UnitOfMeasure::US_FOOT.name()) { + newName += " (ftUS)"; + newNameOk = true; + } + } else if (methodCode == + EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) { + if (ends_with(newName, " height")) { + newName.resize(newName.size() - + strlen(" height")); + newName += " depth"; + newName += unitNameSuffix; + newNameOk = true; + } else if (ends_with(newName, " depth")) { + newName.resize(newName.size() - + strlen(" depth")); + newName += " height"; + newName += unitNameSuffix; + newNameOk = true; + } + } + if (newNameOk) { + props.set(IdentifiedObject::NAME_KEY, newName); + } + return DerivedVerticalCRS::create( + props, NN_NO_CHECK(vertBaseCRS), convNN, + NN_NO_CHECK(vertCS)); + } } } -- cgit v1.2.3