aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/coordinateoperation.cpp180
-rw-r--r--src/iso19111/crs.cpp15
-rw-r--r--src/iso19111/io.cpp177
3 files changed, 223 insertions, 149 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 0f5e4c4d..3ffd208f 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -2043,15 +2043,19 @@ SingleOperation::gridsNeeded(const io::DatabaseContextPtr &databaseContext,
if (opParamvalue) {
const auto &value = opParamvalue->parameterValue();
if (value->type() == ParameterValue::Type::FILENAME) {
- GridDescription desc;
- desc.shortName = value->valueFile();
- if (databaseContext) {
- databaseContext->lookForGridInfo(
- desc.shortName, considerKnownGridsAsAvailable,
- desc.fullName, desc.packageName, desc.url,
- desc.directDownload, desc.openLicense, desc.available);
+ const auto gridNames = split(value->valueFile(), ",");
+ for (const auto &gridName : gridNames) {
+ GridDescription desc;
+ desc.shortName = gridName;
+ if (databaseContext) {
+ databaseContext->lookForGridInfo(
+ desc.shortName, considerKnownGridsAsAvailable,
+ desc.fullName, desc.packageName, desc.url,
+ desc.directDownload, desc.openLicense,
+ desc.available);
+ }
+ res.insert(desc);
}
- res.insert(desc);
}
}
}
@@ -6527,7 +6531,7 @@ struct Transformation::Private {
TransformationPtr forwardOperation_{};
- TransformationNNPtr registerInv(util::BaseObjectNNPtr thisIn,
+ TransformationNNPtr registerInv(const Transformation *thisIn,
TransformationNNPtr invTransform);
};
//! @endcond
@@ -7996,12 +8000,11 @@ createApproximateInverseIfPossible(const Transformation *op) {
//! @cond Doxygen_Suppress
TransformationNNPtr
-Transformation::Private::registerInv(util::BaseObjectNNPtr thisIn,
+Transformation::Private::registerInv(const Transformation *thisIn,
TransformationNNPtr invTransform) {
- invTransform->d->forwardOperation_ =
- util::nn_dynamic_pointer_cast<Transformation>(thisIn);
+ invTransform->d->forwardOperation_ = thisIn->shallowClone().as_nullable();
invTransform->setHasBallparkTransformation(
- invTransform->d->forwardOperation_->hasBallparkTransformation());
+ thisIn->hasBallparkTransformation());
return invTransform;
}
//! @endcond
@@ -8039,12 +8042,24 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
parameterValueNumericAsSI(EPSG_CODE_PARAMETER_Y_AXIS_TRANSLATION);
double z =
parameterValueNumericAsSI(EPSG_CODE_PARAMETER_Z_AXIS_TRANSLATION);
+ auto properties = createPropertiesForInverse(this, false, false);
return d->registerInv(
- shared_from_this(),
- createGeocentricTranslations(
- createPropertiesForInverse(this, false, false), l_targetCRS,
- l_sourceCRS, negate(x), negate(y), negate(z),
- coordinateOperationAccuracies()));
+ this, create(properties, l_targetCRS, l_sourceCRS, nullptr,
+ createMethodMapNameEPSGCode(
+ useOperationMethodEPSGCodeIfPresent(
+ properties, methodEPSGCode)),
+ VectorOfParameters{
+ createOpParamNameEPSGCode(
+ EPSG_CODE_PARAMETER_X_AXIS_TRANSLATION),
+ createOpParamNameEPSGCode(
+ EPSG_CODE_PARAMETER_Y_AXIS_TRANSLATION),
+ createOpParamNameEPSGCode(
+ EPSG_CODE_PARAMETER_Z_AXIS_TRANSLATION),
+ },
+ createParams(common::Length(negate(x)),
+ common::Length(negate(y)),
+ common::Length(negate(z))),
+ coordinateOperationAccuracies()));
}
if (methodEPSGCode == EPSG_CODE_METHOD_MOLODENSKY ||
@@ -8062,14 +8077,14 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
if (methodEPSGCode == EPSG_CODE_METHOD_ABRIDGED_MOLODENSKY) {
return d->registerInv(
- shared_from_this(),
+ this,
createAbridgedMolodensky(
createPropertiesForInverse(this, false, false), l_targetCRS,
l_sourceCRS, negate(x), negate(y), negate(z), negate(da),
negate(df), coordinateOperationAccuracies()));
} else {
return d->registerInv(
- shared_from_this(),
+ this,
createMolodensky(createPropertiesForInverse(this, false, false),
l_targetCRS, l_sourceCRS, negate(x), negate(y),
negate(z), negate(da), negate(df),
@@ -8082,10 +8097,9 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
parameterValueMeasure(EPSG_CODE_PARAMETER_LONGITUDE_OFFSET);
const common::Angle newOffset(negate(offset.value()), offset.unit());
return d->registerInv(
- shared_from_this(),
- createLongitudeRotation(
- createPropertiesForInverse(this, false, false), l_targetCRS,
- l_sourceCRS, newOffset));
+ this, createLongitudeRotation(
+ createPropertiesForInverse(this, false, false),
+ l_targetCRS, l_sourceCRS, newOffset));
}
if (methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC2D_OFFSETS) {
@@ -8100,11 +8114,10 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
offsetLong.unit());
return d->registerInv(
- shared_from_this(),
- createGeographic2DOffsets(
- createPropertiesForInverse(this, false, false), l_targetCRS,
- l_sourceCRS, newOffsetLat, newOffsetLong,
- coordinateOperationAccuracies()));
+ this, createGeographic2DOffsets(
+ createPropertiesForInverse(this, false, false),
+ l_targetCRS, l_sourceCRS, newOffsetLat, newOffsetLong,
+ coordinateOperationAccuracies()));
}
if (methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC3D_OFFSETS) {
@@ -8124,11 +8137,10 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
offsetHeight.unit());
return d->registerInv(
- shared_from_this(),
- createGeographic3DOffsets(
- createPropertiesForInverse(this, false, false), l_targetCRS,
- l_sourceCRS, newOffsetLat, newOffsetLong, newOffsetHeight,
- coordinateOperationAccuracies()));
+ this, createGeographic3DOffsets(
+ createPropertiesForInverse(this, false, false),
+ l_targetCRS, l_sourceCRS, newOffsetLat, newOffsetLong,
+ newOffsetHeight, coordinateOperationAccuracies()));
}
if (methodEPSGCode == EPSG_CODE_METHOD_GEOGRAPHIC2D_WITH_HEIGHT_OFFSETS) {
@@ -8148,11 +8160,10 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
offsetHeight.unit());
return d->registerInv(
- shared_from_this(),
- createGeographic2DWithHeightOffsets(
- createPropertiesForInverse(this, false, false), l_targetCRS,
- l_sourceCRS, newOffsetLat, newOffsetLong, newOffsetHeight,
- coordinateOperationAccuracies()));
+ this, createGeographic2DWithHeightOffsets(
+ createPropertiesForInverse(this, false, false),
+ l_targetCRS, l_sourceCRS, newOffsetLat, newOffsetLong,
+ newOffsetHeight, coordinateOperationAccuracies()));
}
if (methodEPSGCode == EPSG_CODE_METHOD_VERTICAL_OFFSET) {
@@ -8163,7 +8174,7 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
offsetHeight.unit());
return d->registerInv(
- shared_from_this(),
+ this,
createVerticalOffset(createPropertiesForInverse(this, false, false),
l_targetCRS, l_sourceCRS, newOffsetHeight,
coordinateOperationAccuracies()));
@@ -8173,18 +8184,17 @@ TransformationNNPtr Transformation::inverseAsTransformation() const {
const double convFactor = parameterValueNumericAsSI(
EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR);
return d->registerInv(
- shared_from_this(),
- createChangeVerticalUnit(
- createPropertiesForInverse(this, false, false), l_targetCRS,
- l_sourceCRS, common::Scale(1.0 / convFactor),
- coordinateOperationAccuracies()));
+ this, createChangeVerticalUnit(
+ createPropertiesForInverse(this, false, false),
+ l_targetCRS, l_sourceCRS, common::Scale(1.0 / convFactor),
+ coordinateOperationAccuracies()));
}
#ifdef notdef
// We don't need that currently, but we might...
if (methodEPSGCode == EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) {
return d->registerInv(
- shared_from_this(),
+ this,
createHeightDepthReversal(
createPropertiesForInverse(this, false, false), l_targetCRS,
l_sourceCRS, coordinateOperationAccuracies()));
@@ -8989,20 +8999,41 @@ static void ThrowExceptionNotGeodeticGeographic(const char *trfrm_name) {
// ---------------------------------------------------------------------------
-static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
- const crs::CRSNNPtr &crs, bool addPushV3,
- const char *trfrm_name) {
- auto sourceCRSGeog = dynamic_cast<const crs::GeographicCRS *>(crs.get());
- if (!sourceCRSGeog) {
- auto compoundCRS = dynamic_cast<const crs::CompoundCRS *>(crs.get());
+// If crs is a geographic CRS, or a compound CRS of a geographic CRS,
+// or a compoundCRS of a bound CRS of a geographic CRS, return that
+// geographic CRS
+static crs::GeographicCRSPtr
+extractGeographicCRSIfGeographicCRSOrEquivalent(const crs::CRSNNPtr &crs) {
+ auto geogCRS = util::nn_dynamic_pointer_cast<crs::GeographicCRS>(crs);
+ if (!geogCRS) {
+ auto compoundCRS = util::nn_dynamic_pointer_cast<crs::CompoundCRS>(crs);
if (compoundCRS) {
const auto &components = compoundCRS->componentReferenceSystems();
if (!components.empty()) {
- sourceCRSGeog = dynamic_cast<const crs::GeographicCRS *>(
- components[0].get());
+ geogCRS = util::nn_dynamic_pointer_cast<crs::GeographicCRS>(
+ components[0]);
+ if (!geogCRS) {
+ auto boundCRS =
+ util::nn_dynamic_pointer_cast<crs::BoundCRS>(
+ components[0]);
+ if (boundCRS) {
+ geogCRS =
+ util::nn_dynamic_pointer_cast<crs::GeographicCRS>(
+ boundCRS->baseCRS());
+ }
+ }
}
}
}
+ return geogCRS;
+}
+
+// ---------------------------------------------------------------------------
+
+static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
+ const crs::CRSNNPtr &crs, bool addPushV3,
+ const char *trfrm_name) {
+ auto sourceCRSGeog = extractGeographicCRSIfGeographicCRSOrEquivalent(crs);
if (sourceCRSGeog) {
formatter->startInversion();
sourceCRSGeog->_exportToPROJString(formatter);
@@ -9030,17 +9061,7 @@ static void setupPROJGeodeticSourceCRS(io::PROJStringFormatter *formatter,
static void setupPROJGeodeticTargetCRS(io::PROJStringFormatter *formatter,
const crs::CRSNNPtr &crs, bool addPopV3,
const char *trfrm_name) {
- auto targetCRSGeog = dynamic_cast<const crs::GeographicCRS *>(crs.get());
- if (!targetCRSGeog) {
- auto compoundCRS = dynamic_cast<const crs::CompoundCRS *>(crs.get());
- if (compoundCRS) {
- const auto &components = compoundCRS->componentReferenceSystems();
- if (!components.empty()) {
- targetCRSGeog = dynamic_cast<const crs::GeographicCRS *>(
- components[0].get());
- }
- }
- }
+ auto targetCRSGeog = extractGeographicCRSIfGeographicCRSOrEquivalent(crs);
if (targetCRSGeog) {
formatter->addStep("cart");
formatter->setCurrentStepInverted(true);
@@ -9540,14 +9561,14 @@ void Transformation::_exportToPROJString(
: CTABLE2Filename;
if (!hGridShiftFilename.empty()) {
auto sourceCRSGeog =
- dynamic_cast<const crs::GeographicCRS *>(sourceCRS().get());
+ extractGeographicCRSIfGeographicCRSOrEquivalent(sourceCRS());
if (!sourceCRSGeog) {
throw io::FormattingException(
concat("Can apply ", methodName, " only to GeographicCRS"));
}
auto targetCRSGeog =
- dynamic_cast<const crs::GeographicCRS *>(targetCRS().get());
+ extractGeographicCRSIfGeographicCRSOrEquivalent(targetCRS());
if (!targetCRSGeog) {
throw io::FormattingException(
concat("Can apply ", methodName, " only to GeographicCRS"));
@@ -13191,7 +13212,7 @@ CoordinateOperationFactory::Private::createOperations(
return applyInverse(createOperations(targetCRS, sourceCRS, context));
}
- // boundCRS to boundCRS using the same geographic hubCRS
+ // boundCRS to boundCRS
if (boundSrc && boundDst) {
createOperationsBoundToBound(sourceCRS, targetCRS, context, boundSrc,
boundDst, res);
@@ -14327,6 +14348,7 @@ void CoordinateOperationFactory::Private::createOperationsBoundToBound(
ENTER_FUNCTION();
+ // BoundCRS to BoundCRS of horizontal CRS using the same (geographic) hub
const auto &hubSrc = boundSrc->hubCRS();
auto hubSrcGeog = dynamic_cast<const crs::GeographicCRS *>(hubSrc.get());
const auto &hubDst = boundDst->hubCRS();
@@ -14375,6 +14397,28 @@ void CoordinateOperationFactory::Private::createOperationsBoundToBound(
}
}
+ // BoundCRS to BoundCRS of vertical CRS using the same vertical datum
+ // ==> ignore the bound transformation
+ auto baseOfBoundSrcAsVertCRS =
+ dynamic_cast<crs::VerticalCRS *>(boundSrc->baseCRS().get());
+ auto baseOfBoundDstAsVertCRS =
+ dynamic_cast<crs::VerticalCRS *>(boundDst->baseCRS().get());
+ if (baseOfBoundSrcAsVertCRS && baseOfBoundDstAsVertCRS) {
+ const auto datumSrc = baseOfBoundSrcAsVertCRS->datum();
+ const auto datumDst = baseOfBoundDstAsVertCRS->datum();
+ if (datumSrc && datumDst &&
+ datumSrc->nameStr() == datumDst->nameStr() &&
+ (datumSrc->nameStr() != "unknown" ||
+ boundSrc->transformation()->_isEquivalentTo(
+ boundDst->transformation().get(),
+ util::IComparable::Criterion::EQUIVALENT))) {
+ res = createOperations(boundSrc->baseCRS(), boundDst->baseCRS(),
+ context);
+ return;
+ }
+ }
+
+ // BoundCRS to BoundCRS of vertical CRS
auto vertCRSOfBaseOfBoundSrc = boundSrc->baseCRS()->extractVerticalCRS();
auto vertCRSOfBaseOfBoundDst = boundDst->baseCRS()->extractVerticalCRS();
if (hubSrcGeog && hubDstGeog &&
diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp
index c23bd29b..ec342a8f 100644
--- a/src/iso19111/crs.cpp
+++ b/src/iso19111/crs.cpp
@@ -4620,18 +4620,9 @@ BoundCRS::create(const CRSNNPtr &baseCRSIn, const CRSNNPtr &hubCRSIn,
BoundCRSNNPtr
BoundCRS::createFromTOWGS84(const CRSNNPtr &baseCRSIn,
const std::vector<double> &TOWGS84Parameters) {
-
- auto geodCRS = baseCRSIn->extractGeodeticCRS();
- auto targetCRS =
- geodCRS.get() == nullptr ||
- dynamic_cast<const crs::GeographicCRS *>(geodCRS.get())
- ? util::nn_static_pointer_cast<crs::CRS>(
- crs::GeographicCRS::EPSG_4326)
- : util::nn_static_pointer_cast<crs::CRS>(
- crs::GeodeticCRS::EPSG_4978);
- return create(
- baseCRSIn, targetCRS,
- operation::Transformation::createTOWGS84(baseCRSIn, TOWGS84Parameters));
+ auto transf =
+ operation::Transformation::createTOWGS84(baseCRSIn, TOWGS84Parameters);
+ return create(baseCRSIn, transf->targetCRS(), transf);
}
// ---------------------------------------------------------------------------
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 97f741be..9d9fa4a3 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -3987,6 +3987,79 @@ WKTParser::Private::buildParametricDatum(const WKTNodeNNPtr &node) {
// ---------------------------------------------------------------------------
+static CRSNNPtr
+createBoundCRSSourceTransformationCRS(const crs::CRSPtr &sourceCRS,
+ const crs::CRSPtr &targetCRS) {
+ CRSPtr sourceTransformationCRS;
+ if (dynamic_cast<GeographicCRS *>(targetCRS.get())) {
+ GeographicCRSPtr sourceGeographicCRS =
+ sourceCRS->extractGeographicCRS();
+ sourceTransformationCRS = sourceGeographicCRS;
+ if (sourceGeographicCRS) {
+ if (sourceGeographicCRS->datum() != nullptr &&
+ sourceGeographicCRS->primeMeridian()
+ ->longitude()
+ .getSIValue() != 0.0) {
+ sourceTransformationCRS =
+ GeographicCRS::create(
+ util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ sourceGeographicCRS->nameStr() +
+ " (with Greenwich prime meridian)"),
+ datum::GeodeticReferenceFrame::create(
+ util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ sourceGeographicCRS->datum()->nameStr() +
+ " (with Greenwich prime meridian)"),
+ sourceGeographicCRS->datum()->ellipsoid(),
+ util::optional<std::string>(),
+ datum::PrimeMeridian::GREENWICH),
+ sourceGeographicCRS->coordinateSystem())
+ .as_nullable();
+ }
+ } else {
+ auto vertSourceCRS =
+ std::dynamic_pointer_cast<VerticalCRS>(sourceCRS);
+ if (!vertSourceCRS) {
+ throw ParsingException(
+ "Cannot find GeographicCRS or VerticalCRS in sourceCRS");
+ }
+ const auto &axis = vertSourceCRS->coordinateSystem()->axisList()[0];
+ if (axis->unit() == common::UnitOfMeasure::METRE &&
+ &(axis->direction()) == &AxisDirection::UP) {
+ sourceTransformationCRS = sourceCRS;
+ } else {
+ std::string sourceTransformationCRSName(
+ vertSourceCRS->nameStr());
+ if (ends_with(sourceTransformationCRSName, " (ftUS)")) {
+ sourceTransformationCRSName.resize(
+ sourceTransformationCRSName.size() - strlen(" (ftUS)"));
+ }
+ if (ends_with(sourceTransformationCRSName, " depth")) {
+ sourceTransformationCRSName.resize(
+ sourceTransformationCRSName.size() - strlen(" depth"));
+ }
+ if (!ends_with(sourceTransformationCRSName, " height")) {
+ sourceTransformationCRSName += " height";
+ }
+ sourceTransformationCRS =
+ VerticalCRS::create(
+ PropertyMap().set(IdentifiedObject::NAME_KEY,
+ sourceTransformationCRSName),
+ vertSourceCRS->datum(), vertSourceCRS->datumEnsemble(),
+ VerticalCS::createGravityRelatedHeight(
+ common::UnitOfMeasure::METRE))
+ .as_nullable();
+ }
+ }
+ } else {
+ sourceTransformationCRS = sourceCRS;
+ }
+ return NN_NO_CHECK(sourceTransformationCRS);
+}
+
+// ---------------------------------------------------------------------------
+
CRSNNPtr WKTParser::Private::buildVerticalCRS(const WKTNodeNNPtr &node) {
const auto *nodeP = node->GP();
auto &datumNode =
@@ -4111,16 +4184,18 @@ CRSNNPtr WKTParser::Private::buildVerticalCRS(const WKTNodeNNPtr &node) {
gridName != "g2012a_conus.gtx,g2012a_alaska.gtx,"
"g2012a_guam.gtx,g2012a_hawaii.gtx,"
"g2012a_puertorico.gtx,g2012a_samoa.gtx") {
- std::string transformationName(crs->nameStr());
- if (!ends_with(transformationName, " height")) {
- transformationName += " height";
- }
- transformationName += " to WGS84 ellipsoidal height";
+ auto sourceTransformationCRS =
+ createBoundCRSSourceTransformationCRS(
+ crs.as_nullable(),
+ GeographicCRS::EPSG_4979.as_nullable());
auto transformation = Transformation::
createGravityRelatedHeightToGeographic3D(
- PropertyMap().set(IdentifiedObject::NAME_KEY,
- transformationName),
- crs, GeographicCRS::EPSG_4979, nullptr, gridName,
+ PropertyMap().set(
+ IdentifiedObject::NAME_KEY,
+ sourceTransformationCRS->nameStr() +
+ " to WGS84 ellipsoidal height"),
+ sourceTransformationCRS, GeographicCRS::EPSG_4979,
+ nullptr, gridName,
std::vector<PositionalAccuracyNNPtr>());
return nn_static_pointer_cast<CRS>(BoundCRS::create(
crs, GeographicCRS::EPSG_4979, transformation));
@@ -4190,52 +4265,6 @@ CRSNNPtr WKTParser::Private::buildCompoundCRS(const WKTNodeNNPtr &node) {
// ---------------------------------------------------------------------------
-static CRSNNPtr
-createBoundCRSSourceTransformationCRS(const crs::CRSPtr &sourceCRS,
- const crs::CRSPtr &targetCRS) {
- CRSPtr sourceTransformationCRS;
- if (dynamic_cast<GeographicCRS *>(targetCRS.get())) {
- GeographicCRSPtr sourceGeographicCRS =
- sourceCRS->extractGeographicCRS();
- sourceTransformationCRS = sourceGeographicCRS;
- if (sourceGeographicCRS) {
- if (sourceGeographicCRS->datum() != nullptr &&
- sourceGeographicCRS->primeMeridian()
- ->longitude()
- .getSIValue() != 0.0) {
- sourceTransformationCRS =
- GeographicCRS::create(
- util::PropertyMap().set(
- common::IdentifiedObject::NAME_KEY,
- sourceGeographicCRS->nameStr() +
- " (with Greenwich prime meridian)"),
- datum::GeodeticReferenceFrame::create(
- util::PropertyMap().set(
- common::IdentifiedObject::NAME_KEY,
- sourceGeographicCRS->datum()->nameStr() +
- " (with Greenwich prime meridian)"),
- sourceGeographicCRS->datum()->ellipsoid(),
- util::optional<std::string>(),
- datum::PrimeMeridian::GREENWICH),
- sourceGeographicCRS->coordinateSystem())
- .as_nullable();
- }
- } else {
- sourceTransformationCRS =
- std::dynamic_pointer_cast<VerticalCRS>(sourceCRS);
- if (!sourceTransformationCRS) {
- throw ParsingException(
- "Cannot find GeographicCRS or VerticalCRS in sourceCRS");
- }
- }
- } else {
- sourceTransformationCRS = sourceCRS;
- }
- return NN_NO_CHECK(sourceTransformationCRS);
-}
-
-// ---------------------------------------------------------------------------
-
BoundCRSNNPtr WKTParser::Private::buildBoundCRS(const WKTNodeNNPtr &node) {
const auto *nodeP = node->GP();
auto &abridgedNode =
@@ -4515,12 +4544,27 @@ CRSPtr WKTParser::Private::buildCRS(const WKTNodeNNPtr &node) {
const auto *nodeP = node->GP();
const std::string &name(nodeP->value());
+ const auto applyHorizontalBoundCRSParams = [&](const CRSNNPtr &crs) {
+ if (!toWGS84Parameters_.empty()) {
+ auto ret = BoundCRS::createFromTOWGS84(crs, toWGS84Parameters_);
+ toWGS84Parameters_.clear();
+ return util::nn_static_pointer_cast<CRS>(ret);
+ } else if (!datumPROJ4Grids_.empty()) {
+ auto ret = BoundCRS::createFromNadgrids(crs, datumPROJ4Grids_);
+ datumPROJ4Grids_.clear();
+ return util::nn_static_pointer_cast<CRS>(ret);
+ }
+ return crs;
+ };
+
if (isGeodeticCRS(name)) {
if (!isNull(nodeP->lookForChild(WKTConstants::BASEGEOGCRS,
WKTConstants::BASEGEODCRS))) {
- return buildDerivedGeodeticCRS(node);
+ return util::nn_static_pointer_cast<CRS>(
+ applyHorizontalBoundCRSParams(buildDerivedGeodeticCRS(node)));
} else {
- return util::nn_static_pointer_cast<CRS>(buildGeodeticCRS(node));
+ return util::nn_static_pointer_cast<CRS>(
+ applyHorizontalBoundCRSParams(buildGeodeticCRS(node)));
}
}
@@ -4545,12 +4589,14 @@ CRSPtr WKTParser::Private::buildCRS(const WKTNodeNNPtr &node) {
PROJStringParser().createFromPROJString(projString);
auto crs = nn_dynamic_pointer_cast<CRS>(projObj);
if (crs) {
- return crs;
+ return util::nn_static_pointer_cast<CRS>(
+ applyHorizontalBoundCRSParams(NN_NO_CHECK(crs)));
}
} catch (const io::ParsingException &) {
}
}
- return util::nn_static_pointer_cast<CRS>(buildProjectedCRS(node));
+ return util::nn_static_pointer_cast<CRS>(
+ applyHorizontalBoundCRSParams(buildProjectedCRS(node)));
}
if (ci_equal(name, WKTConstants::VERT_CS) ||
@@ -4623,16 +4669,6 @@ BaseObjectNNPtr WKTParser::Private::build(const WKTNodeNNPtr &node) {
auto crs = buildCRS(node);
if (crs) {
- if (!toWGS84Parameters_.empty()) {
- return util::nn_static_pointer_cast<BaseObject>(
- BoundCRS::createFromTOWGS84(NN_NO_CHECK(crs),
- toWGS84Parameters_));
- }
- if (!datumPROJ4Grids_.empty()) {
- return util::nn_static_pointer_cast<BaseObject>(
- BoundCRS::createFromNadgrids(NN_NO_CHECK(crs),
- datumPROJ4Grids_));
- }
return util::nn_static_pointer_cast<BaseObject>(NN_NO_CHECK(crs));
}
@@ -7594,7 +7630,10 @@ std::set<std::string> PROJStringFormatter::getUsedGridNames() const {
for (const auto &step : d->steps_) {
for (const auto &param : step.paramValues) {
if (param.keyEquals("grids")) {
- res.insert(param.value);
+ const auto gridNames = split(param.value, ",");
+ for (const auto &gridName : gridNames) {
+ res.insert(gridName);
+ }
}
}
}