diff options
| -rw-r--r-- | src/Makefile.am | 2 | ||||
| -rw-r--r-- | src/Makefile.in | 17 | ||||
| -rw-r--r-- | src/nad_init.c | 194 | ||||
| -rw-r--r-- | src/pj_apply_gridshift.c | 216 | ||||
| -rw-r--r-- | src/projects.h | 32 |
5 files changed, 77 insertions, 384 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3806d09b..fedb8909 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -58,7 +58,7 @@ libproj_la_SOURCES = \ \ nad_cvt.c nad_init.c nad_intr.c emess.c emess.h \ pj_apply_gridshift.c pj_datums.c pj_datum_set.c pj_transform.c \ - geocent.c geocent.h pj_utils.c + geocent.c geocent.h pj_utils.c pj_gridinfo.c pj_gridlist.c install-exec-local: diff --git a/src/Makefile.in b/src/Makefile.in index 73898766..9ae881ee 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -143,7 +143,7 @@ libproj_la_SOURCES = \ \ nad_cvt.c nad_init.c nad_intr.c emess.c emess.h \ pj_apply_gridshift.c pj_datums.c pj_datum_set.c pj_transform.c \ - geocent.c geocent.h pj_utils.c + geocent.c geocent.h pj_utils.c pj_gridinfo.c pj_gridlist.c subdir = src mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs @@ -178,7 +178,8 @@ am_libproj_la_OBJECTS = PJ_aeqd.lo PJ_gnom.lo PJ_laea.lo PJ_mod_ster.lo \ pj_units.lo pj_zpoly1.lo rtodms.lo vector1.lo pj_release.lo \ nad_cvt.lo nad_init.lo nad_intr.lo emess.lo \ pj_apply_gridshift.lo pj_datums.lo pj_datum_set.lo \ - pj_transform.lo geocent.lo pj_utils.lo + pj_transform.lo geocent.lo pj_utils.lo pj_gridinfo.lo \ + pj_gridlist.lo libproj_la_OBJECTS = $(am_libproj_la_OBJECTS) bin_PROGRAMS = proj$(EXEEXT) nad2nad$(EXEEXT) nad2bin$(EXEEXT) \ geod$(EXEEXT) cs2cs$(EXEEXT) @@ -274,10 +275,12 @@ am__depfiles_maybe = depfiles @AMDEP_TRUE@ ./$(DEPDIR)/pj_ell_set.Plo ./$(DEPDIR)/pj_ellps.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pj_errno.Plo ./$(DEPDIR)/pj_factors.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pj_fwd.Plo ./$(DEPDIR)/pj_geocent.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/pj_init.Plo ./$(DEPDIR)/pj_inv.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/pj_latlong.Plo ./$(DEPDIR)/pj_list.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/pj_malloc.Plo ./$(DEPDIR)/pj_mlfn.Plo \ -@AMDEP_TRUE@ ./$(DEPDIR)/pj_msfn.Plo ./$(DEPDIR)/pj_open_lib.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/pj_gridinfo.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/pj_gridlist.Plo ./$(DEPDIR)/pj_init.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/pj_inv.Plo ./$(DEPDIR)/pj_latlong.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/pj_list.Plo ./$(DEPDIR)/pj_malloc.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/pj_mlfn.Plo ./$(DEPDIR)/pj_msfn.Plo \ +@AMDEP_TRUE@ ./$(DEPDIR)/pj_open_lib.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pj_param.Plo ./$(DEPDIR)/pj_phi2.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pj_pr_list.Plo ./$(DEPDIR)/pj_qsfn.Plo \ @AMDEP_TRUE@ ./$(DEPDIR)/pj_release.Plo \ @@ -530,6 +533,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_factors.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_fwd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_geocent.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_gridinfo.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_gridlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_inv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pj_latlong.Plo@am__quote@ diff --git a/src/nad_init.c b/src/nad_init.c index cdc13d41..77e267e2 100644 --- a/src/nad_init.c +++ b/src/nad_init.c @@ -28,6 +28,9 @@ ****************************************************************************** * * $Log$ + * Revision 1.7 2003/03/15 06:02:02 warmerda + * preliminary NTv2 support, major restructure of datum shifting + * * Revision 1.6 2002/07/08 02:32:05 warmerda * ensure clean C++ builds * @@ -50,171 +53,13 @@ #include <assert.h> #include <string.h> -static int byte_order_test = 1; -#define IS_LSB (((unsigned char *) (&byte_order_test))[0] == 1) - -/************************************************************************/ -/* local_order() */ -/* */ -/* Convert the given words into local order in place. */ -/************************************************************************/ - -static void local_order( unsigned char *data, int word_size, int word_count ) - -{ - /* We only need to do work on LSB machines. Perhaps we should - convert the data files into LSB order to cut workload! */ - - if( IS_LSB ) - { - int word; - - for( word = 0; word < word_count; word++ ) - { - int i; - - for( i = 0; i < word_size/2; i++ ) - { - int t; - - t = data[i]; - data[i] = data[word_size-i-1]; - data[word_size-i-1] = t; - } - - data += word_size; - } - } -} - -/************************************************************************/ -/* nad_load_ntv1() */ -/* */ -/* Load an NTv1 style Canadian grid shift file. */ -/************************************************************************/ - -static struct CTABLE *nad_load_ntv1( FILE * fid ) - -{ - unsigned char header[176]; - struct CTABLE *ct; - LP ur; - double *row_buf; - int row; - - assert( sizeof(int) == 4 ); - assert( sizeof(double) == 8 ); - if( sizeof(int) != 4 || sizeof(double) != 8 ) - { - fprintf( stderr, - "basic types of inappropraiate size in nad_load_ntv1()\n" ); - pj_errno = -38; - return NULL; - } - -/* -------------------------------------------------------------------- */ -/* Read the header. */ -/* -------------------------------------------------------------------- */ - if( fread( header, sizeof(header), 1, fid ) != 1 ) - { - fclose( fid ); - pj_errno = -38; - return 0; - } - -/* -------------------------------------------------------------------- */ -/* Regularize fields of interest. */ -/* -------------------------------------------------------------------- */ - local_order( header+8, 4, 1 ); - local_order( header+24, 8, 1 ); - local_order( header+40, 8, 1 ); - local_order( header+56, 8, 1 ); - local_order( header+72, 8, 1 ); - local_order( header+88, 8, 1 ); - local_order( header+104, 8, 1 ); - - if( *((int *) (header+8)) != 12 ) - { - pj_errno = -38; - printf("NTv1 grid shift file has wrong record count, corrupt?\n"); - return NULL; - } - -/* -------------------------------------------------------------------- */ -/* Fill in CTABLE structure. */ -/* -------------------------------------------------------------------- */ - ct = (struct CTABLE *) pj_malloc(sizeof(struct CTABLE)); - strcpy( ct->id, "NTv1 Grid Shift File" ); - - ct->ll.lam = - *((double *) (header+72)); - ct->ll.phi = *((double *) (header+24)); - ur.lam = - *((double *) (header+56)); - ur.phi = *((double *) (header+40)); - ct->del.lam = *((double *) (header+104)); - ct->del.phi = *((double *) (header+88)); - ct->lim.lam = (int) (fabs(ur.lam-ct->ll.lam)/ct->del.lam + 0.5) + 1; - ct->lim.phi = (int) (fabs(ur.phi-ct->ll.phi)/ct->del.phi + 0.5) + 1; - - ct->ll.lam *= DEG_TO_RAD; - ct->ll.phi *= DEG_TO_RAD; - ct->del.lam *= DEG_TO_RAD; - ct->del.phi *= DEG_TO_RAD; - -/* -------------------------------------------------------------------- */ -/* Fill the data array. */ -/* */ -/* We process one line at a time. Note that the array storage */ -/* direction (e-w) is different in the NTv1 file and what */ -/* the CTABLE is supposed to have. The phi/lam are also */ -/* reversed, and we have to be aware of byte swapping. */ -/* -------------------------------------------------------------------- */ - row_buf = (double *) pj_malloc(ct->lim.lam * sizeof(double) * 2); - ct->cvs = (FLP *) pj_malloc(ct->lim.lam*ct->lim.phi*sizeof(FLP)); - if( row_buf == NULL || ct->cvs == NULL ) - return NULL; - - for( row = 0; row < ct->lim.phi; row++ ) - { - int i; - FLP *cvs; - double *diff_seconds; - - if( fread( row_buf, sizeof(double), ct->lim.lam * 2, fid ) - != 2 * ct->lim.lam ) - { - pj_dalloc( row_buf ); - pj_dalloc( ct->cvs ); - pj_errno = -38; - return NULL; - } - - local_order( (unsigned char *) row_buf, 8, ct->lim.lam * 2 ); - - /* convert seconds to radians */ - diff_seconds = row_buf; - - for( i = 0; i < ct->lim.lam; i++ ) - { - cvs = ct->cvs + (row) * ct->lim.lam - + (ct->lim.lam - i - 1); - - cvs->phi = *(diff_seconds++) * ((PI/180.0) / 3600.0); - cvs->lam = *(diff_seconds++) * ((PI/180.0) / 3600.0); - } - } - - pj_dalloc( row_buf ); - - return ct; -} - /************************************************************************/ /* nad_load_ctable() */ /* */ /* Load a datum shift file already in "CTABLE" format. */ /************************************************************************/ -static struct CTABLE *nad_load_ctable( FILE * fid ) +struct CTABLE *nad_load_ctable( FILE * fid ) { struct CTABLE *ct; int a_size, id_end; @@ -283,32 +128,7 @@ struct CTABLE *nad_init(char *name) return 0; } -/* -------------------------------------------------------------------- */ -/* Load a header, to determine the file type. */ -/* -------------------------------------------------------------------- */ - if( fread( header, sizeof(header), 1, fid ) != 1 ) - { - fclose( fid ); - pj_errno = -38; - return 0; - } - - fseek( fid, SEEK_SET, 0 ); - -/* -------------------------------------------------------------------- */ -/* Determine file type. */ -/* -------------------------------------------------------------------- */ - if( strncmp(header + 0, "HEADER", 6) == 0 - && strncmp(header + 96, "W GRID", 6) == 0 - && strncmp(header + 144, "TO NAD83 ", 16) == 0 ) - { - ct = nad_load_ntv1( fid ); - } - - else - { - ct = nad_load_ctable( fid ); - } + ct = nad_load_ctable( fid ); fclose(fid); return ct; @@ -323,7 +143,9 @@ struct CTABLE *nad_init(char *name) void nad_free(struct CTABLE *ct) { if (ct) { - pj_dalloc(ct->cvs); + if( ct->cvs != NULL ) + pj_dalloc(ct->cvs); + pj_dalloc(ct); } } diff --git a/src/pj_apply_gridshift.c b/src/pj_apply_gridshift.c index 7860cbdd..287ffb07 100644 --- a/src/pj_apply_gridshift.c +++ b/src/pj_apply_gridshift.c @@ -6,10 +6,10 @@ * NAD83 or the reverse). This module is responsible for keeping * a list of loaded grids, and calling with each one that is * allowed for a given datum (expressed as the nadgrids= parameter). - * Author: Frank Warmerdam, warmerda@home.com + * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** - * Copyright (c) 2000, Frank Warmerdam + * Copyright (c) 2000, Frank Warmerdam <warmerdam@pobox.com> * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,6 +31,9 @@ ****************************************************************************** * * $Log$ + * Revision 1.5 2003/03/15 06:02:02 warmerda + * preliminary NTv2 support, major restructure of datum shifting + * * Revision 1.4 2002/07/08 02:32:05 warmerda * ensure clean C++ builds * @@ -51,190 +54,6 @@ #include <string.h> #include <math.h> -#define GRID_MAX 100 - -/* used only by pj_get_grid() and pj_deallocate_grids() */ -static int grid_count = 0; -static char **grid_names = NULL; -static struct CTABLE **grid_list = NULL; - -/* used only by pj_load_nadgrids() and pj_deallocate_grids() */ -static struct CTABLE **last_nadgrids_list = NULL; -static char *last_nadgrids = NULL; - -/************************************************************************/ -/* pj_deallocate_grids() */ -/* */ -/* Deallocate all loaded grids. */ -/************************************************************************/ - -void pj_deallocate_grids() - -{ - if( grid_count > 0 ) - { - int i; - - for( i = 0; i < grid_count; i++ ) - { - if( grid_list[i] != NULL ) - nad_free( grid_list[i] ); - pj_dalloc( grid_names[i] ); - } - - pj_dalloc( grid_names ); - pj_dalloc( grid_list ); - - grid_names = NULL; - grid_list = NULL; - - grid_count = 0; - } - - if( last_nadgrids != NULL ) - { - pj_dalloc( last_nadgrids ); - last_nadgrids = NULL; - - pj_dalloc( last_nadgrids_list ); - last_nadgrids_list = NULL; - } -} - -/************************************************************************/ -/* pj_get_grid() */ -/* */ -/* Find the requested grid in the list, or if not present, try */ -/* and load it. On failure returns NULL and sets pj_errno. */ -/************************************************************************/ - -static struct CTABLE *pj_get_grid( const char *name ) - -{ - int i; - -/* -------------------------------------------------------------------- */ -/* First look in the existing list. */ -/* -------------------------------------------------------------------- */ - for( i = 0; i < grid_count; i++ ) - { - if( strcmp( grid_names[i], name ) == 0 ) - { - if( grid_list[i] == NULL ) - pj_errno = -38; - - return grid_list[i]; - } - } - -/* -------------------------------------------------------------------- */ -/* Add entry for this file in the grid list. */ -/* -------------------------------------------------------------------- */ - if( grid_count == 0 ) - { - grid_names = (char **) pj_malloc(sizeof(char *) * GRID_MAX); - memset( grid_names, 0, sizeof(char *) * GRID_MAX ); - grid_list = (struct CTABLE **) - pj_malloc(sizeof(struct CTABLE *) * GRID_MAX ); - memset( grid_list, 0, sizeof(struct CTABLE *) * GRID_MAX ); - } - else if( grid_count >= GRID_MAX ) - { - pj_errno = -38; - return NULL; - } - - grid_count++; - - grid_names[grid_count-1] = (char *) pj_malloc(strlen(name)+1); - strcpy( grid_names[grid_count-1], name ); - -/* -------------------------------------------------------------------- */ -/* Read the file. */ -/* -------------------------------------------------------------------- */ - grid_list[grid_count-1] = nad_init( (char *) name ); - - return grid_list[grid_count-1]; -} - -/************************************************************************/ -/* pj_load_nadgrids() */ -/* */ -/* This functions loads the list of grids corresponding to a */ -/* particular nadgrids string into a list, and returns it. The */ -/* list is kept around till a request is made with a different */ -/* string in order to cut down on the string parsing cost, and */ -/* the cost of building the list of tables each time. */ -/************************************************************************/ - -static struct CTABLE **pj_load_nadgrids( const char *nadgrids ) - -{ - int nadgrids_count = 0; - const char *s; - - pj_errno = 0; - - if( last_nadgrids != NULL - && strcmp(nadgrids,last_nadgrids) == 0 ) - return last_nadgrids_list; - -/* -------------------------------------------------------------------- */ -/* Free old one, if any, and make space for new list. */ -/* -------------------------------------------------------------------- */ - if( last_nadgrids != NULL ) - { - pj_dalloc(last_nadgrids); - } - - last_nadgrids = (char *) pj_malloc(strlen(nadgrids)+1); - strcpy( last_nadgrids, nadgrids ); - - if( last_nadgrids_list == NULL ) - last_nadgrids_list = (struct CTABLE **) - pj_malloc(sizeof(struct CTABLE *) * GRID_MAX); - -/* -------------------------------------------------------------------- */ -/* Loop processing names out of nadgrids one at a time. */ -/* -------------------------------------------------------------------- */ - for( s = nadgrids; *s != '\0'; ) - { - int end_char; - char name[128]; - - for( end_char = 0; - s[end_char] != '\0' && s[end_char] != ','; - end_char++ ) {} - - if( end_char > sizeof(name) ) - { - pj_errno = -38; - return NULL; - } - - strncpy( name, s, end_char ); - name[end_char] = '\0'; - - s += end_char; - if( *s == ',' ) - s++; - - - last_nadgrids_list[nadgrids_count] = pj_get_grid( name ); - if( last_nadgrids_list[nadgrids_count] == NULL ) - { - pj_errno = -38; - return NULL; - } - - nadgrids_count++; - } - - last_nadgrids_list[nadgrids_count] = NULL; - - return last_nadgrids_list; -} - /************************************************************************/ /* pj_apply_gridshift() */ /************************************************************************/ @@ -244,10 +63,11 @@ int pj_apply_gridshift( const char *nadgrids, int inverse, double *x, double *y, double *z ) { - struct CTABLE **tables = pj_load_nadgrids( nadgrids ); + int grid_count = 0; + PJ_GRIDINFO **tables = pj_gridlist_from_nadgrids( nadgrids, &grid_count); int i; - if( tables == NULL ) + if( tables == NULL || grid_count == 0 ) return pj_errno; for( i = 0; i < point_count; i++ ) @@ -260,9 +80,25 @@ int pj_apply_gridshift( const char *nadgrids, int inverse, input.lam = x[io]; /* keep trying till we find a table that works */ - for( itable = 0; tables[itable] != NULL; itable++ ) + for( itable = 0; itable < grid_count; itable++ ) { - output = nad_cvt( input, inverse, tables[itable] ); + struct CTABLE *ct = tables[itable]->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 * ct->del.phi < input.phi + || ct->ll.lam + ct->lim.lam * ct->del.lam < input.lam ) + continue; + + /* load the grid shift info if we don't have it. */ + if( tables[itable]->ct->cvs == NULL + && !pj_gridinfo_load( tables[itable] ) ) + { + pj_errno = -38; + return pj_errno; + } + + output = nad_cvt( input, inverse, tables[itable]->ct ); if( output.lam != HUGE_VAL ) break; } diff --git a/src/projects.h b/src/projects.h index ff65e574..f417e4a8 100644 --- a/src/projects.h +++ b/src/projects.h @@ -28,6 +28,9 @@ ****************************************************************************** * * $Log$ + * Revision 1.16 2003/03/15 06:02:02 warmerda + * preliminary NTv2 support, major restructure of datum shifting + * * Revision 1.15 2002/12/14 20:35:15 warmerda * fix C_NAMESPACE warning issue with C_NAMESPACE_VAR for variables * @@ -309,6 +312,7 @@ extern struct PJ_PRIME_MERIDIANS pj_prime_meridians[]; #define MAX_TAB_ID 80 typedef struct { float lam, phi; } FLP; typedef struct { int lam, phi; } ILP; + struct CTABLE { char id[MAX_TAB_ID]; /* ascii info */ LP ll; /* lower left corner coordinates */ @@ -316,7 +320,22 @@ struct CTABLE { ILP lim; /* limits of conversion matrix */ FLP *cvs; /* conversion matrix */ }; - /* procedure prototypes */ + +typedef struct _pj_gi { + char *gridname; /* identifying name of grid, eg "conus" or ntv2_0.gsb */ + char *filename; /* full path to filename */ + + const char *format; /* format of this grid, ie "ctable", "ntv1", + "ntv2" or "missing". */ + + int grid_offset; /* offset in file, for delayed loading */ + + struct CTABLE *ct; + + struct _pj_gi *next; +} PJ_GRIDINFO; + +/* procedure prototypes */ double dmstor(const char *, char **); void set_rtodms(int, int); char *rtodms(char *, double, int, int); @@ -371,7 +390,18 @@ int bch2bps(projUV, projUV, projUV **, int, int); LP nad_intr(LP, struct CTABLE *); LP nad_cvt(LP, int, struct CTABLE *); struct CTABLE *nad_init(char *); +struct CTABLE *nad_load_ctable( FILE * fid ); void nad_free(struct CTABLE *); + +/* higher level handling of datum grid shift files */ + +PJ_GRIDINFO **pj_gridlist_from_nadgrids( const char *, int * ); +void pj_deallocate_grids(); + +PJ_GRIDINFO *pj_gridinfo_init( const char * ); +int pj_gridinfo_load( PJ_GRIDINFO * ); +void pj_gridinfo_free( PJ_GRIDINFO * ); + extern char const pj_release[]; #ifndef DISABLE_CVSID |
