From 7ab63b60f656811ee7960a9e7ba07401d61053cd Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Thu, 6 Jan 2022 12:26:45 +0100 Subject: Implement Geographic3D to Depth/Geog2D+Depth as used by ETRS89 to CD Norway depth Fixes #2739 Verified with example from IOGP Guidance Note 7-2 (ver 62, Dec 2021) page 169, with 38 = h_obs - D_obs = 50 - 12. $ echo 60.0015 4.9960 38 | PROJ_LIB=data PROJ_NETWORK=ON bin/cs2cs -d 4 EPSG:4937 EPSG:9883 60.0015 4.9960 5.8827 $ echo 60.0015 4.9960 38 | PROJ_LIB=data PROJ_NETWORK=ON bin/cs2cs -d 4 EPSG:4937 EPSG:4258+9672 60.0015 4.9960 5.8827 $ echo 60.0015 4.9960 5.8827 | PROJ_LIB=data PROJ_NETWORK=ON bin/cs2cs -d 4 EPSG:9883 EPSG:4937 60.0015 4.9960 38.0000 $ echo 60.0015 4.9960 5.8827 | PROJ_LIB=data PROJ_NETWORK=ON bin/cs2cs -d 4 EPSG:4258+9672 EPSG:4937 60.0015 4.9960 38.0000 --- src/iso19111/io.cpp | 7 +++++++ src/iso19111/operation/transformation.cpp | 20 ++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 67877206..6c66b6f8 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -7671,6 +7671,13 @@ const std::string &PROJStringFormatter::toString() const { continue; } + // axisswap order=1,2,-3 is its own inverse + if (step.name == "axisswap" && paramCount == 1 && + step.paramValues[0].equals("order", "1,2,-3")) { + step.inverted = false; + continue; + } + // handle unitconvert inverse if (step.name == "unitconvert" && paramCount == 2 && step.paramValues[0].keyEquals("xy_in") && diff --git a/src/iso19111/operation/transformation.cpp b/src/iso19111/operation/transformation.cpp index 36540242..8bd4f3de 100644 --- a/src/iso19111/operation/transformation.cpp +++ b/src/iso19111/operation/transformation.cpp @@ -2011,8 +2011,8 @@ isGeographic3DToGravityRelatedHeight(const OperationMethodNNPtr &method, "1100", // Geog3D to Geog2D+GravityRelatedHeight (PL txt) "1103", // Geog3D to Geog2D+GravityRelatedHeight (EGM) "1105", // Geog3D to Geog2D+GravityRelatedHeight (ITAL2005) - // "1110", // Geog3D to Geog2D+Depth (Gravsoft) FIXME: to investigate - // how to map this to PROJ pipeline (depth vs height) + "1109", // Geographic3D to Depth (Gravsoft) + "1110", // Geog3D to Geog2D+Depth (Gravsoft) "9661", // Geographic3D to GravityRelatedHeight (EGM) "9662", // Geographic3D to GravityRelatedHeight (Ausgeoid98) "9663", // Geographic3D to GravityRelatedHeight (OSGM-GB) @@ -3164,6 +3164,13 @@ void Transformation::_exportToPROJString( concat("Can apply ", methodName, " only to GeographicCRS")); } + auto targetVertCRS = targetCRS()->extractVerticalCRS(); + if (!targetVertCRS) { + throw io::FormattingException( + concat("Can apply ", methodName, + " only to a target CRS that has a VerticalCRS")); + } + if (!formatter->omitHorizontalConversionInVertTransformation()) { formatter->startInversion(); formatter->pushOmitZUnitConversion(); @@ -3178,6 +3185,15 @@ void Transformation::_exportToPROJString( if (doInversion) { formatter->startInversion(); } + + // For Geographic3D to Depth methods, we rely on the vertical axis + // direction instead of the name/code of the transformation method. + if (targetVertCRS->coordinateSystem()->axisList()[0]->direction() == + cs::AxisDirection::DOWN) { + formatter->addStep("axisswap"); + formatter->addParam("order", "1,2,-3"); + } + formatter->addStep("vgridshift"); formatter->addParam("grids", filename); formatter->addParam("multiplier", 1.0); -- cgit v1.2.3