commit 0e7f4454c103ce4272a9257b2e0c02ba79ba2d30
parent f9b6f7071138180f6b1141ea53a8646e31aab709
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 21 Oct 2022 16:49:24 +0200
Parse the arguments of the htrdr-planeto command
Diffstat:
2 files changed, 296 insertions(+), 1 deletion(-)
diff --git a/src/planeto/htrdr_planeto_args.c b/src/planeto/htrdr_planeto_args.c
@@ -19,6 +19,10 @@
#include "planeto/htrdr_planeto_args.h"
+#include <rsys/cstr.h>
+#include <rsys/stretchy_array.h>
+#include <rsys/mem_allocator.h>
+
#include <getopt.h>
#include <string.h>
@@ -78,6 +82,232 @@ print_help(const char* cmd)
htrdr_fprint_license(cmd, stdout);
}
+static INLINE char*
+str_dup(const char* str)
+{
+ size_t len = 0;
+ char* dup = NULL;
+ ASSERT(str);
+ len = strlen(str) + 1/*NULL char*/;
+ dup = mem_alloc(len);
+ if(!dup) {
+ return NULL;
+ } else {
+ return memcpy(dup, str, len);
+ }
+}
+
+static res_T
+parse_aerosol_parameters(const char* str, void* ptr)
+{
+ enum { MESH, NAME, RADPROP, PHASEFN, PHASEIDS } iparam;
+ struct rnatm_aerosol_args* aerosol = NULL;
+ char buf[BUFSIZ];
+ struct htrdr_planeto_args* args = ptr;
+ char* key;
+ char* val;
+ char* tk_ctx;
+ res_T res = RES_OK;
+ ASSERT(args && str);
+
+ if(strlen(str) >= sizeof(buf) -1/*NULL char*/) {
+ fprintf(stderr, "Could not duplicate the aerosol parameter `%s'\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ key = strtok_r(buf, "=", &tk_ctx);
+ val = strtok_r(NULL, "", &tk_ctx);
+
+ if(!strcmp(key, "mesh")) iparam = MESH;
+ else if(!strcmp(key, "name")) iparam = NAME;
+ else if(!strcmp(key, "radprop")) iparam = RADPROP;
+ else if(!strcmp(key, "phasefn")) iparam = PHASEFN;
+ else if(!strcmp(key, "phaseids")) iparam = PHASEIDS;
+ else {
+ fprintf(stderr, "Invalid aerosol parameter `%s'\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!val) {
+ fprintf(stderr, "Invalid null value for aerosol parameter `%s'\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ASSERT(args->naerosols);
+ aerosol = args->aerosols + (args->naerosols - 1);
+
+ switch(iparam) {
+ case MESH:
+ aerosol->smsh_filename = str_dup(val);
+ if(!aerosol->smsh_filename) res = RES_MEM_ERR;
+ break;
+ case NAME:
+ aerosol->name = str_dup(val);
+ if(!aerosol->name) res = RES_MEM_ERR;
+ break;
+ case RADPROP:
+ aerosol->sars_filename = str_dup(val);
+ if(!aerosol->sars_filename) res = RES_MEM_ERR;
+ break;
+ case PHASEFN:
+ aerosol->phase_fn_lst_filename = str_dup(val);
+ if(!aerosol->phase_fn_lst_filename) res = RES_MEM_ERR;
+ break;
+ case PHASEIDS:
+ aerosol->phase_fn_ids_filename = str_dup(val);
+ if(!aerosol->phase_fn_ids_filename) res = RES_MEM_ERR;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ if(res != RES_OK) {
+ fprintf(stderr, "Unable to parse the aerosol parameter `%s' -- %s\n",
+ str, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_ground_parameters(const char* str, void* ptr)
+{
+ enum { BRDF, MESH, NAME, PROP } iparam;
+ char buf[BUFSIZ];
+ struct htrdr_planeto_args* args = ptr;
+ char* key;
+ char* val;
+ char* tk_ctx;
+ res_T res = RES_OK;
+ ASSERT(args && str);
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr, "Could not duplicate the ground parameter `%s'\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ key = strtok_r(buf, "=", &tk_ctx);
+ val = strtok_r(NULL, "", &tk_ctx);
+
+ if(!strcmp(key, "brdf")) iparam = BRDF;
+ else if(!strcmp(key, "mesh")) iparam = MESH;
+ else if(!strcmp(key, "name")) iparam = NAME;
+ else if(!strcmp(key, "prop")) iparam = PROP;
+ else {
+ fprintf(stderr, "Invalid ground parameter `%s'\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!val) {
+ fprintf(stderr, "Invalid null value for ground parameter `%s'\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ switch(iparam) {
+ case BRDF:
+ args->ground.mtllst_filename = str_dup(val);
+ if(!args->ground.mtllst_filename) res = RES_MEM_ERR;
+ goto error;
+ case MESH:
+ args->ground.smsh_filename = str_dup(val);
+ if(!args->ground.smsh_filename) res = RES_MEM_ERR;
+ break;
+ case NAME:
+ args->ground.name = str_dup(val);
+ if(!args->ground.name) res = RES_MEM_ERR;
+ break;
+ case PROP:
+ args->ground.props_filename = str_dup(val);
+ if(!args->ground.props_filename) res = RES_MEM_ERR;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ if(res != RES_OK) {
+ fprintf(stderr, "Unable to parse the ground parameter `%s' -- %s\n",
+ str, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_gas_parameters(const char* str, void* ptr)
+{
+ enum { MESH, CK, TEMP } iparam;
+ char buf[BUFSIZ];
+ struct htrdr_planeto_args* args = ptr;
+ char* key;
+ char* val;
+ char* tk_ctx;
+ res_T res = RES_OK;
+ ASSERT(args && str);
+
+ if(strlen(str) >= sizeof(buf) -1/*NULL char*/) {
+ fprintf(stderr, "Could not duplicate the gas parameter `%s'\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ key = strtok_r(buf, "=", &tk_ctx);
+ val = strtok_r(NULL, "", &tk_ctx);
+
+ if(!strcmp(key, "mesh")) iparam = MESH;
+ else if(!strcmp(key, "ck")) iparam = CK;
+ else if(!strcmp(key, "temp")) iparam = TEMP;
+ else {
+ fprintf(stderr, "Invalid gas parameter `%s'\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!val) {
+ fprintf(stderr, "Invalid null value for gas parameter `%s'\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ switch(iparam) {
+ case MESH:
+ args->gas.smsh_filename = str_dup(val);
+ if(!args->gas.smsh_filename) res = RES_MEM_ERR;
+ break;
+ case CK:
+ args->gas.sck_filename = str_dup(val);
+ if(!args->gas.sck_filename) res = RES_MEM_ERR;
+ break;
+ case TEMP:
+ args->gas.temperatures_filename = str_dup(val);
+ if(!args->gas.temperatures_filename) res = RES_MEM_ERR;
+ break;
+ default: FATAL("Unreachable code\n"); break;
+ }
+ if(res != RES_OK) {
+ fprintf(stderr, "Unable to parse the gas parameter `%s' -- %s\n",
+ str, res_to_cstr(res));
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
@@ -92,11 +322,47 @@ htrdr_planeto_args_init(struct htrdr_planeto_args* args, int argc, char** argv)
while((opt = getopt(argc, argv, "a:dfG:g:hO:o:s:T:t:V:v")) != -1) {
switch(opt) {
+ case 'a':
+ sa_add(args->aerosols, 1);
+ args->aerosols[args->naerosols] = RNATM_AEROSOL_ARGS_NULL;
+ args->naerosols += 1;
+ res = cstr_parse_list(optarg, ':', parse_aerosol_parameters, args);
+ break;
+ case 'd':
+ args->output_type = HTRDR_PLANETO_ARGS_OUTPUT_OCTREES;
+ break;
+ case 'f':
+ args->force_output_overwrite = 1;
+ break;
+ case 'G':
+ res = cstr_parse_list(optarg, ':', parse_ground_parameters, args);
+ break;
+ case 'g':
+ res = cstr_parse_list(optarg, ':', parse_gas_parameters, args);
+ break;
case 'h':
print_help(argv[0]);
htrdr_planeto_args_release(args);
args->quit = 1;
goto exit;
+ case 'O': args->octrees_storage = optarg; break;
+ case 'o': args->output = optarg; break;
+ case 's':
+ res = htrdr_args_spectral_parse(&args->spectral_domain, optarg);
+ break;
+ case 'T':
+ res = cstr_to_double(optarg, &args->optical_thickness);
+ if(res != RES_OK && args->optical_thickness < 0) res = RES_BAD_ARG;
+ break;
+ case 't':
+ res = cstr_to_uint(optarg, &args->nthreads);
+ if(res != RES_OK && !args->nthreads) res = RES_BAD_ARG;
+ break;
+ case 'V':
+ res = cstr_to_uint(optarg, &args->octree_definition_hint);
+ if(res != RES_OK && !args->octree_definition_hint) res = RES_BAD_ARG;
+ break;
+ case 'v': args->verbose = 1; break;
default: res = RES_BAD_ARG; goto error;
}
if(res != RES_OK) {
@@ -118,6 +384,26 @@ error:
void
htrdr_planeto_args_release(struct htrdr_planeto_args* args)
{
+ size_t i;
ASSERT(args);
+
+ if(args->gas.smsh_filename) mem_rm(args->gas.smsh_filename);
+ if(args->gas.sck_filename) mem_rm(args->gas.sck_filename);
+ if(args->gas.temperatures_filename) mem_rm(args->gas.temperatures_filename);
+ if(args->ground.smsh_filename) mem_rm(args->ground.smsh_filename);
+ if(args->ground.props_filename) mem_rm(args->ground.props_filename);
+ if(args->ground.mtllst_filename) mem_rm(args->ground.mtllst_filename);
+ if(args->ground.name) mem_rm(args->ground.name);
+
+ FOR_EACH(i, 0, args->naerosols) {
+ struct rnatm_aerosol_args* aerosol = args->aerosols + i;
+ if(aerosol->name) mem_rm(aerosol->name);
+ if(aerosol->smsh_filename) mem_rm(aerosol->smsh_filename);
+ if(aerosol->sars_filename) mem_rm(aerosol->sars_filename);
+ if(aerosol->phase_fn_ids_filename) mem_rm(aerosol->phase_fn_ids_filename);
+ if(aerosol->phase_fn_lst_filename) mem_rm(aerosol->phase_fn_lst_filename);
+ }
+ sa_release(args->aerosols);
+
*args = HTRDR_PLANETO_ARGS_DEFAULT;
}
diff --git a/src/planeto/htrdr_planeto_args.h b/src/planeto/htrdr_planeto_args.h
@@ -25,12 +25,19 @@
#include <limits.h> /* UINT_MAX */
+enum htrdr_planeto_args_output_type {
+ HTRDR_PLANETO_ARGS_OUTPUT_IMAGE,
+ HTRDR_PLANETO_ARGS_OUTPUT_OCTREES,
+ HTRDR_PLANETO_ARGS_OUTPUT_TYPES_COUNT__
+};
+
struct htrdr_planeto_ground_args {
char* smsh_filename; /* The Star-Mesh geometry */
char* props_filename; /* Per triangle physical properties */
char* mtllst_filename; /* List of used materials */
+ char* name;
};
-#define HTRDR_PLANETO_GROUND_ARGS_NULL__ {NULL,NULL,NULL}
+#define HTRDR_PLANETO_GROUND_ARGS_NULL__ {NULL,NULL,NULL,NULL}
static const struct htrdr_planeto_ground_args HTRDR_PLANETO_GROUND_ARGS_NULL =
HTRDR_PLANETO_GROUND_ARGS_NULL__;
@@ -55,6 +62,7 @@ struct htrdr_planeto_args {
/* Miscellaneous arguments */
unsigned nthreads; /* Hint on the nimber of threads to use */
+ enum htrdr_planeto_args_output_type output_type;
int force_output_overwrite; /* Replace output if it exists */
int verbose; /* Verbose level */
int quit; /* Stop the command */
@@ -75,6 +83,7 @@ struct htrdr_planeto_args {
HTRDR_ARGS_SPECTRAL_DEFAULT__, /* Spectral domain */ \
\
UINT_MAX, /* Number of threads */ \
+ HTRDR_PLANETO_ARGS_OUTPUT_TYPES_COUNT__, \
0, /* Force output overwrite */ \
0, /* Verbosity level */ \
0 /* Stop the command */ \