diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index f429c328..fef13e41 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -585,6 +585,7 @@ struct CoordinateOperation::Private { util::optional<common::DataEpoch> sourceCoordinateEpoch_{}; util::optional<common::DataEpoch> targetCoordinateEpoch_{}; bool hasBallparkTransformation_ = false; + bool use3DHelmert_ = false; // do not set this for a ProjectedCRS.definingConversion struct CRSStrongRef { @@ -9057,16 +9058,16 @@ void Transformation::_exportToPROJString( double z = parameterValueNumericAsSI(EPSG_CODE_PARAMETER_Z_AXIS_TRANSLATION); - bool addPushPopV3 = - (methodEPSGCode == - EPSG_CODE_METHOD_COORDINATE_FRAME_GEOGRAPHIC_2D || - methodEPSGCode == - EPSG_CODE_METHOD_TIME_DEPENDENT_COORDINATE_FRAME_GEOGRAPHIC_2D || - methodEPSGCode == EPSG_CODE_METHOD_POSITION_VECTOR_GEOGRAPHIC_2D || - methodEPSGCode == - EPSG_CODE_METHOD_TIME_DEPENDENT_POSITION_VECTOR_GEOGRAPHIC_2D || - methodEPSGCode == - EPSG_CODE_METHOD_GEOCENTRIC_TRANSLATION_GEOGRAPHIC_2D); + auto sourceCRSGeog = + dynamic_cast<const crs::GeographicCRS *>(sourceCRS().get()); + auto targetCRSGeog = + dynamic_cast<const crs::GeographicCRS *>(targetCRS().get()); + const bool addPushPopV3 = + !CoordinateOperation::getPrivate()->use3DHelmert_ && + ((sourceCRSGeog && + sourceCRSGeog->coordinateSystem()->axisList().size() == 2) || + (targetCRSGeog && + targetCRSGeog->coordinateSystem()->axisList().size() == 2)); setupPROJGeodeticSourceCRS(formatter, sourceCRS(), addPushPopV3, "Helmert"); @@ -12722,6 +12723,10 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot( const auto candidatesDstGeod(findCandidateGeodCRSForDatum( authFactory, geodDst, geodDst->datum().get())); + const bool sourceAndTargetAre3D = + geodSrc->coordinateSystem()->axisList().size() == 3 && + geodDst->coordinateSystem()->axisList().size() == 3; + auto createTransformations = [&](const crs::CRSNNPtr &candidateSrcGeod, const crs::CRSNNPtr &candidateDstGeod, const CoordinateOperationNNPtr &opFirst, @@ -12749,8 +12754,9 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot( const bool isNullThird = isNullTransformation(opsThird[0]->nameStr()); CoordinateOperationNNPtr opSecondCloned( - (isNullFirst || isNullThird) ? opSecond->shallowClone() - : opSecond); + (isNullFirst || isNullThird || sourceAndTargetAre3D) + ? opSecond->shallowClone() + : opSecond); CoordinateOperation *invCOForward = nullptr; if (isNullFirst || isNullThird) { if (opSecondCloned->identifiers().size() == 1 && @@ -12778,6 +12784,15 @@ void CoordinateOperationFactory::Private::createOperationsWithDatumPivot( } } } + if (sourceAndTargetAre3D) { + opSecondCloned->getPrivate()->use3DHelmert_ = true; + auto invCO = dynamic_cast<InverseCoordinateOperation *>( + opSecondCloned.get()); + if (invCO) { + invCOForward = invCO->forwardOperation().get(); + invCOForward->getPrivate()->use3DHelmert_ = true; + } + } if (isNullFirst) { auto oldTarget(NN_CHECK_ASSERT(opSecondCloned->targetCRS())); setCRSs(opSecondCloned.get(), sourceCRS, oldTarget); |
