aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2022-01-06 12:26:45 +0100
committerEven Rouault <even.rouault@spatialys.com>2022-01-06 12:26:45 +0100
commit7ab63b60f656811ee7960a9e7ba07401d61053cd (patch)
tree536f3fbd6ffe3e61951de8026fb3fd23c313dd80
parent1254a211beac3f479d193794508a3fcea4f8790f (diff)
downloadPROJ-7ab63b60f656811ee7960a9e7ba07401d61053cd.tar.gz
PROJ-7ab63b60f656811ee7960a9e7ba07401d61053cd.zip
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
-rw-r--r--data/sql/grid_alternatives.sql1
-rw-r--r--src/iso19111/io.cpp7
-rw-r--r--src/iso19111/operation/transformation.cpp20
-rw-r--r--test/unit/test_operationfactory.cpp114
4 files changed, 140 insertions, 2 deletions
diff --git a/data/sql/grid_alternatives.sql b/data/sql/grid_alternatives.sql
index 416da2e0..a9560ae3 100644
--- a/data/sql/grid_alternatives.sql
+++ b/data/sql/grid_alternatives.sql
@@ -200,6 +200,7 @@ VALUES
('HREF2018B_NN2000_EUREF89.bin','no_kv_HREF2018B_NN2000_EUREF89.tif',NULL,'GTiff','geoid_like',0,NULL,'https://cdn.proj.org/no_kv_HREF2018B_NN2000_EUREF89.tif',1,1,NULL),
('href2008a.bin','no_kv_href2008a.tif',NULL,'GTiff','geoid_like',0,NULL,'https://cdn.proj.org/no_kv_href2008a.tif',1,1,NULL),
('no_kv_NKGETRF14_EPSG7922_2000.tif','no_kv_NKGETRF14_EPSG7922_2000.tif',NULL,'GTiff','geocentricoffset',0,NULL,'https://cdn.proj.org/no_kv_NKGETRF14_EPSG7922_2000.tif',1,1,NULL),
+('ChartDatum_above_Ellipsoid_EUREF89_v2021a.bin','no_kv_CD_above_Ell_ETRS89_v2021a.tif',NULL,'GTiff','vgridshift',0,NULL,'https://cdn.proj.org/no_kv_CD_above_Ell_ETRS89_v2021a.tif',1,1,NULL),
('no_kv_ETRS89NO_NGO48_TIN.json','no_kv_ETRS89NO_NGO48_TIN.json',NULL,'JSON','tinshift',0,NULL,'https://cdn.proj.org/no_kv_ETRS89NO_NGO48_TIN.json',1,1,NULL),
-- nz_linz - New Zealand
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);
diff --git a/test/unit/test_operationfactory.cpp b/test/unit/test_operationfactory.cpp
index e387b7ab..e78c4e3f 100644
--- a/test/unit/test_operationfactory.cpp
+++ b/test/unit/test_operationfactory.cpp
@@ -791,6 +791,120 @@ TEST(operation, geog3DCRS_to_geog2DCRS_plus_vertCRS_context) {
// ---------------------------------------------------------------------------
+TEST(operation, geog3DCRS_to_vertCRS_depth_context) {
+ auto authFactory =
+ AuthorityFactory::create(DatabaseContext::create(), "EPSG");
+ {
+ auto ctxt =
+ CoordinateOperationContext::create(authFactory, nullptr, 0.0);
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+ auto list = CoordinateOperationFactory::create()->createOperations(
+ authFactory->createCoordinateReferenceSystem("4937"), // ETRS89
+ authFactory->createCoordinateReferenceSystem("9672"),
+ // CD Norway deph
+ ctxt);
+ ASSERT_GE(list.size(), 1U);
+ EXPECT_EQ(list[0]->exportToPROJString(
+ PROJStringFormatter::create(
+ PROJStringFormatter::Convention::PROJ_5,
+ authFactory->databaseContext())
+ .get()),
+ "+proj=pipeline "
+ "+step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +inv +proj=vgridshift "
+ "+grids=no_kv_CD_above_Ell_ETRS89_v2021a.tif +multiplier=1 "
+ "+step +proj=axisswap +order=1,2,-3 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1");
+ }
+ {
+ auto ctxt =
+ CoordinateOperationContext::create(authFactory, nullptr, 0.0);
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+ auto list = CoordinateOperationFactory::create()->createOperations(
+ authFactory->createCoordinateReferenceSystem("9672"),
+ // CD Norway deph
+ authFactory->createCoordinateReferenceSystem("4937"), // ETRS89
+ ctxt);
+ ASSERT_GE(list.size(), 1U);
+ EXPECT_EQ(list[0]->exportToPROJString(
+ PROJStringFormatter::create(
+ PROJStringFormatter::Convention::PROJ_5,
+ authFactory->databaseContext())
+ .get()),
+ "+proj=pipeline "
+ "+step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=axisswap +order=1,2,-3 "
+ "+step +proj=vgridshift "
+ "+grids=no_kv_CD_above_Ell_ETRS89_v2021a.tif +multiplier=1 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1");
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+TEST(operation, geog3DCRS_to_geog2DCRS_plus_vertCRS_depth_context) {
+ auto authFactory =
+ AuthorityFactory::create(DatabaseContext::create(), "EPSG");
+ {
+ auto ctxt =
+ CoordinateOperationContext::create(authFactory, nullptr, 0.0);
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+ auto list = CoordinateOperationFactory::create()->createOperations(
+ authFactory->createCoordinateReferenceSystem("4937"), // ETRS89
+ authFactory->createCoordinateReferenceSystem("9883"),
+ // ETRS89 + CD Norway deph
+ ctxt);
+ ASSERT_GE(list.size(), 1U);
+ EXPECT_EQ(list[0]->exportToPROJString(
+ PROJStringFormatter::create(
+ PROJStringFormatter::Convention::PROJ_5,
+ authFactory->databaseContext())
+ .get()),
+ "+proj=pipeline "
+ "+step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +inv +proj=vgridshift "
+ "+grids=no_kv_CD_above_Ell_ETRS89_v2021a.tif +multiplier=1 "
+ "+step +proj=axisswap +order=1,2,-3 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1");
+ }
+ {
+ auto ctxt =
+ CoordinateOperationContext::create(authFactory, nullptr, 0.0);
+ ctxt->setSpatialCriterion(
+ CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
+ auto list = CoordinateOperationFactory::create()->createOperations(
+ authFactory->createCoordinateReferenceSystem("9883"),
+ // ETRS89 + CD Norway deph
+ authFactory->createCoordinateReferenceSystem("4937"), // ETRS89
+ ctxt);
+ ASSERT_GE(list.size(), 1U);
+ EXPECT_EQ(list[0]->exportToPROJString(
+ PROJStringFormatter::create(
+ PROJStringFormatter::Convention::PROJ_5,
+ authFactory->databaseContext())
+ .get()),
+ "+proj=pipeline "
+ "+step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=deg +xy_out=rad "
+ "+step +proj=axisswap +order=1,2,-3 "
+ "+step +proj=vgridshift "
+ "+grids=no_kv_CD_above_Ell_ETRS89_v2021a.tif +multiplier=1 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg "
+ "+step +proj=axisswap +order=2,1");
+ }
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, geogCRS_to_geogCRS_noop) {
auto op = CoordinateOperationFactory::create()->createOperation(