aboutsummaryrefslogtreecommitdiff
path: root/src/transformations/vgridshift.cpp
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2020-01-22 18:31:26 +0100
committerGitHub <noreply@github.com>2020-01-22 18:31:26 +0100
commitdb31b6dfa9c8fe37d5706d95ce81012b8db3c3b9 (patch)
treedc592c2b56f8af476c42a51f5dbc6ee04fabc280 /src/transformations/vgridshift.cpp
parent1ad703a58ce1867fe2ede96ebced1bdec9c63d65 (diff)
downloadPROJ-db31b6dfa9c8fe37d5706d95ce81012b8db3c3b9.tar.gz
PROJ-db31b6dfa9c8fe37d5706d95ce81012b8db3c3b9.zip
Merge RFC4 (#1865)
This commit is the result of the squashing of rfc4_dev branch in a single commit. It implements mostly RFC 4 related work. * Grid handling: - remove obsolete and presumably unfinished implementation of grid catalog functionality - all grid functionality is in grids.cpp/.hpp - vertical and horizontal grid shift: rework to no longer load whole grid into memory - remove hgrids and vgrids member from PJ structure, and store them in hgridshift/vgridshift/deformation structures - build systems: add optional libtiff dependency. Must be explicitly disabled if not desired - add support for horizontal and vertical grids in GeoTIFF, if libtiff is available - add GenericShiftGridSet and GenericShiftGrid classes, relying on TIFF grids, that can be used for generic purpose grid-based adjustment - add a +proj=xyzgridshift method to perform geocentric translation by grid. Used for French NTF to RGF93 transformation using gr3df97a.tif grid - deformation: add support for +grids= for GeoTIFF grids - horizontal grid shift: fix failures on points slightly outside a subgrid (fixes #209) * File management: - add a filemanager.cpp/.hpp to deal with file related work - test for legacy proj_api.h fileapi - proj.h: add proj_context_set_fileapi() and proj_context_set_sqlite3_vfs_name() (fixes #866) - add capability to read resource files from the user writable directory * Network access: - build systems: add optional curl dependency - add a curl-based default implementation for network related functionality - proj.h: add C API to control network functionality, and optionaly provide network callbacks - add data/proj.ini with default settings - add a SQLite3 local cache of downloaded chunks - add proj_is_download_needed() and proj_download_file() * Use Win32 Unicode APIs and expect all strings to be UTF-8 (fixes #1765) For backward compatibility, if PROJ_LIB content is found to be not UTF-8 or pointing to a non existing directory, then an attempt at interpretating it in the ANSI page encoding is done. proj_context_set_search_paths() now assumes strings to be in UTF-8, and functions returning paths will also return values in UTF-8.
Diffstat (limited to 'src/transformations/vgridshift.cpp')
-rw-r--r--src/transformations/vgridshift.cpp119
1 files changed, 96 insertions, 23 deletions
diff --git a/src/transformations/vgridshift.cpp b/src/transformations/vgridshift.cpp
index de0cdd8c..121b795a 100644
--- a/src/transformations/vgridshift.cpp
+++ b/src/transformations/vgridshift.cpp
@@ -6,26 +6,67 @@
#include <time.h>
#include "proj_internal.h"
+#include "grids.hpp"
PROJ_HEAD(vgridshift, "Vertical grid shift");
+using namespace NS_PROJ;
+
namespace { // anonymous namespace
-struct pj_opaque_vgridshift {
- double t_final;
- double t_epoch;
- double forward_multiplier;
+struct vgridshiftData {
+ double t_final = 0;
+ 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 pj_opaque_vgridshift *Q = (struct pj_opaque_vgridshift *) P->opaque;
+ struct vgridshiftData *Q = (struct vgridshiftData *) P->opaque;
PJ_COORD point = {{0,0,0,0}};
point.lpz = lpz;
- if (P->vgridlist_geoid != nullptr) {
+ if ( Q->defer_grid_opening ) {
+ Q->defer_grid_opening = false;
+ Q->grids = pj_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. */
- point.xyz.z += proj_vgrid_value(P, point.lp, Q->forward_multiplier);
+ point.xyz.z += pj_vgrid_value(P, Q->grids, point.lp, Q->forward_multiplier);
}
return point.xyz;
@@ -33,14 +74,23 @@ static PJ_XYZ forward_3d(PJ_LPZ lpz, PJ *P) {
static PJ_LPZ reverse_3d(PJ_XYZ xyz, PJ *P) {
- struct pj_opaque_vgridshift *Q = (struct pj_opaque_vgridshift *) P->opaque;
+ struct vgridshiftData *Q = (struct vgridshiftData *) P->opaque;
PJ_COORD point = {{0,0,0,0}};
point.xyz = xyz;
- if (P->vgridlist_geoid != nullptr) {
+ if ( Q->defer_grid_opening ) {
+ Q->defer_grid_opening = false;
+ Q->grids = pj_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. */
- point.xyz.z -= proj_vgrid_value(P, point.lp, Q->forward_multiplier);
+ point.xyz.z -= pj_vgrid_value(P, Q->grids, point.lp, Q->forward_multiplier);
}
return point.lpz;
@@ -48,7 +98,7 @@ static PJ_LPZ reverse_3d(PJ_XYZ xyz, PJ *P) {
static PJ_COORD forward_4d(PJ_COORD obs, PJ *P) {
- struct pj_opaque_vgridshift *Q = (struct pj_opaque_vgridshift *) P->opaque;
+ struct vgridshiftData *Q = (struct vgridshiftData *) P->opaque;
PJ_COORD point = obs;
/* If transformation is not time restricted, we always call it */
@@ -66,7 +116,7 @@ static PJ_COORD forward_4d(PJ_COORD obs, PJ *P) {
}
static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) {
- struct pj_opaque_vgridshift *Q = (struct pj_opaque_vgridshift *) P->opaque;
+ struct vgridshiftData *Q = (struct vgridshiftData *) P->opaque;
PJ_COORD point = obs;
/* If transformation is not time restricted, we always call it */
@@ -82,16 +132,34 @@ static PJ_COORD reverse_4d(PJ_COORD obs, PJ *P) {
return point;
}
+static PJ *destructor (PJ *P, int errlev) {
+ if (nullptr==P)
+ return nullptr;
+
+ delete static_cast<struct vgridshiftData*>(P->opaque);
+ P->opaque = nullptr;
+
+ 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) {
- struct pj_opaque_vgridshift *Q = static_cast<struct pj_opaque_vgridshift*>(pj_calloc (1, sizeof (struct pj_opaque_vgridshift)));
- if (nullptr==Q)
- return pj_default_destructor (P, ENOMEM);
+ 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.");
- return pj_default_destructor(P, PJD_ERR_NO_ARGS);
+ return destructor(P, PJD_ERR_NO_ARGS);
}
/* TODO: Refactor into shared function that can be used */
@@ -120,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. */
- 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 pj_default_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 = pj_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;