commit afd1e2db180e7818548fa8413a692bd9772bfb35
parent cf5b83c4776a3160e169fe288ebb213e8f9a80e4
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Wed, 4 Nov 2015 16:40:30 +0100
Add the '-G NUM' option
Sample 'NUM' geometries, dump their data and exit. The dumped data are
written to OUTPUT (or stdout if OUTPUT is not defined) and followed the
Alias Wavefront obj file format.
Diffstat:
4 files changed, 175 insertions(+), 49 deletions(-)
diff --git a/src/schiff.c b/src/schiff.c
@@ -32,6 +32,7 @@
#include <rsys/stretchy_array.h>
+#include <star/s3d.h>
#include <star/sschiff.h>
#include <star/ssp.h>
@@ -39,57 +40,105 @@
* Helper functions
******************************************************************************/
static res_T
-run(const struct schiff_args* args)
+dump_geometries
+ (const struct schiff_args* args,
+ struct sschiff_geometry_distribution* distrib,
+ struct ssp_rng* rng,
+ FILE* stream)
{
- FILE* fp = stdout;
- struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
- struct sschiff_estimator* estimator = NULL;
- struct sschiff_estimator_state* states = NULL;
- struct sschiff_device* sschiff = NULL;
- struct ssp_rng* rng = NULL;
- size_t iwlen, nwlens;
+ struct s3d_device* s3d = NULL;
+ struct s3d_scene* scn = NULL;
+ struct s3d_shape* shape = NULL;
+ struct sschiff_material mtl_dummy;
+ unsigned i;
res_T res = RES_OK;
- ASSERT(args);
+ ASSERT(args && distrib && rng && stream);
- if(args->output_filename) {
- fp = fopen(args->output_filename, "w");
- if(!fp) {
- fprintf(stderr,
- "Couldn't open the output file `%s'.", args->output_filename);
- res = RES_IO_ERR;
- goto error;
- }
+ res = s3d_device_create(NULL, NULL, 0, &s3d);
+ if(res != RES_OK) {
+ fprintf(stderr, "Couldn't create the Star-3D device.\n");
+ goto error;
}
-
- res = ssp_rng_create(&mem_default_allocator, &ssp_rng_threefry, &rng);
+ res = s3d_scene_create(s3d, &scn);
if(res != RES_OK) {
- fprintf(stderr, "Couldn't create the Random Number Generator.\n");
+ fprintf(stderr, "Couldn't create the Star-3D scene.\n");
goto error;
}
-
- res = sschiff_device_create(NULL, NULL, 0, NULL, &sschiff);
+ res = s3d_shape_create_mesh(s3d, &shape);
if(res != RES_OK) {
- fprintf(stderr, "Couldn't create the Star Schiff device.\n");
+ fprintf(stderr, "Couldn't create the Star-3D shape.\n");
+ goto error;
+ }
+ res = s3d_scene_attach_shape(scn, shape);
+ if(res != RES_OK) {
+ fprintf(stderr, "Couldn't attach the Star-3D shape to the Star-3D scene.\n");
goto error;
}
- res = schiff_geometry_distribution_init
- (&distrib, &args->geom, args->properties);
+ FOR_EACH(i, 0, args->ngeoms_dump) {
+ unsigned ivert, nverts;
+ unsigned itri, ntris;
+ res = distrib->sample(rng, &mtl_dummy, shape, distrib->context);
+ if(res != RES_OK) {
+ fprintf(stderr, "Couldn't sample the micro organism geometry.\n");
+ goto error;
+ }
+
+ fprintf(stream, "g schiff_geometry_%u\n", i);
+
+ /* Dump vertex position */
+ fprintf(stream, "# List of vertex positions\n");
+ S3D(mesh_get_vertices_count(shape, &nverts));
+ FOR_EACH(ivert, 0, nverts) {
+ struct s3d_attrib attr;
+ S3D(mesh_get_vertex_attrib(shape, ivert, S3D_POSITION, &attr));
+ fprintf(stream, "v %f %f %f\n", SPLIT3(attr.value));
+ }
+
+ /* Dump triangle indices */
+ fprintf(stream, "# Vertex indices of the triangular faces\n");
+ S3D(mesh_get_triangles_count(shape, &ntris));
+ FOR_EACH(itri, 0, ntris) {
+ unsigned ids[3];
+ S3D(mesh_get_triangle_indices(shape, itri, ids));
+ fprintf(stream, "f %u %u %u\n", SPLIT3(ids));
+ }
+ }
+
+exit:
+ if(s3d) S3D(device_ref_put(s3d));
+ if(scn) S3D(scene_ref_put(scn));
+ if(shape) S3D(shape_ref_put(shape));
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+run_integration
+ (const struct schiff_args* args,
+ struct sschiff_geometry_distribution* distrib,
+ struct ssp_rng* rng,
+ FILE* stream)
+{
+ struct sschiff_device* sschiff = NULL;
+ struct sschiff_estimator* estimator = NULL;
+ struct sschiff_estimator_state* states = NULL;
+ size_t iwlen, nwlens;
+ res_T res = RES_OK;
+ ASSERT(args && sa_size(args->wavelengths) && rng && stream);
+
+ res = sschiff_device_create(NULL, NULL, 0, NULL, &sschiff);
if(res != RES_OK) {
- fprintf(stderr,
- "Couldn't initialise the Star Schiff geometry distribution.\n");
+ fprintf(stderr, "Couldn't create the Star Schiff device.\n");
goto error;
}
+
/* Invoke the Schiff integration */
nwlens = sa_size(args->wavelengths);
- res = sschiff_integrate(sschiff, rng, &distrib, args->wavelengths, nwlens, 1,
+ res = sschiff_integrate(sschiff, rng, distrib, args->wavelengths, nwlens, 1,
args->ngeoms, args->ndirs, &estimator);
-
- /* Release before the check of the integration error code since if an error
- * occurred the function will return without releasing the distribution. */
- schiff_geometry_distribution_release(&distrib);
-
if(res != RES_OK) {
fprintf(stderr, "Schiff integration error.\n");
goto error;
@@ -99,7 +148,7 @@ run(const struct schiff_args* args)
states = sa_add(states, nwlens);
SSCHIFF(estimator_get_states(estimator, states));
- fprintf(fp,
+ fprintf(stream,
"# Line format \"W E E' A A' S S' P P'\" with \"W\" the wavelength in meter,\n"
"# \"E\", \"A\", and \"S\" the estimation of the extinction, absorption and\n"
"# scattering cross section, respectively, and \"P\" the estimation of the\n"
@@ -110,29 +159,81 @@ run(const struct schiff_args* args)
FOR_EACH(iwlen, 0, nwlens) {
const struct sschiff_estimator_value* val;
- fprintf(fp, "%g ", states[iwlen].wavelength);
+ fprintf(stream, "%g ", states[iwlen].wavelength);
val = states[iwlen].values + SSCHIFF_EXTINCTION_CROSS_SECTION;
- fprintf(fp, "%g %g ", val->E, val->SE);
+ fprintf(stream, "%g %g ", val->E, val->SE);
val = states[iwlen].values + SSCHIFF_ABSORPTION_CROSS_SECTION;
- fprintf(fp, "%g %g ", val->E, val->SE);
+ fprintf(stream, "%g %g ", val->E, val->SE);
val = states[iwlen].values + SSCHIFF_SCATTERING_CROSS_SECTION;
- fprintf(fp, "%g %g ", val->E, val->SE);
+ fprintf(stream, "%g %g ", val->E, val->SE);
val = states[iwlen].values + SSCHIFF_AVERAGE_PROJECTED_AREA;
- fprintf(fp, "%g %g\n", val->E, val->SE);
+ fprintf(stream, "%g %g\n", val->E, val->SE);
}
exit:
- if(fp && fp != stdout) fclose(fp);
if(estimator) SSCHIFF(estimator_ref_put(estimator));
if(sschiff) SSCHIFF(device_ref_put(sschiff));
- if(rng) SSP(rng_ref_put(rng));
sa_release(states);
return res;
error:
goto exit;
}
+static res_T
+run(const struct schiff_args* args)
+{
+ FILE* fp = stdout;
+ struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION;
+ struct ssp_rng* rng = NULL;
+ res_T res = RES_OK;
+ ASSERT(args);
+
+ if(args->output_filename) {
+ fp = fopen(args->output_filename, "w");
+ if(!fp) {
+ fprintf(stderr,
+ "Couldn't open the output file `%s'.", args->output_filename);
+ res = RES_IO_ERR;
+ goto error;
+ }
+ }
+
+ res = ssp_rng_create(&mem_default_allocator, &ssp_rng_threefry, &rng);
+ if(res != RES_OK) {
+ fprintf(stderr, "Couldn't create the Random Number Generator.\n");
+ goto error;
+ }
+
+ res = schiff_geometry_distribution_init
+ (&distrib, &args->geom, args->properties);
+ if(res != RES_OK) {
+ fprintf(stderr,
+ "Couldn't initialise the Star Schiff geometry distribution.\n");
+ goto error;
+ }
+
+ if(args->ngeoms_dump) {
+ res = dump_geometries(args, &distrib, rng, fp);
+ } else {
+ res = run_integration(args, &distrib, rng, fp);
+ }
+
+ /* Release before the check of the integration error code since if an error
+ * occurred the function will return without releasing the distribution. */
+ schiff_geometry_distribution_release(&distrib);
+
+ if(res != RES_OK)
+ goto error;
+
+exit:
+ if(fp && fp != stdout) fclose(fp);
+ if(rng) SSP(rng_ref_put(rng));
+ return res;
+error:
+ goto exit;
+}
+
/*******************************************************************************
* Entry point
******************************************************************************/
@@ -145,7 +246,7 @@ main(int argc, char** argv)
res = schiff_args_init(&args, argc, argv);
if(res != RES_OK) goto error;
- if(!args.wavelengths) goto exit;
+ if(!args.ngeoms_dump && !args.wavelengths) goto exit;
res = run(&args);
if(res != RES_OK) goto error;
@@ -159,3 +260,4 @@ error:
err = 1;
goto exit;
}
+
diff --git a/src/schiff_args.c b/src/schiff_args.c
@@ -47,7 +47,7 @@ static void
print_help(const char* binary)
{
printf(
-"Usage: %s [OPTION]... [FILE]\n"
+"Usage: %s [OPTIONS] [FILE]\n"
"Estimate the radiative properties of micro organisms with an \"Approximation\n"
"Method for Short Wavelength or High Energy Scattering\" (L. Schiff, 1956).\n\n",
binary);
@@ -73,6 +73,14 @@ print_help(const char* binary)
" realisations. Default is %u.\n",
SCHIFF_ARGS_NULL.ngeoms);
printf(
+" -G NUM sampled `NUM' geometries with respect to the defined\n"
+" distribution, dump their data and exit. The data are written to\n"
+" OUTPUT or stdout whether the `-o' option is defined or not,\n"
+" respectively. The outputted data followed the Alias Wavefront\n"
+" obj file format.\n");
+ printf(
+" -h display this help and exit.\n");
+ printf(
" -o OUTPUT write results to OUTPUT. If not defined, write results to\n"
" stdout.\n");
printf(
@@ -82,8 +90,7 @@ print_help(const char* binary)
" r = 1/(ln(S)*x*sqrt(2PI)) * exp(-(ln(x)-ln(R))^2 / (2*ln(S)^2))\n",
SCHIFF_SPHERE_DEFAULT.nslices);
printf(
-" -w A[:B]... list of wavelengths (in micron) to integrate. At least one\n"
-" wavelength must be provided.\n");
+" -w A[:B]... list of wavelengths (in micron) to integrate.\n");
}
static res_T
@@ -225,12 +232,13 @@ schiff_args_init
ASSERT(argc && argv && args);
*args = SCHIFF_ARGS_NULL;
- while((opt = getopt(argc, argv, "c:d:g:ho:s:w:")) != -1) {
+ while((opt = getopt(argc, argv, "c:d:g:G:ho:s:w:")) != -1) {
res_T res = RES_OK;
switch(opt) {
case 'c': res = parse_cylinder_distribution(optarg, args); break;
case 'd': res = cstr_to_uint(optarg, &args->ndirs); break;
case 'g': res = cstr_to_uint(optarg, &args->ngeoms); break;
+ case 'G': res = cstr_to_uint(optarg, &args->ngeoms_dump); break;
case 'h':
print_help(argv[0]);
schiff_args_release(args);
@@ -249,8 +257,20 @@ schiff_args_init
}
}
+ if(args->geom.type == SCHIFF_NONE) {
+ fprintf(stderr,
+ "Missing geometry distribution.\nTry '%s -h' for more information.\n",
+ argv[0]);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(args->ngeoms_dump) goto exit;
+
if(!args->wavelengths) {
- fprintf(stderr, "Missing wavelength(s).\n");
+ fprintf(stderr,
+ "Usage: %s [OPTIONS] [FILE].\nTry '%s -h' for more information.\n",
+ argv[0], argv[0]);
res = RES_BAD_ARG;
goto error;
}
@@ -263,7 +283,9 @@ schiff_args_init
if(res != RES_OK) goto error;
if(!args->properties) {
- fprintf(stderr, "Missing optical properties.\n");
+ fprintf(stderr,
+ "Missing optical properties.\nTry '%s -h' for more information.\n",
+ argv[0]);
res = RES_BAD_ARG;
goto error;
}
diff --git a/src/schiff_args.h b/src/schiff_args.h
@@ -37,6 +37,7 @@ struct schiff_args {
struct schiff_optical_properties* properties;
double* wavelengths;
struct schiff_geometry geom;
+ unsigned ngeoms_dump;
unsigned ngeoms;
unsigned ndirs;
};
@@ -46,6 +47,7 @@ static const struct schiff_args SCHIFF_ARGS_NULL = {
NULL, /* List of optical properties */
NULL, /* List of wavelength to integrate */
SCHIFF_GEOMETRY_NULL__,
+ 0, /* # Dumped geometries */
1000, /* # Sampled geometries */
100, /* # Sampled directions per gemetry */
};
diff --git a/src/schiff_geometry.c b/src/schiff_geometry.c
@@ -204,7 +204,7 @@ schiff_geometry_distribution_init
{
struct geometry_distribution_context* ctx = NULL;
res_T res = RES_OK;
- ASSERT(distrib && geom && properties);
+ ASSERT(distrib && geom);
ctx = mem_calloc(1, sizeof(struct geometry_distribution_context));
if(!ctx) {