~ubuntu-branches/ubuntu/breezy/proj/breezy

« back to all changes in this revision

Viewing changes to src/pj_gridinfo.c

  • Committer: Bazaar Package Importer
  • Author(s): Peter S Galbraith
  • Date: 2004-11-06 19:44:53 UTC
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20041106194453-axnsmkh1zplal8mz
Tags: upstream-4.4.9
ImportĀ upstreamĀ versionĀ 4.4.9

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * $Id: pj_gridinfo.c,v 1.6 2004/10/30 04:03:03 fwarmerdam Exp $
 
3
 *
 
4
 * Project:  PROJ.4
 
5
 * Purpose:  Functions for handling individual PJ_GRIDINFO's.  Includes
 
6
 *           loaders for all formats but CTABLE (in nad_init.c).
 
7
 * Author:   Frank Warmerdam, warmerdam@pobox.com
 
8
 *
 
9
 ******************************************************************************
 
10
 * Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
 
11
 *
 
12
 * Permission is hereby granted, free of charge, to any person obtaining a
 
13
 * copy of this software and associated documentation files (the "Software"),
 
14
 * to deal in the Software without restriction, including without limitation
 
15
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
16
 * and/or sell copies of the Software, and to permit persons to whom the
 
17
 * Software is furnished to do so, subject to the following conditions:
 
18
 *
 
19
 * The above copyright notice and this permission notice shall be included
 
20
 * in all copies or substantial portions of the Software.
 
21
 *
 
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
23
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
25
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
27
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
28
 * DEALINGS IN THE SOFTWARE.
 
29
 ******************************************************************************
 
30
 *
 
31
 * $Log: pj_gridinfo.c,v $
 
32
 * Revision 1.6  2004/10/30 04:03:03  fwarmerdam
 
33
 * fixed reported information in ctable debug message
 
34
 *
 
35
 * Revision 1.5  2003/08/20 13:23:58  warmerda
 
36
 * Avoid unsigned char / char casting issues for VC++.
 
37
 *
 
38
 * Revision 1.4  2003/03/19 03:36:41  warmerda
 
39
 * Fixed so swap_words() works when it should.
 
40
 *
 
41
 * Revision 1.3  2003/03/17 19:44:45  warmerda
 
42
 * improved debugging, reduce header read size
 
43
 *
 
44
 * Revision 1.2  2003/03/17 18:56:34  warmerda
 
45
 * implement heirarchical NTv2 gridinfos
 
46
 *
 
47
 * Revision 1.1  2003/03/15 06:01:18  warmerda
 
48
 * New
 
49
 *
 
50
 */
 
51
 
 
52
#define PJ_LIB__
 
53
 
 
54
#include <projects.h>
 
55
#include <string.h>
 
56
#include <math.h>
 
57
#include <errno.h>
 
58
#include <assert.h>
 
59
 
 
60
/************************************************************************/
 
61
/*                             swap_words()                             */
 
62
/*                                                                      */
 
63
/*      Convert the byte order of the given word(s) in place.           */
 
64
/************************************************************************/
 
65
 
 
66
static int  byte_order_test = 1;
 
67
#define IS_LSB  (((unsigned char *) (&byte_order_test))[0] == 1)
 
68
 
 
69
static void swap_words( unsigned char *data, int word_size, int word_count )
 
70
 
 
71
{
 
72
    int word;
 
73
 
 
74
    for( word = 0; word < word_count; word++ )
 
75
    {
 
76
        int     i;
 
77
        
 
78
        for( i = 0; i < word_size/2; i++ )
 
79
        {
 
80
            int t;
 
81
            
 
82
            t = data[i];
 
83
            data[i] = data[word_size-i-1];
 
84
            data[word_size-i-1] = t;
 
85
        }
 
86
        
 
87
        data += word_size;
 
88
    }
 
89
}
 
90
 
 
91
/************************************************************************/
 
92
/*                          pj_gridinfo_free()                          */
 
93
/************************************************************************/
 
94
 
 
95
void pj_gridinfo_free( PJ_GRIDINFO *gi )
 
