/* file: readgsf.c function: reader purpose: to read in lonmin-latmin-depth triples from gmf files. date: 22 Nov 94 history: originally "readgmf" converted to "readgsf" for HMPS97 Improvements, Nov 1997 author: David H. Fabre notes: (from the main.c file of the chrtr program:) The application programmer must supply a function 'reader' that reads the data in the input files. The argument list for the function is as follows : int reader (float *lon, float *lat, float *zvalue, int prime_meridian, char *input_filenames[], int numfiles) lon - longitude value (in minutes, west negative) to pass to caller lat - latitude value (in minutes, south negative) to pass to caller zvalue - z value (user units) to pass to caller prime_meridian - passed to reader, 1 if area covered crosses the prime_meridian input_filenames - passed to reader, array of pointers to input filenames to be read numfiles - passed to reader, number of input filenames int returned - 0 on a good read, 1 if all data has been read (the last few lines of the reader_gen.c (general reader) are:) *lon *= 60.0; (these convert deg to mins) *lat *= 60.0; if (prime_meridian) *lon += 21600.0; (this adds 360 deg to the lon) return (0); */ #include #include #include "gsf.h" #include "ellipsoid.h" /* for AXIS(WE) and RFLAT(WE) */ #include "geod.h" /* for geo_direct prototype */ #define DEG2RAD 0.0174532925199432957692 /* if TEST_READGSF is defined then we'll be testing the reader, it is defined in the make.test makefile */ /*#define TEST_READGSF*/ /* used to define nonsensical values of lonmin-latmin-depth */ #define NONSENSE 1.0e10 /******************************************************************************/ /* prototypes for functions in the file (staticized functions are hidden from outside .c.o files) */ int open_gsffile(char *filename); int read_rec(); void place_beam(int prime_meridian, int beamon, float *lonmin, float *latmin, float *depth); int reader(float *lonmin, float *latmin, float *depth, int prime_meridian, char *filename[], int numfiles); /* main is only for testing and can be turned off by not defining TEST_READGSF */ #ifdef TEST_READGSF int main(int argc, char *argv[]); /* don't change to char **argv Dave */ #endif /******************************************************************************/ /* file global declarations */ static int gsfHandle; static gsfRecords gsfRec; static gsfDataID id; /* reccnt is used only for testing */ #ifdef TEST_READGSF static int reccnt; #endif /******************************************************************************/ int open_gsffile(char *filename) /* open a file */ { if ( gsfOpen(filename, GSF_READONLY, &gsfHandle) == -1 ) { printf("pblm opening <%s>\n", filename); return 0; } else { gsfSeek(gsfHandle, GSF_REWIND); /* just in case */ return 1; } } /* open_gsffile */ /******************************************************************************/ int read_rec() { int stat; int i; while ( (stat = gsfRead(gsfHandle, GSF_NEXT_RECORD, &id, &gsfRec, NULL, 0)) != -1 && id.recordID != GSF_RECORD_SWATH_BATHYMETRY_PING ); #ifdef TEST_READGSF if ( stat != -1 && id.recordID == GSF_RECORD_SWATH_BATHYMETRY_PING ) { /*printf("read_rec: number_beams = %d\n", gsfRec.mb_ping.number_beams);*/ ++reccnt; } #endif /*printf("read_rec: stat = %d\n", stat);*/ /*printf("read_rec: id.recordID = %d\n", id.recordID);*/ return (stat != -1 && id.recordID == GSF_RECORD_SWATH_BATHYMETRY_PING); } /* read_rec */ /******************************************************************************/ void place_beam(int prime_meridian, int beamon, float *lonmin, float *latmin, float *depth) { static ELLIPSOID ellip=WE; short stat=1; double lat, lon, az2; int special; if ( (gsfRec.mb_ping.ping_flags & GSF_IGNORE_PING) || (gsfRec.mb_ping.beam_flags[beamon] & GSF_IGNORE_BEAM) ) { *depth = NONSENSE; } else { /* printf("place_beam: %lf %lf %.1lf %.2lf %.2lf %.2lf\n", gsfRec.mb_ping.latitude, gsfRec.mb_ping.longitude, gsfRec.mb_ping.heading, gsfRec.mb_ping.along_track[beamon], gsfRec.mb_ping.across_track[beamon], gsfRec.mb_ping.depth[beamon]); printf("AXIS = %lf, RFLAT = %lf\n", AXIS(ellip), RFLAT(ellip)); */ special = 0; stat = 0; lat = gsfRec.mb_ping.latitude; lon = gsfRec.mb_ping.longitude; if ( gsfRec.mb_ping.along_track ) { if ( gsfRec.mb_ping.along_track[beamon] == 0.0 && gsfRec.mb_ping.across_track[beamon] == 0.0) { /* very special case - probably single beam */ special = 1; } if (fabs(gsfRec.mb_ping.along_track[beamon]) > 0.0) stat = geo_direct( AXIS(ellip), RFLAT(ellip), gsfRec.mb_ping.latitude, gsfRec.mb_ping.longitude, gsfRec.mb_ping.heading, gsfRec.mb_ping.along_track[beamon], &lat, &lon, &az2 ); } /* if there is an alongtrack value */ /*printf("stat along = %d\n", stat); printf("lat %lf lon %lf az2 %lf\n", lat, lon, az2);*/ if (stat == 0 && fabs(gsfRec.mb_ping.across_track[beamon])>0.0) stat = geo_direct( AXIS(ellip), RFLAT(ellip), lat, lon, gsfRec.mb_ping.heading + 90.0, gsfRec.mb_ping.across_track[beamon], &lat, &lon, &az2 ); /*printf("stat across = %d\n", stat); printf("lat %lf lon %lf az2 %lf\n", lat, lon, az2);*/ if (stat == 0 || special) /* it worked or special */ { *lonmin = (float)( 60.0*lon ); /* convert to min */ if (prime_meridian) *lonmin += 21600.0;/* +360 deg min*/ *latmin = (float)( 60.0*lat ); /* convert to min */ *depth = (float)( gsfRec.mb_ping.depth[beamon] ); } else { *depth = NONSENSE; } } } /* place_beam */ /******************************************************************************/ int reader(float *lonmin, float *latmin, float *depth, int prime_meridian, char *filename[], int numfiles) /* notes: 1. this routine is a bit convoluted because i had to use the single reader for a list of filenames. it would fit better if the higher level routine would have done the file opening and passed in a file ptr, maybe. 2. this routine is keyed upon the beamon flag. it should only be -2 the first time through. thereafter it'll be -1, 0, ..., number_beams-1. the -1 case indicates that we need to read another record cause we just opened the next file on the previous attempt to return. the 0 thru number_beams-1 set indicates just to take the next beamon. when it gets to be number_beams we try to read another record. if the stat of the read is invalid we try to open another file. if the file opening doesn't work return a 1 indicating that we're through. 3. by design we'll be returning bad lat,lon pairs whenever we open a new file after the first one. the main routine has a gross check that should see these values as nonsensical and consider it a bad point. 4. an invalid depth value is set to NONSENSE, which should be non- sensical enough to be ignored by the main routine . */ { static int beamon=(-2); static int fileon=(-1); static int stat; int ans=0; if ( beamon == -2 && ++fileon < numfiles && open_gsffile(filename[fileon]) && (stat = read_rec()) ) { beamon = 0; } else if ( beamon == -1 && (stat = read_rec()) ) { beamon = 0; } else if (beamon < gsfRec.mb_ping.number_beams-1) { ++beamon; } /* else beamon == number_beams so */ else if ( (stat = read_rec()) ) { beamon = 0; } if (!stat) { gsfClose(gsfHandle); if ( ++fileon >= numfiles || !open_gsffile(filename[fileon]) ) { ans = 1; } else { *lonmin = *latmin = *depth = NONSENSE; beamon = -1; } } else { /*printf("reader: placing beam %d\n", beamon);*/ place_beam(prime_meridian, beamon, lonmin, latmin, depth); } if (*depth == NONSENSE) *lonmin = *latmin = NONSENSE; return ans; } /* reader */ #ifdef TEST_READGSF /******************************************************************************/ int main(int argc, char *argv[]) { float lonmin, latmin, depth; int cnt=0, valid_cnt=0; reccnt = 0; if (argc < 2) { printf("usage: %s \n", argv[0]); } else { while ( !reader(&lonmin, &latmin, &depth, 0, &argv[1], argc-1) ) { ++cnt; /*if (depth != NONSENSE)*/ printf("%.9f %.9f %.3f\n", lonmin/60., latmin/60., depth); if (lonmin != NONSENSE && latmin != NONSENSE && depth != NONSENSE) ++valid_cnt; } } printf("#records=%d #beams=%d #valid beams=%d\n", reccnt, cnt, valid_cnt); return cnt; } /* main */ #endif