aboutsummaryrefslogtreecommitdiff
path: root/src/PJ_pipeline.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/PJ_pipeline.c')
-rw-r--r--src/PJ_pipeline.c110
1 files changed, 50 insertions, 60 deletions
diff --git a/src/PJ_pipeline.c b/src/PJ_pipeline.c
index 2b012193..af9c5394 100644
--- a/src/PJ_pipeline.c
+++ b/src/PJ_pipeline.c
@@ -72,7 +72,7 @@
Thomas Knudsen, thokn@sdfe.dk, 2016-05-20
********************************************************************************
-* Copyright (c) 2016, Thomas Knudsen / SDFE
+* Copyright (c) 2016, 2017, 2018 Thomas Knudsen / SDFE
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -96,6 +96,7 @@ Thomas Knudsen, thokn@sdfe.dk, 2016-05-20
#define PJ_LIB__
#include <geodesic.h>
+#include <proj.h>
#include "proj_internal.h"
#include "projects.h"
@@ -107,7 +108,6 @@ PROJ_HEAD(pipeline, "Transformation pipeline manager");
struct pj_opaque {
int reversible;
int steps;
- int verbose;
char **argv;
char **current_argv;
PJ **pipeline;
@@ -124,52 +124,6 @@ static LP pipeline_reverse (XY xyz, PJ *P);
-/********************************************************************
-
- ISOMORPHIC TRANSFORMATIONS
-
-*********************************************************************
-
- In this context, an isomorphic transformation is a proj PJ
- object returning the same kind of coordinates that it
- receives, i.e. a transformation from angular to angular or
- linear to linear coordinates.
-
- The degrees-to-radians operation is an example of the former,
- while the latter is typical for most of the datum shift
- operations used in geodesy, e.g. the Helmert 7-parameter shift.
-
- Isomorphic transformations trips up the pj_inv/pj_fwd
- functions, which try to check input sanity and scale output to
- internal proj units, under the assumption that if input is of
- angular type, then output must be of linear (or vice versa).
-
- Hence, to avoid having pj_inv/pj_fwd stomping on output (or
- choking on input), we need a way to tell them that they should
- accept whatever is being handed to them.
-
- The P->left and P->right elements indicate isomorphism.
-
- For classic proj style projections, P->left has the value
- PJ_IO_UNITS_RADIANS, while P->right has the value
- PJ_IO_UNITS_CLASSIC, indicating that the forward driver expects
- angular input coordinates, and provides linear output coordinates,
- scaled by the P->a semimajor axis length.
-
- Newer projections may set P->left and P->right to either
- PJ_IO_UNITS_METERS, PJ_IO_UNITS_RADIANS or PJ_IO_UNITS_ANY,
- to indicate their I/O style.
-
- For the forward driver, left indicates input coordinate
- type, while right indicates output coordinate type.
-
- For the inverse driver, left indicates output coordinate
- type, while right indicates input coordinate type.
-
-*********************************************************************/
-
-
-
static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) {
int i, first_step, last_step;
@@ -184,7 +138,6 @@ static PJ_COORD pipeline_forward_4d (PJ_COORD point, PJ *P) {
}
-
static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) {
int i, first_step, last_step;
@@ -198,37 +151,59 @@ static PJ_COORD pipeline_reverse_4d (PJ_COORD point, PJ *P) {
}
-/* Delegate the work to pipeline_forward_4d() */
+
+
static XYZ pipeline_forward_3d (LPZ lpz, PJ *P) {
PJ_COORD point = {{0,0,0,0}};
+ int i;
point.lpz = lpz;
- point = pipeline_forward_4d (point, P);
+
+ for (i = 1; i <= P->opaque->steps; i++)
+ point = pj_approx_3D_trans (P->opaque->pipeline[i], 1, point);
+
return point.xyz;
}
-/* Delegate the work to pipeline_reverse_4d() */
+
static LPZ pipeline_reverse_3d (XYZ xyz, PJ *P) {
PJ_COORD point = {{0,0,0,0}};
+ int i;
point.xyz = xyz;
- point = pipeline_reverse_4d (point, P);
+
+ for (i = P->opaque->steps; i > 0 ; i--)
+ point = pj_approx_3D_trans (P->opaque->pipeline[i], -1, point);
+
return point.lpz;
}
+
+
+
static XY pipeline_forward (LP lp, PJ *P) {
PJ_COORD point = {{0,0,0,0}};
+ int i;
point.lp = lp;
- point = pipeline_forward_4d (point, P);
+
+ for (i = 1; i <= P->opaque->steps; i++)
+ point = pj_approx_2D_trans (P->opaque->pipeline[i], 1, point);
+
return point.xy;
}
+
static LP pipeline_reverse (XY xy, PJ *P) {
PJ_COORD point = {{0,0,0,0}};
+ int i;
point.xy = xy;
- point = pipeline_reverse_4d (point, P);
+ for (i = P->opaque->steps; i > 0 ; i--)
+ point = pj_approx_2D_trans (P->opaque->pipeline[i], -1, point);
+
return point.lp;
}
+
+
static void *destructor (PJ *P, int errlev) {
int i;
if (0==P)
@@ -240,8 +215,7 @@ static void *destructor (PJ *P, int errlev) {
/* Deallocate each pipeine step, then pipeline array */
if (0!=P->opaque->pipeline)
for (i = 0; i < P->opaque->steps; i++)
- if (0!=P->opaque->pipeline[i+1])
- P->opaque->pipeline[i+1]->destructor (P->opaque->pipeline[i+1], errlev);
+ proj_destroy (P->opaque->pipeline[i+1]);
pj_dealloc (P->opaque->pipeline);
pj_dealloc (P->opaque->argv);
@@ -264,6 +238,8 @@ static PJ *pj_create_pipeline (PJ *P, size_t steps) {
}
+
+
/* count the number of args in pipeline definition */
static size_t argc_params (paralist *params) {
size_t argc = 0;
@@ -288,6 +264,9 @@ static char **argv_params (paralist *params, size_t argc) {
return argv;
}
+
+
+
/* Being the special operator that the pipeline is, we have to handle the */
/* ellipsoid differently than usual. In general, the pipeline operation does */
/* not need an ellipsoid, but in some cases it is beneficial nonetheless. */
@@ -335,18 +314,29 @@ static void set_ellipsoid(PJ *P) {
}
+
+
PJ *OPERATION(pipeline,0) {
int i, nsteps = 0, argc;
int i_pipeline = -1, i_first_step = -1, i_current_step;
char **argv, **current_argv;
- P->fwd4d = pipeline_forward_4d;
- P->inv4d = pipeline_reverse_4d;
+ P->fwd4d = pipeline_forward_4d;
+ P->inv4d = pipeline_reverse_4d;
P->fwd3d = pipeline_forward_3d;
P->inv3d = pipeline_reverse_3d;
P->fwd = pipeline_forward;
P->inv = pipeline_reverse;
P->destructor = destructor;
+ P->is_pipeline = 1;
+
+ /* Currently, the pipeline driver is a raw bit mover, enabling other operations */
+ /* to collaborate efficiently. All prep/fin stuff is done at the step levels. */
+ P->skip_fwd_prepare = 1;
+ P->skip_fwd_finalize = 1;
+ P->skip_inv_prepare = 1;
+ P->skip_inv_finalize = 1;
+
P->opaque = pj_calloc (1, sizeof(struct pj_opaque));
if (0==P->opaque)
@@ -376,7 +366,7 @@ PJ *OPERATION(pipeline,0) {
if (0==strcmp ("proj=pipeline", argv[i])) {
if (-1 != i_pipeline) {
- proj_log_error (P, "Pipeline: Nesting only allowed when child pipelines are wrapped in +init's");
+ proj_log_error (P, "Pipeline: Nesting only allowed when child pipelines are wrapped in '+init's");
return destructor (P, PJD_ERR_MALFORMED_PIPELINE); /* ERROR: nested pipelines */
}
i_pipeline = i;