96
 
 
97
{
 
98
    if( gi == NULL )
 
99
        return;
 
100
 
 
101
    if( gi->child != NULL )
 
102
    {
 
103
        PJ_GRIDINFO *child, *next;
 
104
 
 
105
        for( child = gi->child; child != NULL; child=next)
 
106
        {
 
107
            next=child->next;
 
108
            pj_gridinfo_free( child );
 
109
        }
 
110
    }
 
111
 
 
112
    if( gi->ct != NULL )
 
113
        nad_free( gi->ct );
 
114
    
 
115
    free( gi->gridname );
 
116
    if( gi->filename != NULL )
 
117
        free( gi->filename );
 
118
 
 
119
    pj_dalloc( gi );
 
120
}
 
121
 
 
122
/************************************************************************/
 
123
/*                          pj_gridinfo_load()                          */
 
124
/*                                                                      */
 
125
/*      This function is intended to implement delayed loading of       */
 
126
/*      the data contents of a grid file.  The header and related       */
 
127
/*      stuff are loaded by pj_gridinfo_init().                         */
 
128
/************************************************************************/
 
129
 
 
130
int pj_gridinfo_load( PJ_GRIDINFO *gi )
 
131
 
 
132
{
 
133
    if( gi == NULL || gi->ct == NULL )
 
134
        return 0;
 
135
 
 
136
/* -------------------------------------------------------------------- */
 
137
/*      ctable is currently loaded on initialization though there is    */
 
138
/*      no real reason not to support delayed loading for it as well.   */
 
139
/* -------------------------------------------------------------------- */
 
140
    if( strcmp(gi->format,"ctable") == 0 )
 
141
    {
 
142
        FILE *fid;
 
143
        int result;
 
144
 
 
145
        fid = pj_open_lib( gi->filename, "rb" );
 
146
        
 
147
        if( fid == NULL )
 
148
        {
 
149
            pj_errno = -38;
 
150
            return 0;
 
151
        }
 
152
 
 
153
        result = nad_ctable_load( gi->ct, fid );
 
154
 
 
155
        fclose( fid );
 
156
 
 
157
        return result;
 
158
    }
 
159
 
 
160
/* -------------------------------------------------------------------- */
 
161
/*      NTv1 format.                                                    */
 
162
/*      We process one line at a time.  Note that the array storage     */
 
163
/*      direction (e-w) is different in the NTv1 file and what          */
 
164
/*      the CTABLE is supposed to have.  The phi/lam are also           */
 
165
/*      reversed, and we have to be aware of byte swapping.             */
 
166
/* -------------------------------------------------------------------- */
 
167
    else if( strcmp(gi->format,"ntv1") == 0 )
 
168
    {
 
169
        double  *row_buf;
 
170
        int     row;
 
171
        FILE *fid;
 
172
 
 
173
        fid = pj_open_lib( gi->filename, "rb" );
 
174
        
 
175
        if( fid == NULL )
 
176
        {
 
177
            pj_errno = -38;
 
178
            return 0;
 
179
        }
 
180
 
 
181
        fseek( fid, gi->grid_offset, SEEK_SET );
 
182
 
 
183
        row_buf = (double *) pj_malloc(gi->ct->lim.lam * sizeof(double) * 2);
 
184
        gi->ct->cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
 
185
        if( row_buf == NULL || gi->ct->cvs == NULL )
 
186
        {
 
187
            pj_errno = -38;
 
188
            return 0;
 
189
        }
 
190
        
 
191
        for( row = 0; row < gi->ct->lim.phi; row++ )
 
192
        {
 
193
            int     i;
 
194
            FLP     *cvs;
 
195
            double  *diff_seconds;
 
196
 
 
197
            if( fread( row_buf, sizeof(double), gi->ct->lim.lam * 2, fid ) 
 
198
                != 2 * gi->ct->lim.lam )
 
199
            {
 
200
                pj_dalloc( row_buf );
 
201
                pj_dalloc( gi->ct->cvs );
 
202
                pj_errno = -38;
 
203
                return 0;
 
204
            }
 
205
 
 
206
            if( IS_LSB )
 
207
                swap_words( (unsigned char *) row_buf, 8, gi->ct->lim.lam*2 );
 
208
 
 
209
            /* convert seconds to radians */
 
210
            diff_seconds = row_buf;
 
211
 
 
212
            for( i = 0; i < gi->ct->lim.lam; i++ )
 
213
            {
 
214
                cvs = gi->ct->cvs + (row) * gi->ct->lim.lam
 
215
                    + (gi->ct->lim.lam - i - 1);
 
216
 
 
217
                cvs->phi = *(diff_seconds++) * ((PI/180.0) / 3600.0);
 
218
                cvs->lam = *(diff_seconds++) * ((PI/180.0) / 3600.0);
 
219
            }
 
220
        }
 
221
 
 
222
        pj_dalloc( row_buf );
 
223
 
 
224
        fclose( fid );
 
225
 
 
226
        return 1;
 
227
    }
 
228
 
 
229
/* -------------------------------------------------------------------- */
 
230
/*      NTv2 format.                                                    */
 
231
/*      We process one line at a time.  Note that the array storage     */
 
232
/*      direction (e-w) is different in the NTv2 file and what          */
 
233
/*      the CTABLE is supposed to have.  The phi/lam are also           */
 
234
/*      reversed, and we have to be aware of byte swapping.             */
 
235
/* -------------------------------------------------------------------- */
 
236
    else if( strcmp(gi->format,"ntv2") == 0 )
 
237
    {
 
238
        float   *row_buf;
 
239
        int     row;
 
240
        FILE *fid;
 
241
 
 
242
        if( getenv("PROJ_DEBUG") != NULL )
 
243
        {
 
244
            fprintf( stderr, "NTv2 - loading grid %s\n", gi->ct->id );
 
245
        }
 
246
 
 
247
        fid = pj_open_lib( gi->filename, "rb" );
 
248
        
 
249
        if( fid == NULL )
 
250
        {
 
251
            pj_errno = -38;
 
252
            return 0;
 
253
        }
 
254
 
 
255
        fseek( fid, gi->grid_offset, SEEK_SET );
 
256
 
 
257
        row_buf = (float *) pj_malloc(gi->ct->lim.lam * sizeof(float) * 4);
 
258
        gi->ct->cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
 
259
        if( row_buf == NULL || gi->ct->cvs == NULL )
 
260
        {
 
261
            pj_errno = -38;
 
262
            return 0;
 
263
        }
 
264
        
 
265
        for( row = 0; row < gi->ct->lim.phi; row++ )
 
266
        {
 
267
            int     i;
 
268
            FLP     *cvs;
 
269
            float   *diff_seconds;
 
270
 
 
271
            if( fread( row_buf, sizeof(float), gi->ct->lim.lam*4, fid ) 
 
272
                != 4 * gi->ct->lim.lam )
 
273
            {
 
274
                pj_dalloc( row_buf );
 
275
                pj_dalloc( gi->ct->cvs );
 
276
                gi->ct->cvs = NULL;
 
277
                pj_errno = -38;
 
278
                return 0;
 
279
            }
 
280
 
 
281
            if( !IS_LSB )
 
282
                swap_words( (unsigned char *) row_buf, 4, 
 
283
                            gi->ct->lim.lam*4 );
 
284
 
 
285
            /* convert seconds to radians */
 
286
            diff_seconds = row_buf;
 
287
 
 
288
            for( i = 0; i < gi->ct->lim.lam; i++ )
 
289
            {
 
290
                cvs = gi->ct->cvs + (row) * gi->ct->lim.lam
 
291
                    + (gi->ct->lim.lam - i - 1);
 
292
 
 
293
                cvs->phi = *(diff_seconds++) * ((PI/180.0) / 3600.0);
 
294
                cvs->lam = *(diff_seconds++) * ((PI/180.0) / 3600.0);
 
295
                diff_seconds += 2; /* skip accuracy values */
 
296
            }
 
297
        }
 
298
 
 
299
        pj_dalloc( row_buf );
 
300
 
 
301
        fclose( fid );
 
302
 
 
303
        return 1;
 
304
    }
 
305
 
 
306
    else
 
307
    {
 
308
        return 0;
 
309
    }
 
310
}
 
