diff options
| -rw-r--r-- | data/sql/grid_alternatives.sql | 1 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 7 | ||||
| -rw-r--r-- | src/iso19111/operation/transformation.cpp | 20 | ||||
| -rw-r--r-- | test/unit/test_operationfactory.cpp | 114 |
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( |
