Skip to content

Commit e5e3a6b

Browse files
authored
Merge pull request #4341 from rouault/GDA94_AHD_to_GDA2020_AVWS
createOperations(): fine tune for 'GDA94 + AHD height' to 'GDA2020 to AVWS height'
2 parents 067fe73 + 2f38bbb commit e5e3a6b

File tree

2 files changed

+61
-17
lines changed

2 files changed

+61
-17
lines changed

src/iso19111/operation/coordinateoperationfactory.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6467,17 +6467,23 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
64676467
if (srcGeog == nullptr || dstGeog == nullptr) {
64686468
return;
64696469
}
6470-
6471-
// Use PointMotionOperations if appropriate and available
6470+
const bool srcGeogIsSameAsDstGeog = srcGeog->_isEquivalentTo(
6471+
dstGeog.get(), util::IComparable::Criterion::EQUIVALENT);
64726472
const auto &authFactory = context.context->getAuthorityFactory();
64736473
auto dbContext =
64746474
authFactory ? authFactory->databaseContext().as_nullable() : nullptr;
6475+
const auto intermGeogSrc = srcGeog->promoteTo3D(std::string(), dbContext);
6476+
const auto intermGeogDst =
6477+
srcGeogIsSameAsDstGeog ? intermGeogSrc
6478+
: dstGeog->promoteTo3D(std::string(), dbContext);
6479+
const auto opsGeogSrcToGeogDst = createOperations(
6480+
intermGeogSrc, sourceEpoch, intermGeogDst, targetEpoch, context);
64756481