311
 
 
312
/************************************************************************/
 
313
/*                       pj_gridinfo_init_ntv2()                        */
 
314
/*                                                                      */
 
315
/*      Load a ntv2 (.gsb) file.                                        */
 
316
/************************************************************************/
 
317
 
 
318
static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
 
319
 
 
320
{
 
321
    unsigned char header[11*16];
 
322
    int num_subfiles, subfile;
 
323
 
 
324
    assert( sizeof(int) == 4 );
 
325
    assert( sizeof(double) == 8 );
 
326
    if( sizeof(int) != 4 || sizeof(double) != 8 )
 
327
    {
 
328
        fprintf( stderr, 
 
329
                 "basic types of inappropraiate size in pj_gridinfo_init_ntv2()\n" );
 
330
        pj_errno = -38;
 
331
        return 0;
 
332
    }
 
333
 
 
334
/* -------------------------------------------------------------------- */
 
335
/*      Read the overview header.                                       */
 
336
/* -------------------------------------------------------------------- */
 
337
    if( fread( header, sizeof(header), 1, fid ) != 1 )
 
338
    {
 
339
        pj_errno = -38;
 
340
        return 0;
 
341
    }
 
342
 
 
343
/* -------------------------------------------------------------------- */
 
344
/*      Byte swap interesting fields if needed.                         */
 
345
/* -------------------------------------------------------------------- */
 
346
    if( !IS_LSB )
 
347
    {
 
348
        swap_words( header+8, 4, 1 );
 
349
        swap_words( header+8+16, 4, 1 );
 
350
        swap_words( header+8+32, 4, 1 );
 
351
        swap_words( header+8+7*16, 8, 1 );
 
352
        swap_words( header+8+8*16, 8, 1 );
 
353
        swap_words( header+8+9*16, 8, 1 );
 
354
        swap_words( header+8+10*16, 8, 1 );
 
355
    }
 
356
 
 
357
/* -------------------------------------------------------------------- */
 
358
/*      Get the subfile count out ... all we really use for now.        */
 
359
/* -------------------------------------------------------------------- */
 
360
    memcpy( &num_subfiles, header+8+32, 4 );
 
361
 
 
362
/* ==================================================================== */
 
363
/*      Step through the subfiles, creating a PJ_GRIDINFO for each.     */
 
364
/* ==================================================================== */
 
365
    for( subfile = 0; subfile < num_subfiles; subfile++ )
 
366
    {
 
367
        struct CTABLE *ct;
 
368
        LP ur;
 
369
        int gs_count;
 
370
        PJ_GRIDINFO *gi;
 
371
 
 
372
/* -------------------------------------------------------------------- */
 
373
/*      Read header.                                                    */
 
374
/* -------------------------------------------------------------------- */
 
375
        if( fread( header, sizeof(header), 1, fid ) != 1 )
 
376
        {
 
377
            pj_errno = -38;
 
378
            return 0;
 
379
        }
 
380
 
 
381
        if( strncmp((const char *) header,"SUB_NAME",8) != 0 )
 
382
        {
 
383
            pj_errno = -38;
 
384
            return 0;
 
385
        }
 
386
        
 
387
/* -------------------------------------------------------------------- */
 
388
/*      Byte swap interesting fields if needed.                         */
 
389
/* -------------------------------------------------------------------- */
 
390
        if( !IS_LSB )
 
391
        {
 
392
            swap_words( header+8+16*4, 8, 1 );
 
393
            swap_words( header+8+16*5, 8, 1 );
 
394
            swap_words( header+8+16*6, 8, 1 );
 
395
            swap_words( header+8+16*7, 8, 1 );
 
396
            swap_words( header+8+16*8, 8, 1 );
 
397
            swap_words( header+8+16*9, 8, 1 );
 
398
            swap_words( header+8+16*10, 4, 1 );
 
399
        }
 
400
        
 
401
/* -------------------------------------------------------------------- */
 
402
/*      Initialize a corresponding "ct" structure.                      */
 
403
/* -------------------------------------------------------------------- */
 
404
        ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
 
405
        strncpy( ct->id, (const char *) header + 8, 8 );
 
406
        ct->id[8] = '\0';
 
407
 
 
408
        ct->ll.lam = - *((double *) (header+7*16+8)); /* W_LONG */
 
409
        ct->ll.phi = *((double *) (header+4*16+8));   /* S_LAT */
 
410
 
 
411
        ur.lam = - *((double *) (header+6*16+8));     /* E_LONG */
 
412
        ur.phi = *((double *) (header+5*16+8));       /* N_LAT */
 
413
 
 
414
        ct->del.lam = *((double *) (header+9*16+8));
 
415
        ct->del.phi = *((double *) (header+8*16+8));
 
416
 
 
417
        ct->lim.lam = (int) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1;
 
418
        ct->lim.phi = (int) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1;
 
419
 
 
420
        if( getenv("PROJ_DEBUG") != NULL )
 
421
            fprintf( stderr, 
 
422
                     "NTv2 %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
 
423
                     ct->id, 
 
424
                     ct->lim.lam, ct->lim.phi,
 
425
                     ct->ll.lam/3600.0, ct->ll.phi/3600.0,
 
426
                     ur.lam/3600.0, ur.phi/3600.0 );
 
427
 
 
428
        ct->ll.lam *= DEG_TO_RAD/3600.0;
 
429
        ct->ll.phi *= DEG_TO_RAD/3600.0;
 
430
        ct->del.lam *= DEG_TO_RAD/3600.0;
 
431
        ct->del.phi *= DEG_TO_RAD/3600.0;
 
432
 
 
433
        memcpy( &gs_count, header + 8 + 16*10, 4 );
 
434
        if( gs_count != ct->lim.lam * ct->lim.phi )
 
435
        {
 
436
            fprintf( stderr, 
 
437
                     "GS_COUNT(%d) does not match expected cells (%dx%d=%d)\n",
 
438
                     gs_count, ct->lim.lam, ct->lim.phi, 
 
439
                     ct->lim.lam * ct->lim.phi );
 
440
            pj_errno = -38;
 
441
            return 0;
 
442
        }
 
443
 
 
444
        ct->cvs = NULL;
 
445
 
 
446
/* -------------------------------------------------------------------- */
 
447
/*      Create a new gridinfo for this if we aren't processing the      */
 
448
/*      1st subfile, and initialize our grid info.                      */
 
449
/* -------------------------------------------------------------------- */
 
450
        if( subfile == 0 )
 
451
            gi = gilist;
 
452
        else
 
453
        {
 
454
            gi = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO));
 
455
            memset( gi, 0, sizeof(PJ_GRIDINFO) );
 
456
    
 
457
            gi->gridname = strdup( gilist->gridname );
 
458
            gi->filename = strdup( gilist->filename );
 
459
            gi->next = NULL;
 
460
        }
 
