aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/coordinateoperation.cpp26
-rw-r--r--src/io.cpp18
-rw-r--r--test/unit/test_io.cpp14
-rw-r--r--test/unit/test_operation.cpp30
4 files changed, 88 insertions, 0 deletions
diff --git a/src/coordinateoperation.cpp b/src/coordinateoperation.cpp
index 42cc806e..e0e02931 100644
--- a/src/coordinateoperation.cpp
+++ b/src/coordinateoperation.cpp
@@ -8220,6 +8220,32 @@ bool SingleOperation::exportToPROJStringGeneric(
if (isAxisOrderReversal(methodEPSGCode)) {
formatter->addStep("axisswap");
formatter->addParam("order", "2,1");
+ auto sourceCRSGeog =
+ dynamic_cast<const crs::GeographicCRS *>(sourceCRS().get());
+ auto targetCRSGeog =
+ dynamic_cast<const crs::GeographicCRS *>(targetCRS().get());
+ if (sourceCRSGeog && targetCRSGeog) {
+ const auto &unitSrc =
+ sourceCRSGeog->coordinateSystem()->axisList()[0]->unit();
+ const auto &unitDst =
+ targetCRSGeog->coordinateSystem()->axisList()[0]->unit();
+ if (!unitSrc._isEquivalentTo(
+ unitDst, util::IComparable::Criterion::EQUIVALENT)) {
+ formatter->addStep("unitconvert");
+ auto projUnit = unitSrc.exportToPROJString();
+ if (projUnit.empty()) {
+ formatter->addParam("xy_in", unitSrc.conversionToSI());
+ } else {
+ formatter->addParam("xy_in", projUnit);
+ }
+ projUnit = unitDst.exportToPROJString();
+ if (projUnit.empty()) {
+ formatter->addParam("xy_out", unitDst.conversionToSI());
+ } else {
+ formatter->addParam("xy_out", projUnit);
+ }
+ }
+ }
return true;
}
diff --git a/src/io.cpp b/src/io.cpp
index 8a58816f..c2ca484d 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -4708,6 +4708,24 @@ const std::string &PROJStringFormatter::toString() const {
break;
}
+ // axisswap order=2,1, unitconvert, axisswap order=2,1 -> can
+ // suppress axisswap
+ if (i + 1 < d->steps_.size() && prevStep.name == "axisswap" &&
+ curStep.name == "unitconvert" && prevStepParamCount == 1 &&
+ prevStep.paramValues[0].equals("order", "2,1")) {
+ auto iterNext = iterCur;
+ ++iterNext;
+ auto &nextStep = *iterNext;
+ if (nextStep.name == "axisswap" &&
+ nextStep.paramValues.size() == 1 &&
+ nextStep.paramValues[0].equals("order", "2,1")) {
+ d->steps_.erase(iterPrev);
+ d->steps_.erase(iterNext);
+ changeDone = true;
+ break;
+ }
+ }
+
// for practical purposes WGS84 and GRS80 ellipsoids are
// equivalents (cartesian transform between both lead to differences
// of the order of 1e-14 deg..).
diff --git a/test/unit/test_io.cpp b/test/unit/test_io.cpp
index 00da162c..6ccd5578 100644
--- a/test/unit/test_io.cpp
+++ b/test/unit/test_io.cpp
@@ -5381,6 +5381,20 @@ TEST(io, projstringformatter_cart_grs80_wgs84) {
// ---------------------------------------------------------------------------
+TEST(io, projstringformatter_axisswap_unitconvert_axisswap) {
+ auto fmt = PROJStringFormatter::create();
+ fmt->addStep("axisswap");
+ fmt->addParam("order", "2,1");
+ fmt->addStep("unitconvert");
+ fmt->addParam("xy_in", "rad");
+ fmt->addParam("xy_out", "deg");
+ fmt->addStep("axisswap");
+ fmt->addParam("order", "2,1");
+ EXPECT_EQ(fmt->toString(), "+proj=unitconvert +xy_in=rad +xy_out=deg");
+}
+
+// ---------------------------------------------------------------------------
+
TEST(io, projparse_longlat) {
auto expected = "GEODCRS[\"unknown\",\n"
diff --git a/test/unit/test_operation.cpp b/test/unit/test_operation.cpp
index e62eddf9..528aa6b8 100644
--- a/test/unit/test_operation.cpp
+++ b/test/unit/test_operation.cpp
@@ -1142,6 +1142,36 @@ TEST(operation, transformation_createTOWGS84) {
// ---------------------------------------------------------------------------
+TEST(operation, createAxisOrderReversal) {
+
+ auto latLongDeg = GeographicCRS::create(
+ PropertyMap(), GeodeticReferenceFrame::EPSG_6326,
+ EllipsoidalCS::createLatitudeLongitude(UnitOfMeasure::DEGREE));
+ auto longLatDeg = GeographicCRS::create(
+ PropertyMap(), GeodeticReferenceFrame::EPSG_6326,
+ EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::DEGREE));
+ {
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ latLongDeg, longLatDeg);
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=axisswap +order=2,1");
+ }
+ {
+ auto longLatRad = GeographicCRS::create(
+ PropertyMap(), GeodeticReferenceFrame::EPSG_6326,
+ EllipsoidalCS::createLongitudeLatitude(UnitOfMeasure::RADIAN));
+ auto op = CoordinateOperationFactory::create()->createOperation(
+ longLatRad, latLongDeg);
+ ASSERT_TRUE(op != nullptr);
+ EXPECT_EQ(op->exportToPROJString(PROJStringFormatter::create().get()),
+ "+proj=pipeline +step +proj=axisswap +order=2,1 "
+ "+step +proj=unitconvert +xy_in=rad +xy_out=deg");
+ }
+}
+
+// ---------------------------------------------------------------------------
+
TEST(operation, utm_export) {
auto conv = Conversion::createUTM(PropertyMap(), 1, false);
EXPECT_EQ(conv->exportToPROJString(PROJStringFormatter::create().get()),