Skip to content

Commit 2c27beb

Browse files
committed
Fix issue with WGS 84 + EGM2008 -> Amersfoort + NAP height (master only)
Fixes https://lists.osgeo.org/pipermail/proj/2026-February/011959.html Output of projinfo EPSG:4326+3855 EPSG:7415 --spatial-test intersects --------------------------------------------------------------------- 9.7.1 +++++ Operation No. 1: ``` unknown id, Inverse of WGS 84 to EGM2008 height (1) + Inverse of ETRS89 to WGS 84 (1) + ETRS89 to NAP height (2) + Inverse of Amersfoort to ETRS89 (9) + RD New, 1.114 m, Netherlands - onshore, including Waddenzee, Dutch Wadden Islands and 12-mile offshore coastal zone., at least one grid missing PROJ string: +proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=vgridshift +grids=us_nga_egm08_25.tif +multiplier=1 +step +inv +proj=vgridshift +grids=nl_nsgi_nlgeo2018.tif +multiplier=1 +step +inv +proj=hgridshift +grids=nl_nsgi_rdtrans2018.tif +step +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel ``` master before this change +++++++++++++++++++++++++ Operation No. 1: ``` unknown id, Inverse of WGS 84 to EGM2008 height (1) + Inverse of ETRS89-NLD [AGRS2010] to WGS 84 (1) + ETRS89-NLD [AGRS2010] to NAP height (2) + Inverse of Amersfoort to ETRS89-NLD [AGRS2010] (9) + RD New, 1.123 m, Netherlands - onshore and offshore., at least one grid missing PROJ string: +proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=vgridshift +grids=us_nga_egm08_25.tif +multiplier=1 +step +inv +proj=vgridshift +grids=nl_nsgi_nlgeo2018.tif +multiplier=1 +step +inv +proj=hgridshift +grids=nl_nsgi_rdtrans2018.tif +step +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel OPERATIONACCURACY[1.123], USAGE[ SCOPE["unknown"], AREA["Netherlands - onshore and offshore."], BBOX[50.75,2.53,55.77,7.22]]] ``` Operation No. 3: ``` unknown id, Inverse of WGS 84 to EGM2008 height (1) + Inverse of Amersfoort to WGS 84 (4) + ETRS89-NLD [AGRS2010] to NAP height (2) using Amersfoort to ETRS89-NLD [AGRS2010] (9) + RD New, 1.123 m, Netherlands - onshore, including Waddenzee, Dutch Wadden Islands and 12-mile offshore coastal zone., at least one grid missing PROJ string: +proj=pipeline +step +proj=axisswap +order=2,1 +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=vgridshift +grids=us_nga_egm08_25.tif +multiplier=1 +step +proj=cart +ellps=WGS84 +step +inv +proj=helmert +x=565.4171 +y=50.3319 +z=465.5524 +rx=0.398957388243134 +ry=-0.343987817378283 +rz=1.87740163998045 +s=4.0725 +convention=coordinate_frame +step +inv +proj=cart +ellps=bessel +step +proj=push +v_1 +v_2 +step +proj=hgridshift +grids=nl_nsgi_rdtrans2018.tif +omit_inv +step +inv +proj=vgridshift +grids=nl_nsgi_nlgeo2018.tif +multiplier=1 +step +inv +proj=hgridshift +grids=nl_nsgi_rdtrans2018.tif +omit_fwd +step +proj=pop +v_1 +v_2 +step +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel OPERATIONACCURACY[1.123], USAGE[ SCOPE["unknown"], AREA["Netherlands - onshore, including Waddenzee, Dutch Wadden Islands and 12-mile offshore coastal zone."], BBOX[50.75,3.2,53.7,7.22]]] ``` Analysis -------- Due to the ETRS89 datum ensemble changes, PROJ synthetized a new operation (operation 3) that has the same accuracy than the "correct" (operation 1), and a smaller area of use, thus it was selected. However that choice was not super relevant compared to 1, because it relied on using Amersfoort CRS in 3D (with ellipsoidal height), through the Helmert transformation "Amersfoort to WGS 84 (4)"). Given that there's no entry in the database for a 3D Amersfoort CRS, this possibility should be discarded when there is an alternative that uses only known objects.
1 parent ac9ac9f commit 2c27beb

File tree

2 files changed

+67
-2
lines changed

2 files changed

+67
-2
lines changed

src/iso19111/operation/coordinateoperationfactory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7033,15 +7033,15 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
70337033
}
70347034
}
70357035

7036-
// Keep the results of this new attempt, if there are better
7036+
// Use the results of this new attempt if they are better
70377037
// than the previous ones
70387038
if (bestAccuracy2 >= 0 &&
70397039
(bestAccuracy < 0 || (bestAccuracy2 < bestAccuracy ||
70407040
(bestAccuracy2 == bestAccuracy &&
70417041
bestStepCount2 < bestStepCount)))) {
70427042
bestAccuracy = bestAccuracy2;
70437043
bestStepCount = bestStepCount2;
7044-
res.insert(res.end(), res2.begin(), res2.end());
7044+
res = std::move(res2);
70457045
}
70467046
};
70477047