461
 
 
462
        gi->ct = ct;
 
463
        gi->format = "ntv2";
 
464
        gi->grid_offset = ftell( fid );
 
465
 
 
466
/* -------------------------------------------------------------------- */
 
467
/*      Attach to the correct list or sublist.                          */
 
468
/* -------------------------------------------------------------------- */
 
469
        if( strncmp((const char *)header+24,"NONE",4) == 0 )
 
470
        {
 
471
            if( gi != gilist )
 
472
            {
 
473
                PJ_GRIDINFO *lnk;
 
474
 
 
475
                for( lnk = gilist; lnk->next != NULL; lnk = lnk->next ) {}
 
476
                lnk->next = gi;
 
477
            }
 
478
        }
 
479
 
 
480
        else
 
481
        {
 
482
            PJ_GRIDINFO *lnk;
 
483
            PJ_GRIDINFO *gp = gilist;
 
484
            
 
485
            while( gp != NULL 
 
486
                   && strncmp(gp->ct->id,(const char*)header+24,8) != 0 )
 
487
                gp = gp->next;
 
488
 
 
489
            if( gp == NULL )
 
490
            {
 
491
                if( getenv("PROJ_DEBUG") != NULL )
 
492
                    fprintf( stderr, "pj_gridinfo_init_ntv2(): "
 
493
                             "failed to find parent %8.8s for %.\n", 
 
494
                             (const char *) header+24, gi->ct->id );
 
495
 
 
496
                for( lnk = gp; lnk->next != NULL; lnk = lnk->next ) {}
 
497
                lnk->next = gi;
 
498
            }
 
499
            else if( gp->child == NULL )
 
500
            {
 
501
                gp->child = gi;
 
502
            }
 
503
            else
 
504
            {
 
505
                for( lnk = gp->child; lnk->next != NULL; lnk = lnk->next ) {}
 
506
                lnk->next = gi;
 
507
            }
 
508
        }
 
