aboutsummaryrefslogtreecommitdiff
path: root/src/crs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/crs.cpp')
-rw-r--r--src/crs.cpp125
1 files changed, 109 insertions, 16 deletions
diff --git a/src/crs.cpp b/src/crs.cpp
index dab704b4..a204a037 100644
--- a/src/crs.cpp
+++ b/src/crs.cpp
@@ -87,6 +87,7 @@ namespace crs {
//! @cond Doxygen_Suppress
struct CRS::Private {
BoundCRSPtr canonicalBoundCRS_{};
+ std::string extensionProj4_{};
};
//! @endcond
@@ -745,6 +746,8 @@ GeodeticCRS::create(const util::PropertyMap &properties,
GeodeticCRS::nn_make_shared<GeodeticCRS>(datum, datumEnsemble, cs));
crs->assignSelf(crs);
crs->setProperties(properties);
+ properties.getStringValue("EXTENSION_PROJ4",
+ crs->CRS::getPrivate()->extensionProj4_);
return crs;
}
@@ -789,6 +792,8 @@ GeodeticCRS::create(const util::PropertyMap &properties,
GeodeticCRS::nn_make_shared<GeodeticCRS>(datum, datumEnsemble, cs));
crs->assignSelf(crs);
crs->setProperties(properties);
+ properties.getStringValue("EXTENSION_PROJ4",
+ crs->CRS::getPrivate()->extensionProj4_);
return crs;
}
@@ -850,6 +855,17 @@ void GeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const {
}
cs->_exportToWKT(formatter);
ObjectUsage::baseExportToWKT(formatter);
+
+ if (!isWKT2 && !formatter->useESRIDialect()) {
+ const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
+ if (!extensionProj4.empty()) {
+ formatter->startNode(io::WKTConstants::EXTENSION, false);
+ formatter->addQuotedString("PROJ4");
+ formatter->addQuotedString(extensionProj4);
+ formatter->endNode();
+ }
+ }
+
formatter->endNode();
}
//! @endcond
@@ -862,7 +878,8 @@ void GeodeticCRS::addGeocentricUnitConversionIntoPROJString(
const auto &axisList = coordinateSystem()->axisList();
const auto &unit = axisList[0]->unit();
- if (unit != common::UnitOfMeasure::METRE) {
+ if (!unit._isEquivalentTo(common::UnitOfMeasure::METRE,
+ util::IComparable::Criterion::EQUIVALENT)) {
if (formatter->convention() ==
io::PROJStringFormatter::Convention::PROJ_4) {
io::FormattingException::Throw("GeodeticCRS::exportToPROJString(): "
@@ -885,6 +902,9 @@ void GeodeticCRS::addGeocentricUnitConversionIntoPROJString(
const auto &toSI = unit.conversionToSI();
formatter->addParam("xy_out", toSI);
formatter->addParam("z_out", toSI);
+ } else if (formatter->convention() ==
+ io::PROJStringFormatter::Convention::PROJ_4) {
+ formatter->addParam("units", "m");
}
}
//! @endcond
@@ -895,6 +915,16 @@ void GeodeticCRS::addGeocentricUnitConversionIntoPROJString(
void GeodeticCRS::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(io::FormattingException)
{
+ if (formatter->convention() ==
+ io::PROJStringFormatter::Convention::PROJ_4) {
+ const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
+ if (!extensionProj4.empty()) {
+ formatter->ingestPROJString(extensionProj4);
+ formatter->addNoDefs(false);
+ return;
+ }
+ }
+
if (!isGeocentric()) {
io::FormattingException::Throw(
"GeodeticCRS::exportToPROJString() only "
@@ -907,14 +937,7 @@ void GeodeticCRS::_exportToPROJString(
} else {
formatter->addStep("cart");
}
- ellipsoid()->_exportToPROJString(formatter);
- if (formatter->convention() ==
- io::PROJStringFormatter::Convention::PROJ_4) {
- const auto &TOWGS84Params = formatter->getTOWGS84Parameters();
- if (TOWGS84Params.size() == 7) {
- formatter->addParam("towgs84", TOWGS84Params);
- }
- }
+ addDatumInfoToPROJString(formatter);
addGeocentricUnitConversionIntoPROJString(formatter);
}
//! @endcond
@@ -1421,6 +1444,8 @@ GeographicCRS::create(const util::PropertyMap &properties,
GeographicCRS::nn_make_shared<GeographicCRS>(datum, datumEnsemble, cs));
crs->assignSelf(crs);
crs->setProperties(properties);
+ properties.getStringValue("EXTENSION_PROJ4",
+ crs->CRS::getPrivate()->extensionProj4_);
return crs;
}
@@ -1626,6 +1651,16 @@ void GeographicCRS::addAngularUnitConvertAndAxisSwap(
void GeographicCRS::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(io::FormattingException)
{
+ if (formatter->convention() ==
+ io::PROJStringFormatter::Convention::PROJ_4) {
+ const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
+ if (!extensionProj4.empty()) {
+ formatter->ingestPROJString(extensionProj4);
+ formatter->addNoDefs(false);
+ return;
+ }
+ }
+
if (!formatter->omitProjLongLatIfPossible() ||
primeMeridian()->longitude().getSIValue() != 0.0 ||
!formatter->getTOWGS84Parameters().empty() ||
@@ -1763,7 +1798,15 @@ void VerticalCRS::_exportToWKT(io::WKTFormatter *formatter) const {
if (!isWKT2) {
axisList[0]->unit()._exportToWKT(formatter);
}
+
+ const auto oldAxisOutputRule = formatter->outputAxis();
+ if (oldAxisOutputRule ==
+ io::WKTFormatter::OutputAxisRule::WKT1_GDAL_EPSG_STYLE) {
+ formatter->setOutputAxis(io::WKTFormatter::OutputAxisRule::YES);
+ }
cs->_exportToWKT(formatter);
+ formatter->setOutputAxis(oldAxisOutputRule);
+
ObjectUsage::baseExportToWKT(formatter);
formatter->endNode();
}
@@ -2231,6 +2274,22 @@ const cs::CartesianCSNNPtr &ProjectedCRS::coordinateSystem() PROJ_CONST_DEFN {
void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2;
+ const auto &l_coordinateSystem = d->coordinateSystem();
+ const auto &axisList = l_coordinateSystem->axisList();
+
+ const auto exportAxis = [&l_coordinateSystem, &axisList, &formatter]() {
+ const auto oldAxisOutputRule = formatter->outputAxis();
+ if (oldAxisOutputRule ==
+ io::WKTFormatter::OutputAxisRule::WKT1_GDAL_EPSG_STYLE) {
+ if (&axisList[0]->direction() == &cs::AxisDirection::EAST &&
+ &axisList[1]->direction() == &cs::AxisDirection::NORTH) {
+ formatter->setOutputAxis(io::WKTFormatter::OutputAxisRule::YES);
+ }
+ }
+ l_coordinateSystem->_exportToWKT(formatter);
+ formatter->setOutputAxis(oldAxisOutputRule);
+ };
+
if (!isWKT2 && !formatter->useESRIDialect() &&
starts_with(nameStr(), "Popular Visualisation CRS / Mercator")) {
formatter->startNode(io::WKTConstants::PROJCS, !identifiers().empty());
@@ -2263,9 +2322,8 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
formatter->add(0.0);
formatter->endNode();
- const auto &axisList = d->coordinateSystem()->axisList();
axisList[0]->unit()._exportToWKT(formatter);
- d->coordinateSystem()->_exportToWKT(formatter);
+ exportAxis();
derivingConversionRef()->addWKTExtensionNode(formatter);
ObjectUsage::baseExportToWKT(formatter);
formatter->endNode();
@@ -2321,7 +2379,6 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
l_baseCRS->_exportToWKT(formatter);
}
- const auto &axisList = d->coordinateSystem()->axisList();
formatter->pushAxisLinearUnit(
common::UnitOfMeasure::create(axisList[0]->unit()));
@@ -2338,10 +2395,18 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
axisList[0]->unit()._exportToWKT(formatter);
}
- d->coordinateSystem()->_exportToWKT(formatter);
+ exportAxis();
if (!isWKT2 && !formatter->useESRIDialect()) {
- derivingConversionRef()->addWKTExtensionNode(formatter);
+ const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
+ if (!extensionProj4.empty()) {
+ formatter->startNode(io::WKTConstants::EXTENSION, false);
+ formatter->addQuotedString("PROJ4");
+ formatter->addQuotedString(extensionProj4);
+ formatter->endNode();
+ } else {
+ derivingConversionRef()->addWKTExtensionNode(formatter);
+ }
}
ObjectUsage::baseExportToWKT(formatter);
@@ -2355,6 +2420,16 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const {
void ProjectedCRS::_exportToPROJString(
io::PROJStringFormatter *formatter) const // throw(io::FormattingException)
{
+ if (formatter->convention() ==
+ io::PROJStringFormatter::Convention::PROJ_4) {
+ const auto &extensionProj4 = CRS::getPrivate()->extensionProj4_;
+ if (!extensionProj4.empty()) {
+ formatter->ingestPROJString(extensionProj4);
+ formatter->addNoDefs(false);
+ return;
+ }
+ }
+
baseExportToPROJString(formatter);
}
@@ -2384,6 +2459,8 @@ ProjectedCRS::create(const util::PropertyMap &properties,
crs->assignSelf(crs);
crs->setProperties(properties);
crs->setDerivingConversionCRS();
+ properties.getStringValue("EXTENSION_PROJ4",
+ crs->CRS::getPrivate()->extensionProj4_);
return crs;
}
@@ -2404,7 +2481,8 @@ void ProjectedCRS::addUnitConvertAndAxisSwap(io::PROJStringFormatter *formatter,
bool axisSpecFound) const {
const auto &axisList = d->coordinateSystem()->axisList();
const auto &unit = axisList[0]->unit();
- if (unit != common::UnitOfMeasure::METRE) {
+ if (!unit._isEquivalentTo(common::UnitOfMeasure::METRE,
+ util::IComparable::Criterion::EQUIVALENT)) {
auto projUnit = unit.exportToPROJString();
const double toSI = unit.conversionToSI();
if (formatter->convention() ==
@@ -2426,6 +2504,12 @@ void ProjectedCRS::addUnitConvertAndAxisSwap(io::PROJStringFormatter *formatter,
formatter->addParam("units", projUnit);
}
}
+ } else if (formatter->convention() ==
+ io::PROJStringFormatter::Convention::PROJ_4) {
+ // could come from the hardcoded def of webmerc
+ if (!formatter->hasParam("units")) {
+ formatter->addParam("units", "m");
+ }
}
if (formatter->convention() ==
@@ -3234,8 +3318,17 @@ 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, GeographicCRS::EPSG_4326,
+ baseCRSIn, targetCRS,
operation::Transformation::createTOWGS84(baseCRSIn, TOWGS84Parameters));
}