diff options
Diffstat (limited to 'src/apply_vgridshift.cpp')
| -rw-r--r-- | src/apply_vgridshift.cpp | 361 |
1 files changed, 0 insertions, 361 deletions
diff --git a/src/apply_vgridshift.cpp b/src/apply_vgridshift.cpp deleted file mode 100644 index daa44858..00000000 --- a/src/apply_vgridshift.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/****************************************************************************** - * Project: PROJ.4 - * Purpose: Apply vertical datum shifts based on grid shift files, normally - * geoid grids mapping WGS84 to NAVD88 or something similar. - * Author: Frank Warmerdam, warmerdam@pobox.com - * - ****************************************************************************** - * Copyright (c) 2010, Frank Warmerdam <warmerdam@pobox.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - *****************************************************************************/ - -#define PJ_LIB__ - -#include <assert.h> -#include <stdio.h> -#include <string.h> - -#include <math.h> -#include "proj_internal.h" - -static int is_nodata(float value, double vmultiplier) -{ - /* nodata? */ - /* GTX official nodata value if -88.88880f, but some grids also */ - /* use other big values for nodata (e.g naptrans2008.gtx has */ - /* nodata values like -2147479936), so test them too */ - return value * vmultiplier > 1000 || value * vmultiplier < -1000 || value == -88.88880f; -} - -static double read_vgrid_value( PJ *defn, PJ_LP input, double vmultiplier, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) { - int itable = 0; - double value = HUGE_VAL; - double grid_x, grid_y; - long grid_ix, grid_iy; - long grid_ix2, grid_iy2; - float *cvs; - /* do not deal with NaN coordinates */ - /* cppcheck-suppress duplicateExpression */ - if( isnan(input.phi) || isnan(input.lam) ) - itable = *gridlist_count_p; - - /* keep trying till we find a table that works */ - for ( ; itable < *gridlist_count_p; itable++ ) - { - PJ_GRIDINFO *gi = tables[itable]; - - ct = gi->ct; - - /* skip tables that don't match our point at all (latitude check). */ - if( ct->ll.phi > input.phi - || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi ) - continue; - - bool fullWorldLongExtent = false; - if( fabs(ct->lim.lam * ct->del.lam - 2 * M_PI) < 1e-10 ) - { - fullWorldLongExtent = true; - } - - /* skip tables that don't match our point at all (longitude check). */ - else if( ct->ll.lam > input.lam - || ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam ) - continue; - - /* If we have child nodes, check to see if any of them apply. */ - while( gi->child != nullptr ) - { - PJ_GRIDINFO *child; - - for( child = gi->child; child != nullptr; child = child->next ) - { - struct CTABLE *ct1 = child->ct; - - fullWorldLongExtent = false; - - if( ct1->ll.phi > input.phi - || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi) - continue; - - if( fabs(ct1->lim.lam * ct1->del.lam - 2 * M_PI) < 1e-10 ) - { - fullWorldLongExtent = true; - } - else if( ct1->ll.lam > input.lam - || ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam) - continue; - - break; - } - - /* we didn't find a more refined child node to use, so go with current grid */ - if( child == nullptr ) - { - break; - } - - /* Otherwise let's try for childrens children .. */ - gi = child; - ct = child->ct; - } - - /* load the grid shift info if we don't have it. */ - if( ct->cvs == nullptr ) - { - pj_gridinfo_load( pj_get_ctx(defn), gi ); - } - if( ct->cvs == nullptr ) - { - pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID ); - return PJD_ERR_FAILED_TO_LOAD_GRID; - } - - /* Interpolation a location within the grid */ - grid_x = (input.lam - ct->ll.lam) / ct->del.lam; - if( fullWorldLongExtent ) { - // The first fmod goes to ]-lim, lim[ range - // So we add lim again to be in ]0, 2*lim[ and fmod again - grid_x = fmod( - fmod(grid_x + ct->lim.lam, ct->lim.lam) + ct->lim.lam, - ct->lim.lam); - } - grid_y = (input.phi - ct->ll.phi) / ct->del.phi; - grid_ix = lround(floor(grid_x)); - assert(grid_ix >= 0 && grid_ix < ct->lim.lam); - grid_iy = lround(floor(grid_y)); - assert(grid_iy >= 0 && grid_iy < ct->lim.phi); - grid_x -= grid_ix; - grid_y -= grid_iy; - - grid_ix2 = grid_ix + 1; - if( grid_ix2 >= ct->lim.lam ) { - if( fullWorldLongExtent ) { - grid_ix2 = 0; - } else { - grid_ix2 = ct->lim.lam - 1; - } - } - grid_iy2 = grid_iy + 1; - if( grid_iy2 >= ct->lim.phi ) - grid_iy2 = ct->lim.phi - 1; - - cvs = (float *) ct->cvs; - { - float value_a = cvs[grid_ix + grid_iy * ct->lim.lam]; - float value_b = cvs[grid_ix2 + grid_iy * ct->lim.lam]; - float value_c = cvs[grid_ix + grid_iy2 * ct->lim.lam]; - float value_d = cvs[grid_ix2 + grid_iy2 * ct->lim.lam]; - double total_weight = 0.0; - int n_weights = 0; - value = 0.0f; - if( !is_nodata(value_a, vmultiplier) ) - { - double weight = (1.0-grid_x) * (1.0-grid_y); - value += value_a * weight; - total_weight += weight; - n_weights ++; - } - if( !is_nodata(value_b, vmultiplier) ) - { - double weight = (grid_x) * (1.0-grid_y); - value += value_b * weight; - total_weight += weight; - n_weights ++; - } - if( !is_nodata(value_c, vmultiplier) ) - { - double weight = (1.0-grid_x) * (grid_y); - value += value_c * weight; - total_weight += weight; - n_weights ++; - } - if( !is_nodata(value_d, vmultiplier) ) - { - double weight = (grid_x) * (grid_y); - value += value_d * weight; - total_weight += weight; - n_weights ++; - } - if( n_weights == 0 ) - value = HUGE_VAL; - else if( n_weights != 4 ) - value /= total_weight; - } - - } - - return value * vmultiplier; -} - -/************************************************************************/ -/* pj_apply_vgridshift() */ -/* */ -/* This implementation takes uses the gridlist from a coordinate */ -/* system definition. If the gridlist has not yet been */ -/* populated in the coordinate system definition we set it up */ -/* now. */ -/************************************************************************/ -int pj_apply_vgridshift( PJ *defn, const char *listname, - PJ_GRIDINFO ***gridlist_p, - int *gridlist_count_p, - int inverse, - long point_count, int point_offset, - double *x, double *y, double *z ) - -{ - int i; - static int debug_count = 0; - PJ_GRIDINFO **tables; - struct CTABLE ct; - - if( *gridlist_p == nullptr ) - { - *gridlist_p = - pj_gridlist_from_nadgrids( pj_get_ctx(defn), - pj_param(defn->ctx,defn->params,listname).s, - gridlist_count_p ); - - if( *gridlist_p == nullptr || *gridlist_count_p == 0 ) - return defn->ctx->last_errno; - } - - if( *gridlist_count_p == 0 ) - { - pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID); - return PJD_ERR_FAILED_TO_LOAD_GRID; - } - - tables = *gridlist_p; - defn->ctx->last_errno = 0; - - for( i = 0; i < point_count; i++ ) - { - double value; - long io = i * point_offset; - PJ_LP input; - - input.phi = y[io]; - input.lam = x[io]; - - value = read_vgrid_value(defn, input, 1.0, gridlist_count_p, tables, &ct); - - if( inverse ) - z[io] -= value; - else - z[io] += value; - if( value != HUGE_VAL ) - { - if( debug_count++ < 20 ) { - proj_log_trace(defn, "pj_apply_gridshift(): used %s", ct.id); - break; - } - } - - if( value == HUGE_VAL ) - { - int itable; - std::string gridlist; - - proj_log_debug(defn, - "pj_apply_vgridshift(): failed to find a grid shift table for\n" - " location (%.7fdW,%.7fdN)", - x[io] * RAD_TO_DEG, - y[io] * RAD_TO_DEG ); - - for( itable = 0; itable < *gridlist_count_p; itable++ ) - { - PJ_GRIDINFO *gi = tables[itable]; - if( itable == 0 ) - gridlist += " tried: "; - else - gridlist += ','; - gridlist += gi->gridname; - } - - proj_log_debug(defn, "%s", gridlist.c_str()); - pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA ); - - return PJD_ERR_GRID_AREA; - } - } - - return 0; -} - -/**********************************************/ -int proj_vgrid_init(PJ* P, const char *grids) { -/********************************************** - - Initizalize and populate gridlist. - - Takes a PJ-object and the plus-parameter - name that is used in the proj-string to - specify the grids to load, e.g. "+grids". - The + should be left out here. - - Returns the number of loaded grids. - -***********************************************/ - - /* prepend "s" to the "grids" string to allow usage with pj_param */ - char *sgrids = (char *) pj_malloc( (strlen(grids)+1+1) *sizeof(char) ); - sprintf(sgrids, "%s%s", "s", grids); - - if (P->vgridlist_geoid == nullptr) { - P->vgridlist_geoid = pj_gridlist_from_nadgrids( - P->ctx, - pj_param(P->ctx, P->params, sgrids).s, - &(P->vgridlist_geoid_count) - ); - - if( P->vgridlist_geoid == nullptr || P->vgridlist_geoid_count == 0 ) { - pj_dealloc(sgrids); - return 0; - } - } - - if (P->vgridlist_geoid_count == 0) { - proj_errno_set(P, PJD_ERR_FAILED_TO_LOAD_GRID); - } - - pj_dealloc(sgrids); - return P->vgridlist_geoid_count; -} - -/***********************************************/ -double proj_vgrid_value(PJ *P, PJ_LP lp, double vmultiplier){ -/*********************************************** - - Read grid value at position lp in grids loaded - with proj_grid_init. - - Returns the grid value of the given coordinate. - -************************************************/ - - struct CTABLE used_grid; - double value; - memset(&used_grid, 0, sizeof(struct CTABLE)); - - value = read_vgrid_value(P, lp, vmultiplier, &(P->vgridlist_geoid_count), P->vgridlist_geoid, &used_grid); - proj_log_trace(P, "proj_vgrid_value: (%f, %f) = %f", lp.lam*RAD_TO_DEG, lp.phi*RAD_TO_DEG, value); - - return value; -} |
