aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2019-11-25 14:56:31 +0100
committerEven Rouault <even.rouault@spatialys.com>2019-11-25 15:07:25 +0100
commitd81ffc6fa8a32db72bdfd1ff034c705222d0cdb3 (patch)
tree8a20b9d0b7dfbda3e13b089bfa17960f855e217c /src
parentddd8a1243a5eb43ad209e934526c5c87848343b7 (diff)
downloadPROJ-d81ffc6fa8a32db72bdfd1ff034c705222d0cdb3.tar.gz
PROJ-d81ffc6fa8a32db72bdfd1ff034c705222d0cdb3.zip
Pipeline: support +omit_fwd and +omit_inv keywords
Inspired from syntax of https://github.com/OSGeo/PROJ/pull/453/files but 'rebased' on top of previous commit that cleans up the pipeline implementation Different situations: - +omit_fwd: the step when followed in the forward path will be omitted the step when followed in the reverse path will be executed - +omit_fwd +inv: the step when followed in the forward path will be omitted the step when followed in the reverse path will be executed (with the inv method) - +omit_inv: the step when followed in the forward path will be executed the step when followed in the reverse path will be omitted - +omit_inv +inv: the step when followed in the forward path will be executed (with the inv method) the step when followed in the reverse path will be omitted This will be used in the next commit to optimize constructs like +step +proj=hgridshift +grids=foo +step +proj=vgridshift +grids=bar +step +inv +proj=hgridshift +grids=foo Such steps are used for CRS to CRS transformations where applying the vertical grid requires to do a transformation to an interpolating CRS. One can notice that in the last step will just restore the horizontal coordinates before the first step, so doing an inverse hgridshift is overkill. So that could be optimized as: +step +proj=push +v_1 +v_2 +step +proj=hgridshift +grids=foo +omit_inv +step +proj=vgridshift +grids=bar +step +inv +proj=hgridshift +grids=foo +omit_fwd +step +proj=pop +v_1 +v_2 In the forward path, this will be equivalent to: +step +proj=push +v_1 +v_2 +step +proj=hgridshift +grids=foo +step +proj=vgridshift +grids=bar +step +prop=pop +v_1 +v_2 And similarly in the reverse path, this will be quivalent to: +step +proj=push +v_1 +v_2 +step +proj=hgridshift +grids=foo +step +inv +proj=vgridshift +grids=bar +step +proj=pop +v_1 +v_2
Diffstat (limited to 'src')
-rw-r--r--src/iso19111/io.cpp13
-rw-r--r--src/pipeline.cpp57
2 files changed, 58 insertions, 12 deletions
diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp
index 678c5d98..d994277b 100644
--- a/src/iso19111/io.cpp
+++ b/src/iso19111/io.cpp
@@ -6284,6 +6284,15 @@ struct Step {
};
std::vector<KeyValue> paramValues{};
+
+ bool hasKey(const char *keyName) const {
+ for (const auto &kv : paramValues) {
+ if (kv.key == keyName) {
+ return true;
+ }
+ }
+ return false;
+ }
};
Step::KeyValue::KeyValue(const char *keyIn, const std::string &valueIn)
@@ -6813,7 +6822,9 @@ const std::string &PROJStringFormatter::toString() const {
if (d->steps_.size() > 1 ||
(d->steps_.size() == 1 &&
- (d->steps_.front().inverted || !d->globalParamValues_.empty()))) {
+ (d->steps_.front().inverted || d->steps_.front().hasKey("omit_inv") ||
+ d->steps_.front().hasKey("omit_fwd") ||
+ !d->globalParamValues_.empty()))) {
d->appendToResult("+proj=pipeline");
for (const auto &paramValue : d->globalParamValues_) {
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index bc6708b0..99b2bdfb 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -116,9 +116,14 @@ namespace { // anonymous namespace
struct Step {
PJ* pj = nullptr;
-
- Step(PJ* pjIn): pj(pjIn) {}
- Step(Step&& other): pj(std::move(other.pj)) { other.pj = nullptr; }
+ bool omit_fwd = false;
+ bool omit_inv = false;
+
+ Step(PJ* pjIn, bool omitFwdIn, bool omitInvIn):
+ pj(pjIn), omit_fwd(omitFwdIn), omit_inv(omitInvIn) {}
+ Step(Step&& other): pj(std::move(other.pj)),
+ omit_fwd(other.omit_fwd),
+ omit_inv(other.omit_inv) { other.pj = nullptr; }
Step(const Step&) = delete;
Step& operator=(const Step&) = delete;
@@ -161,7 +166,12 @@ void pj_pipeline_assign_context_to_steps( PJ* P, PJ_CONTEXT* ctx )
static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) {
auto opaque = static_cast<struct pj_opaque*>(P->opaque);
for( auto& step: opaque->steps )
- point = proj_trans (step.pj, PJ_FWD, point);
+ {
+ if( !step.omit_fwd )
+ {
+ point = proj_trans (step.pj, PJ_FWD, point);
+ }
+ }
return point;
}
@@ -171,7 +181,11 @@ static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) {
auto opaque = static_cast<struct pj_opaque*>(P->opaque);
for( auto it = opaque->steps.rbegin(); it != opaque->steps.rend(); ++it )
{
- point = proj_trans (it->pj, PJ_INV, point);
+ const auto& step = *it;
+ if( !step.omit_inv )
+ {
+ point = proj_trans (step.pj, PJ_INV, point);
+ }
}
return point;
@@ -185,7 +199,12 @@ static PJ_XYZ pipeline_forward_3d (PJ_LPZ lpz, PJ *P) {
point.lpz = lpz;
auto opaque = static_cast<struct pj_opaque*>(P->opaque);
for( auto& step: opaque->steps )
- point = pj_approx_3D_trans (step.pj, PJ_FWD, point);
+ {
+ if( !step.omit_fwd )
+ {
+ point = pj_approx_3D_trans (step.pj, PJ_FWD, point);
+ }
+ }
return point.xyz;
}
@@ -197,7 +216,11 @@ static PJ_LPZ pipeline_reverse_3d (PJ_XYZ xyz, PJ *P) {
auto opaque = static_cast<struct pj_opaque*>(P->opaque);
for( auto it = opaque->steps.rbegin(); it != opaque->steps.rend(); ++it )
{
- point = proj_trans (it->pj, PJ_INV, point);
+ const auto& step = *it;
+ if( !step.omit_inv )
+ {
+ point = proj_trans (step.pj, PJ_INV, point);
+ }
}
return point.lpz;
@@ -211,7 +234,12 @@ static PJ_XY pipeline_forward (PJ_LP lp, PJ *P) {
point.lp = lp;
auto opaque = static_cast<struct pj_opaque*>(P->opaque);
for( auto& step: opaque->steps )
- point = pj_approx_2D_trans (step.pj, PJ_FWD, point);
+ {
+ if( !step.omit_fwd )
+ {
+ point = pj_approx_2D_trans (step.pj, PJ_FWD, point);
+ }
+ }
return point.xy;
}
@@ -223,7 +251,11 @@ static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P) {
auto opaque = static_cast<struct pj_opaque*>(P->opaque);
for( auto it = opaque->steps.rbegin(); it != opaque->steps.rend(); ++it )
{
- point = pj_approx_2D_trans (it->pj, PJ_INV, point);
+ const auto& step = *it;
+ if( !step.omit_inv )
+ {
+ point = pj_approx_2D_trans (step.pj, PJ_INV, point);
+ }
}
return point.lp;
@@ -476,13 +508,16 @@ PJ *OPERATION(pipeline,0) {
proj_errno_restore (P, err);
/* Is this step inverted? */
- for (j = 0; j < current_argc; j++)
+ for (j = 0; j < current_argc; j++) {
if (0==strcmp("inv", current_argv[j])) {
/* if +inv exists in both global and local args the forward operation should be used */
next_step->inverted = next_step->inverted == 0 ? 1 : 0;
}
+ }
- opaque->steps.emplace_back(next_step);
+ bool omit_fwd = pj_param(P->ctx, next_step->params, "bomit_fwd").i != 0;
+ bool omit_inv = pj_param(P->ctx, next_step->params, "bomit_inv").i != 0;
+ opaque->steps.emplace_back(next_step, omit_fwd, omit_inv);
proj_log_trace (P, "Pipeline at [%p]: step at [%p] (%s) done", P, next_step, current_argv[0]);
}