509
 
 
510
/* -------------------------------------------------------------------- */
 
511
/*      Seek past the data.                                             */
 
512
/* -------------------------------------------------------------------- */
 
513
        fseek( fid, gs_count * 16, SEEK_CUR );
 
514
    }
 
515
 
 
516
    return 1;
 
517
}
 
518
 
 
519
/************************************************************************/
 
520
/*                       pj_gridinfo_init_ntv1()                        */
 
521
/*                                                                      */
 
522
/*      Load an NTv1 style Canadian grid shift file.                    */
 
523
/************************************************************************/
 
524
 
 
525
static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
 
526
 
 
527
{
 
528
    unsigned char header[176];
 
529
    struct CTABLE *ct;
 
530
    LP          ur;
 
531
    
 
532
    assert( sizeof(int) == 4 );
 
533
    assert( sizeof(double) == 8 );
 
534
    if( sizeof(int) != 4 || sizeof(double) != 8 )
 
535
    {
 
536
        fprintf( stderr, 
 
537
                 "basic types of inappropraiate size in nad_load_ntv1()\n" );
 
538
        pj_errno = -38;
 
539
        return 0;
 
540
    }
 
541
 
 
542
/* -------------------------------------------------------------------- */
 
543
/*      Read the header.                                                */
 
544
/* -------------------------------------------------------------------- */
 
545
    if( fread( header, sizeof(header), 1, fid ) != 1 )
 
546
    {
 
547
        pj_errno = -38;
 
548
        return 0;
 
549
    }
 
550
 
 
551
/* -------------------------------------------------------------------- */
 
552
/*      Regularize fields of interest.                                  */
 
553
/* -------------------------------------------------------------------- */
 
554
    if( IS_LSB )
 
555
    {
 
556
        swap_words( header+8, 4, 1 );
 
557
        swap_words( header+24, 8, 1 );
 
558
        swap_words( header+40, 8, 1 );
 
559
        swap_words( header+56, 8, 1 );
 
560
        swap_words( header+72, 8, 1 );
 
561
        swap_words( header+88, 8, 1 );
 
562
        swap_words( header+104, 8, 1 );
 
563
    }
 
564
 
 
565
    if( *((int *) (header+8)) != 12 )
 
566
    {
 
567
        pj_errno = -38;
 
568
        printf("NTv1 grid shift file has wrong record count, corrupt?\n");
 
569
        return 0;
 
570
    }
 
571
 
 
572
/* -------------------------------------------------------------------- */
 
573
/*      Fill in CTABLE structure.                                       */
 
574
/* -------------------------------------------------------------------- */
 
575
    ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
 
576
    strcpy( ct->id, "NTv1 Grid Shift File" );
 
577
 
 
578
    ct->ll.lam = - *((double *) (header+72));
 
579
    ct->ll.phi = *((double *) (header+24));
 
580
    ur.lam = - *((double *) (header+56));
 
581
    ur.phi = *((double *) (header+40));
 
582
    ct->del.lam = *((double *) (header+104));
 
583
    ct->del.phi = *((double *) (header+88));
 
584
    ct->lim.lam = (int) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1;
 
585
    ct->lim.phi = (int) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1;
 
586
 
 
587
    if( getenv("PROJ_DEBUG") != NULL )
 
588
        fprintf( stderr, 
 
589
                 "NTv1 %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
 
590
                 ct->lim.lam, ct->lim.phi,
 
591
                 ct->ll.lam, ct->ll.phi, ur.lam, ur.phi );
 
592
 
 
593
    ct->ll.lam *= DEG_TO_RAD;
 
594
    ct->ll.phi *= DEG_TO_RAD;
 
595
    ct->del.lam *= DEG_TO_RAD;
 
596
    ct->del.phi *= DEG_TO_RAD;
 
597
    ct->cvs = NULL;
 
598
 
 
599
    gi->ct = ct;
 
600
    gi->grid_offset = ftell( fid );
 
601
    gi->format = "ntv1";
 
602
 
 
603
    return 1;
 
604
}
 