6482+
// Use PointMotionOperations if appropriate and available
64766483
if (authFactory && sourceEpoch.has_value() && targetEpoch.has_value() &&
64776484
!sourceEpoch->coordinateEpoch()._isEquivalentTo(
64786485
targetEpoch->coordinateEpoch()) &&
6479-
srcGeog->_isEquivalentTo(dstGeog.get(),
6480-
util::IComparable::Criterion::EQUIVALENT)) {
6486+
srcGeogIsSameAsDstGeog) {
64816487
const auto pmoSrc = authFactory->getPointMotionOperationsFor(
64826488
NN_NO_CHECK(srcGeog), true);
64836489
if (!pmoSrc.empty()) {
@@ -6603,9 +6609,20 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
66036609
// If we didn't find a non-ballpark transformation between
66046610
// the 2 vertical CRS, then try through intermediate geographic
66056611
// CRS
6612+
// Do that although when the geographic CRS of the source and
6613+
// target CRS are not the same, but only if they have a 3D
6614+
// known version, and there is a non-ballpark transformation
6615+
// between them.
6616+
// This helps for "GDA94 + AHD height" to "GDA2020 + AVWS
6617+
// height" going through GDA94 3D and GDA2020 3D
66066618
bTryThroughIntermediateGeogCRS =
66076619
(verticalTransforms.size() == 1 &&
6608-
verticalTransforms.front()->hasBallparkTransformation());
6620+
verticalTransforms.front()->hasBallparkTransformation()) ||
6621+
(!srcGeogIsSameAsDstGeog &&
6622+
!intermGeogSrc->identifiers().empty() &&
6623+
!intermGeogDst->identifiers().empty() &&
6624+
!opsGeogSrcToGeogDst.empty() &&
6625+
!opsGeogSrcToGeogDst.front()->hasBallparkTransformation());
66096626
}
66106627
}
66116628
}
@@ -6663,14 +6680,6 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
66636680
// WGS 84 + EGM96 --> ETRS89 + Belfast height where
66646681
// there is a geoid model for EGM96 referenced to WGS 84
66656682
// and a geoid model for Belfast height referenced to ETRS89
6666-
const auto intermGeogSrc =
6667-
srcGeog->promoteTo3D(std::string(), dbContext);
6668-
const bool intermGeogSrcIsSameAsIntermGeogDst =
6669-
srcGeog->_isEquivalentTo(dstGeog.get());
6670-
const auto intermGeogDst =
6671-
intermGeogSrcIsSameAsIntermGeogDst
6672-
? intermGeogSrc
6673-
: dstGeog->promoteTo3D(std::string(), dbContext);
66746683
const auto opsSrcToGeog = createOperations(
66756684
sourceCRS, sourceEpoch, intermGeogSrc, sourceEpoch, context);
66766685
const auto opsGeogToTarget = createOperations(
@@ -6710,9 +6719,6 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
67106719
double bestAccuracy = -1;
67116720
size_t bestStepCount = 0;
67126721
if (hasNonTrivialSrcTransf && hasNonTrivialTargetTransf) {
6713-
const auto opsGeogSrcToGeogDst =
6714-
createOperations(intermGeogSrc, sourceEpoch, intermGeogDst,
6715-
targetEpoch, context);
67166722
// In first pass, exclude (horizontal) ballpark operations, but
67176723
// accept them in second pass.
67186724
for (int pass = 0; pass <= 1 && res.empty(); pass++) {
@@ -6741,7 +6747,7 @@ void CoordinateOperationFactory::Private::createOperationsCompoundToCompound(
67416747
try {
67426748
res.emplace_back(
67436749
ConcatenatedOperation::createComputeMetadata(
6744-
intermGeogSrcIsSameAsIntermGeogDst
6750+
srcGeogIsSameAsDstGeog
67456751
? std::vector<
67466752
CoordinateOperationNNPtr>{op1,
67476753
op3}

test/unit/test_operationfactory.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5992,6 +5992,44 @@ TEST(operation, compoundCRS_to_compoundCRS_context_helmert) {
59925992

59935993
// ---------------------------------------------------------------------------
59945994

5995+
TEST(operation, compoundCRS_to_compoundCRS_GDA94_AHD_to_GDA2020_AVWS) {
5996+
auto dbContext = DatabaseContext::create();
5997+
auto authFactory = AuthorityFactory::create(dbContext, "EPSG");
5998+
auto ctxt = CoordinateOperationContext::create(authFactory, nullptr, 0.0);
5999+
ctxt->setGridAvailabilityUse(
6000+
CoordinateOperationContext::GridAvailabilityUse::
6001+
IGNORE_GRID_AVAILABILITY);
6002+
ctxt->setSpatialCriterion(
6003+
CoordinateOperationContext::SpatialCriterion::PARTIAL_INTERSECTION);
6004+
auto list = CoordinateOperationFactory::create()->createOperations(
6005+
// GDA94 + AHD height
6006+
authFactory->createCoordinateReferenceSystem("9464"),
6007+
// GDA2020 + AVWS height
6008+
authFactory->createCoordinateReferenceSystem("9462"), ctxt);
6009+
ASSERT_GE(list.size(), 1U);
6010+
EXPECT_EQ(list[0]->nameStr(),
6011+
"Inverse of 'GDA94 to GDA94 + AHD height (1)' + "
6012+
"GDA94 to GDA2020 (1) + "
6013+
"GDA2020 to AVWS height (2)");
6014+
EXPECT_EQ(list[0]->exportToPROJString(PROJStringFormatter::create().get()),
6015+
"+proj=pipeline "
6016+
"+step +proj=axisswap +order=2,1 "
6017+
"+step +proj=unitconvert +xy_in=deg +xy_out=rad "
6018+
"+step +proj=vgridshift +grids=au_ga_AUSGeoid09_V1.01.tif "
6019+
"+multiplier=1 "
6020+
"+step +proj=cart +ellps=GRS80 "
6021+
"+step +proj=helmert +x=0.06155 +y=-0.01087 +z=-0.04019 "
6022+
"+rx=-0.0394924 +ry=-0.0327221 +rz=-0.0328979 +s=-0.009994 "
6023+
"+convention=coordinate_frame "
6024+
"+step +inv +proj=cart +ellps=GRS80 "
6025+
"+step +inv +proj=vgridshift +grids=au_ga_AGQG_20201120.tif "
6026+
"+multiplier=1 "
6027+
"+step +proj=unitconvert +xy_in=rad +xy_out=deg "
6028+
"+step +proj=axisswap +order=2,1");
6029+
}
6030+
6031+
// ---------------------------------------------------------------------------
6032+
59956033
TEST(
59966034
operation,
59976035
compoundCRS_to_compoundCRS_concatenated_operation_with_two_vert_transformation) {

0 commit comments

Comments
 (0)