1
1
/******************************************************************************
2
* $Id: pj_apply_gridshift.c,v 1.2 2001/03/15 16:57:55 warmerda Exp $
2
* $Id: pj_apply_gridshift.c,v 1.8 2003/03/20 21:29:41 warmerda Exp $
5
5
* Purpose: Apply datum shifts based on grid shift files (normally NAD27 to
6
6
* NAD83 or the reverse). This module is responsible for keeping
7
7
* a list of loaded grids, and calling with each one that is
8
8
* allowed for a given datum (expressed as the nadgrids= parameter).
9
* Author: Frank Warmerdam, warmerda@home.com
9
* Author: Frank Warmerdam, warmerdam@pobox.com
11
11
******************************************************************************
12
* Copyright (c) 2000, Frank Warmerdam
12
* Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
14
14
* Permission is hereby granted, free of charge, to any person obtaining a
15
15
* copy of this software and associated documentation files (the "Software"),
31
31
******************************************************************************
33
33
* $Log: pj_apply_gridshift.c,v $
34
* Revision 1.8 2003/03/20 21:29:41 warmerda
35
* Fixed bug in checking against grid bounds.
37
* Revision 1.7 2003/03/17 19:45:23 warmerda
38
* improved error handling
40
* Revision 1.6 2003/03/17 18:56:34 warmerda
41
* implement heirarchical NTv2 gridinfos
43
* Revision 1.5 2003/03/15 06:02:02 warmerda
44
* preliminary NTv2 support, major restructure of datum shifting
46
* Revision 1.4 2002/07/08 02:32:05 warmerda
47
* ensure clean C++ builds
49
* Revision 1.3 2002/04/30 16:27:27 warmerda
50
* improve debug output
34
52
* Revision 1.2 2001/03/15 16:57:55 warmerda
35
53
* fixed intermittent problem in pj_load_nadgrids()
45
63
#include <string.h>
50
/* used only by pj_get_grid() and pj_deallocate_grids() */
51
static int grid_count = 0;
52
static char **grid_names = NULL;
53
static struct CTABLE **grid_list = NULL;
55
/* used only by pj_load_nadgrids() and pj_deallocate_grids() */
56
static struct CTABLE **last_nadgrids_list = NULL;
57
static char *last_nadgrids = NULL;
59
/************************************************************************/
60
/* pj_deallocate_grids() */
62
/* Deallocate all loaded grids. */
63
/************************************************************************/
65
void pj_deallocate_grids()
72
for( i = 0; i < grid_count; i++ )
74
if( grid_list[i] != NULL )
75
nad_free( grid_list[i] );
76
pj_dalloc( grid_names[i] );
79
pj_dalloc( grid_names );
80
pj_dalloc( grid_list );
88
if( last_nadgrids != NULL )
90
pj_dalloc( last_nadgrids );
93
pj_dalloc( last_nadgrids_list );
94
last_nadgrids_list = NULL;
98
/************************************************************************/
101
/* Find the requested grid in the list, or if not present, try */
102
/* and load it. On failure returns NULL and sets pj_errno. */
103
/************************************************************************/
105
static struct CTABLE *pj_get_grid( const char *name )
110
/* -------------------------------------------------------------------- */
111
/* First look in the existing list. */
112
/* -------------------------------------------------------------------- */
113
for( i = 0; i < grid_count; i++ )
115
if( strcmp( grid_names[i], name ) == 0 )
117
if( grid_list[i] == NULL )
124
/* -------------------------------------------------------------------- */
125
/* Add entry for this file in the grid list. */
126
/* -------------------------------------------------------------------- */
127
if( grid_count == 0 )
129
grid_names = pj_malloc(sizeof(char *) * GRID_MAX);
130
memset( grid_names, 0, sizeof(char *) * GRID_MAX );
131
grid_list = pj_malloc(sizeof(struct CTABLE *) * GRID_MAX );
132
memset( grid_list, 0, sizeof(struct CTABLE *) * GRID_MAX );
134
else if( grid_count >= GRID_MAX )
142
grid_names[grid_count-1] = (char *) pj_malloc(strlen(name)+1);
143
strcpy( grid_names[grid_count-1], name );
145
/* -------------------------------------------------------------------- */
147
/* -------------------------------------------------------------------- */
148
grid_list[grid_count-1] = nad_init( (char *) name );
150
return grid_list[grid_count-1];
153
/************************************************************************/
154
/* pj_load_nadgrids() */
156
/* This functions loads the list of grids corresponding to a */
157
/* particular nadgrids string into a list, and returns it. The */
158
/* list is kept around till a request is made with a different */
159
/* string in order to cut down on the string parsing cost, and */
160
/* the cost of building the list of tables each time. */
161
/************************************************************************/
163
static struct CTABLE **pj_load_nadgrids( const char *nadgrids )
166
int nadgrids_count = 0;
171
if( last_nadgrids != NULL
172
&& strcmp(nadgrids,last_nadgrids) == 0 )
173
return last_nadgrids_list;
175
/* -------------------------------------------------------------------- */
176
/* Free old one, if any, and make space for new list. */
177
/* -------------------------------------------------------------------- */
178
if( last_nadgrids != NULL )
180
pj_dalloc(last_nadgrids);
183
last_nadgrids = (char *) pj_malloc(strlen(nadgrids)+1);
184
strcpy( last_nadgrids, nadgrids );
186
if( last_nadgrids_list == NULL )
187
last_nadgrids_list = (struct CTABLE **)
188
pj_malloc(sizeof(struct CTABLE *) * GRID_MAX);
190
/* -------------------------------------------------------------------- */
191
/* Loop processing names out of nadgrids one at a time. */
192
/* -------------------------------------------------------------------- */
193
for( s = nadgrids; *s != '\0'; )
199
s[end_char] != '\0' && s[end_char] != ',';
202
if( end_char > sizeof(name) )
208
strncpy( name, s, end_char );
209
name[end_char] = '\0';
216
last_nadgrids_list[nadgrids_count] = pj_get_grid( name );
217
if( last_nadgrids_list[nadgrids_count] == NULL )
223
last_nadgrids_list[nadgrids_count] = NULL;
225
return last_nadgrids_list;
228
66
/************************************************************************/
229
67
/* pj_apply_gridshift() */
230
68
/************************************************************************/
249
93
input.phi = y[io];
250
94
input.lam = x[io];
95
output.phi = HUGE_VAL;
96
output.lam = HUGE_VAL;
252
98
/* keep trying till we find a table that works */
253
for( itable = 0; tables[itable] != NULL; itable++ )
99
for( itable = 0; itable < grid_count; itable++ )
255
output = nad_cvt( input, inverse, tables[itable] );
101
PJ_GRIDINFO *gi = tables[itable];
102
struct CTABLE *ct = gi->ct;
104
/* skip tables that don't match our point at all. */
105
if( ct->ll.phi > input.phi || ct->ll.lam > input.lam
106
|| ct->ll.phi + (ct->lim.phi-1) * ct->del.phi < input.phi
107
|| ct->ll.lam + (ct->lim.lam-1) * ct->del.lam < input.lam )
110
/* If we have child nodes, check to see if any of them apply. */
111
if( gi->child != NULL )
115
for( child = gi->child; child != NULL; child = child->next )
117
struct CTABLE *ct1 = child->ct;
119
if( ct1->ll.phi > input.phi || ct1->ll.lam > input.lam
120
|| ct1->ll.phi+(ct1->lim.phi-1)*ct1->del.phi < input.phi
121
|| ct1->ll.lam+(ct1->lim.lam-1)*ct1->del.lam < input.lam)
127
/* we found a more refined child node to use */
135
/* load the grid shift info if we don't have it. */
136
if( ct->cvs == NULL && !pj_gridinfo_load( gi ) )
142
output = nad_cvt( input, inverse, ct );
256
143
if( output.lam != HUGE_VAL )
145
if( debug_flag && debug_count++ < 20 )
147
"pj_apply_gridshift(): used %s\n",
260
153
if( output.lam == HUGE_VAL )
158
"pj_apply_gridshift(): failed to find a grid shift table for\n"
159
" location (%.7fdW,%.7fdN)\n",
161
y[io] * RAD_TO_DEG );
163
" tried: %s\n", nadgrids );