aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKristian Evers <kristianevers@gmail.com>2019-01-03 22:12:22 +0100
committerKristian Evers <kristianevers@gmail.com>2019-01-04 14:02:06 +0100
commitedb068401822c0cb7047019ae7a1dac587778ce3 (patch)
tree00897a41abd674fa841492cdf4fda86d4778d399 /src
parent78d4126eb54d3f066d7225c160707fc68ae31229 (diff)
downloadPROJ-edb068401822c0cb7047019ae7a1dac587778ce3.tar.gz
PROJ-edb068401822c0cb7047019ae7a1dac587778ce3.zip
Replace PJ_IO_UNITS_WHATEVER with units from neighbour steps
With this commit we make sure that proj_angular_input() and proj_angular_output return the correct result for any given pipeline.
Diffstat (limited to 'src')
-rw-r--r--src/conversions/unitconvert.cpp6
-rw-r--r--src/pipeline.cpp59
2 files changed, 60 insertions, 5 deletions
diff --git a/src/conversions/unitconvert.cpp b/src/conversions/unitconvert.cpp
index cbd81a7d..1e3372d6 100644
--- a/src/conversions/unitconvert.cpp
+++ b/src/conversions/unitconvert.cpp
@@ -457,6 +457,8 @@ PJ *CONVERSION(unitconvert,0) {
P->left = PJ_IO_UNITS_WHATEVER;
P->right = PJ_IO_UNITS_WHATEVER;
+ P->skip_fwd_prepare = 1;
+ P->skip_inv_prepare = 1;
/* if no time input/output unit is specified we can skip them */
Q->t_in_id = -1;
@@ -476,6 +478,8 @@ PJ *CONVERSION(unitconvert,0) {
}
if (f != 0.0)
Q->xy_factor *= f;
+ if (normalized_name != nullptr && strcmp(normalized_name, "Radian") == 0)
+ P->left = PJ_IO_UNITS_RADIANS;
}
if ((name = pj_param (P->ctx, P->params, "sxy_out").s) != nullptr) {
@@ -489,6 +493,8 @@ PJ *CONVERSION(unitconvert,0) {
}
if (f != 0.0)
Q->xy_factor /= f;
+ if (normalized_name != nullptr && strcmp(normalized_name, "Radian") == 0)
+ P->right= PJ_IO_UNITS_RADIANS;
}
if( xy_in_is_linear >= 0 && xy_out_is_linear >= 0 &&
diff --git a/src/pipeline.cpp b/src/pipeline.cpp
index 5f7efe08..b24f71e7 100644
--- a/src/pipeline.cpp
+++ b/src/pipeline.cpp
@@ -329,6 +329,33 @@ static void set_ellipsoid(PJ *P) {
}
+static enum pj_io_units get_next_non_whatever_unit(void *pipeline_data, int step, PJ_DIRECTION dir) {
+ PJ **pipeline = static_cast<struct pj_opaque*>(pipeline_data)->pipeline;
+ int nsteps = static_cast<struct pj_opaque*>(pipeline_data)->steps;
+ int i;
+
+ if (dir == PJ_FWD) {
+ for (i = step+1; i<=nsteps; i++) {
+ if (pj_left(pipeline[i]) != pj_right(pipeline[i]))
+ return pj_left(pipeline[i]);
+ if (pj_left(pipeline[i]) != PJ_IO_UNITS_WHATEVER)
+ return pj_left(pipeline[i]);
+ if (pj_right(pipeline[i]) != PJ_IO_UNITS_WHATEVER)
+ return pj_right(pipeline[i]);
+ }
+ } else {
+ for (i=step; i>1; i--) {
+ if (pj_right(pipeline[i]) != pj_left(pipeline[i]))
+ return pj_right(pipeline[i]);
+ if (pj_right(pipeline[i]) != PJ_IO_UNITS_WHATEVER)
+ return pj_right(pipeline[i]);
+ if (pj_left(pipeline[i]) != PJ_IO_UNITS_WHATEVER)
+ return pj_left(pipeline[i]);
+ }
+ }
+ return PJ_IO_UNITS_WHATEVER;
+}
+
PJ *OPERATION(pipeline,0) {
@@ -480,14 +507,36 @@ PJ *OPERATION(pipeline,0) {
}
}
- /* Check that output units from step i are compatible with expected units in step i+1 */
+
+ /* Replace PJ_IO_UNITS_WHATEVER with input/output units of neighbouring steps where */
+ /* it make sense. It does in most cases but not always, for instance */
+ /* proj=pipeline step proj=unitconvert xy_in=deg xy_out=rad step ... */
+ /* where the left-hand side units of the first step shouldn't be changed to RADIANS */
+ /* as it will result in deg->rad conversions in cs2cs and other applications. */
+ PJ **pipeline = static_cast<struct pj_opaque*>(P->opaque)->pipeline;
+ for (i=1; i<=nsteps; i++) {
+ if (pj_left(pipeline[i]) == PJ_IO_UNITS_WHATEVER && pj_right(pipeline[i]) == PJ_IO_UNITS_WHATEVER) {
+ pipeline[i]->left = get_next_non_whatever_unit(P->opaque, i, PJ_FWD);
+ pipeline[i]->right = get_next_non_whatever_unit(P->opaque, i, PJ_FWD);
+ }
+ }
+
+ for (i=nsteps; i>0; i--) {
+ if (pj_left(pipeline[i]) == PJ_IO_UNITS_WHATEVER && pj_right(pipeline[i]) == PJ_IO_UNITS_WHATEVER) {
+ pipeline[i]->right = get_next_non_whatever_unit(P->opaque, i, PJ_INV);
+ pipeline[i]->left = get_next_non_whatever_unit(P->opaque, i, PJ_INV);
+ }
+ }
+
+ /* Check that units between each steps match each other, fail if they don't */
for (i = 1; i < nsteps; i++) {
- enum pj_io_units unit_returned = pj_right (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i]);
- enum pj_io_units unit_expected = pj_left (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i+1]);
+ enum pj_io_units curr_step_output = pj_right (pipeline[i]);
+ enum pj_io_units next_step_input = pj_left (pipeline[i+1]);
- if ( unit_returned == PJ_IO_UNITS_WHATEVER || unit_expected == PJ_IO_UNITS_WHATEVER )
+ if ( curr_step_output == PJ_IO_UNITS_WHATEVER || next_step_input == PJ_IO_UNITS_WHATEVER )
continue;
- if ( unit_returned != unit_expected ) {
+
+ if ( curr_step_output != next_step_input ) {
proj_log_error (P, "Pipeline: Mismatched units between step %d and %d", i, i+1);
return destructor (P, PJD_ERR_MALFORMED_PIPELINE);
}