aboutsummaryrefslogtreecommitdiff
path: root/src/pj_apply_vgridshift.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pj_apply_vgridshift.c')
-rw-r--r--src/pj_apply_vgridshift.c305
1 files changed, 187 insertions, 118 deletions
diff --git a/src/pj_apply_vgridshift.c b/src/pj_apply_vgridshift.c
index 35047a19..3c7cc210 100644
--- a/src/pj_apply_vgridshift.c
+++ b/src/pj_apply_vgridshift.c
@@ -28,23 +28,120 @@
#define PJ_LIB__
-#include <projects.h>
#include <string.h>
#include <math.h>
+#include "proj_internal.h"
+#include "projects.h"
+
+static double pj_read_vgrid_value( PJ *defn, LP input, int *gridlist_count_p, PJ_GRIDINFO **tables, struct CTABLE *ct) {
+ int itable = 0;
+ double value = HUGE_VAL;
+ double grid_x, grid_y;
+ int grid_ix, grid_iy;
+ int grid_ix2, grid_iy2;
+ float *cvs;
+ /* do not deal with NaN coordinates */
+ if( input.phi != input.phi || input.lam != 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. */
+ if( ct->ll.phi > input.phi || ct->ll.lam > input.lam
+ || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi
+ || 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 != NULL )
+ {
+ PJ_GRIDINFO *child;
+
+ for( child = gi->child; child != NULL; child = child->next )
+ {
+ struct CTABLE *ct1 = child->ct;
+
+ if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam
+ || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi
+ || 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 == NULL )
+ {
+ 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 == NULL && !pj_gridinfo_load( pj_get_ctx(defn), gi ) )
+ {
+ 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;
+ grid_y = (input.phi - ct->ll.phi) / ct->del.phi;
+ grid_ix = (int) floor(grid_x);
+ grid_iy = (int) floor(grid_y);
+ grid_x -= grid_ix;
+ grid_y -= grid_iy;
+
+ grid_ix2 = grid_ix + 1;
+ if( grid_ix2 >= ct->lim.lam )
+ 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;
+ value = cvs[grid_ix + grid_iy * ct->lim.lam]
+ * (1.0-grid_x) * (1.0-grid_y)
+ + cvs[grid_ix2 + grid_iy * ct->lim.lam]
+ * (grid_x) * (1.0-grid_y)
+ + cvs[grid_ix + grid_iy2 * ct->lim.lam]
+ * (1.0-grid_x) * (grid_y)
+ + cvs[grid_ix2 + grid_iy2 * ct->lim.lam]
+ * (grid_x) * (grid_y);
+
+ /* 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 */
+ if( value > 1000 || value < -1000 || value == -88.88880f )
+ value = HUGE_VAL;
+
+
+ return value;
+}
/************************************************************************/
/* pj_apply_vgridshift() */
/* */
-/* This implementation takes uses the gridlist from a coordinate */
+/* 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,
+ PJ_GRIDINFO ***gridlist_p,
int *gridlist_count_p,
- int inverse,
+ int inverse,
long point_count, int point_offset,
double *x, double *y, double *z )
@@ -52,22 +149,23 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
int i;
static int debug_count = 0;
PJ_GRIDINFO **tables;
+ struct CTABLE ct;
if( *gridlist_p == NULL )
{
- *gridlist_p =
- pj_gridlist_from_nadgrids( pj_get_ctx(defn),
+ *gridlist_p =
+ pj_gridlist_from_nadgrids( pj_get_ctx(defn),
pj_param(defn->ctx,defn->params,listname).s,
gridlist_count_p );
if( *gridlist_p == NULL || *gridlist_count_p == 0 )
return defn->ctx->last_errno;
}
-
+
if( *gridlist_count_p == 0 )
{
- pj_ctx_set_errno( defn->ctx, -38);
- return -38;
+ pj_ctx_set_errno( defn->ctx, PJD_ERR_FAILED_TO_LOAD_GRID);
+ return PJD_ERR_FAILED_TO_LOAD_GRID;
}
tables = *gridlist_p;
@@ -75,127 +173,37 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
for( i = 0; i < point_count; i++ )
{
+ double value;
long io = i * point_offset;
LP input;
- int itable = 0;
- double value = HUGE_VAL;
input.phi = y[io];
input.lam = x[io];
- /* do not deal with NaN coordinates */
- if( input.phi != input.phi || input.lam != input.lam )
- itable = *gridlist_count_p;
+ value = pj_read_vgrid_value(defn, input, gridlist_count_p, tables, &ct);
- /* keep trying till we find a table that works */
- for( ; itable < *gridlist_count_p; itable++ )
+ if( inverse )
+ z[io] -= value;
+ else
+ z[io] += value;
+ if( value != HUGE_VAL )
{
- PJ_GRIDINFO *gi = tables[itable];
- struct CTABLE *ct = gi->ct;
- double grid_x, grid_y;
- int grid_ix, grid_iy;
- int grid_ix2, grid_iy2;
- float *cvs;
-
- /* skip tables that don't match our point at all. */
- if( ct->ll.phi > input.phi || ct->ll.lam > input.lam
- || ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi
- || 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 != NULL )
- {
- PJ_GRIDINFO *child;
-
- for( child = gi->child; child != NULL; child = child->next )
- {
- struct CTABLE *ct1 = child->ct;
-
- if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam
- || ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi
- || 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 == NULL )
- {
- 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 == NULL && !pj_gridinfo_load( pj_get_ctx(defn), gi ) )
- {
- pj_ctx_set_errno( defn->ctx, -38 );
- return -38;
- }
-
- /* Interpolation a location within the grid */
- grid_x = (input.lam - ct->ll.lam) / ct->del.lam;
- grid_y = (input.phi - ct->ll.phi) / ct->del.phi;
- grid_ix = (int) floor(grid_x);
- grid_iy = (int) floor(grid_y);
- grid_x -= grid_ix;
- grid_y -= grid_iy;
-
- grid_ix2 = grid_ix + 1;
- if( grid_ix2 >= ct->lim.lam )
- 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;
- value = cvs[grid_ix + grid_iy * ct->lim.lam]
- * (1.0-grid_x) * (1.0-grid_y)
- + cvs[grid_ix2 + grid_iy * ct->lim.lam]
- * (grid_x) * (1.0-grid_y)
- + cvs[grid_ix + grid_iy2 * ct->lim.lam]
- * (1.0-grid_x) * (grid_y)
- + cvs[grid_ix2 + grid_iy2 * ct->lim.lam]
- * (grid_x) * (grid_y);
-
- /* 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 */
- if( value > 1000 || value < -1000 || value == -88.88880f )
- value = HUGE_VAL;
- else
- {
- if( inverse )
- z[io] -= value;
- else
- z[io] += value;
- }
-
- if( value != HUGE_VAL )
- {
- if( debug_count++ < 20 )
- pj_log( defn->ctx, PJ_LOG_DEBUG_MINOR,
- "pj_apply_gridshift(): used %s",
- ct->id );
+ if( debug_count++ < 20 ) {
+ proj_log_trace(defn, "pj_apply_gridshift(): used %s", ct.id);
break;
}
}
if( value == HUGE_VAL )
{
+ int itable;
char gridlist[3000];
- pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
- "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 );
+ 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 );
gridlist[0] = '\0';
for( itable = 0; itable < *gridlist_count_p; itable++ )
@@ -212,10 +220,10 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
else
sprintf( gridlist+strlen(gridlist), ",%s", gi->gridname );
}
- pj_log( defn->ctx, PJ_LOG_DEBUG_MAJOR,
- "%s", gridlist );
-
+
+ proj_log_debug(defn, "%s", gridlist);
pj_ctx_set_errno( defn->ctx, PJD_ERR_GRID_AREA );
+
return PJD_ERR_GRID_AREA;
}
}
@@ -223,3 +231,64 @@ int pj_apply_vgridshift( PJ *defn, const char *listname,
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 == NULL) {
+ 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 == NULL || 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, LP lp){
+/***********************************************
+
+ 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 = pj_read_vgrid_value(P, lp, &(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;
+}
+