aboutsummaryrefslogtreecommitdiff
path: root/src/transformations/vgridshift.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/transformations/vgridshift.cpp')
-rw-r--r--src/transformations/vgridshift.cpp75
1 files changed, 68 insertions, 7 deletions
diff --git a/src/transformations/vgridshift.cpp b/src/transformations/vgridshift.cpp
index b964f45b..3e7a015e 100644
--- a/src/transformations/vgridshift.cpp
+++ b/src/transformations/vgridshift.cpp
@@ -18,14 +18,51 @@ struct vgridshiftData {
double t_epoch = 0;
double forward_multiplier = 0;
ListOfVGrids grids{};
+ bool defer_grid_opening = false;
};
} // anonymous namespace
+static void deal_with_vertcon_gtx_hack(PJ *P)
+{
+ struct vgridshiftData *Q = (struct vgridshiftData *) P->opaque;
+ // The .gtx VERTCON files stored millimetres, but the .tif files
+ // are in metres.
+ if( Q->forward_multiplier != 0.001 ) {
+ return;
+ }
+ const char* gridname = pj_param(P->ctx, P->params, "sgrids").s;
+ if( !gridname ) {
+ return;
+ }
+ if( strcmp(gridname, "vertconw.gtx") != 0 &&
+ strcmp(gridname, "vertconc.gtx") != 0 &&
+ strcmp(gridname, "vertcone.gtx") != 0 ) {
+ return;
+ }
+ if( Q->grids.empty() ) {
+ return;
+ }
+ const auto& grids = Q->grids[0]->grids();
+ if( !grids.empty() &&
+ grids[0]->name().find(".tif") != std::string::npos ) {
+ Q->forward_multiplier = 1.0;
+ }
+}
+
static PJ_XYZ forward_3d(PJ_LPZ lpz, PJ *P) {
struct vgridshiftData *Q = (struct vgridshiftData *) P->opaque;
PJ_COORD point = {{0,0,0,0}};
point.lpz = lpz;
+ if ( Q->defer_grid_opening ) {
+ Q->defer_grid_opening = false;
+ Q->grids = proj_vgrid_init(P, "grids");
+ deal_with_vertcon_gtx_hack(P);
+ if ( proj_errno(P) ) {
+ return proj_coord_error().xyz;
+ }
+ }
+
if (!Q->grids.empty()) {
/* Only try the gridshift if at least one grid is loaded,
* otherwise just pass the coordinate through unchanged. */
@@ -41,6 +78,15 @@ static PJ_LPZ reverse_3d(PJ_XYZ xyz, PJ *P) {
PJ_COORD point = {{0,0,0,0}};
point.xyz = xyz;
+ if ( Q->defer_grid_opening ) {
+ Q->defer_grid_opening = false;
+ Q->grids = proj_vgrid_init(P, "grids");
+ deal_with_vertcon_gtx_hack(P);
+ if ( proj_errno(P) ) {
+ return proj_coord_error().lpz;
+ }
+ }
+
if (!Q->grids.empty()) {
/* Only try the gridshift if at least one grid is loaded,
* otherwise just pass the coordinate through unchanged. */
@@ -96,10 +142,20 @@ static PJ *destructor (PJ *P, int errlev) {
return pj_default_destructor(P, errlev);
}
+static void reassign_context( PJ* P, PJ_CONTEXT* ctx )
+{
+ auto Q = (struct vgridshiftData *) P->opaque;
+ for( auto& grid: Q->grids ) {
+ grid->reassign_context(ctx);
+ }
+}
+
+
PJ *TRANSFORMATION(vgridshift,0) {
auto Q = new vgridshiftData;
P->opaque = (void *) Q;
P->destructor = destructor;
+ P->reassign_context = reassign_context;
if (!pj_param(P->ctx, P->params, "tgrids").i) {
proj_log_error(P, "vgridshift: +grids parameter missing.");
@@ -132,13 +188,18 @@ PJ *TRANSFORMATION(vgridshift,0) {
Q->forward_multiplier = pj_param(P->ctx, P->params, "dmultiplier").f;
}
- /* Build gridlist. P->vgridlist_geoid can be empty if +grids only ask for optional grids. */
- Q->grids = proj_vgrid_init(P, "grids");
-
- /* Was gridlist compiled properly? */
- if ( proj_errno(P) ) {
- proj_log_error(P, "vgridshift: could not find required grid(s).");
- return destructor(P, PJD_ERR_FAILED_TO_LOAD_GRID);
+ if( P->ctx->defer_grid_opening ) {
+ Q->defer_grid_opening = true;
+ }
+ else {
+ /* Build gridlist. P->vgridlist_geoid can be empty if +grids only ask for optional grids. */
+ Q->grids = proj_vgrid_init(P, "grids");
+
+ /* Was gridlist compiled properly? */
+ if ( proj_errno(P) ) {
+ proj_log_error(P, "vgridshift: could not find required grid(s).");
+ return destructor(P, PJD_ERR_FAILED_TO_LOAD_GRID);
+ }
}
P->fwd4d = forward_4d;