aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/coordinateoperation.cpp40
-rw-r--r--src/iso19111/io.cpp95
2 files changed, 135 insertions, 0 deletions
diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp
index 7cac18bf..14b1024d 100644
--- a/src/iso19111/coordinateoperation.cpp
+++ b/src/iso19111/coordinateoperation.cpp
@@ -8138,6 +8138,18 @@ void Transformation::_exportToPROJString(
double z =
parameterValueNumericAsSI(EPSG_CODE_PARAMETER_Z_AXIS_TRANSLATION);
+ if (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) {
+ formatter->addStep("push");
+ formatter->addParam("v_3");
+ }
+
setupPROJGeodeticSourceCRS(formatter, sourceCRS(), "Helmert");
formatter->addStep("helmert");
@@ -8204,6 +8216,18 @@ void Transformation::_exportToPROJString(
setupPROJGeodeticTargetCRS(formatter, targetCRS(), "Helmert");
+ if (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) {
+ formatter->addStep("pop");
+ formatter->addParam("v_3");
+ }
+
return;
}
@@ -8250,6 +8274,14 @@ void Transformation::_exportToPROJString(
double pz = parameterValueNumericAsSI(
EPSG_CODE_PARAMETER_ORDINATE_3_EVAL_POINT);
+ if (methodEPSGCode ==
+ EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_2D ||
+ methodEPSGCode ==
+ EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_2D) {
+ formatter->addStep("push");
+ formatter->addParam("v_3");
+ }
+
setupPROJGeodeticSourceCRS(formatter, sourceCRS(),
"Molodensky-Badekas");
@@ -8273,6 +8305,14 @@ void Transformation::_exportToPROJString(
setupPROJGeodeticTargetCRS(formatter, targetCRS(),
"Molodensky-Badekas");
+ if (methodEPSGCode ==
+ EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_PV_GEOGRAPHIC_2D ||
+ methodEPSGCode ==
+ EPSG_CODE_METHOD_MOLODENSKY_BADEKAS_CF_GEOGRAPHIC_2D) {
+ formatter->addStep("pop");
+ formatter->addParam("v_3");
+ }
+
return;
}
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 0e9eac02..6edce579 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -4837,6 +4837,12 @@ const std::string &PROJStringFormatter::toString() const {
step.paramValues[1].keyEquals("xy_out") &&
step.paramValues[0].value == step.paramValues[1].value) {
iter = d->steps_.erase(iter);
+ } else if (step.name == "push" && step.inverted) {
+ step.name = "pop";
+ step.inverted = false;
+ } else if (step.name == "pop" && step.inverted) {
+ step.name = "push";
+ step.inverted = false;
} else {
++iter;
}
@@ -4912,6 +4918,30 @@ const std::string &PROJStringFormatter::toString() const {
break;
}
+ // push v_x followed by pop v_x is a no-op.
+ if (curStep.name == "pop" && prevStep.name == "push" &&
+ !curStep.inverted && !prevStep.inverted &&
+ curStepParamCount == 1 && prevStepParamCount == 1 &&
+ curStep.paramValues[0].key == prevStep.paramValues[0].key) {
+ ++iterCur;
+ d->steps_.erase(iterPrev, iterCur);
+ changeDone = true;
+ break;
+ }
+
+ // pop v_x followed by push v_x is, almost, a no-op. For our
+ // purposes,
+ // we consider it as a no-op for better pipeline optimizations.
+ if (curStep.name == "push" && prevStep.name == "pop" &&
+ !curStep.inverted && !prevStep.inverted &&
+ curStepParamCount == 1 && prevStepParamCount == 1 &&
+ curStep.paramValues[0].key == prevStep.paramValues[0].key) {
+ ++iterCur;
+ d->steps_.erase(iterPrev, iterCur);
+ changeDone = true;
+ break;
+ }
+
// unitconvert (xy) followed by its inverse is a no-op
if (curStep.name == "unitconvert" &&
prevStep.name == "unitconvert" && !curStep.inverted &&
@@ -5072,6 +5102,71 @@ const std::string &PROJStringFormatter::toString() const {
}
}
+ // axisswap order=2,1, pop/push v_3, axisswap order=2,1 -> can
+ // suppress axisswap
+ if (i + 1 < d->steps_.size() && prevStep.name == "axisswap" &&
+ (curStep.name == "push" || curStep.name == "pop") &&
+ prevStepParamCount == 1 &&
+ prevStep.paramValues[0].equals("order", "2,1") &&
+ curStepParamCount == 1 && curStep.paramValues[0].key == "v_3") {
+ 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;
+ }
+ }
+
+ // push v_3, axisswap order=2,1, pop v_3 -> can suppress push/pop
+ if (i + 1 < d->steps_.size() && prevStep.name == "push" &&
+ prevStepParamCount == 1 &&
+ prevStep.paramValues[0].key == "v_3" &&
+ curStep.name == "axisswap" && curStepParamCount == 1 &&
+ curStep.paramValues[0].equals("order", "2,1")) {
+ auto iterNext = iterCur;
+ ++iterNext;
+ auto &nextStep = *iterNext;
+ if (nextStep.name == "pop" &&
+ nextStep.paramValues.size() == 1 &&
+ nextStep.paramValues[0].key == "v_3") {
+ d->steps_.erase(iterPrev);
+ d->steps_.erase(iterNext);
+ changeDone = true;
+ break;
+ }
+ }
+
+ // unitconvert xy_in=A xy_out=B, pop/push v_3, unitconvert xy_in=B
+ // xy_out=A -> can suppress unitconvert
+ if (i + 1 < d->steps_.size() && prevStep.name == "unitconvert" &&
+ (curStep.name == "push" || curStep.name == "pop") &&
+ prevStepParamCount == 2 &&
+ prevStep.paramValues[0].key == "xy_in" &&
+ prevStep.paramValues[1].key == "xy_out" &&
+ curStepParamCount == 1 && curStep.paramValues[0].key == "v_3") {
+ auto iterNext = iterCur;
+ ++iterNext;
+ auto &nextStep = *iterNext;
+ if (nextStep.name == "unitconvert" &&
+ nextStep.paramValues.size() == 2 &&
+ nextStep.paramValues[0].key == "xy_in" &&
+ nextStep.paramValues[1].key == "xy_out" &&
+ nextStep.paramValues[0].value ==
+ prevStep.paramValues[1].value &&
+ nextStep.paramValues[1].value ==
+ prevStep.paramValues[0].value) {
+ 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..).