From fb69e67f8694fd61943cc9f9c2da75ec35ce9841 Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 11 Jan 2018 16:34:47 +0100 Subject: Fail gracefully when invalid inverse operation is specified in cct. Similar to proj and cs2cs, cct now returns immediately when trying to do an inverse operation that is not possible, for example using proj=urm5 which doesn't have an inverse: $ cct.exe -I +proj=pipeline +step +proj=urm5 +n=0.5 Inverse operation not available --- src/cct.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cct.c b/src/cct.c index f315ae1a..7e48311a 100644 --- a/src/cct.c +++ b/src/cct.c @@ -217,9 +217,15 @@ int main(int argc, char **argv) { return 1; } - /* We have no API call for inverting an operation, so we brute force it. */ - if (direction==-1) + if (direction==-1) { + /* fail if an inverse operation is not available */ + if (!proj_pj_info(P).has_inverse) { + fprintf (stderr, "Inverse operation not available\n"); + return 1; + } + /* We have no API call for inverting an operation, so we brute force it. */ P->inverted = !(P->inverted); + } direction = 1; /* Allocate input buffer */ -- cgit v1.2.3 From b6c8e417d71dca9ac04f57660da2c94a0a85e8ff Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Thu, 11 Jan 2018 16:40:01 +0100 Subject: Set inv*-functions to zero on pipeline PJ's where an inverse does not exist. Some projections do not have an inverse mapping. If such a projection is used as a (forward) step in a pipeline we won't be able to perform an inverse operation using the pipeline. By setting the inv, inv3d and inv4d pointers to zero we signal to the caller that an inverse mapping is not available. --- src/PJ_pipeline.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/PJ_pipeline.c b/src/PJ_pipeline.c index af9c5394..3dcc85d9 100644 --- a/src/PJ_pipeline.c +++ b/src/PJ_pipeline.c @@ -320,6 +320,7 @@ PJ *OPERATION(pipeline,0) { int i, nsteps = 0, argc; int i_pipeline = -1, i_first_step = -1, i_current_step; char **argv, **current_argv; + PJ *Q; P->fwd4d = pipeline_forward_4d; P->inv4d = pipeline_reverse_4d; @@ -429,14 +430,29 @@ PJ *OPERATION(pipeline,0) { /* Is this step inverted? */ for (j = 0; j < current_argc; j++) - if (0==strcmp("inv", current_argv[j])) + if (0==strcmp("inv", current_argv[j])) { next_step->inverted = 1; + } P->opaque->pipeline[i+1] = next_step; proj_log_trace (P, "Pipeline at [%p]: step at [%p] done", P, next_step); } + /* determine if an inverse operation is possible */ + for (i = 1; i <= nsteps; i++) { + Q = P->opaque->pipeline[i]; + if ( ( Q->inverted && (Q->fwd || Q->fwd3d || Q->fwd4d) ) || + ( Q->inv || Q->inv3d || Q->inv4d) ) { + continue; + } else { + P->inv = 0; + P->inv3d = 0; + P->inv4d = 0; + break; + } + } + proj_log_trace (P, "Pipeline: %d steps built. Determining i/o characteristics", nsteps); /* Determine forward input (= reverse output) data type */ -- cgit v1.2.3 From 9181fcfebde8a3969dc49100674f16286119059b Mon Sep 17 00:00:00 2001 From: Kristian Evers Date: Tue, 16 Jan 2018 13:16:18 +0100 Subject: Fix "double inversions" in pipelines, require a defined forward operation. "+proj=pipeline +inv +step +urm5 +n=0.5 +inv" now works as expected, returning the forward operation of urm5. In principle adding more +inv's should also work, resulting in the forward operation when an even number of +inv's are present, and the inverse when an odd number of +inv's are present. "+proj=pipeline +step +urm5 +n=0.5 +inv" fails at initialization since no forward operation can be performed. This is a new requirement, but aligns perfectly with the rest of the library since no operation without a forward method exists. --- src/PJ_pipeline.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/PJ_pipeline.c b/src/PJ_pipeline.c index 3dcc85d9..befc8557 100644 --- a/src/PJ_pipeline.c +++ b/src/PJ_pipeline.c @@ -320,7 +320,6 @@ PJ *OPERATION(pipeline,0) { int i, nsteps = 0, argc; int i_pipeline = -1, i_first_step = -1, i_current_step; char **argv, **current_argv; - PJ *Q; P->fwd4d = pipeline_forward_4d; P->inv4d = pipeline_reverse_4d; @@ -431,7 +430,8 @@ PJ *OPERATION(pipeline,0) { /* Is this step inverted? */ for (j = 0; j < current_argc; j++) if (0==strcmp("inv", current_argv[j])) { - next_step->inverted = 1; + /* if +inv exists in both global and local args the forward operation should be used */ + next_step->inverted = next_step->inverted == 0 ? 1 : 0; } P->opaque->pipeline[i+1] = next_step; @@ -439,9 +439,21 @@ PJ *OPERATION(pipeline,0) { proj_log_trace (P, "Pipeline at [%p]: step at [%p] done", P, next_step); } + /* Require a forward path through the pipeline */ + for (i = 1; i <= nsteps; i++) { + PJ *Q = P->opaque->pipeline[i]; + if ( ( Q->inverted && (Q->inv || Q->inv3d || Q->fwd4d) ) || + (!Q->inverted && (Q->fwd || Q->fwd3d || Q->fwd4d) ) ) { + continue; + } else { + proj_log_error (P, "Pipeline: A forward operation couldn't be constructed"); + return destructor (P, PJD_ERR_MALFORMED_PIPELINE); + } + } + /* determine if an inverse operation is possible */ for (i = 1; i <= nsteps; i++) { - Q = P->opaque->pipeline[i]; + PJ *Q = P->opaque->pipeline[i]; if ( ( Q->inverted && (Q->fwd || Q->fwd3d || Q->fwd4d) ) || ( Q->inv || Q->inv3d || Q->inv4d) ) { continue; -- cgit v1.2.3