test/unit/test_operationfactory.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6585,6 +6585,71 @@ TEST(operation, compoundCRS_to_compoundCRS_issue_3328) {
65856585

65866586
// ---------------------------------------------------------------------------
65876587

6588+
TEST(operation, compoundCRS_to_compoundCRS_WGS84_EGM2008_to_RD_new_NAP_height) {
6589+
auto authFactory =
6590+
AuthorityFactory::create(DatabaseContext::create(), "EPSG");
6591+
auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
6592+
ctxt->setGridAvailabilityUse(
6593+
CoordinateOperationContext::GridAvailabilityUse::
6594+
IGNORE_GRID_AVAILABILITY);
6595+
ctxt->setSpatialCriterion(
6596+
CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
6597+
auto list = CoordinateOperationFactory::create()->createOperations(
6598+
// WGS 84 + EGM2008 height
6599+
authFactory->createCoordinateReferenceSystem("9518"),
6600+
// Amersfoort / RD New + NAP height
6601+
authFactory->createCoordinateReferenceSystem("7415"), ctxt);
6602+
6603+
ASSERT_EQ(list.size(), 4U);
6604+
6605+
EXPECT_FALSE(list[0]->hasBallparkTransformation());
6606+
EXPECT_EQ(list[0]->nameStr(),
6607+
"Inverse of WGS 84 to EGM2008 height (1) + "
6608+
"Inverse of ETRS89-NLD [AGRS2010] to WGS 84 (1) + "
6609+
"ETRS89-NLD [AGRS2010] to NAP height (2) + "
6610+
"Inverse of Amersfoort to ETRS89-NLD [AGRS2010] (9) + RD New");
6611+
EXPECT_EQ(
6612+
list[0]->exportToPROJString(PROJStringFormatter::create().get()),
6613+
"+proj=pipeline "
6614+
"+step +proj=axisswap +order=2,1 "
6615+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
6616+
"+step +proj=vgridshift +grids=us_nga_egm08_25.tif +multiplier=1 "
6617+
"+step +inv +proj=vgridshift +grids=nl_nsgi_nlgeo2018.tif "
6618+
"+multiplier=1 "
6619+
"+step +inv +proj=hgridshift +grids=nl_nsgi_rdtrans2018.tif "
6620+
"+step +proj=sterea +lat_0=52.1561605555556 +lon_0=5.38763888888889 "
6621+
"+k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel");
6622+
ASSERT_EQ(list[0]->coordinateOperationAccuracies().size(), 1U);
6623+
EXPECT_EQ(list[0]->coordinateOperationAccuracies()[0]->value(), "1.123");
6624+
6625+
EXPECT_FALSE(list[1]->hasBallparkTransformation());
6626+
EXPECT_EQ(list[1]->nameStr(),
6627+
"Inverse of WGS 84 to EGM2008 height (1) + "
6628+
"Inverse of ETRS89-NLD [AGRS2010] to WGS 84 (1) + "
6629+
"ETRS89-NLD [AGRS2010] to NAP height (2) + "
6630+
"Inverse of Amersfoort to ETRS89-NLD [AGRS2010] (8) + RD New");
6631+
ASSERT_EQ(list[1]->coordinateOperationAccuracies().size(), 1U);
6632+
EXPECT_EQ(list[1]->coordinateOperationAccuracies()[0]->value(), "1.373");
6633+
6634+
// Using not available "WGS 84 to EGM2008 height (2)" with 1' EGM2008 grid
6635+
EXPECT_FALSE(list[2]->hasBallparkTransformation());
6636+
EXPECT_EQ(list[2]->nameStr(),
6637+
"Inverse of WGS 84 to EGM2008 height (2) + "
6638+
"Inverse of ETRS89-NLD [AGRS2010] to WGS 84 (1) + "
6639+
"ETRS89-NLD [AGRS2010] to NAP height (2) + "
6640+
"Inverse of Amersfoort to ETRS89-NLD [AGRS2010] (9) + RD New");
6641+
6642+
// Using not available "WGS 84 to EGM2008 height (2)" with 1' EGM2008 grid
6643+
EXPECT_FALSE(list[3]->hasBallparkTransformation());
6644+
EXPECT_EQ(list[3]->nameStr(),
6645+
"Inverse of WGS 84 to EGM2008 height (2) + "
6646+
"Inverse of ETRS89-NLD [AGRS2010] to WGS 84 (1) + "
6647+
"ETRS89-NLD [AGRS2010] to NAP height (2) + "
6648+
"Inverse of Amersfoort to ETRS89-NLD [AGRS2010] (8) + RD New");
6649+
}
6650+
6651+
// ---------------------------------------------------------------------------
6652+
65886653
TEST(
65896654
operation,
65906655
compoundCRS_to_compoundCRS_concatenated_operation_with_two_vert_transformation_and_ballpark_geog) {

0 commit comments

Comments
 (0)