aboutsummaryrefslogtreecommitdiff
path: root/src/iso19111
diff options
context:
space:
mode:
Diffstat (limited to 'src/iso19111')
-rw-r--r--src/iso19111/factory.cpp2
-rw-r--r--src/iso19111/operation/concatenatedoperation.cpp32
-rw-r--r--src/iso19111/operation/conversion.cpp66
-rw-r--r--src/iso19111/operation/coordinateoperationfactory.cpp15
-rw-r--r--src/iso19111/operation/parammappings.cpp6
-rw-r--r--src/iso19111/operation/singleoperation.cpp44
6 files changed, 140 insertions, 25 deletions
diff --git a/src/iso19111/factory.cpp b/src/iso19111/factory.cpp
index 5a81506b..7b83484d 100644
--- a/src/iso19111/factory.cpp
+++ b/src/iso19111/factory.cpp
@@ -5613,6 +5613,8 @@ operation::CoordinateOperationNNPtr AuthorityFactory::createCoordinateOperation(
int method_code_int = std::atoi(method_code.c_str());
if (operation::isAxisOrderReversal(method_code_int) ||
method_code_int == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT ||
+ method_code_int ==
+ EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR ||
method_code_int == EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) {
auto op = operation::Conversion::create(props, propsMethod,
parameters, values);
diff --git a/src/iso19111/operation/concatenatedoperation.cpp b/src/iso19111/operation/concatenatedoperation.cpp
index a1c0dca8..ad2ab65b 100644
--- a/src/iso19111/operation/concatenatedoperation.cpp
+++ b/src/iso19111/operation/concatenatedoperation.cpp
@@ -48,6 +48,7 @@
#include "proj.h"
#include "proj_internal.h" // M_PI
// clang-format on
+#include "proj_constants.h"
#include "proj_json_streaming_writer.hpp"
@@ -341,6 +342,37 @@ void ConcatenatedOperation::fixStepsDirection(
if (l_sourceCRS && l_targetCRS) {
op->setCRSs(NN_NO_CHECK(l_sourceCRS), NN_NO_CHECK(l_targetCRS),
nullptr);
+ } else if (l_sourceCRS && l_targetCRS == nullptr &&
+ conv->method()->getEPSGCode() ==
+ EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL) {
+ // Needed for EPSG:7987 e.g.
+ auto vertCRS =
+ dynamic_cast<const crs::VerticalCRS *>(l_sourceCRS.get());
+ if (vertCRS && ends_with(l_sourceCRS->nameStr(), " height") &&
+ &vertCRS->coordinateSystem()->axisList()[0]->direction() ==
+ &cs::AxisDirection::UP) {
+ op->setCRSs(
+ NN_NO_CHECK(l_sourceCRS),
+ crs::VerticalCRS::create(
+ util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ l_sourceCRS->nameStr().substr(
+ 0, l_sourceCRS->nameStr().size() -
+ strlen(" height")) +
+ " depth"),
+ vertCRS->datum(), vertCRS->datumEnsemble(),
+ cs::VerticalCS::create(
+ util::PropertyMap(),
+ cs::CoordinateSystemAxis::create(
+ util::PropertyMap().set(
+ common::IdentifiedObject::NAME_KEY,
+ "Gravity-related depth"),
+ "D", cs::AxisDirection::DOWN,
+ vertCRS->coordinateSystem()
+ ->axisList()[0]
+ ->unit()))),
+ nullptr);
+ }
}
} else if (!conv && l_sourceCRS && l_targetCRS) {
diff --git a/src/iso19111/operation/conversion.cpp b/src/iso19111/operation/conversion.cpp
index e9d688b7..e2e77562 100644
--- a/src/iso19111/operation/conversion.cpp
+++ b/src/iso19111/operation/conversion.cpp
@@ -2252,6 +2252,26 @@ Conversion::createChangeVerticalUnit(const util::PropertyMap &properties,
// ---------------------------------------------------------------------------
+/** \brief Instantiate a conversion based on the Change of Vertical Unit
+ * method (without explicit conversion factor)
+ *
+ * This method is defined as [EPSG:1104]
+ * (https://www.epsg-registry.org/export.htm?gml=urn:ogc:def:method:EPSG::1104)
+ *
+ * @param properties See \ref general_properties of the conversion. If the name
+ * is not provided, it is automatically set.
+ * @return a new Conversion.
+ */
+ConversionNNPtr
+Conversion::createChangeVerticalUnit(const util::PropertyMap &properties) {
+ return create(properties,
+ createMethodMapNameEPSGCode(
+ EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR),
+ VectorOfParameters{}, VectorOfValues{});
+}
+
+// ---------------------------------------------------------------------------
+
/** \brief Instantiate a conversion based on the Height Depth Reversal
* method.
*
@@ -2409,6 +2429,14 @@ CoordinateOperationNNPtr Conversion::inverse() const {
return conv;
}
+ if (methodEPSGCode ==
+ EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR) {
+ auto conv = createChangeVerticalUnit(
+ createPropertiesForInverse(this, false, false));
+ conv->setCRSs(this, true);
+ return conv;
+ }
+
const bool l_isAxisOrderReversal2D = isAxisOrderReversal2D(methodEPSGCode);
const bool l_isAxisOrderReversal3D = isAxisOrderReversal3D(methodEPSGCode);
if (l_isAxisOrderReversal2D || l_isAxisOrderReversal3D) {
@@ -3345,7 +3373,8 @@ void Conversion::_exportToPROJString(
const auto &methodName = l_method->nameStr();
const int methodEPSGCode = l_method->getEPSGCode();
const bool isZUnitConversion =
- methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT;
+ methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT ||
+ methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR;
const bool isAffineParametric =
methodEPSGCode == EPSG_CODE_METHOD_AFFINE_PARAMETRIC_TRANSFORMATION;
const bool isGeographicGeocentric =
@@ -3368,6 +3397,8 @@ void Conversion::_exportToPROJString(
}
auto l_sourceCRS = sourceCRS();
+ auto l_targetCRS = targetCRS();
+
crs::GeographicCRSPtr srcGeogCRS;
if (!formatter->getCRSExport() && l_sourceCRS && applySourceCRSModifiers) {
@@ -3633,8 +3664,35 @@ void Conversion::_exportToPROJString(
} else if (formatter->convention() ==
io::PROJStringFormatter::Convention::PROJ_5 &&
isZUnitConversion) {
- double convFactor = parameterValueNumericAsSI(
- EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR);
+ double convFactor;
+ if (methodEPSGCode == EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT) {
+ convFactor = parameterValueNumericAsSI(
+ EPSG_CODE_PARAMETER_UNIT_CONVERSION_SCALAR);
+ } else {
+ assert(methodEPSGCode ==
+ EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR);
+ const auto vertSrcCRS =
+ dynamic_cast<const crs::VerticalCRS *>(l_sourceCRS.get());
+ const auto vertTgtCRS =
+ dynamic_cast<const crs::VerticalCRS *>(l_targetCRS.get());
+ if (vertSrcCRS && vertTgtCRS) {
+ const double convSrc = vertSrcCRS->coordinateSystem()
+ ->axisList()[0]
+ ->unit()
+ .conversionToSI();
+ const double convDst = vertTgtCRS->coordinateSystem()
+ ->axisList()[0]
+ ->unit()
+ .conversionToSI();
+ convFactor = convSrc / convDst;
+ } else {
+ throw io::FormattingException(
+ "Export of "
+ "EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR "
+ "conversion to a PROJ string "
+ "requires an input and output vertical CRS");
+ }
+ }
auto uom = common::UnitOfMeasure(std::string(), convFactor,
common::UnitOfMeasure::Type::LINEAR)
.exportToPROJString();
@@ -3686,8 +3744,6 @@ void Conversion::_exportToPROJString(
bConversionDone = true;
}
- auto l_targetCRS = targetCRS();
-
bool bAxisSpecFound = false;
if (!bConversionDone) {
const MethodMapping *mapping = getMapping(l_method.get());
diff --git a/src/iso19111/operation/coordinateoperationfactory.cpp b/src/iso19111/operation/coordinateoperationfactory.cpp
index eb560cc9..13d245bb 100644
--- a/src/iso19111/operation/coordinateoperationfactory.cpp
+++ b/src/iso19111/operation/coordinateoperationfactory.cpp
@@ -2097,6 +2097,17 @@ static std::string buildTransfName(const std::string &srcName,
// ---------------------------------------------------------------------------
+static std::string buildConvName(const std::string &srcName,
+ const std::string &targetName) {
+ std::string name("Conversion from ");
+ name += srcName;
+ name += " to ";
+ name += targetName;
+ return name;
+}
+
+// ---------------------------------------------------------------------------
+
static SingleOperationNNPtr createPROJBased(
const util::PropertyMap &properties,
const io::IPROJStringExportableNNPtr &projExportable,
@@ -4273,8 +4284,8 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert(
((srcIsUp && dstIsDown) || (srcIsDown && dstIsUp));
const double factor = convSrc / convDst;
- auto name = buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr());
if (!equivalentVDatum) {
+ auto name = buildTransfName(sourceCRS->nameStr(), targetCRS->nameStr());
name += BALLPARK_VERTICAL_TRANSFORMATION;
auto conv = Transformation::createChangeVerticalUnit(
util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, name),
@@ -4285,6 +4296,7 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert(
conv->setHasBallparkTransformation(true);
res.push_back(conv);
} else if (convSrc != convDst || !heightDepthReversal) {
+ auto name = buildConvName(sourceCRS->nameStr(), targetCRS->nameStr());
auto conv = Conversion::createChangeVerticalUnit(
util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, name),
// In case of a height depth reversal, we should probably have
@@ -4293,6 +4305,7 @@ void CoordinateOperationFactory::Private::createOperationsVertToVert(
conv->setCRSs(sourceCRS, targetCRS, nullptr);
res.push_back(conv);
} else {
+ auto name = buildConvName(sourceCRS->nameStr(), targetCRS->nameStr());
auto conv = Conversion::createHeightDepthReversal(
util::PropertyMap().set(common::IdentifiedObject::NAME_KEY, name));
conv->setCRSs(sourceCRS, targetCRS, nullptr);
diff --git a/src/iso19111/operation/parammappings.cpp b/src/iso19111/operation/parammappings.cpp
index 15ecb24f..5999d535 100644
--- a/src/iso19111/operation/parammappings.cpp
+++ b/src/iso19111/operation/parammappings.cpp
@@ -924,6 +924,7 @@ const struct MethodNameCode methodNameCodes[] = {
METHOD_NAME_CODE(COLOMBIA_URBAN),
// Other conversions
METHOD_NAME_CODE(CHANGE_VERTICAL_UNIT),
+ METHOD_NAME_CODE(CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR),
METHOD_NAME_CODE(HEIGHT_DEPTH_REVERSAL),
METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_2D),
METHOD_NAME_CODE(AXIS_ORDER_REVERSAL_3D),
@@ -1308,9 +1309,12 @@ static const MethodMapping otherMethodMappings[] = {
{EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT,
EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT, nullptr, nullptr, nullptr,
paramsChangeVerticalUnit},
+ {EPSG_NAME_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR,
+ EPSG_CODE_METHOD_CHANGE_VERTICAL_UNIT_NO_CONV_FACTOR, nullptr, nullptr,
+ nullptr, nullptr},
{EPSG_NAME_METHOD_HEIGHT_DEPTH_REVERSAL,
EPSG_CODE_METHOD_HEIGHT_DEPTH_REVERSAL, nullptr, nullptr, nullptr,
- paramsChangeVerticalUnit},
+ nullptr},
{EPSG_NAME_METHOD_AXIS_ORDER_REVERSAL_2D,
EPSG_CODE_METHOD_AXIS_ORDER_REVERSAL_2D, nullptr, nullptr, nullptr,
nullptr},
diff --git a/src/iso19111/operation/singleoperation.cpp b/src/iso19111/operation/singleoperation.cpp
index 6812819c..2f60828e 100644
--- a/src/iso19111/operation/singleoperation.cpp
+++ b/src/iso19111/operation/singleoperation.cpp
@@ -1525,31 +1525,39 @@ std::list<std::string> SingleOperation::validateParameters() const {
const auto &l_method = method();
const auto &methodName = l_method->nameStr();
- const MethodMapping *methodMapping = nullptr;
const auto methodEPSGCode = l_method->getEPSGCode();
+
+ const auto findMapping = [methodEPSGCode, &methodName](
+ const MethodMapping *mappings,
+ size_t mappingCount) -> const MethodMapping * {
+ if (methodEPSGCode != 0) {
+ for (size_t i = 0; i < mappingCount; ++i) {
+ const auto &mapping = mappings[i];
+ if (methodEPSGCode == mapping.epsg_code) {
+ return &mapping;
+ }
+ }
+ }
+ for (size_t i = 0; i < mappingCount; ++i) {
+ const auto &mapping = mappings[i];
+ if (metadata::Identifier::isEquivalentName(mapping.wkt2_name,
+ methodName.c_str())) {
+ return &mapping;
+ }
+ }
+ return nullptr;
+ };
+
size_t nProjectionMethodMappings = 0;
const auto projectionMethodMappings =
getProjectionMethodMappings(nProjectionMethodMappings);
- for (size_t i = 0; i < nProjectionMethodMappings; ++i) {
- const auto &mapping = projectionMethodMappings[i];
- if (metadata::Identifier::isEquivalentName(mapping.wkt2_name,
- methodName.c_str()) ||
- (methodEPSGCode != 0 && methodEPSGCode == mapping.epsg_code)) {
- methodMapping = &mapping;
- }
- }
+ const MethodMapping *methodMapping =
+ findMapping(projectionMethodMappings, nProjectionMethodMappings);
if (methodMapping == nullptr) {
size_t nOtherMethodMappings = 0;
const auto otherMethodMappings =
getOtherMethodMappings(nOtherMethodMappings);
- for (size_t i = 0; i < nOtherMethodMappings; ++i) {
- const auto &mapping = otherMethodMappings[i];
- if (metadata::Identifier::isEquivalentName(mapping.wkt2_name,
- methodName.c_str()) ||
- (methodEPSGCode != 0 && methodEPSGCode == mapping.epsg_code)) {
- methodMapping = &mapping;
- }
- }
+ methodMapping = findMapping(otherMethodMappings, nOtherMethodMappings);
}
if (!methodMapping) {
res.emplace_back("Unknown method " + methodName);
@@ -1661,7 +1669,7 @@ std::list<std::string> SingleOperation::validateParameters() const {
}
return res;
-}
+} // namespace operation
// ---------------------------------------------------------------------------