aboutsummaryrefslogtreecommitdiff
path: root/src/nad2bin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/nad2bin.cpp')
-rw-r--r--src/nad2bin.cpp382
1 files changed, 382 insertions, 0 deletions
diff --git a/src/nad2bin.cpp b/src/nad2bin.cpp
new file mode 100644
index 00000000..eb8672a5
--- /dev/null
+++ b/src/nad2bin.cpp
@@ -0,0 +1,382 @@
+/* Convert bivariate ASCII NAD27 to NAD83 tables to NTv2 binary structure */
+#include <stdio.h>
+#include <stdlib.h>
+
+#define PJ_LIB__
+#include "proj_internal.h"
+#include "projects.h"
+#define U_SEC_TO_RAD 4.848136811095359935899141023e-12
+
+/************************************************************************/
+/* swap_words() */
+/* */
+/* Convert the byte order of the given word(s) in place. */
+/************************************************************************/
+
+static const int byte_order_test = 1;
+#define IS_LSB (((const unsigned char *) (&byte_order_test))[0] == 1)
+
+static void swap_words( void *data_in, int word_size, int word_count )
+
+{
+ int word;
+ unsigned char *data = (unsigned char *) data_in;
+
+ for( word = 0; word < word_count; word++ )
+ {
+ int i;
+
+ for( i = 0; i < word_size/2; i++ )
+ {
+ unsigned char t;
+
+ t = data[i];
+ data[i] = data[word_size-i-1];
+ data[word_size-i-1] = t;
+ }
+
+ data += word_size;
+ }
+}
+
+/************************************************************************/
+/* Usage() */
+/************************************************************************/
+
+static void Usage()
+{
+ fprintf(stderr,
+ "usage: nad2bin [-f ctable/ctable2/ntv2] binary_output < ascii_source\n" );
+ exit(1);
+}
+
+/************************************************************************/
+/* main() */
+/************************************************************************/
+int main(int argc, char **argv) {
+ struct CTABLE ct;
+ FLP *p, t;
+ size_t tsize;
+ int i, j, ichk;
+ long lam, laml, phi, phil;
+ FILE *fp;
+
+ const char *output_file = NULL;
+
+ const char *format = "ctable2";
+ const char *GS_TYPE = "SECONDS";
+ const char *VERSION = "";
+ const char *SYSTEM_F = "NAD27";
+ const char *SYSTEM_T = "NAD83";
+ const char *SUB_NAME = "";
+ const char *CREATED = "";
+ const char *UPDATED = "";
+
+/* ==================================================================== */
+/* Process arguments. */
+/* ==================================================================== */
+ for( i = 1; i < argc; i++ )
+ {
+ if( i < argc-1 && strcmp(argv[i],"-f") == 0 )
+ {
+ format = argv[++i];
+ }
+ else if( output_file == NULL )
+ {
+ output_file = argv[i];
+ }
+ else
+ Usage();
+ }
+
+ if( output_file == NULL )
+ Usage();
+
+ fprintf( stdout, "Output Binary File Format: %s\n", format );
+
+/* ==================================================================== */
+/* Read the ASCII Table */
+/* ==================================================================== */
+
+ memset(ct.id,0,MAX_TAB_ID);
+ if ( NULL == fgets(ct.id, MAX_TAB_ID, stdin) ) {
+ perror("fgets");
+ exit(1);
+ }
+ /* cppcheck-suppress invalidscanf */
+ if ( EOF == scanf("%d %d %*d %lf %lf %lf %lf", &ct.lim.lam, &ct.lim.phi,
+ &ct.ll.lam, &ct.del.lam, &ct.ll.phi, &ct.del.phi) ) {
+ perror("scanf");
+ exit(1);
+ }
+ if (!(ct.cvs = (FLP *)malloc(tsize = ct.lim.lam * ct.lim.phi *
+ sizeof(FLP)))) {
+ perror("mem. alloc");
+ exit(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;
+ /* load table */
+ p = ct.cvs;
+ for (i = 0; i < ct.lim.phi; ++i) {
+ /* cppcheck-suppress invalidscanf */
+ if ( EOF == scanf("%d:%ld %ld", &ichk, &laml, &phil) ) {
+ perror("scanf on row");
+ exit(1);
+ }
+ if (ichk != i) {
+ fprintf(stderr,"format check on row\n");
+ exit(1);
+ }
+ t.lam = (float) (laml * U_SEC_TO_RAD);
+ t.phi = (float) (phil * U_SEC_TO_RAD);
+ *p++ = t;
+ for (j = 1; j < ct.lim.lam; ++j) {
+ /* cppcheck-suppress invalidscanf */
+ if ( EOF == scanf("%ld %ld", &lam, &phi) ) {
+ perror("scanf on column");
+ exit(1);
+ }
+ t.lam = (float) ((laml += lam) * U_SEC_TO_RAD);
+ t.phi = (float) ((phil += phi) * U_SEC_TO_RAD);
+ *p++ = t;
+ }
+ }
+ if (feof(stdin)) {
+ fprintf(stderr, "premature EOF\n");
+ exit(1);
+ }
+
+/* ==================================================================== */
+/* Write out the old ctable format - this is machine and byte */
+/* order specific. */
+/* ==================================================================== */
+ if( strcmp(format,"ctable") == 0 )
+ {
+ if (!(fp = fopen(output_file, "wb"))) {
+ perror(output_file);
+ exit(2);
+ }
+ if (fwrite(&ct, sizeof(ct), 1, fp) != 1 ||
+ fwrite(ct.cvs, tsize, 1, fp) != 1) {
+ fprintf(stderr, "output failure\n");
+ exit(2);
+ }
+ fclose( fp );
+ exit(0); /* normal completion */
+ }
+
+/* ==================================================================== */
+/* Write out the old ctable format - this is machine and byte */
+/* order specific. */
+/* ==================================================================== */
+ if( strcmp(format,"ctable2") == 0 )
+ {
+ char header[160];
+
+ if (!(fp = fopen(output_file, "wb"))) {
+ perror(output_file);
+ exit(2);
+ }
+
+ /* cppcheck-suppress sizeofCalculation */
+ STATIC_ASSERT( MAX_TAB_ID == 80 );
+ /* cppcheck-suppress sizeofCalculation */
+ STATIC_ASSERT( sizeof(pj_int32) == 4 ); /* for ct.lim.lam/phi */
+
+ memset( header, 0, sizeof(header) );
+
+ memcpy( header + 0, "CTABLE V2.0 ", 16 );
+ memcpy( header + 16, ct.id, 80 );
+ memcpy( header + 96, &ct.ll.lam, 8 );
+ memcpy( header + 104, &ct.ll.phi, 8 );
+ memcpy( header + 112, &ct.del.lam, 8 );
+ memcpy( header + 120, &ct.del.phi, 8 );
+ memcpy( header + 128, &ct.lim.lam, 4 );
+ memcpy( header + 132, &ct.lim.phi, 4 );
+
+ /* force into LSB format */
+ if( !IS_LSB )
+ {
+ swap_words( header + 96, 8, 4 );
+ swap_words( header + 128, 4, 2 );
+ swap_words( ct.cvs, 4, ct.lim.lam * 2 * ct.lim.phi );
+ }
+
+ if( fwrite( header, sizeof(header), 1, fp ) != 1 ) {
+ perror( "fwrite" );
+ exit( 2 );
+ }
+
+ if (fwrite(ct.cvs, tsize, 1, fp) != 1) {
+ perror( "fwrite" );
+ exit(2);
+ }
+
+ fclose( fp );
+ exit(0); /* normal completion */
+ }
+
+/* ==================================================================== */
+/* Write out the NTv2 format grid shift file. */
+/* ==================================================================== */
+ if( strcmp(format,"ntv2") == 0 )
+ {
+ if (!(fp = fopen(output_file, "wb")))
+ {
+ perror(output_file);
+ exit(2);
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write the file header. */
+/* -------------------------------------------------------------------- */
+ {
+ char achHeader[11*16];
+
+ memset( achHeader, 0, sizeof(achHeader) );
+
+ memcpy( achHeader + 0*16, "NUM_OREC", 8 );
+ achHeader[ 0*16 + 8] = 0xb;
+
+ memcpy( achHeader + 1*16, "NUM_SREC", 8 );
+ achHeader[ 1*16 + 8] = 0xb;
+
+ memcpy( achHeader + 2*16, "NUM_FILE", 8 );
+ achHeader[ 2*16 + 8] = 0x1;
+
+ memcpy( achHeader + 3*16, "GS_TYPE ", 16 );
+ memcpy( achHeader + 3*16+8, GS_TYPE, MIN(16,strlen(GS_TYPE)) );
+
+ memcpy( achHeader + 4*16, "VERSION ", 16 );
+ memcpy( achHeader + 4*16+8, VERSION, MIN(16,strlen(VERSION)) );
+
+ memcpy( achHeader + 5*16, "SYSTEM_F ", 16 );
+ memcpy( achHeader + 5*16+8, SYSTEM_F, MIN(16,strlen(SYSTEM_F)) );
+
+ memcpy( achHeader + 6*16, "SYSTEM_T ", 16 );
+ memcpy( achHeader + 6*16+8, SYSTEM_T, MIN(16,strlen(SYSTEM_T)) );
+
+ memcpy( achHeader + 7*16, "MAJOR_F ", 8);
+ memcpy( achHeader + 8*16, "MINOR_F ", 8 );
+ memcpy( achHeader + 9*16, "MAJOR_T ", 8 );
+ memcpy( achHeader + 10*16, "MINOR_T ", 8 );
+
+ fwrite( achHeader, 1, sizeof(achHeader), fp );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write the grid header. */
+/* -------------------------------------------------------------------- */
+ {
+ unsigned char achHeader[11*16];
+ double dfValue;
+ pj_int32 nGSCount = ct.lim.lam * ct.lim.phi;
+ LP ur;
+
+ ur.lam = ct.ll.lam + (ct.lim.lam-1) * ct.del.lam;
+ ur.phi = ct.ll.phi + (ct.lim.phi-1) * ct.del.phi;
+
+ /* cppcheck-suppress sizeofCalculation */
+ STATIC_ASSERT( sizeof(nGSCount) == 4 );
+
+ memset( achHeader, 0, sizeof(achHeader) );
+
+ memcpy( achHeader + 0*16, "SUB_NAME ", 16 );
+ memcpy( achHeader + 0*16+8, SUB_NAME, MIN(16,strlen(SUB_NAME)) );
+
+ memcpy( achHeader + 1*16, "PARENT ", 16 );
+ memcpy( achHeader + 1*16+8, "NONE", MIN(16,strlen("NONE")) );
+
+ memcpy( achHeader + 2*16, "CREATED ", 16 );
+ memcpy( achHeader + 2*16+8, CREATED, MIN(16,strlen(CREATED)) );
+
+ memcpy( achHeader + 3*16, "UPDATED ", 16 );
+ memcpy( achHeader + 3*16+8, UPDATED, MIN(16,strlen(UPDATED)) );
+
+ memcpy( achHeader + 4*16, "S_LAT ", 8 );
+ dfValue = ct.ll.phi * 3600.0 / DEG_TO_RAD;
+ memcpy( achHeader + 4*16 + 8, &dfValue, 8 );
+
+ memcpy( achHeader + 5*16, "N_LAT ", 8 );
+ dfValue = ur.phi * 3600.0 / DEG_TO_RAD;
+ memcpy( achHeader + 5*16 + 8, &dfValue, 8 );
+
+ memcpy( achHeader + 6*16, "E_LONG ", 8 );
+ dfValue = -1 * ur.lam * 3600.0 / DEG_TO_RAD;
+ memcpy( achHeader + 6*16 + 8, &dfValue, 8 );
+
+ memcpy( achHeader + 7*16, "W_LONG ", 8 );
+ dfValue = -1 * ct.ll.lam * 3600.0 / DEG_TO_RAD;
+ memcpy( achHeader + 7*16 + 8, &dfValue, 8 );
+
+ memcpy( achHeader + 8*16, "LAT_INC ", 8 );
+ dfValue = ct.del.phi * 3600.0 / DEG_TO_RAD;
+ memcpy( achHeader + 8*16 + 8, &dfValue, 8 );
+
+ memcpy( achHeader + 9*16, "LONG_INC", 8 );
+ dfValue = ct.del.lam * 3600.0 / DEG_TO_RAD;
+ memcpy( achHeader + 9*16 + 8, &dfValue, 8 );
+
+ memcpy( achHeader + 10*16, "GS_COUNT", 8 );
+ memcpy( achHeader + 10*16+8, &nGSCount, 4 );
+
+ if( !IS_LSB )
+ {
+ swap_words( achHeader + 4*16 + 8, 8, 1 );
+ swap_words( achHeader + 5*16 + 8, 8, 1 );
+ swap_words( achHeader + 6*16 + 8, 8, 1 );
+ swap_words( achHeader + 7*16 + 8, 8, 1 );
+ swap_words( achHeader + 8*16 + 8, 8, 1 );
+ swap_words( achHeader + 9*16 + 8, 8, 1 );
+ swap_words( achHeader + 10*16 + 8, 4, 1 );
+ }
+
+ fwrite( achHeader, 1, sizeof(achHeader), fp );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Write the actual grid cells. */
+/* -------------------------------------------------------------------- */
+ {
+ float *row_buf;
+ int row;
+
+ row_buf = (float *) pj_malloc(ct.lim.lam * sizeof(float) * 4);
+ memset( row_buf, 0, sizeof(float)*4 );
+
+ for( row = 0; row < ct.lim.phi; row++ )
+ {
+ for( i = 0; i < ct.lim.lam; i++ )
+ {
+ FLP *cvs = ct.cvs + (row) * ct.lim.lam
+ + (ct.lim.lam - i - 1);
+
+ /* convert radians to seconds */
+ row_buf[i*4+0] = (float) (cvs->phi * (3600.0 / (M_PI/180.0)));
+ row_buf[i*4+1] = (float) (cvs->lam * (3600.0 / (M_PI/180.0)));
+
+ /* We leave the accuracy values as zero */
+ }
+
+ if( !IS_LSB )
+ swap_words( row_buf, 4, ct.lim.lam * 4 );
+
+ if( fwrite( row_buf, sizeof(float), ct.lim.lam*4, fp )
+ != (size_t)( 4 * ct.lim.lam ) )
+ {
+ perror( "write()" );
+ exit( 2 );
+ }
+ }
+ }
+
+ fclose( fp );
+ exit(0); /* normal completion */
+ }
+
+ fprintf( stderr, "Unsupported format, nothing written.\n" );
+ exit( 3 );
+}