/Proj4/pj_gridinfo.c

http://github.com/route-me/route-me · C · 716 lines · 430 code · 119 blank · 167 comment · 123 complexity · f65adc5c2251229b627b73a48ba1943a MD5 · raw file

  1. /******************************************************************************
  2. * $Id: pj_gridinfo.c,v 1.8 2006/11/17 22:16:30 mloskot 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.8 2006/11/17 22:16:30 mloskot
  33. * Uploaded PROJ.4 port for Windows CE.
  34. *
  35. * Revision 1.7 2005/07/07 00:16:03 fwarmerdam
  36. * Fixed debug fprintf syntax per:
  37. * http://bugzilla.remotesensing.org/show_bug.cgi?id=886
  38. *
  39. * Revision 1.6 2004/10/30 04:03:03 fwarmerdam
  40. * fixed reported information in ctable debug message
  41. *
  42. * Revision 1.5 2003/08/20 13:23:58 warmerda
  43. * Avoid unsigned char / char casting issues for VC++.
  44. *
  45. * Revision 1.4 2003/03/19 03:36:41 warmerda
  46. * Fixed so swap_words() works when it should.
  47. *
  48. * Revision 1.3 2003/03/17 19:44:45 warmerda
  49. * improved debugging, reduce header read size
  50. *
  51. * Revision 1.2 2003/03/17 18:56:34 warmerda
  52. * implement heirarchical NTv2 gridinfos
  53. *
  54. * Revision 1.1 2003/03/15 06:01:18 warmerda
  55. * New
  56. *
  57. */
  58. #define PJ_LIB__
  59. #include "projects.h"
  60. #include <string.h>
  61. #include <math.h>
  62. #include <errno.h>
  63. #ifdef _WIN32_WCE
  64. /* assert.h includes all Windows API headers and causes 'LP' name clash.
  65. * Here assert we disable assert() for Windows CE.
  66. * TODO - mloskot: re-implement porting friendly assert
  67. */
  68. # define assert(exp) ((void)0)
  69. #else
  70. # include <assert.h>
  71. #endif /* _WIN32_WCE */
  72. /************************************************************************/
  73. /* swap_words() */
  74. /* */
  75. /* Convert the byte order of the given word(s) in place. */
  76. /************************************************************************/
  77. static int byte_order_test = 1;
  78. #define IS_LSB (((unsigned char *) (&byte_order_test))[0] == 1)
  79. static void swap_words( unsigned char *data, int word_size, int word_count )
  80. {
  81. int word;
  82. for( word = 0; word < word_count; word++ )
  83. {
  84. int i;
  85. for( i = 0; i < word_size/2; i++ )
  86. {
  87. int t;
  88. t = data[i];
  89. data[i] = data[word_size-i-1];
  90. data[word_size-i-1] = t;
  91. }
  92. data += word_size;
  93. }
  94. }
  95. /************************************************************************/
  96. /* pj_gridinfo_free() */
  97. /************************************************************************/
  98. void pj_gridinfo_free( PJ_GRIDINFO *gi )
  99. {
  100. if( gi == NULL )
  101. return;
  102. if( gi->child != NULL )
  103. {
  104. PJ_GRIDINFO *child, *next;
  105. for( child = gi->child; child != NULL; child=next)
  106. {
  107. next=child->next;
  108. pj_gridinfo_free( child );
  109. }
  110. }
  111. if( gi->ct != NULL )
  112. nad_free( gi->ct );
  113. free( gi->gridname );
  114. if( gi->filename != NULL )
  115. free( gi->filename );
  116. pj_dalloc( gi );
  117. }
  118. /************************************************************************/
  119. /* pj_gridinfo_load() */
  120. /* */
  121. /* This function is intended to implement delayed loading of */
  122. /* the data contents of a grid file. The header and related */
  123. /* stuff are loaded by pj_gridinfo_init(). */
  124. /************************************************************************/
  125. int pj_gridinfo_load( PJ_GRIDINFO *gi )
  126. {
  127. if( gi == NULL || gi->ct == NULL )
  128. return 0;
  129. /* -------------------------------------------------------------------- */
  130. /* ctable is currently loaded on initialization though there is */
  131. /* no real reason not to support delayed loading for it as well. */
  132. /* -------------------------------------------------------------------- */
  133. if( strcmp(gi->format,"ctable") == 0 )
  134. {
  135. FILE *fid;
  136. int result;
  137. fid = pj_open_lib( gi->filename, "rb" );
  138. if( fid == NULL )
  139. {
  140. pj_errno = -38;
  141. return 0;
  142. }
  143. result = nad_ctable_load( gi->ct, fid );
  144. fclose( fid );
  145. return result;
  146. }
  147. /* -------------------------------------------------------------------- */
  148. /* NTv1 format. */
  149. /* We process one line at a time. Note that the array storage */
  150. /* direction (e-w) is different in the NTv1 file and what */
  151. /* the CTABLE is supposed to have. The phi/lam are also */
  152. /* reversed, and we have to be aware of byte swapping. */
  153. /* -------------------------------------------------------------------- */
  154. else if( strcmp(gi->format,"ntv1") == 0 )
  155. {
  156. double *row_buf;
  157. int row;
  158. FILE *fid;
  159. fid = pj_open_lib( gi->filename, "rb" );
  160. if( fid == NULL )
  161. {
  162. pj_errno = -38;
  163. return 0;
  164. }
  165. fseek( fid, gi->grid_offset, SEEK_SET );
  166. row_buf = (double *) pj_malloc(gi->ct->lim.lam * sizeof(double) * 2);
  167. gi->ct->cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
  168. if( row_buf == NULL || gi->ct->cvs == NULL )
  169. {
  170. pj_errno = -38;
  171. return 0;
  172. }
  173. for( row = 0; row < gi->ct->lim.phi; row++ )
  174. {
  175. int i;
  176. FLP *cvs;
  177. double *diff_seconds;
  178. if( fread( row_buf, sizeof(double), gi->ct->lim.lam * 2, fid )
  179. != 2 * gi->ct->lim.lam )
  180. {
  181. pj_dalloc( row_buf );
  182. pj_dalloc( gi->ct->cvs );
  183. pj_errno = -38;
  184. return 0;
  185. }
  186. if( IS_LSB )
  187. swap_words( (unsigned char *) row_buf, 8, gi->ct->lim.lam*2 );
  188. /* convert seconds to radians */
  189. diff_seconds = row_buf;
  190. for( i = 0; i < gi->ct->lim.lam; i++ )
  191. {
  192. cvs = gi->ct->cvs + (row) * gi->ct->lim.lam
  193. + (gi->ct->lim.lam - i - 1);
  194. cvs->phi = *(diff_seconds++) * ((PI/180.0) / 3600.0);
  195. cvs->lam = *(diff_seconds++) * ((PI/180.0) / 3600.0);
  196. }
  197. }
  198. pj_dalloc( row_buf );
  199. fclose( fid );
  200. return 1;
  201. }
  202. /* -------------------------------------------------------------------- */
  203. /* NTv2 format. */
  204. /* We process one line at a time. Note that the array storage */
  205. /* direction (e-w) is different in the NTv2 file and what */
  206. /* the CTABLE is supposed to have. The phi/lam are also */
  207. /* reversed, and we have to be aware of byte swapping. */
  208. /* -------------------------------------------------------------------- */
  209. else if( strcmp(gi->format,"ntv2") == 0 )
  210. {
  211. float *row_buf;
  212. int row;
  213. FILE *fid;
  214. if( getenv("PROJ_DEBUG") != NULL )
  215. {
  216. fprintf( stderr, "NTv2 - loading grid %s\n", gi->ct->id );
  217. }
  218. fid = pj_open_lib( gi->filename, "rb" );
  219. if( fid == NULL )
  220. {
  221. pj_errno = -38;
  222. return 0;
  223. }
  224. fseek( fid, gi->grid_offset, SEEK_SET );
  225. row_buf = (float *) pj_malloc(gi->ct->lim.lam * sizeof(float) * 4);
  226. gi->ct->cvs = (FLP *) pj_malloc(gi->ct->lim.lam*gi->ct->lim.phi*sizeof(FLP));
  227. if( row_buf == NULL || gi->ct->cvs == NULL )
  228. {
  229. pj_errno = -38;
  230. return 0;
  231. }
  232. for( row = 0; row < gi->ct->lim.phi; row++ )
  233. {
  234. int i;
  235. FLP *cvs;
  236. float *diff_seconds;
  237. if( fread( row_buf, sizeof(float), gi->ct->lim.lam*4, fid )
  238. != 4 * gi->ct->lim.lam )
  239. {
  240. pj_dalloc( row_buf );
  241. pj_dalloc( gi->ct->cvs );
  242. gi->ct->cvs = NULL;
  243. pj_errno = -38;
  244. return 0;
  245. }
  246. if( !IS_LSB )
  247. swap_words( (unsigned char *) row_buf, 4,
  248. gi->ct->lim.lam*4 );
  249. /* convert seconds to radians */
  250. diff_seconds = row_buf;
  251. for( i = 0; i < gi->ct->lim.lam; i++ )
  252. {
  253. cvs = gi->ct->cvs + (row) * gi->ct->lim.lam
  254. + (gi->ct->lim.lam - i - 1);
  255. cvs->phi = *(diff_seconds++) * ((PI/180.0) / 3600.0);
  256. cvs->lam = *(diff_seconds++) * ((PI/180.0) / 3600.0);
  257. diff_seconds += 2; /* skip accuracy values */
  258. }
  259. }
  260. pj_dalloc( row_buf );
  261. fclose( fid );
  262. return 1;
  263. }
  264. else
  265. {
  266. return 0;
  267. }
  268. }
  269. /************************************************************************/
  270. /* pj_gridinfo_init_ntv2() */
  271. /* */
  272. /* Load a ntv2 (.gsb) file. */
  273. /************************************************************************/
  274. static int pj_gridinfo_init_ntv2( FILE *fid, PJ_GRIDINFO *gilist )
  275. {
  276. unsigned char header[11*16];
  277. int num_subfiles, subfile;
  278. assert( sizeof(int) == 4 );
  279. assert( sizeof(double) == 8 );
  280. if( sizeof(int) != 4 || sizeof(double) != 8 )
  281. {
  282. fprintf( stderr,
  283. "basic types of inappropraiate size in pj_gridinfo_init_ntv2()\n" );
  284. pj_errno = -38;
  285. return 0;
  286. }
  287. /* -------------------------------------------------------------------- */
  288. /* Read the overview header. */
  289. /* -------------------------------------------------------------------- */
  290. if( fread( header, sizeof(header), 1, fid ) != 1 )
  291. {
  292. pj_errno = -38;
  293. return 0;
  294. }
  295. /* -------------------------------------------------------------------- */
  296. /* Byte swap interesting fields if needed. */
  297. /* -------------------------------------------------------------------- */
  298. if( !IS_LSB )
  299. {
  300. swap_words( header+8, 4, 1 );
  301. swap_words( header+8+16, 4, 1 );
  302. swap_words( header+8+32, 4, 1 );
  303. swap_words( header+8+7*16, 8, 1 );
  304. swap_words( header+8+8*16, 8, 1 );
  305. swap_words( header+8+9*16, 8, 1 );
  306. swap_words( header+8+10*16, 8, 1 );
  307. }
  308. /* -------------------------------------------------------------------- */
  309. /* Get the subfile count out ... all we really use for now. */
  310. /* -------------------------------------------------------------------- */
  311. memcpy( &num_subfiles, header+8+32, 4 );
  312. /* ==================================================================== */
  313. /* Step through the subfiles, creating a PJ_GRIDINFO for each. */
  314. /* ==================================================================== */
  315. for( subfile = 0; subfile < num_subfiles; subfile++ )
  316. {
  317. struct CTABLE *ct;
  318. LP ur;
  319. int gs_count;
  320. PJ_GRIDINFO *gi;
  321. /* -------------------------------------------------------------------- */
  322. /* Read header. */
  323. /* -------------------------------------------------------------------- */
  324. if( fread( header, sizeof(header), 1, fid ) != 1 )
  325. {
  326. pj_errno = -38;
  327. return 0;
  328. }
  329. if( strncmp((const char *) header,"SUB_NAME",8) != 0 )
  330. {
  331. pj_errno = -38;
  332. return 0;
  333. }
  334. /* -------------------------------------------------------------------- */
  335. /* Byte swap interesting fields if needed. */
  336. /* -------------------------------------------------------------------- */
  337. if( !IS_LSB )
  338. {
  339. swap_words( header+8+16*4, 8, 1 );
  340. swap_words( header+8+16*5, 8, 1 );
  341. swap_words( header+8+16*6, 8, 1 );
  342. swap_words( header+8+16*7, 8, 1 );
  343. swap_words( header+8+16*8, 8, 1 );
  344. swap_words( header+8+16*9, 8, 1 );
  345. swap_words( header+8+16*10, 4, 1 );
  346. }
  347. /* -------------------------------------------------------------------- */
  348. /* Initialize a corresponding "ct" structure. */
  349. /* -------------------------------------------------------------------- */
  350. ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
  351. strncpy( ct->id, (const char *) header + 8, 8 );
  352. ct->id[8] = '\0';
  353. ct->ll.lam = - *((double *) (header+7*16+8)); /* W_LONG */
  354. ct->ll.phi = *((double *) (header+4*16+8)); /* S_LAT */
  355. ur.lam = - *((double *) (header+6*16+8)); /* E_LONG */
  356. ur.phi = *((double *) (header+5*16+8)); /* N_LAT */
  357. ct->del.lam = *((double *) (header+9*16+8));
  358. ct->del.phi = *((double *) (header+8*16+8));
  359. ct->lim.lam = (int) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1;
  360. ct->lim.phi = (int) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1;
  361. if( getenv("PROJ_DEBUG") != NULL )
  362. fprintf( stderr,
  363. "NTv2 %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
  364. ct->id,
  365. ct->lim.lam, ct->lim.phi,
  366. ct->ll.lam/3600.0, ct->ll.phi/3600.0,
  367. ur.lam/3600.0, ur.phi/3600.0 );
  368. ct->ll.lam *= DEG_TO_RAD/3600.0;
  369. ct->ll.phi *= DEG_TO_RAD/3600.0;
  370. ct->del.lam *= DEG_TO_RAD/3600.0;
  371. ct->del.phi *= DEG_TO_RAD/3600.0;
  372. memcpy( &gs_count, header + 8 + 16*10, 4 );
  373. if( gs_count != ct->lim.lam * ct->lim.phi )
  374. {
  375. fprintf( stderr,
  376. "GS_COUNT(%d) does not match expected cells (%dx%d=%d)\n",
  377. gs_count, ct->lim.lam, ct->lim.phi,
  378. ct->lim.lam * ct->lim.phi );
  379. pj_errno = -38;
  380. return 0;
  381. }
  382. ct->cvs = NULL;
  383. /* -------------------------------------------------------------------- */
  384. /* Create a new gridinfo for this if we aren't processing the */
  385. /* 1st subfile, and initialize our grid info. */
  386. /* -------------------------------------------------------------------- */
  387. if( subfile == 0 )
  388. gi = gilist;
  389. else
  390. {
  391. gi = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO));
  392. memset( gi, 0, sizeof(PJ_GRIDINFO) );
  393. gi->gridname = strdup( gilist->gridname );
  394. gi->filename = strdup( gilist->filename );
  395. gi->next = NULL;
  396. }
  397. gi->ct = ct;
  398. gi->format = "ntv2";
  399. gi->grid_offset = ftell( fid );
  400. /* -------------------------------------------------------------------- */
  401. /* Attach to the correct list or sublist. */
  402. /* -------------------------------------------------------------------- */
  403. if( strncmp((const char *)header+24,"NONE",4) == 0 )
  404. {
  405. if( gi != gilist )
  406. {
  407. PJ_GRIDINFO *lnk;
  408. for( lnk = gilist; lnk->next != NULL; lnk = lnk->next ) {}
  409. lnk->next = gi;
  410. }
  411. }
  412. else
  413. {
  414. PJ_GRIDINFO *lnk;
  415. PJ_GRIDINFO *gp = gilist;
  416. while( gp != NULL
  417. && strncmp(gp->ct->id,(const char*)header+24,8) != 0 )
  418. gp = gp->next;
  419. if( gp == NULL )
  420. {
  421. if( getenv("PROJ_DEBUG") != NULL )
  422. fprintf( stderr, "pj_gridinfo_init_ntv2(): "
  423. "failed to find parent %8.8s for %s.\n",
  424. (const char *) header+24, gi->ct->id );
  425. if (gp) {
  426. for( lnk = gp; lnk->next != NULL; lnk = lnk->next ) {}
  427. lnk->next = gi;
  428. }
  429. }
  430. else if( gp->child == NULL )
  431. {
  432. gp->child = gi;
  433. }
  434. else
  435. {
  436. for( lnk = gp->child; lnk->next != NULL; lnk = lnk->next ) {}
  437. lnk->next = gi;
  438. }
  439. }
  440. /* -------------------------------------------------------------------- */
  441. /* Seek past the data. */
  442. /* -------------------------------------------------------------------- */
  443. fseek( fid, gs_count * 16, SEEK_CUR );
  444. }
  445. return 1;
  446. }
  447. /************************************************************************/
  448. /* pj_gridinfo_init_ntv1() */
  449. /* */
  450. /* Load an NTv1 style Canadian grid shift file. */
  451. /************************************************************************/
  452. static int pj_gridinfo_init_ntv1( FILE * fid, PJ_GRIDINFO *gi )
  453. {
  454. unsigned char header[176];
  455. struct CTABLE *ct;
  456. LP ur;
  457. assert( sizeof(int) == 4 );
  458. assert( sizeof(double) == 8 );
  459. if( sizeof(int) != 4 || sizeof(double) != 8 )
  460. {
  461. fprintf( stderr,
  462. "basic types of inappropraiate size in nad_load_ntv1()\n" );
  463. pj_errno = -38;
  464. return 0;
  465. }
  466. /* -------------------------------------------------------------------- */
  467. /* Read the header. */
  468. /* -------------------------------------------------------------------- */
  469. if( fread( header, sizeof(header), 1, fid ) != 1 )
  470. {
  471. pj_errno = -38;
  472. return 0;
  473. }
  474. /* -------------------------------------------------------------------- */
  475. /* Regularize fields of interest. */
  476. /* -------------------------------------------------------------------- */
  477. if( IS_LSB )
  478. {
  479. swap_words( header+8, 4, 1 );
  480. swap_words( header+24, 8, 1 );
  481. swap_words( header+40, 8, 1 );
  482. swap_words( header+56, 8, 1 );
  483. swap_words( header+72, 8, 1 );
  484. swap_words( header+88, 8, 1 );
  485. swap_words( header+104, 8, 1 );
  486. }
  487. if( *((int *) (header+8)) != 12 )
  488. {
  489. pj_errno = -38;
  490. printf("NTv1 grid shift file has wrong record count, corrupt?\n");
  491. return 0;
  492. }
  493. /* -------------------------------------------------------------------- */
  494. /* Fill in CTABLE structure. */
  495. /* -------------------------------------------------------------------- */
  496. ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE));
  497. strcpy( ct->id, "NTv1 Grid Shift File" );
  498. ct->ll.lam = - *((double *) (header+72));
  499. ct->ll.phi = *((double *) (header+24));
  500. ur.lam = - *((double *) (header+56));
  501. ur.phi = *((double *) (header+40));
  502. ct->del.lam = *((double *) (header+104));
  503. ct->del.phi = *((double *) (header+88));
  504. ct->lim.lam = (int) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1;
  505. ct->lim.phi = (int) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1;
  506. if( getenv("PROJ_DEBUG") != NULL )
  507. fprintf( stderr,
  508. "NTv1 %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
  509. ct->lim.lam, ct->lim.phi,
  510. ct->ll.lam, ct->ll.phi, ur.lam, ur.phi );
  511. ct->ll.lam *= DEG_TO_RAD;
  512. ct->ll.phi *= DEG_TO_RAD;
  513. ct->del.lam *= DEG_TO_RAD;
  514. ct->del.phi *= DEG_TO_RAD;
  515. ct->cvs = NULL;
  516. gi->ct = ct;
  517. gi->grid_offset = ftell( fid );
  518. gi->format = "ntv1";
  519. return 1;
  520. }
  521. /************************************************************************/
  522. /* pj_gridinfo_init() */
  523. /* */
  524. /* Open and parse header details from a datum gridshift file */
  525. /* returning a list of PJ_GRIDINFOs for the grids in that */
  526. /* file. This superceeds use of nad_init() for modern */
  527. /* applications. */
  528. /************************************************************************/
  529. PJ_GRIDINFO *pj_gridinfo_init( const char *gridname )
  530. {
  531. char fname[MAX_PATH_FILENAME+1];
  532. PJ_GRIDINFO *gilist;
  533. FILE *fp;
  534. char header[160];
  535. errno = pj_errno = 0;
  536. /* -------------------------------------------------------------------- */
  537. /* Initialize a GRIDINFO with stub info we would use if it */
  538. /* cannot be loaded. */
  539. /* -------------------------------------------------------------------- */
  540. gilist = (PJ_GRIDINFO *) pj_malloc(sizeof(PJ_GRIDINFO));
  541. memset( gilist, 0, sizeof(PJ_GRIDINFO) );
  542. gilist->gridname = strdup( gridname );
  543. gilist->filename = NULL;
  544. gilist->format = "missing";
  545. gilist->grid_offset = 0;
  546. gilist->ct = NULL;
  547. gilist->next = NULL;
  548. /* -------------------------------------------------------------------- */
  549. /* Open the file using the usual search rules. */
  550. /* -------------------------------------------------------------------- */
  551. strcpy(fname, gridname);
  552. if (!(fp = pj_open_lib(fname, "rb"))) {
  553. pj_errno = errno;
  554. return gilist;
  555. }
  556. gilist->filename = strdup(fname);
  557. /* -------------------------------------------------------------------- */
  558. /* Load a header, to determine the file type. */
  559. /* -------------------------------------------------------------------- */
  560. if( fread( header, sizeof(header), 1, fp ) != 1 )
  561. {
  562. fclose( fp );
  563. pj_errno = -38;
  564. return gilist;
  565. }
  566. fseek( fp, SEEK_SET, 0 );
  567. /* -------------------------------------------------------------------- */
  568. /* Determine file type. */
  569. /* -------------------------------------------------------------------- */
  570. if( strncmp(header + 0, "HEADER", 6) == 0
  571. && strncmp(header + 96, "W GRID", 6) == 0
  572. && strncmp(header + 144, "TO NAD83 ", 16) == 0 )
  573. {
  574. pj_gridinfo_init_ntv1( fp, gilist );
  575. }
  576. else if( strncmp(header + 0, "NUM_OREC", 8) == 0
  577. && strncmp(header + 48, "GS_TYPE", 7) == 0 )
  578. {
  579. pj_gridinfo_init_ntv2( fp, gilist );
  580. }
  581. else
  582. {
  583. struct CTABLE *ct = nad_ctable_init( fp );
  584. gilist->format = "ctable";
  585. gilist->ct = ct;
  586. if( getenv("PROJ_DEBUG") != NULL )
  587. fprintf( stderr,
  588. "Ctable %s %dx%d: LL=(%.9g,%.9g) UR=(%.9g,%.9g)\n",
  589. ct->id,
  590. ct->lim.lam, ct->lim.phi,
  591. ct->ll.lam * RAD_TO_DEG, ct->ll.phi * RAD_TO_DEG,
  592. (ct->ll.lam + (ct->lim.lam-1)*ct->del.lam) * RAD_TO_DEG,
  593. (ct->ll.phi + (ct->lim.phi-1)*ct->del.phi) * RAD_TO_DEG );
  594. }
  595. fclose(fp);
  596. return gilist;
  597. }