diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/factory.cpp | 2 | ||||
| -rw-r--r-- | src/iso19111/operation/concatenatedoperation.cpp | 32 | ||||
| -rw-r--r-- | src/iso19111/operation/conversion.cpp | 66 | ||||
| -rw-r--r-- | src/iso19111/operation/coordinateoperationfactory.cpp | 15 | ||||
| -rw-r--r-- | src/iso19111/operation/parammappings.cpp | 6 | ||||
| -rw-r--r-- | src/iso19111/operation/singleoperation.cpp | 44 | ||||
| -rw-r--r-- | src/proj_constants.h | 3 |
7 files changed, 143 insertions, 25 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp index 5a81506b..7b83484d 100644 --- a/src/iso19111/factory.cpp +++ b/src/iso19111/factory.cpp @@ -5613,6 +5613,8 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation( int method_code_int = std::atoi(method_code.c_str()); if (operation::isAxisOrderReversal(method_code_int) || method_code_int == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT || + method_code_int == + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR || method_code_int == EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) { auto op = operation::Conversion::create(props, propsMethod, parameters, values); diff --git a/src/iso19111/operation/concatenatedoperation.cpp b/src/iso19111/operation/concatenatedoperation.cpp index a1c0dca8..ad2ab65b 100644 --- a/src/iso19111/operation/concatenatedoperation.cpp +++ b/src/iso19111/operation/concatenatedoperation.cpp @@ -48,6 +48,7 @@ #include "proj.h" #include "proj_internal.h" // M_PI // clang-format on +#include "proj_constants.h" #include "proj_json_streaming_writer.hpp" @@ -341,6 +342,37 @@ void ConcatenatedOperation::fixStepsDirection( if (l_sourceCRS && l_targetCRS) { op->setCRSs(NN_NO_CHECK(l_sourceCRS), NN_NO_CHECK(l_targetCRS), nullptr); + } else if (l_sourceCRS && l_targetCRS == nullptr && + conv->method()->getEPSGCode() == + EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) { + // Needed for EPSG:7987 e.g. + auto vertCRS = + dynamic_cast<const crs::VerticalCRS *>(l_sourceCRS.get()); + if (vertCRS && ends_with(l_sourceCRS->nameStr(), " height") && + &vertCRS->coordinateSystem()->axisList()[0]->direction() == + &cs::AxisDirection::UP) { + op->setCRSs( + NN_NO_CHECK(l_sourceCRS), + crs::VerticalCRS::create( + util::PropertyMap().set( + common::IdentifiedObject::NAME_KEY, + l_sourceCRS->nameStr().substr( + 0, l_sourceCRS->nameStr().size() - + strlen(" height")) + + " depth"), + vertCRS->datum(), vertCRS->datumEnsemble(), + cs::VerticalCS::create( + util::PropertyMap(), + cs::CoordinateSystemAxis::create( + util::PropertyMap().set( + common::IdentifiedObject::NAME_KEY, + "Gravity-related depth"), + "D", cs::AxisDirection::DOWN, + vertCRS->coordinateSystem() + ->axisList()[0] + ->unit()))), + nullptr); + } } } else if (!conv && l_sourceCRS && l_targetCRS) { diff --git a/src/iso19111/operation/conversion.cpp b/src/iso19111/operation/conversion.cpp index e9d688b7..e2e77562 100644 --- a/src/iso19111/operation/conversion.cpp +++ b/src/iso19111/operation/conversion.cpp @@ -2252,6 +2252,26 @@ Conversion::createChangeVerticalUnit(const util::PropertyMap &properties, // --------------------------------------------------------------------------- +/** \brief Instantiate a conversion based on the Change of Vertical Unit + * method (without explicit conversion factor) + * + * This method is defined as [EPSG:1104] + * (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::1104) + * + * @param properties See \ref general_properties of the conversion. If the name + * is not provided, it is automatically set. + * @return a new Conversion. + */ +ConversionNNPtr +Conversion::createChangeVerticalUnit(const util::PropertyMap &properties) { + return create(properties, + createMethodMapNameEPSGCode( + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR), + VectorOfParameters{}, VectorOfValues{}); +} + +// --------------------------------------------------------------------------- + /** \brief Instantiate a conversion based on the Height Depth Reversal * method. * @@ -2409,6 +2429,14 @@ CoordinateOperationNNPtr Conversion::inverse() const { return conv; } + if (methodEPSGCode == + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR) { + auto conv = createChangeVerticalUnit( + createPropertiesForInverse(this, false, false)); + conv->setCRSs(this, true); + return conv; + } + const bool l_isAxisOrderReversal2D = isAxisOrderReversal2D(methodEPSGCode); const bool l_isAxisOrderReversal3D = isAxisOrderReversal3D(methodEPSGCode); if (l_isAxisOrderReversal2D || l_isAxisOrderReversal3D) { @@ -3345,7 +3373,8 @@ void Conversion::_exportToPROJString( const auto &methodName = l_method->nameStr(); const int methodEPSGCode = l_method->getEPSGCode(); const bool isZUnitConversion = - methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT; + methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT || + methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR; const bool isAffineParametric = methodEPSGCode == EPSG_CODE_METHOD_AFFINE_PARAMETRIC_TRANSFORMATION; const bool isGeographicGeocentric = @@ -3368,6 +3397,8 @@ void Conversion::_exportToPROJString( } auto l_sourceCRS = sourceCRS(); + auto l_targetCRS = targetCRS(); + crs::GeographicCRSPtr srcGeogCRS; if (!formatter->getCRSExport() && l_sourceCRS && applySourceCRSModifiers) { @@ -3633,8 +3664,35 @@ void Conversion::_exportToPROJString( } else if (formatter->convention() == io::PROJStringFormatter::Convention::PROJ_5 && isZUnitConversion) { - double convFactor = parameterValueNumericAsSI( - EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR); + double convFactor; + if (methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT) { + convFactor = parameterValueNumericAsSI( + EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR); + } else { + assert(methodEPSGCode == + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR); + const auto vertSrcCRS = + dynamic_cast<const crs::VerticalCRS *>(l_sourceCRS.get()); + const auto vertTgtCRS = + dynamic_cast<const crs::VerticalCRS *>(l_targetCRS.get()); + if (vertSrcCRS && vertTgtCRS) { + const double convSrc = vertSrcCRS->coordinateSystem() + ->axisList()[0] + ->unit() + .conversionToSI(); + const double convDst = vertTgtCRS->coordinateSystem() + ->axisList()[0] + ->unit() + .conversionToSI(); + convFactor = convSrc / convDst; + } else { + throw io::FormattingException( + "Export of " + "EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR " + "conversion to a PROJ string " + "requires an input and output vertical CRS"); + } + } auto uom = common::UnitOfMeasure(std::string(), convFactor, common::UnitOfMeasure::Type::LINEAR) .exportToPROJString(); @@ -3686,8 +3744,6 @@ void Conversion::_exportToPROJString( bConversionDone = true; } - auto l_targetCRS = targetCRS(); - bool bAxisSpecFound = false; if (!bConversionDone) { const MethodMapping *mapping = getMapping(l_method.get()); diff --git a/src/iso19111/operation/coordinateoperationfactory.cpp b/src/iso19111/operation/coordinateoperationfactory.cpp index eb560cc9..13d245bb 100644 --- a/src/iso19111/operation/coordinateoperationfactory.cpp +++ b/src/iso19111/operation/coordinateoperationfactory.cpp @@ -2097,6 +2097,17 @@ static std::string buildTransfName(const std::string &srcName, // --------------------------------------------------------------------------- +static std::string buildConvName(const std::string &srcName, + const std::string &targetName) { + std::string name("Conversion from "); + name += srcName; + name += " to "; + name += targetName; + return name; +} + +// --------------------------------------------------------------------------- + static SingleOperationNNPtr createPROJBased( const util::PropertyMap &properties, const io::IPROJStringExportableNNPtr &projExportable, @@ -4273,8 +4284,8 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert( ((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp)); const double factor = convSrc / convDst; - auto name = buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr()); if (!equivalentVDatum) { + auto name = buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr()); name += BALLPARK_VERTICAL_TRANSFORMATION; auto conv = Transformation::createChangeVerticalUnit( util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, name), @@ -4285,6 +4296,7 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert( conv->setHasBallparkTransformation(true); res.push_back(conv); } else if (convSrc != convDst || !heightDepthReversal) { + auto name = buildConvName(sourceCRS->nameStr(), targetCRS->nameStr()); auto conv = Conversion::createChangeVerticalUnit( util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, name), // In case of a height depth reversal, we should probably have @@ -4293,6 +4305,7 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert( conv->setCRSs(sourceCRS, targetCRS, nullptr); res.push_back(conv); } else { + auto name = buildConvName(sourceCRS->nameStr(), targetCRS->nameStr()); auto conv = Conversion::createHeightDepthReversal( util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, name)); conv->setCRSs(sourceCRS, targetCRS, nullptr); diff --git a/src/iso19111/operation/parammappings.cpp b/src/iso19111/operation/parammappings.cpp index 15ecb24f..5999d535 100644 --- a/src/iso19111/operation/parammappings.cpp +++ b/src/iso19111/operation/parammappings.cpp @@ -924,6 +924,7 @@ const struct MethodNameCode methodNameCodes[] = { METHOD_NAME_CODE(COLOMBIA_URBAN), // Other conversions METHOD_NAME_CODE(CHANGE_VERTICAL_UNIT), + METHOD_NAME_CODE(CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR), METHOD_NAME_CODE(HEIGHT_DEPTH_REVERSAL), METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_2D), METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_3D), @@ -1308,9 +1309,12 @@ static const MethodMapping otherMethodMappings[] = { {EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT, EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT, nullptr, nullptr, nullptr, paramsChangeVerticalUnit}, + {EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR, + EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR, nullptr, nullptr, + nullptr, nullptr}, {EPSG_NAME_METHOD_HEIGHT_DEPTH_REVERSAL, EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL, nullptr, nullptr, nullptr, - paramsChangeVerticalUnit}, + nullptr}, {EPSG_NAME_METHOD_AXIS_ORDER_REVERSAL_2D, EPSG_CODE_METHOD_AXIS_ORDER_REVERSAL_2D, nullptr, nullptr, nullptr, nullptr}, diff --git a/src/iso19111/operation/singleoperation.cpp b/src/iso19111/operation/singleoperation.cpp index 6812819c..2f60828e 100644 --- a/src/iso19111/operation/singleoperation.cpp +++ b/src/iso19111/operation/singleoperation.cpp @@ -1525,31 +1525,39 @@ std::list<std::string> SingleOperation::validateParameters() const { const auto &l_method = method(); const auto &methodName = l_method->nameStr(); - const MethodMapping *methodMapping = nullptr; const auto methodEPSGCode = l_method->getEPSGCode(); + + const auto findMapping = [methodEPSGCode, &methodName]( + const MethodMapping *mappings, + size_t mappingCount) -> const MethodMapping * { + if (methodEPSGCode != 0) { + for (size_t i = 0; i < mappingCount; ++i) { + const auto &mapping = mappings[i]; + if (methodEPSGCode == mapping.epsg_code) { + return &mapping; + } + } + } + for (size_t i = 0; i < mappingCount; ++i) { + const auto &mapping = mappings[i]; + if (metadata::Identifier::isEquivalentName(mapping.wkt2_name, + methodName.c_str())) { + return &mapping; + } + } + return nullptr; + }; + size_t nProjectionMethodMappings = 0; const auto projectionMethodMappings = getProjectionMethodMappings(nProjectionMethodMappings); - for (size_t i = 0; i < nProjectionMethodMappings; ++i) { - const auto &mapping = projectionMethodMappings[i]; - if (metadata::Identifier::isEquivalentName(mapping.wkt2_name, - methodName.c_str()) || - (methodEPSGCode != 0 && methodEPSGCode == mapping.epsg_code)) { - methodMapping = &mapping; - } - } + const MethodMapping *methodMapping = + findMapping(projectionMethodMappings, nProjectionMethodMappings); if (methodMapping == nullptr) { size_t nOtherMethodMappings = 0; const auto otherMethodMappings = getOtherMethodMappings(nOtherMethodMappings); - for (size_t i = 0; i < nOtherMethodMappings; ++i) { - const auto &mapping = otherMethodMappings[i]; - if (metadata::Identifier::isEquivalentName(mapping.wkt2_name, - methodName.c_str()) || - (methodEPSGCode != 0 && methodEPSGCode == mapping.epsg_code)) { - methodMapping = &mapping; - } - } + methodMapping = findMapping(otherMethodMappings, nOtherMethodMappings); } if (!methodMapping) { res.emplace_back("Unknown method " + methodName); @@ -1661,7 +1669,7 @@ std::list<std::string> SingleOperation::validateParameters() const { } return res; -} +} // namespace operation // --------------------------------------------------------------------------- diff --git a/src/proj_constants.h b/src/proj_constants.h index baea05da..66d04294 100644 --- a/src/proj_constants.h +++ b/src/proj_constants.h @@ -582,6 +582,9 @@ #define EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT 1069 #define EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT "Change of Vertical Unit" +#define EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR 1104 +#define EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR "Change of Vertical Unit" + #define EPSG_NAME_PARAMETER_UNIT_CONVERSION_SCALAR "Unit conversion scalar" #define EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR 1051 |
