tesseroids/lib/parsers.c
2021-05-05 10:58:03 +08:00

1411 lines
42 KiB
C

/*
Input and output parsing tools.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "logger.h"
#include "version.h"
#include "parsers.h"
#include "constants.h"
#include "geometry.h"
/* Parse basic command line arguments for programs */
int parse_basic_args(int argc, char **argv, const char *progname,
BASIC_ARGS *args, void (*print_help)(void))
{
int bad_args = 0, parsed_args = 0, total_args = 1, i;
char *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help();
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(strcmp(params, "version"))
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
else
{
print_version(progname);
return 2;
}
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
if(parsed_args == 0)
{
args->inputfname = argv[i];
parsed_args++;
}
else
{
log_error("invalid argument '%s'. Already given model file %s",
argv[i], args->inputfname);
bad_args++;
}
}
}
/* Check if parsing went well */
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
return 1;
}
if(parsed_args < total_args)
{
return 3;
}
return 0;
}
/* Parse command line arguments for tess2prism program */
int parse_tess2prism_args(int argc, char **argv, const char *progname,
TESS2PRISM_ARGS *args, void (*print_help)(void))
{
int bad_args = 0, parsed_args = 0, total_args = 1, i;
char *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
args->flatten = 0;
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help();
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(!strcmp(params, "version"))
{
print_version(progname);
return 2;
}
else if(!strcmp(params, "flatten"))
{
args->flatten = 1;
}
else
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
if(parsed_args == 0)
{
args->inputfname = argv[i];
parsed_args++;
}
else
{
log_error("invalid argument '%s'. Already given model file %s",
argv[i], args->inputfname);
bad_args++;
}
}
}
/* Check if parsing went well */
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
return 1;
}
if(parsed_args < total_args)
{
return 3;
}
return 0;
}
/* Parse command line arguments for tessmass program */
int parse_tessmass_args(int argc, char **argv, const char *progname,
TESSMASS_ARGS *args, void (*print_help)(void))
{
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_r = 0, i, nchar,
nread;
char *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
args->use_range = 0;
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help();
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(strcmp(params, "version"))
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
else
{
print_version(progname);
return 2;
}
break;
}
case 'r':
{
if(parsed_r)
{
log_error("repeated argument -r");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf/%lf%n", &(args->low_dens),
&(args->high_dens), &nchar);
if(nread != 2 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_r = 1;
args->use_range = 1;
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
if(parsed_args == 0)
{
args->inputfname = argv[i];
parsed_args++;
}
else
{
log_error("invalid argument '%s'. Already given model file %s",
argv[i], args->inputfname);
bad_args++;
}
}
}
/* Check if parsing went well */
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
return 1;
}
if(parsed_args < total_args)
{
return 3;
}
return 0;
}
/* Parse command line arguments for tessmodgen program */
int parse_tessmodgen_args(int argc, char **argv, const char *progname,
TESSMODGEN_ARGS *args, void (*print_help)(void))
{
int bad_args = 0, parsed_args = 0, total_args = 2, parsed_s = 0,
parsed_z = 0, parsed_d = 0, i, nchar, nread;
char *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
args->fix_density = 0;
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help();
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(strcmp(params, "version"))
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
else
{
print_version(progname);
return 2;
}
break;
}
case 's':
{
if(parsed_s)
{
log_error("repeated argument -s");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf/%lf%n", &(args->dlon),
&(args->dlat), &nchar);
if(nread != 2 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_s = 1;
parsed_args++;
break;
}
case 'z':
{
if(parsed_z)
{
log_error("repeated argument -z");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf%n", &(args->ref), &nchar);
if(nread != 1 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_z = 1;
parsed_args++;
break;
}
case 'd':
{
if(parsed_d)
{
log_error("repeated argument -d");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf%n", &(args->dens), &nchar);
if(nread != 1 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_d = 1;
args->fix_density = 1;
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
}
/* Check if parsing went well */
if(bad_args > 0 || parsed_args != total_args)
{
if(parsed_args < total_args)
{
log_error("%s: missing input arguments. given %d out of %d.",
progname, parsed_args, total_args);
}
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
}
return 1;
}
return 0;
}
/* Parse command line arguments for tesslayers program */
int parse_tesslayers_args(int argc, char **argv, const char *progname,
TESSLAYERS_ARGS *args, void (*print_help)(void))
{
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_s = 0,
i, nchar, nread;
char *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help();
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(strcmp(params, "version"))
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
else
{
print_version(progname);
return 2;
}
break;
}
case 's':
{
if(parsed_s)
{
log_error("repeated argument -s");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf/%lf%n", &(args->dlon),
&(args->dlat), &nchar);
if(nread != 2 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_s = 1;
parsed_args++;
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
}
/* Check if parsing went well */
if(bad_args > 0 || parsed_args != total_args)
{
if(parsed_args < total_args)
{
log_error("%s: missing input arguments. given %d out of %d.",
progname, parsed_args, total_args);
}
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
}
return 1;
}
return 0;
}
/* Parse command line arguments for tessg* programs */
int parse_tessg_args(int argc, char **argv, const char *progname,
TESSG_ARGS *args, void (*print_help)(const char *))
{
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_order = 0,
parsed_ratio = 0, i, nchar, nread;
char *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
args->lon_order = 2;
args->lat_order = 2;
args->r_order = 2;
args->adaptative = 1;
args->ratio = 0; /* zero means use the default for the program */
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help(progname);
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(strcmp(params, "version"))
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
else
{
print_version(progname);
return 2;
}
break;
}
case 'a':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(!args->adaptative)
{
log_error("repeated option -a");
bad_args++;
break;
}
args->adaptative = 0;
break;
case 'o':
{
if(parsed_order)
{
log_error("repeated option -o");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%d/%d/%d%n", &(args->lon_order),
&(args->lat_order), &(args->r_order), &nchar);
if(nread != 3 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_order = 1;
break;
}
case 't':
{
if(parsed_ratio)
{
log_error("repeated option -t");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf%n", &(args->ratio), &nchar);
if(nread != 1 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_ratio = 1;
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
if(parsed_args == 0)
{
args->modelfname = argv[i];
parsed_args++;
}
else
{
log_error("invalid argument '%s'. Already given model file %s",
argv[i], args->modelfname);
bad_args++;
}
}
}
/* Check if parsing went well */
if(bad_args > 0 || parsed_args != total_args)
{
if(parsed_args < total_args)
{
log_error("%s: missing input file.",
progname, parsed_args, total_args);
}
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
}
return 1;
}
return 0;
}
/* Parse command line arguments for tessgrd program */
int parse_tessgrd_args(int argc, char **argv, TESSGRD_ARGS *args,
void (*print_help)(void))
{
int bad_args = 0, parsed_args = 0, total_args = 3, parsed_r = 0,
parsed_b = 0, parsed_z = 0, i, nchar, nread;
char progname[] = "tessgrd", *params;
/* Default values for options */
args->verbose = 0;
args->logtofile = 0;
/* Parse arguments */
for(i = 1; i < argc; i++)
{
if(argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'h':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
print_help();
return 2;
case 'v':
if(argv[i][2] != '\0')
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
if(args->verbose)
{
log_error("repeated option -v");
bad_args++;
break;
}
args->verbose = 1;
break;
case 'l':
{
if(args->logtofile)
{
log_error("repeated option -l");
bad_args++;
break;
}
params = &argv[i][2];
if(strlen(params) == 0)
{
log_error("bad input argument -l. Missing filename.");
bad_args++;
}
else
{
args->logtofile = 1;
args->logfname = params;
}
break;
}
case '-':
{
params = &argv[i][2];
if(strcmp(params, "version"))
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
else
{
print_version(progname);
return 2;
}
break;
}
case 'r':
{
if(parsed_r)
{
log_error("repeated argument -r");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf/%lf/%lf/%lf%n", &(args->w),
&(args->e), &(args->s), &(args->n), &nchar);
if(nread != 4 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_args++;
parsed_r = 1;
break;
}
case 'b':
{
if(parsed_b)
{
log_error("repeated argument -b");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%d/%d%n", &(args->nlon),
&(args->nlat), &nchar);
if(nread != 2 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_args++;
parsed_b = 1;
break;
}
case 'z':
{
if(parsed_z)
{
log_error("repeated argument -z");
bad_args++;
break;
}
params = &argv[i][2];
nchar = 0;
nread = sscanf(params, "%lf%n", &(args->height), &nchar);
if(nread != 1 || *(params + nchar) != '\0')
{
log_error("bad input argument '%s'", argv[i]);
bad_args++;
}
parsed_args++;
parsed_z = 1;
break;
}
default:
log_error("invalid argument '%s'", argv[i]);
bad_args++;
break;
}
}
else
{
log_error("invalid argument '%s'", argv[i]);
bad_args++;
}
}
/* Check if parsing went well */
if(bad_args > 0 || parsed_args != total_args)
{
if(parsed_args < total_args)
{
log_error("%s: missing input arguments. given %d out of %d.",
progname, parsed_args, total_args);
}
if(parsed_args > total_args)
{
log_error("%s: too many input arguments. given %d, max %d.",
progname, parsed_args, total_args);
}
if(bad_args > 0)
{
log_error("%d bad input argument(s)", bad_args);
}
return 1;
}
return 0;
}
/* Strip trailing spaces and newlines from the end of a string */
void strstrip(char *str)
{
int i;
for(i = strlen(str) - 1; i >= 0; i--)
{
if(str[i] != ' ' && str[i] != '\n' && str[i] != '\r' && str[i] != '\0')
break;
}
str[i + 1] = '\0';
}
/* Read a single tesseroid from a string */
int gets_tess(const char *str, TESSEROID *tess)
{
double w, e, s, n, top, bot, dens;
int nread, nchars;
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf%n", &w, &e, &s,
&n, &top, &bot, &dens, &nchars);
if(nread != 7 || str[nchars] != '\0')
{
/* Something wrong with the tesseroid string */
return 1;
}
if((w > e) || (s > n) || (top < bot))
{
/* Model bounds in wrong order */
return 2;
}
if((w == e) || (s == n) || (top == bot))
{
/* Tesseroid has zero volume */
return 3;
}
tess->w = w;
tess->e = e;
tess->s = s;
tess->n = n;
tess->r1 = MEAN_EARTH_RADIUS + bot;
tess->r2 = MEAN_EARTH_RADIUS + top;
tess->density = dens;
return 0;
}
/* Read tesseroids from an open file and store them in an array */
TESSEROID * read_tess_model(FILE *modelfile, int *size)
{
TESSEROID *model, *tmp;
int buffsize = 100, line, badinput = 0, error_exit = 0, gets_error;
char sbuff[10000];
/* Start with a single buffer allocation and expand later if necessary */
model = (TESSEROID *)malloc(buffsize*sizeof(TESSEROID));
if(model == NULL)
{
log_error("problem allocating initial memory to load tesseroid model.");
return NULL;
}
*size = 0;
for(line = 1; !feof(modelfile); line++)
{
if(fgets(sbuff, 10000, modelfile) == NULL)
{
if(ferror(modelfile))
{
log_error("problem encountered reading line %d.", line);
error_exit = 1;
break;
}
}
else
{
/* Check for comments and blank lines */
if(sbuff[0] == '#' || sbuff[0] == '\r' || sbuff[0] == '\n')
{
continue;
}
if(*size == buffsize)
{
buffsize += buffsize;
tmp = (TESSEROID *)realloc(model, buffsize*sizeof(TESSEROID));
if(tmp == NULL)
{
/* Need to free because realloc leaves unchanged in case of
error */
free(model);
log_error("problem expanding memory for tesseroid model. Model is too big.");
return NULL;
}
model = tmp;
}
/* Remove any trailing spaces or newlines */
strstrip(sbuff);
gets_error = gets_tess(sbuff, &model[*size]);
if(gets_error == 1)
{
log_error("bad/invalid tesseroid at line %d.", line);
badinput = 1;
continue;
}
if(gets_error == 2)
{
log_error("invalid tesseroid dimensions at line %d. Must be w < e, s < n, top > bottom.", line);
badinput = 1;
continue;
}
if(gets_error == 3)
{
log_warning("ignoring tesseroid with zero volume at line %d. This should not impact the computations.", line);
continue;
}
(*size)++;
}
}
if(badinput || error_exit)
{
free(model);
return NULL;
}
/* Adjust the size of the model */
if(*size != 0)
{
tmp = (TESSEROID *)realloc(model, (*size)*sizeof(TESSEROID));
if(tmp == NULL)
{
/* Need to free because realloc leaves unchanged in case of
error */
free(model);
log_error("problem freeing excess memory for tesseroid model.");
return NULL;
}
model = tmp;
}
return model;
}
/* Read a single rectangular prism from a string */
int gets_prism(const char *str, PRISM *prism)
{
double x1, x2, y1, y2, z1, z2, dens;
int nread, nchars;
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf%n", &x1, &x2, &y1, &y2,
&z1, &z2, &dens, &nchars);
/* Check if there are extra characters in the line. This indicates
* that the model is wrong or was generated by tess2prism without the
* --flatten flag */
if(nread != 7 || str[nchars] != '\0')
{
return 1;
}
prism->x1 = x1;
prism->x2 = x2;
prism->y1 = y1;
prism->y2 = y2;
prism->z1 = z1;
prism->z2 = z2;
prism->density = dens;
return 0;
}
/* Read a single rectangular prism and the spherical coordinates of its top
from a string */
int gets_prism_sph(const char *str, PRISM *prism)
{
double dx, dy, dz, dens, lon, lat, r;
int nread, nchars;
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf%n",
&dx, &dy, &dz, &dens, &lon, &lat, &r, &nchars);
/* Check if there are extra characters in the line. This indicates
* that the model is wrong or was generated by tess2prism without the
* --flatten flag */
if(nread != 7 || str[nchars] != '\0')
{
return 1;
}
prism->x1 = -0.5*dx;
prism->x2 = 0.5*dx;
prism->y1 = -0.5*dy;
prism->y2 = 0.5*dy;
prism->z1 = 0.;
prism->z2 = dz;
prism->density = dens;
prism->lon = lon;
prism->lat = lat;
prism->r = r;
return 0;
}
/* Read rectangular prisms from an open file and store them in an array. */
PRISM * read_prism_model(FILE *modelfile, int pos, int *size)
{
PRISM *model, *tmp;
int buffsize = 100, line, badinput = 0, error_exit = 0;
char sbuff[10000];
/* Start with a single buffer allocation and expand later if necessary */
model = (PRISM *)malloc(buffsize*sizeof(PRISM));
if(model == NULL)
{
log_error("problem allocating initial memory to load prism model.");
return NULL;
}
*size = 0;
for(line = 1; !feof(modelfile); line++)
{
if(fgets(sbuff, 10000, modelfile) == NULL)
{
if(ferror(modelfile))
{
log_error("problem encountered reading line %d.", line);
error_exit = 1;
break;
}
}
else
{
/* Check for comments and blank lines */
if(sbuff[0] == '#' || sbuff[0] == '\r' || sbuff[0] == '\n')
{
continue;
}
if(*size == buffsize)
{
buffsize += buffsize;
tmp = (PRISM *)realloc(model, buffsize*sizeof(PRISM));
if(tmp == NULL)
{
/* Need to free because realloc leaves unchanged in case of
error */
free(model);
log_error("problem expanding memory for prism model.\nModel is too big.");
return NULL;
}
model = tmp;
}
/* Remove any trailing spaces or newlines */
strstrip(sbuff);
/* Check if r, lon, lat are expected as well */
if(pos)
{
if(gets_prism_sph(sbuff, &model[*size]))
{
log_warning(
"bad/invalid prism at line %d.",
line);
badinput = 1;
continue;
}
}
else
{
if(gets_prism(sbuff, &model[*size]))
{
log_warning("bad/invalid prism at line %d", line);
badinput = 1;
continue;
}
}
(*size)++;
}
}
if(badinput || error_exit)
{
free(model);
return NULL;
}
/* Adjust the size of the model */
if(*size != 0)
{
tmp = (PRISM *)realloc(model, (*size)*sizeof(PRISM));
if(tmp == NULL)
{
/* Need to free because realloc leaves unchanged in case of
error */
free(model);
log_error("problem freeing excess memory for prism model");
return NULL;
}
model = tmp;
}
return model;
}
/* Read the coordinates, height, thickness and densities of the layers */
int gets_layers(const char *str, double dlon, double dlat,
TESSEROID *tessbuff, int buffsize)
{
int nlayers, end, nchars, argsread;
double lon, lat, height, top, thickness, density;
argsread = sscanf(str, "%lf %lf %lf%n", &lon, &lat, &height, &nchars);
if(argsread != 3)
{
log_error("failed to read lon, lat, and height");
return -1;
}
if(str[nchars] == '\0')
{
log_error("missing thickness and density values");
return -1;
}
top = height + MEAN_EARTH_RADIUS;
end = nchars;
for(nlayers = 0; str[end] != '\0'; nlayers++)
{
if(nlayers == buffsize)
{
log_error("too many layers! Max = %d", buffsize);
return -1;
}
argsread = sscanf(str + end, "%lf %lf%n", &thickness, &density,
&nchars);
if(argsread != 2)
{
log_error("missing thickness or density value");
return -1;
}
if(thickness < 0)
{
log_error("can't have negative thickness");
return -1;
}
tessbuff[nlayers].density = density;
tessbuff[nlayers].w = lon - 0.5*dlon;
tessbuff[nlayers].e = lon + 0.5*dlon;
tessbuff[nlayers].s = lat - 0.5*dlat;
tessbuff[nlayers].n = lat + 0.5*dlat;
tessbuff[nlayers].r2 = top;
tessbuff[nlayers].r1 = top - thickness;
top -= thickness;
end += nchars;
}
return nlayers;
}