1 /******************************************************************************
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
9 ******************************************************************************
10 * Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com>
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:
19 * The above copyright notice and this permission notice shall be included
20 * in all copies or substantial portions of the Software.
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 *****************************************************************************/
39 /* assert.h includes all Windows API headers and causes 'LP' name clash.
40 * Here assert we disable assert() for Windows CE.
41 * TODO - mloskot: re-implement porting friendly assert
43 # define assert(exp) ((void)0)
46 #endif /* _WIN32_WCE */
48 /************************************************************************/
51 /* Convert the byte order of the given word(s) in place. */
52 /************************************************************************/
54 static int byte_order_test
= 1;
55 #define IS_LSB (((unsigned char *) (&byte_order_test))[0] == 1)
57 static void swap_words( unsigned char *data
, int word_size
, int word_count
)
62 for( word
= 0; word
< word_count
; word
++ )
66 for( i
= 0; i
< word_size
/2; i
++ )
71 data
[i
] = data
[word_size
-i
-1];
72 data
[word_size
-i
-1] = t
;
79 /************************************************************************/
80 /* pj_gridinfo_free() */
81 /************************************************************************/
83 void pj_gridinfo_free( projCtx ctx
, PJ_GRIDINFO
*gi
)
89 if( gi
->child
!= NULL
)
91 PJ_GRIDINFO
*child
, *next
;
93 for( child
= gi
->child
; child
!= NULL
; child
=next
)
96 pj_gridinfo_free( ctx
, child
);
103 free( gi
->gridname
);
104 if( gi
->filename
!= NULL
)
105 free( gi
->filename
);
110 /************************************************************************/
111 /* pj_gridinfo_load() */
113 /* This function is intended to implement delayed loading of */
114 /* the data contents of a grid file. The header and related */
115 /* stuff are loaded by pj_gridinfo_init(). */
116 /************************************************************************/
118 int pj_gridinfo_load( projCtx ctx
, PJ_GRIDINFO
*gi
)
121 struct CTABLE ct_tmp
;
123 if( gi
== NULL
|| gi
->ct
== NULL
)
127 if( gi
->ct
->cvs
!= NULL
)
133 memcpy(&ct_tmp
, gi
->ct
, sizeof(struct CTABLE
));
135 /* -------------------------------------------------------------------- */
136 /* Original platform specific CTable format. */
137 /* -------------------------------------------------------------------- */
138 if( strcmp(gi
->format
,"ctable") == 0 )
143 fid
= pj_open_lib( ctx
, gi
->filename
, "rb" );
147 pj_ctx_set_errno( ctx
, -38 );
152 result
= nad_ctable_load( ctx
, &ct_tmp
, fid
);
154 pj_ctx_fclose( ctx
, fid
);
156 gi
->ct
->cvs
= ct_tmp
.cvs
;
162 /* -------------------------------------------------------------------- */
163 /* CTable2 format. */
164 /* -------------------------------------------------------------------- */
165 else if( strcmp(gi
->format
,"ctable2") == 0 )
170 fid
= pj_open_lib( ctx
, gi
->filename
, "rb" );
174 pj_ctx_set_errno( ctx
, -38 );
179 result
= nad_ctable2_load( ctx
, &ct_tmp
, fid
);
181 pj_ctx_fclose( ctx
, fid
);
183 gi
->ct
->cvs
= ct_tmp
.cvs
;
189 /* -------------------------------------------------------------------- */
191 /* We process one line at a time. Note that the array storage */
192 /* direction (e-w) is different in the NTv1 file and what */
193 /* the CTABLE is supposed to have. The phi/lam are also */
194 /* reversed, and we have to be aware of byte swapping. */
195 /* -------------------------------------------------------------------- */
196 else if( strcmp(gi
->format
,"ntv1") == 0 )
202 fid
= pj_open_lib( ctx
, gi
->filename
, "rb" );
206 pj_ctx_set_errno( ctx
, -38 );
211 pj_ctx_fseek( ctx
, fid
, gi
->grid_offset
, SEEK_SET
);
213 row_buf
= (double *) pj_malloc(gi
->ct
->lim
.lam
* sizeof(double) * 2);
214 ct_tmp
.cvs
= (FLP
*) pj_malloc(gi
->ct
->lim
.lam
*gi
->ct
->lim
.phi
*sizeof(FLP
));
215 if( row_buf
== NULL
|| ct_tmp
.cvs
== NULL
)
217 pj_ctx_set_errno( ctx
, -38 );
222 for( row
= 0; row
< gi
->ct
->lim
.phi
; row
++ )
226 double *diff_seconds
;
228 if( pj_ctx_fread( ctx
, row_buf
,
229 sizeof(double), gi
->ct
->lim
.lam
* 2, fid
)
230 != 2 * gi
->ct
->lim
.lam
)
232 pj_dalloc( row_buf
);
233 pj_dalloc( ct_tmp
.cvs
);
234 pj_ctx_set_errno( ctx
, -38 );
239 swap_words( (unsigned char *) row_buf
, 8, gi
->ct
->lim
.lam
*2 );
241 /* convert seconds to radians */
242 diff_seconds
= row_buf
;
244 for( i
= 0; i
< gi
->ct
->lim
.lam
; i
++ )
246 cvs
= ct_tmp
.cvs
+ (row
) * gi
->ct
->lim
.lam
247 + (gi
->ct
->lim
.lam
- i
- 1);
249 cvs
->phi
= *(diff_seconds
++) * ((PI
/180.0) / 3600.0);
250 cvs
->lam
= *(diff_seconds
++) * ((PI
/180.0) / 3600.0);
254 pj_dalloc( row_buf
);
256 pj_ctx_fclose( ctx
, fid
);
258 gi
->ct
->cvs
= ct_tmp
.cvs
;
264 /* -------------------------------------------------------------------- */
266 /* We process one line at a time. Note that the array storage */
267 /* direction (e-w) is different in the NTv2 file and what */
268 /* the CTABLE is supposed to have. The phi/lam are also */
269 /* reversed, and we have to be aware of byte swapping. */
270 /* -------------------------------------------------------------------- */
271 else if( strcmp(gi
->format
,"ntv2") == 0 )
277 pj_log( ctx
, PJ_LOG_DEBUG_MINOR
,
278 "NTv2 - loading grid %s", gi
->ct
->id
);
280 fid
= pj_open_lib( ctx
, gi
->filename
, "rb" );
284 pj_ctx_set_errno( ctx
, -38 );
289 pj_ctx_fseek( ctx
, fid
, gi
->grid_offset
, SEEK_SET
);
291 row_buf
= (float *) pj_malloc(gi
->ct
->lim
.lam
* sizeof(float) * 4);
292 ct_tmp
.cvs
= (FLP
*) pj_malloc(gi
->ct
->lim
.lam
*gi
->ct
->lim
.phi
*sizeof(FLP
));
293 if( row_buf
== NULL
|| ct_tmp
.cvs
== NULL
)
295 pj_ctx_set_errno( ctx
, -38 );
300 for( row
= 0; row
< gi
->ct
->lim
.phi
; row
++ )
306 if( pj_ctx_fread( ctx
, row_buf
, sizeof(float),
307 gi
->ct
->lim
.lam
*4, fid
)
308 != 4 * gi
->ct
->lim
.lam
)
310 pj_dalloc( row_buf
);
311 pj_dalloc( ct_tmp
.cvs
);
312 pj_ctx_set_errno( ctx
, -38 );
318 swap_words( (unsigned char *) row_buf
, 4,
321 /* convert seconds to radians */
322 diff_seconds
= row_buf
;
324 for( i
= 0; i
< gi
->ct
->lim
.lam
; i
++ )
326 cvs
= ct_tmp
.cvs
+ (row
) * gi
->ct
->lim
.lam
327 + (gi
->ct
->lim
.lam
- i
- 1);
329 cvs
->phi
= *(diff_seconds
++) * ((PI
/180.0) / 3600.0);
330 cvs
->lam
= *(diff_seconds
++) * ((PI
/180.0) / 3600.0);
331 diff_seconds
+= 2; /* skip accuracy values */
335 pj_dalloc( row_buf
);
337 pj_ctx_fclose( ctx
, fid
);
339 gi
->ct
->cvs
= ct_tmp
.cvs
;
345 /* -------------------------------------------------------------------- */
347 /* -------------------------------------------------------------------- */
348 else if( strcmp(gi
->format
,"gtx") == 0 )
350 int words
= gi
->ct
->lim
.lam
* gi
->ct
->lim
.phi
;
353 fid
= pj_open_lib( ctx
, gi
->filename
, "rb" );
357 pj_ctx_set_errno( ctx
, -38 );
362 pj_ctx_fseek( ctx
, fid
, gi
->grid_offset
, SEEK_SET
);
364 ct_tmp
.cvs
= (FLP
*) pj_malloc(words
*sizeof(float));
365 if( ct_tmp
.cvs
== NULL
)
367 pj_ctx_set_errno( ctx
, -38 );
372 if( pj_ctx_fread( ctx
, ct_tmp
.cvs
, sizeof(float), words
, fid
)
375 pj_dalloc( ct_tmp
.cvs
);
381 swap_words( (unsigned char *) ct_tmp
.cvs
, 4, words
);
383 pj_ctx_fclose( ctx
, fid
);
384 gi
->ct
->cvs
= ct_tmp
.cvs
;
396 /************************************************************************/
397 /* pj_gridinfo_init_ntv2() */
399 /* Seek a parent grid file by name from a grid list */
400 /************************************************************************/
402 static PJ_GRIDINFO
* pj_gridinfo_parent( PJ_GRIDINFO
*gilist
,
403 const char *name
, int length
)
407 if( strncmp(gilist
->ct
->id
,name
,length
) == 0 ) return gilist
;
410 PJ_GRIDINFO
*parent
=pj_gridinfo_parent( gilist
->child
, name
, length
);
411 if( parent
) return parent
;
418 /************************************************************************/
419 /* pj_gridinfo_init_ntv2() */
421 /* Load a ntv2 (.gsb) file. */
422 /************************************************************************/
424 static int pj_gridinfo_init_ntv2( projCtx ctx
, PAFile fid
, PJ_GRIDINFO
*gilist
)
426 unsigned char header
[11*16];
427 int num_subfiles
, subfile
;
429 assert( sizeof(int) == 4 );
430 assert( sizeof(double) == 8 );
431 if( sizeof(int) != 4 || sizeof(double) != 8 )
433 pj_log( ctx
, PJ_LOG_ERROR
,
434 "basic types of inappropraiate size in pj_gridinfo_init_ntv2()" );
435 pj_ctx_set_errno( ctx
, -38 );
439 /* -------------------------------------------------------------------- */
440 /* Read the overview header. */
441 /* -------------------------------------------------------------------- */
442 if( pj_ctx_fread( ctx
, header
, sizeof(header
), 1, fid
) != 1 )
444 pj_ctx_set_errno( ctx
, -38 );
448 /* -------------------------------------------------------------------- */
449 /* Byte swap interesting fields if needed. */
450 /* -------------------------------------------------------------------- */
453 swap_words( header
+8, 4, 1 );
454 swap_words( header
+8+16, 4, 1 );
455 swap_words( header
+8+32, 4, 1 );
456 swap_words( header
+8+7*16, 8, 1 );
457 swap_words( header
+8+8*16, 8, 1 );
458 swap_words( header
+8+9*16, 8, 1 );
459 swap_words( header
+8+10*16, 8, 1 );
462 /* -------------------------------------------------------------------- */
463 /* Get the subfile count out ... all we really use for now. */
464 /* -------------------------------------------------------------------- */
465 memcpy( &num_subfiles
, header
+8+32, 4 );
467 /* ==================================================================== */
468 /* Step through the subfiles, creating a PJ_GRIDINFO for each. */
469 /* ==================================================================== */
470 for( subfile
= 0; subfile
< num_subfiles
; subfile
++ )
477 /* -------------------------------------------------------------------- */
479 /* -------------------------------------------------------------------- */
480 if( pj_ctx_fread( ctx
, header
, sizeof(header
), 1, fid
) != 1 )
482 pj_ctx_set_errno( ctx
, -38 );
486 if( strncmp((const char *) header
,"SUB_NAME",8) != 0 )
488 pj_ctx_set_errno( ctx
, -38 );
492 /* -------------------------------------------------------------------- */
493 /* Byte swap interesting fields if needed. */
494 /* -------------------------------------------------------------------- */
497 swap_words( header
+8+16*4, 8, 1 );
498 swap_words( header
+8+16*5, 8, 1 );
499 swap_words( header
+8+16*6, 8, 1 );
500 swap_words( header
+8+16*7, 8, 1 );
501 swap_words( header
+8+16*8, 8, 1 );
502 swap_words( header
+8+16*9, 8, 1 );
503 swap_words( header
+8+16*10, 4, 1 );
506 /* -------------------------------------------------------------------- */
507 /* Initialize a corresponding "ct" structure. */
508 /* -------------------------------------------------------------------- */
509 ct
= (struct CTABLE
*) pj_malloc(sizeof(struct CTABLE
));
510 strncpy( ct
->id
, (const char *) header
+ 8, 8 );
513 ct
->ll
.lam
= - *((double *) (header
+7*16+8)); /* W_LONG */
514 ct
->ll
.phi
= *((double *) (header
+4*16+8)); /* S_LAT */
516 ur
.lam
= - *((double *) (header
+6*16+8)); /* E_LONG */
517 ur
.phi
= *((double *) (header
+5*16+8)); /* N_LAT */
519 ct
->del
.lam
= *((double *) (header
+9*16+8));
520 ct
->del
.phi
= *((double *) (header
+8*16+8));
522 ct
->lim
.lam
= (int) (fabs(ur
.lam
-ct
->ll
.lam
)/ct
->del
.lam
+ 0.5) + 1;
523 ct
->lim
.phi
= (int) (fabs(ur
.phi
-ct
->ll
.phi
)/ct
->del
.phi
+ 0.5) + 1;
525 pj_log( ctx
, PJ_LOG_DEBUG_MINOR
,
526 "NTv2 %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
528 ct
->lim
.lam
, ct
->lim
.phi
,
529 ct
->ll
.lam
/3600.0, ct
->ll
.phi
/3600.0,
530 ur
.lam
/3600.0, ur
.phi
/3600.0 );
532 ct
->ll
.lam
*= DEG_TO_RAD
/3600.0;
533 ct
->ll
.phi
*= DEG_TO_RAD
/3600.0;
534 ct
->del
.lam
*= DEG_TO_RAD
/3600.0;
535 ct
->del
.phi
*= DEG_TO_RAD
/3600.0;
537 memcpy( &gs_count
, header
+ 8 + 16*10, 4 );
538 if( gs_count
!= ct
->lim
.lam
* ct
->lim
.phi
)
540 pj_log( ctx
, PJ_LOG_ERROR
,
541 "GS_COUNT(%d) does not match expected cells (%dx%d=%d)\n",
542 gs_count
, ct
->lim
.lam
, ct
->lim
.phi
,
543 ct
->lim
.lam
* ct
->lim
.phi
);
544 pj_ctx_set_errno( ctx
, -38 );
550 /* -------------------------------------------------------------------- */
551 /* Create a new gridinfo for this if we aren't processing the */
552 /* 1st subfile, and initialize our grid info. */
553 /* -------------------------------------------------------------------- */
558 gi
= (PJ_GRIDINFO
*) pj_malloc(sizeof(PJ_GRIDINFO
));
559 memset( gi
, 0, sizeof(PJ_GRIDINFO
) );
561 gi
->gridname
= strdup( gilist
->gridname
);
562 gi
->filename
= strdup( gilist
->filename
);
568 gi
->grid_offset
= pj_ctx_ftell( ctx
, fid
);
570 /* -------------------------------------------------------------------- */
571 /* Attach to the correct list or sublist. */
572 /* -------------------------------------------------------------------- */
573 if( strncmp((const char *)header
+24,"NONE",4) == 0 )
579 for( lnk
= gilist
; lnk
->next
!= NULL
; lnk
= lnk
->next
) {}
587 PJ_GRIDINFO
*gp
= pj_gridinfo_parent(gilist
,
588 (const char*)header
+24,8);
592 pj_log( ctx
, PJ_LOG_ERROR
,
593 "pj_gridinfo_init_ntv2(): "
594 "failed to find parent %8.8s for %s.\n",
595 (const char *) header
+24, gi
->ct
->id
);
597 for( lnk
= gilist
; lnk
->next
!= NULL
; lnk
= lnk
->next
) {}
602 if( gp
->child
== NULL
)
608 for( lnk
= gp
->child
; lnk
->next
!= NULL
; lnk
= lnk
->next
) {}
614 /* -------------------------------------------------------------------- */
615 /* Seek past the data. */
616 /* -------------------------------------------------------------------- */
617 pj_ctx_fseek( ctx
, fid
, gs_count
* 16, SEEK_CUR
);
623 /************************************************************************/
624 /* pj_gridinfo_init_ntv1() */
626 /* Load an NTv1 style Canadian grid shift file. */
627 /************************************************************************/
629 static int pj_gridinfo_init_ntv1( projCtx ctx
, PAFile fid
, PJ_GRIDINFO
*gi
)
632 unsigned char header
[176];
636 assert( sizeof(int) == 4 );
637 assert( sizeof(double) == 8 );
638 if( sizeof(int) != 4 || sizeof(double) != 8 )
640 pj_log( ctx
, PJ_LOG_ERROR
,
641 "basic types of inappropraiate size in nad_load_ntv1()" );
642 pj_ctx_set_errno( ctx
, -38 );
646 /* -------------------------------------------------------------------- */
647 /* Read the header. */
648 /* -------------------------------------------------------------------- */
649 if( pj_ctx_fread( ctx
, header
, sizeof(header
), 1, fid
) != 1 )
651 pj_ctx_set_errno( ctx
, -38 );
655 /* -------------------------------------------------------------------- */
656 /* Regularize fields of interest. */
657 /* -------------------------------------------------------------------- */
660 swap_words( header
+8, 4, 1 );
661 swap_words( header
+24, 8, 1 );
662 swap_words( header
+40, 8, 1 );
663 swap_words( header
+56, 8, 1 );
664 swap_words( header
+72, 8, 1 );
665 swap_words( header
+88, 8, 1 );
666 swap_words( header
+104, 8, 1 );
669 if( *((int *) (header
+8)) != 12 )
671 pj_log( ctx
, PJ_LOG_ERROR
,
672 "NTv1 grid shift file has wrong record count, corrupt?" );
673 pj_ctx_set_errno( ctx
, -38 );
677 /* -------------------------------------------------------------------- */
678 /* Fill in CTABLE structure. */
679 /* -------------------------------------------------------------------- */
680 ct
= (struct CTABLE
*) pj_malloc(sizeof(struct CTABLE
));
681 strcpy( ct
->id
, "NTv1 Grid Shift File" );
683 ct
->ll
.lam
= - *((double *) (header
+72));
684 ct
->ll
.phi
= *((double *) (header
+24));
685 ur
.lam
= - *((double *) (header
+56));
686 ur
.phi
= *((double *) (header
+40));
687 ct
->del
.lam
= *((double *) (header
+104));
688 ct
->del
.phi
= *((double *) (header
+88));
689 ct
->lim
.lam
= (int) (fabs(ur
.lam
-ct
->ll
.lam
)/ct
->del
.lam
+ 0.5) + 1;
690 ct
->lim
.phi
= (int) (fabs(ur
.phi
-ct
->ll
.phi
)/ct
->del
.phi
+ 0.5) + 1;
692 pj_log( ctx
, PJ_LOG_DEBUG_MINOR
,
693 "NTv1 %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
694 ct
->lim
.lam
, ct
->lim
.phi
,
695 ct
->ll
.lam
, ct
->ll
.phi
, ur
.lam
, ur
.phi
);
697 ct
->ll
.lam
*= DEG_TO_RAD
;
698 ct
->ll
.phi
*= DEG_TO_RAD
;
699 ct
->del
.lam
*= DEG_TO_RAD
;
700 ct
->del
.phi
*= DEG_TO_RAD
;
704 gi
->grid_offset
= pj_ctx_ftell( ctx
, fid
);
710 /************************************************************************/
711 /* pj_gridinfo_init_gtx() */
713 /* Load a NOAA .gtx vertical datum shift file. */
714 /************************************************************************/
716 static int pj_gridinfo_init_gtx( projCtx ctx
, PAFile fid
, PJ_GRIDINFO
*gi
)
719 unsigned char header
[40];
721 double xorigin
,yorigin
,xstep
,ystep
;
724 assert( sizeof(int) == 4 );
725 assert( sizeof(double) == 8 );
726 if( sizeof(int) != 4 || sizeof(double) != 8 )
728 pj_log( ctx
, PJ_LOG_ERROR
,
729 "basic types of inappropraiate size in nad_load_gtx()" );
730 pj_ctx_set_errno( ctx
, -38 );
734 /* -------------------------------------------------------------------- */
735 /* Read the header. */
736 /* -------------------------------------------------------------------- */
737 if( pj_ctx_fread( ctx
, header
, sizeof(header
), 1, fid
) != 1 )
739 pj_ctx_set_errno( ctx
, -38 );
743 /* -------------------------------------------------------------------- */
744 /* Regularize fields of interest and extract. */
745 /* -------------------------------------------------------------------- */
748 swap_words( header
+0, 8, 4 );
749 swap_words( header
+32, 4, 2 );
752 memcpy( &yorigin
, header
+0, 8 );
753 memcpy( &xorigin
, header
+8, 8 );
754 memcpy( &ystep
, header
+16, 8 );
755 memcpy( &xstep
, header
+24, 8 );
757 memcpy( &rows
, header
+32, 4 );
758 memcpy( &columns
, header
+36, 4 );
760 if( xorigin
< -360 || xorigin
> 360
761 || yorigin
< -90 || yorigin
> 90 )
763 pj_log( ctx
, PJ_LOG_ERROR
,
764 "gtx file header has invalid extents, corrupt?");
765 pj_ctx_set_errno( ctx
, -38 );
769 /* -------------------------------------------------------------------- */
770 /* Fill in CTABLE structure. */
771 /* -------------------------------------------------------------------- */
772 ct
= (struct CTABLE
*) pj_malloc(sizeof(struct CTABLE
));
773 strcpy( ct
->id
, "GTX Vertical Grid Shift File" );
775 ct
->ll
.lam
= xorigin
;
776 ct
->ll
.phi
= yorigin
;
779 ct
->lim
.lam
= columns
;
782 /* some GTX files come in 0-360 and we shift them back into the
783 expected -180 to 180 range if possible. This does not solve
784 problems with grids spanning the dateline. */
785 if( ct
->ll
.lam
>= 180.0 )
788 if( ct
->ll
.lam
>= 0.0 && ct
->ll
.lam
+ ct
->del
.lam
* ct
->lim
.lam
> 180.0 )
790 pj_log( ctx
, PJ_LOG_DEBUG_MAJOR
,
791 "This GTX spans the dateline! This will cause problems." );
794 pj_log( ctx
, PJ_LOG_DEBUG_MINOR
,
795 "GTX %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)",
796 ct
->lim
.lam
, ct
->lim
.phi
,
797 ct
->ll
.lam
, ct
->ll
.phi
,
798 ct
->ll
.lam
+ (columns
-1)*xstep
, ct
->ll
.phi
+ (rows
-1)*ystep
);
800 ct
->ll
.lam
*= DEG_TO_RAD
;
801 ct
->ll
.phi
*= DEG_TO_RAD
;
802 ct
->del
.lam
*= DEG_TO_RAD
;
803 ct
->del
.phi
*= DEG_TO_RAD
;
807 gi
->grid_offset
= 40;
813 /************************************************************************/
814 /* pj_gridinfo_init() */
816 /* Open and parse header details from a datum gridshift file */
817 /* returning a list of PJ_GRIDINFOs for the grids in that */
818 /* file. This superceeds use of nad_init() for modern */
820 /************************************************************************/
822 PJ_GRIDINFO
*pj_gridinfo_init( projCtx ctx
, const char *gridname
)
825 char fname
[MAX_PATH_FILENAME
+1];
830 errno
= pj_errno
= 0;
833 /* -------------------------------------------------------------------- */
834 /* Initialize a GRIDINFO with stub info we would use if it */
835 /* cannot be loaded. */
836 /* -------------------------------------------------------------------- */
837 gilist
= (PJ_GRIDINFO
*) pj_malloc(sizeof(PJ_GRIDINFO
));
838 memset( gilist
, 0, sizeof(PJ_GRIDINFO
) );
840 gilist
->gridname
= strdup( gridname
);
841 gilist
->filename
= NULL
;
842 gilist
->format
= "missing";
843 gilist
->grid_offset
= 0;
847 /* -------------------------------------------------------------------- */
848 /* Open the file using the usual search rules. */
849 /* -------------------------------------------------------------------- */
850 strcpy(fname
, gridname
);
851 if (!(fp
= pj_open_lib(ctx
, fname
, "rb"))) {
852 ctx
->last_errno
= 0; /* don't treat as a persistent error */
856 gilist
->filename
= strdup(fname
);
858 /* -------------------------------------------------------------------- */
859 /* Load a header, to determine the file type. */
860 /* -------------------------------------------------------------------- */
861 if( pj_ctx_fread( ctx
, header
, sizeof(header
), 1, fp
) != 1 )
863 pj_ctx_fclose( ctx
, fp
);
864 pj_ctx_set_errno( ctx
, -38 );
868 pj_ctx_fseek( ctx
, fp
, SEEK_SET
, 0 );
870 /* -------------------------------------------------------------------- */
871 /* Determine file type. */
872 /* -------------------------------------------------------------------- */
873 if( strncmp(header
+ 0, "HEADER", 6) == 0
874 && strncmp(header
+ 96, "W GRID", 6) == 0
875 && strncmp(header
+ 144, "TO NAD83 ", 16) == 0 )
877 pj_gridinfo_init_ntv1( ctx
, fp
, gilist
);
880 else if( strncmp(header
+ 0, "NUM_OREC", 8) == 0
881 && strncmp(header
+ 48, "GS_TYPE", 7) == 0 )
883 pj_gridinfo_init_ntv2( ctx
, fp
, gilist
);
886 else if( strlen(gridname
) > 4
887 && (strcmp(gridname
+strlen(gridname
)-3,"gtx") == 0
888 || strcmp(gridname
+strlen(gridname
)-3,"GTX") == 0) )
890 pj_gridinfo_init_gtx( ctx
, fp
, gilist
);
893 else if( strncmp(header
+ 0,"CTABLE V2",9) == 0 )
895 struct CTABLE
*ct
= nad_ctable2_init( ctx
, fp
);
897 gilist
->format
= "ctable2";
900 pj_log( ctx
, PJ_LOG_DEBUG_MAJOR
,
901 "Ctable2 %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
903 ct
->lim
.lam
, ct
->lim
.phi
,
904 ct
->ll
.lam
* RAD_TO_DEG
, ct
->ll
.phi
* RAD_TO_DEG
,
905 (ct
->ll
.lam
+ (ct
->lim
.lam
-1)*ct
->del
.lam
) * RAD_TO_DEG
,
906 (ct
->ll
.phi
+ (ct
->lim
.phi
-1)*ct
->del
.phi
) * RAD_TO_DEG
);
911 struct CTABLE
*ct
= nad_ctable_init( ctx
, fp
);
914 pj_log( ctx
, PJ_LOG_DEBUG_MAJOR
,
915 "CTABLE ct is NULL.");
918 gilist
->format
= "ctable";
921 pj_log( ctx
, PJ_LOG_DEBUG_MAJOR
,
922 "Ctable %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
924 ct
->lim
.lam
, ct
->lim
.phi
,
925 ct
->ll
.lam
* RAD_TO_DEG
, ct
->ll
.phi
* RAD_TO_DEG
,
926 (ct
->ll
.lam
+ (ct
->lim
.lam
-1)*ct
->del
.lam
) * RAD_TO_DEG
,
927 (ct
->ll
.phi
+ (ct
->lim
.phi
-1)*ct
->del
.phi
) * RAD_TO_DEG
);
931 pj_ctx_fclose(ctx
, fp
);