605
 
 
606
/************************************************************************/
 
607
/*                          pj_gridinfo_init()                          */
 
608
/*                                                                      */
 
609
/*      Open and parse header details from a datum gridshift file       */
 
610
/*      returning a list of PJ_GRIDINFOs for the grids in that          */
 
611
/*      file.  This superceeds use of nad_init() for modern             */
 
612
/*      applications.                                                   */
 
613
/************************************************************************/
 
614
 
 
615
PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
 
616
 
 
617
{
 
618
    char        fname[MAX_PATH_FILENAME+1];
 
619
    PJ_GRIDINFO *gilist;
 
620
    FILE        *fp;
 
621
    char        header[160];
 
622
 
 
623
    errno = pj_errno = 0;
 
624
 
 
625
/* -------------------------------------------------------------------- */
 
626
/*      Initialize a GRIDINFO with stub info we would use if it         */
 
627
/*      cannot be loaded.                                               */
 
628
/* -------------------------------------------------------------------- */
 
629
    gilist = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO));
 
630
    memset( gilist, 0, sizeof(PJ_GRIDINFO) );
 
631
    
 
632
    gilist->gridname = strdup( gridname );
 
633
    gilist->filename = NULL;
 
634
    gilist->format = "missing";
 
635
    gilist->grid_offset = 0;
 
