diff options
Diffstat (limited to 'src/pipeline.cpp')
| -rw-r--r-- | src/pipeline.cpp | 311 |
1 files changed, 168 insertions, 143 deletions
diff --git a/src/pipeline.cpp b/src/pipeline.cpp index 847f8194..96767143 100644 --- a/src/pipeline.cpp +++ b/src/pipeline.cpp @@ -101,6 +101,7 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-20 #include <stddef.h> #include <string.h> #include <stack> +#include <vector> #include "geodesic.h" #include "proj.h" @@ -112,15 +113,33 @@ PROJ_HEAD(push, "Save coordinate value on pipeline stack"); /* Projection specific elements for the PJ object */ namespace { // anonymous namespace -struct pj_opaque { - int steps; - char **argv; - char **current_argv; - PJ **pipeline; - std::stack<double> *stack[4]; + +struct Step { + PJ* 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; + + ~Step() { + proj_destroy(pj); + } +}; + +struct Pipeline { + char **argv = nullptr; + char **current_argv = nullptr; + std::vector<Step> steps{}; + std::stack<double> stack[4]; }; -struct pj_opaque_pushpop { +struct PushPop { bool v1; bool v2; bool v3; @@ -138,32 +157,37 @@ static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P); void pj_pipeline_assign_context_to_steps( PJ* P, PJ_CONTEXT* ctx ) { - for (int i = 1; i <= static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - proj_assign_context(static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], ctx); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto& step: pipeline->steps ) + proj_assign_context(step.pj, ctx); } static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) { - int i, first_step, last_step; - - first_step = 1; - last_step = static_cast<struct pj_opaque*>(P->opaque)->steps + 1; - - for (i = first_step; i != last_step; i++) - point = proj_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto& step: pipeline->steps ) + { + if( !step.omit_fwd ) + { + point = proj_trans (step.pj, PJ_FWD, point); + } + } return point; } static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) { - int i, first_step, last_step; - - first_step = static_cast<struct pj_opaque*>(P->opaque)->steps; - last_step = 0; - - for (i = first_step; i != last_step; i--) - point = proj_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto iterStep = pipeline->steps.rbegin(); + iterStep != pipeline->steps.rend(); ++iterStep ) + { + const auto& step = *iterStep; + if( !step.omit_inv ) + { + point = proj_trans (step.pj, PJ_INV, point); + } + } return point; } @@ -173,11 +197,15 @@ static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) { static PJ_XYZ pipeline_forward_3d (PJ_LPZ lpz, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.lpz = lpz; - - for (i = 1; i <= static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - point = pj_approx_3D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto& step: pipeline->steps ) + { + if( !step.omit_fwd ) + { + point = pj_approx_3D_trans (step.pj, PJ_FWD, point); + } + } return point.xyz; } @@ -185,11 +213,17 @@ static PJ_XYZ pipeline_forward_3d (PJ_LPZ lpz, PJ *P) { static PJ_LPZ pipeline_reverse_3d (PJ_XYZ xyz, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.xyz = xyz; - - for (i = static_cast<struct pj_opaque*>(P->opaque)->steps; i > 0 ; i--) - point = pj_approx_3D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto iterStep = pipeline->steps.rbegin(); + iterStep != pipeline->steps.rend(); ++iterStep ) + { + const auto& step = *iterStep; + if( !step.omit_inv ) + { + point = proj_trans (step.pj, PJ_INV, point); + } + } return point.lpz; } @@ -199,11 +233,15 @@ static PJ_LPZ pipeline_reverse_3d (PJ_XYZ xyz, PJ *P) { static PJ_XY pipeline_forward (PJ_LP lp, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.lp = lp; - - for (i = 1; i <= static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - point = pj_approx_2D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_FWD, point); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto& step: pipeline->steps ) + { + if( !step.omit_fwd ) + { + point = pj_approx_2D_trans (step.pj, PJ_FWD, point); + } + } return point.xy; } @@ -211,10 +249,17 @@ static PJ_XY pipeline_forward (PJ_LP lp, PJ *P) { static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P) { PJ_COORD point = {{0,0,0,0}}; - int i; point.xy = xy; - for (i = static_cast<struct pj_opaque*>(P->opaque)->steps; i > 0 ; i--) - point = pj_approx_2D_trans (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i], PJ_INV, point); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + for( auto iterStep = pipeline->steps.rbegin(); + iterStep != pipeline->steps.rend(); ++iterStep ) + { + const auto& step = *iterStep; + if( !step.omit_inv ) + { + point = pj_approx_2D_trans (step.pj, PJ_INV, point); + } + } return point.lp; } @@ -223,44 +268,24 @@ static PJ_LP pipeline_reverse (PJ_XY xy, PJ *P) { static PJ *destructor (PJ *P, int errlev) { - int i; if (nullptr==P) return nullptr; if (nullptr==P->opaque) return pj_default_destructor (P, errlev); - /* Deallocate each pipeline step, then pipeline array */ - if (nullptr!=static_cast<struct pj_opaque*>(P->opaque)->pipeline) - for (i = 0; i < static_cast<struct pj_opaque*>(P->opaque)->steps; i++) - proj_destroy (static_cast<struct pj_opaque*>(P->opaque)->pipeline[i+1]); - pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->pipeline); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); - pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->argv); - pj_dealloc (static_cast<struct pj_opaque*>(P->opaque)->current_argv); + pj_dealloc (pipeline->argv); + pj_dealloc (pipeline->current_argv); - for (i=0; i<4; i++) - delete static_cast<struct pj_opaque*>(P->opaque)->stack[i]; + delete pipeline; + P->opaque = nullptr; return pj_default_destructor(P, errlev); } -static PJ *pj_create_pipeline (PJ *P, size_t steps) { - - /* Room for the pipeline: An array of PJ * with room for sentinels at both ends */ - static_cast<struct pj_opaque*>(P->opaque)->pipeline = static_cast<PJ**>(pj_calloc (steps + 2, sizeof(PJ *))); - if (nullptr==static_cast<struct pj_opaque*>(P->opaque)->pipeline) - return nullptr; - - static_cast<struct pj_opaque*>(P->opaque)->steps = (int)steps; - - return P; -} - - - - /* count the number of args in pipeline definition, and mark all args as used */ static size_t argc_params (paralist *params) { size_t argc = 0; @@ -345,28 +370,30 @@ 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; +static enum pj_io_units get_next_non_whatever_unit(struct Pipeline* pipeline, size_t step, PJ_DIRECTION dir) { + const auto& steps = pipeline->steps; + const auto nsteps = steps.size(); 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]); + for (size_t i = step+1; i<nsteps; i++) { + auto pj = steps[i].pj; + if (pj_left(pj) != pj_right(pj)) + return pj_left(pj); + if (pj_left(pj) != PJ_IO_UNITS_WHATEVER) + return pj_left(pj); + if (pj_right(pj) != PJ_IO_UNITS_WHATEVER) + return pj_right(pj); } } 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]); + for (size_t i=step; i>0;) { + i--; + auto pj = steps[i].pj; + if (pj_right(pj) != pj_left(pj)) + return pj_right(pj); + if (pj_right(pj) != PJ_IO_UNITS_WHATEVER) + return pj_right(pj); + if (pj_left(pj) != PJ_IO_UNITS_WHATEVER) + return pj_left(pj); } } return PJ_IO_UNITS_WHATEVER; @@ -396,20 +423,17 @@ PJ *OPERATION(pipeline,0) { P->skip_inv_finalize = 1; - P->opaque = static_cast<struct pj_opaque*>(pj_calloc (1, sizeof(struct pj_opaque))); + P->opaque = new (std::nothrow) Pipeline(); if (nullptr==P->opaque) return destructor(P, ENOMEM); - /* initialize stack */ - for (i=0; i<4; i++) - static_cast<struct pj_opaque*>(P->opaque)->stack[i] = new std::stack<double>; - argc = (int)argc_params (P->params); - static_cast<struct pj_opaque*>(P->opaque)->argv = argv = argv_params (P->params, argc); + auto pipeline = static_cast<struct Pipeline*>(P->opaque); + pipeline->argv = argv = argv_params (P->params, argc); if (nullptr==argv) return destructor (P, ENOMEM); - static_cast<struct pj_opaque*>(P->opaque)->current_argv = current_argv = static_cast<char**>(pj_calloc (argc, sizeof (char *))); + pipeline->current_argv = current_argv = static_cast<char**>(pj_calloc (argc, sizeof (char *))); if (nullptr==current_argv) return destructor (P, ENOMEM); @@ -435,7 +459,6 @@ PJ *OPERATION(pipeline,0) { } } nsteps--; /* Last instance of +step is just a sentinel */ - static_cast<struct pj_opaque*>(P->opaque)->steps = nsteps; if (-1==i_pipeline) return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: no pipeline def */ @@ -443,10 +466,6 @@ PJ *OPERATION(pipeline,0) { if (0==nsteps) return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: no pipeline def */ - /* Make room for the pipeline and execution indicators */ - if (nullptr==pj_create_pipeline (P, nsteps)) - return destructor (P, ENOMEM); - set_ellipsoid(P); /* Now loop over all steps, building a new set of arguments for each init */ @@ -492,20 +511,23 @@ 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; } + } - static_cast<struct pj_opaque*>(P->opaque)->pipeline[i+1] = 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; + pipeline->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]); } /* Require a forward path through the pipeline */ - for (i = 1; i <= nsteps; i++) { - PJ *Q = static_cast<struct pj_opaque*>(P->opaque)->pipeline[i]; + for( auto& step: pipeline->steps) { + PJ *Q = step.pj; if ( ( Q->inverted && (Q->inv || Q->inv3d || Q->fwd4d) ) || (!Q->inverted && (Q->fwd || Q->fwd3d || Q->fwd4d) ) ) { continue; @@ -516,8 +538,8 @@ PJ *OPERATION(pipeline,0) { } /* determine if an inverse operation is possible */ - for (i = 1; i <= nsteps; i++) { - PJ *Q = static_cast<struct pj_opaque*>(P->opaque)->pipeline[i]; + for( auto& step: pipeline->steps) { + PJ *Q = step.pj; if ( pj_has_inverse(Q) ) { continue; } else { @@ -534,31 +556,33 @@ PJ *OPERATION(pipeline,0) { /* 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=0; i<nsteps; i++) { + auto pj = pipeline->steps[i].pj; + if (pj_left(pj) == PJ_IO_UNITS_WHATEVER && pj_right(pj) == PJ_IO_UNITS_WHATEVER) { + pj->left = get_next_non_whatever_unit(pipeline, i, PJ_FWD); + pj->right = get_next_non_whatever_unit(pipeline, 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); + for (i=nsteps; i>0;) { + --i; + auto pj = pipeline->steps[i].pj; + if (pj_left(pj) == PJ_IO_UNITS_WHATEVER && pj_right(pj) == PJ_IO_UNITS_WHATEVER) { + pj->right = get_next_non_whatever_unit(pipeline, i, PJ_INV); + pj->left = get_next_non_whatever_unit(pipeline, 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 curr_step_output = pj_right (pipeline[i]); - enum pj_io_units next_step_input = pj_left (pipeline[i+1]); + for (i = 0; i + 1 < nsteps; i++) { + enum pj_io_units curr_step_output = pj_right (pipeline->steps[i].pj); + enum pj_io_units next_step_input = pj_left (pipeline->steps[i+1].pj); if ( curr_step_output == PJ_IO_UNITS_WHATEVER || next_step_input == PJ_IO_UNITS_WHATEVER ) continue; if ( curr_step_output != next_step_input ) { - proj_log_error (P, "Pipeline: Mismatched units between step %d and %d", i, i+1); + proj_log_error (P, "Pipeline: Mismatched units between step %d and %d", i+1, i+2); return destructor (P, PJD_ERR_MALFORMED_PIPELINE); } } @@ -566,10 +590,10 @@ PJ *OPERATION(pipeline,0) { proj_log_trace (P, "Pipeline: %d steps built. Determining i/o characteristics", nsteps); /* Determine forward input (= reverse output) data type */ - P->left = pj_left (static_cast<struct pj_opaque*>(P->opaque)->pipeline[1]); + P->left = pj_left (pipeline->steps.front().pj); /* Now, correspondingly determine forward output (= reverse input) data type */ - P->right = pj_right (static_cast<struct pj_opaque*>(P->opaque)->pipeline[nsteps]); + P->right = pj_right (pipeline->steps.back().pj); return P; } @@ -577,17 +601,17 @@ static PJ_COORD push(PJ_COORD point, PJ *P) { if (P->parent == nullptr) return point; - struct pj_opaque *pipeline = static_cast<struct pj_opaque*>(P->parent->opaque); - struct pj_opaque_pushpop *opaque = static_cast<struct pj_opaque_pushpop*>(P->opaque); + struct Pipeline *pipeline = static_cast<struct Pipeline*>(P->parent->opaque); + struct PushPop *pushpop = static_cast<struct PushPop*>(P->opaque); - if (opaque->v1) - pipeline->stack[0]->push(point.v[0]); - if (opaque->v2) - pipeline->stack[1]->push(point.v[1]); - if (opaque->v3) - pipeline->stack[2]->push(point.v[2]); - if (opaque->v4) - pipeline->stack[3]->push(point.v[3]); + if (pushpop->v1) + pipeline->stack[0].push(point.v[0]); + if (pushpop->v2) + pipeline->stack[1].push(point.v[1]); + if (pushpop->v3) + pipeline->stack[2].push(point.v[2]); + if (pushpop->v4) + pipeline->stack[3].push(point.v[3]); return point; } @@ -596,27 +620,27 @@ static PJ_COORD pop(PJ_COORD point, PJ *P) { if (P->parent == nullptr) return point; - struct pj_opaque *pipeline = static_cast<struct pj_opaque*>(P->parent->opaque); - struct pj_opaque_pushpop *opaque = static_cast<struct pj_opaque_pushpop*>(P->opaque); + struct Pipeline *pipeline = static_cast<struct Pipeline*>(P->parent->opaque); + struct PushPop *pushpop = static_cast<struct PushPop*>(P->opaque); - if (opaque->v1 && !pipeline->stack[0]->empty()) { - point.v[0] = pipeline->stack[0]->top(); - pipeline->stack[0]->pop(); + if (pushpop->v1 && !pipeline->stack[0].empty()) { + point.v[0] = pipeline->stack[0].top(); + pipeline->stack[0].pop(); } - if (opaque->v2 && !pipeline->stack[1]->empty()) { - point.v[1] = pipeline->stack[1]->top(); - pipeline->stack[1]->pop(); + if (pushpop->v2 && !pipeline->stack[1].empty()) { + point.v[1] = pipeline->stack[1].top(); + pipeline->stack[1].pop(); } - if (opaque->v3 && !pipeline->stack[2]->empty()) { - point.v[2] = pipeline->stack[2]->top(); - pipeline->stack[2]->pop(); + if (pushpop->v3 && !pipeline->stack[2].empty()) { + point.v[2] = pipeline->stack[2].top(); + pipeline->stack[2].pop(); } - if (opaque->v4 && !pipeline->stack[3]->empty()) { - point.v[3] = pipeline->stack[3]->top(); - pipeline->stack[3]->pop(); + if (pushpop->v4 && !pipeline->stack[3].empty()) { + point.v[3] = pipeline->stack[3].top(); + pipeline->stack[3].pop(); } return point; @@ -625,21 +649,22 @@ static PJ_COORD pop(PJ_COORD point, PJ *P) { static PJ *setup_pushpop(PJ *P) { - P->opaque = static_cast<struct pj_opaque_pushpop*>(pj_calloc (1, sizeof(struct pj_opaque_pushpop))); + auto pushpop = static_cast<struct PushPop*>(pj_calloc (1, sizeof(struct PushPop))); + P->opaque = pushpop; if (nullptr==P->opaque) return destructor(P, ENOMEM); if (pj_param_exists(P->params, "v_1")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v1 = true; + pushpop->v1 = true; if (pj_param_exists(P->params, "v_2")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v2 = true; + pushpop->v2 = true; if (pj_param_exists(P->params, "v_3")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v3 = true; + pushpop->v3 = true; if (pj_param_exists(P->params, "v_4")) - static_cast<struct pj_opaque_pushpop*>(P->opaque)->v4 = true; + pushpop->v4 = true; P->left = PJ_IO_UNITS_WHATEVER; P->right = PJ_IO_UNITS_WHATEVER; |