636
    gilist->ct = NULL;
 
637
    gilist->next = NULL;
 
638
 
 
639
/* -------------------------------------------------------------------- */
 
640
/*      Open the file using the usual search rules.                     */
 
641
/* -------------------------------------------------------------------- */
 
642
    strcpy(fname, gridname);
 
643
    if (!(fp = pj_open_lib(fname, "rb"))) {
 
644
        pj_errno = errno;
 
645
        return gilist;
 
646
    }
 
647
 
 
648
    gilist->filename = strdup(fname);
 
649
    
 
650
/* -------------------------------------------------------------------- */
 
651
/*      Load a header, to determine the file type.                      */
 
652
/* -------------------------------------------------------------------- */
 
653
    if( fread( header, sizeof(header), 1, fp ) != 1 )
 
654
    {
 
655
        fclose( fp );
 
656
        pj_errno = -38;
 
657
        return gilist;
 
658
    }
 
659
 
 
660
    fseek( fp, SEEK_SET, 0 );
 
661
 
 
662
/* -------------------------------------------------------------------- */
 
663
/*      Determine file type.                                            */
 
664
/* -------------------------------------------------------------------- */
 
665
    if( strncmp(header + 0, "HEADER", 6) == 0 
 
666
        && strncmp(header + 96, "W GRID", 6) == 0 
 
667
        && strncmp(header + 144, "TO      NAD83   ", 16) == 0 )
 
668
    {
 
669
        pj_gridinfo_init_ntv1( fp, gilist );
 
670
    }
 
671
    
 
672
    else if( strncmp(header + 0, "NUM_OREC", 8) == 0 
 
673
             && strncmp(header + 48, "GS_TYPE", 7) == 0 )
 
674
    {
 
675
        pj_gridinfo_init_ntv2( fp, gilist );
 
676
    }
 
677
    
 
678
    else
 
679
    {
 
680
        struct CTABLE *ct = nad_ctable_init( fp );
 
681
 
 
682
        gilist->format = "ctable";
 
683
        gilist->ct = ct;
 
684
 
 
685
        if( getenv("PROJ_DEBUG") != NULL )
 
686
            fprintf( stderr, 
 
687
                     "Ctable %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
 
688
                     ct->id, 
 
689
                     ct->lim.lam, ct->lim.phi,
 
690
                     ct->ll.lam * RAD_TO_DEG, ct->ll.phi * RAD_TO_DEG,
 
691
                     (ct->ll.lam + (ct->lim.lam-1)*ct->del.lam) * RAD_TO_DEG, 
 
692
                     (ct->ll.phi + (ct->lim.phi-1)*ct->del.phi) * RAD_TO_DEG );
 
693
    }
 
694
 
 
695
    fclose(fp);
 
696
 
 
697
    return gilist;
 
698
}