star-phor-input

File format for describing photoreactor configurations
git clone https://www.edstar.cnrs.fr/git/star-phor-input.git
Log | Files | Refs | README | LICENSE

commit 4d57423397b6ac7aa0a6cd184ca160d9c180ef88
parent 7d41b6c42c46e3bd1a4bd59ee66cf841501b0679
Author: Eduardo Fontana Lazzari <edufonlaz@gmail.com>
Date:   Mon, 24 Mar 2025 13:46:49 +0100

Allow unit specification for geometries in the input file

Geometries are now scaled according to the specified unit.
Added corresponding tests and documentation.

Diffstat:
Mdoc/star-phor-input.scd | 3++-
Msrc/sphin_geometry.c | 13++++++++++++-
Msrc/test_sphin_load_geometry.c | 40++++++++++++++++++++++++++++++++++++----
3 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/doc/star-phor-input.scd b/doc/star-phor-input.scd @@ -56,9 +56,10 @@ The file format describing a photoreactive system is as follows:++ [<sensor>]++ [<surface-source>]++ ++ -<geometry> ::= *geometry:* <geometry-side> <geometry-filename>++ +<geometry> ::= *geometry:* <geometry-side> <geometry-filename> [<geometry-unit>]++ <geometry-side> ::= *FRONT* | *BACK*++ <geometry-filename> ::= path % STL files only; spaces not allowed ++ +<geometry-unit> ::= *m* | *cm* | *mm* | *km* % if no unit is specified, meter is assumed++ ++ <sensor> ::= *sensor:* [<comment>]++ *response_function:* real++ diff --git a/src/sphin_geometry.c b/src/sphin_geometry.c @@ -104,10 +104,12 @@ geometry_parse char* side = NULL; char* filename = NULL; char* token_ptr = NULL; + char* unit = NULL; struct sphin_geometry* geom = NULL; struct sstl* sstl = NULL; struct sstl_desc sstl_desc; double* coords = NULL; + double scaling_factor; size_t* indices = NULL; res_T res = RES_OK; @@ -133,6 +135,15 @@ geometry_parse filename = strtok_r(NULL, " \t", &token_ptr); if (NULL == filename){ res = RES_BAD_ARG; goto error; } + /* Parse unit and evaluate scaling factor*/ + unit = strtok_r(NULL, " \t", &token_ptr); + if (NULL == unit + || 0 == strcmp(unit, "m")){scaling_factor = 1e+00;} + else if (0 == strcmp(unit, "cm")){scaling_factor = 1e-02;} + else if (0 == strcmp(unit, "mm")){scaling_factor = 1e-03;} + else if (0 == strcmp(unit, "km")){scaling_factor = 1e+03;} + else { res = RES_BAD_ARG; goto error; } + /* Create geometry */ res = geometry_create(sphin, filename, &geom); if (RES_OK != res) { goto error; } @@ -154,7 +165,7 @@ geometry_parse indices = darray_size_t_data_get(&geom->indices); FOR_EACH(i, 0, sstl_desc.vertices_count*3) { - coords[i] = (double)sstl_desc.vertices[i]; + coords[i] = (double)sstl_desc.vertices[i]*scaling_factor; } FOR_EACH(i, 0, sstl_desc.triangles_count*3) { indices[i] = (size_t)sstl_desc.indices[i]; diff --git a/src/test_sphin_load_geometry.c b/src/test_sphin_load_geometry.c @@ -25,6 +25,7 @@ #include "sphin.h" #include "test_sphin_utils.h" +#include <rsys/math.h> #include <rsys/mem_allocator.h> #include <string.h> @@ -48,8 +49,8 @@ write_stl_test_files " facet normal 0.0 0.0 -1.0\n" " outer loop\n" " vertex 0.0 0.0 0.0\n" - " vertex 1.0 0.0 0.0\n" - " vertex 0.0 1.0 0.0\n" + " vertex 1.935 0.0 0.0\n" + " vertex 0.0 0.0 3.142\n" " endloop\n" " endfacet\n" "endsolid"; @@ -168,8 +169,11 @@ test_geometry_api CHK(fp = fopen(path, "w+")); fprintf(fp, "\t\t surface : \"surface name\"\n"); fprintf(fp, "\tgeometry: FRONT test_0.stl\t\n"); - fprintf(fp, "\tgeometry: BACK test_1.stl \t\n"); + fprintf(fp, "\tgeometry: BACK test_1.stl\t\n"); fprintf(fp, "\tgeometry: BACK test_2.stl\n"); + fprintf(fp, "\tgeometry: BACK test_1.stl cm\t\n"); + fprintf(fp, "\tgeometry: BACK test_1.stl mm\t\n"); + fprintf(fp, "\tgeometry: BACK test_1.stl km\t\n"); fclose(fp); CHK(sphin_load(sphin, path, &config) == RES_OK); @@ -178,7 +182,7 @@ test_geometry_api CHK(sphin_config_get_surface(config, 0, &surface) == RES_OK); CHK(sphin_surface_get_geometry_count(NULL, &ngeometries) == RES_BAD_ARG); CHK(sphin_surface_get_geometry_count(surface, &ngeometries) == RES_OK); - CHK(ngeometries == 3); + CHK(ngeometries == 6); igeometry = 0; CHK(sphin_surface_get_geometry(surface, igeometry, &geom) == RES_OK); @@ -204,6 +208,34 @@ test_geometry_api CHK(desc.mesh.vertex_count == 8); CHK(strcmp(desc.filename, "test_2.stl") == 0); + /* Test geometry units */ + + /* In the following assertions, we use an epsilon (tolerable error) of 1e-6 + * instead of the 1e-15 used elsewhere in sphin. This is because, although + * sphin performs all computations using doubles, the third-party library + * star-stl, which is used to parse STL files, handles mesh coordinates + * using floats (even though those are exposed as doubles by sphin). + * As a result, the precision of geometrical coordinates is + * limited to approximately six digits. */ + + igeometry++; + CHK(sphin_surface_get_geometry(surface, igeometry, &geom) == RES_OK); + CHK(sphin_geometry_get_desc(geom, &desc) == RES_OK); + CHK(eq_eps(desc.mesh.coords[3], 0.01935, 1e-9)); + CHK(eq_eps(desc.mesh.coords[8], 0.03142, 1e-9)); + + igeometry++; + CHK(sphin_surface_get_geometry(surface, igeometry, &geom) == RES_OK); + CHK(sphin_geometry_get_desc(geom, &desc) == RES_OK); + CHK(eq_eps(desc.mesh.coords[3], 0.001935, 1e-8)); + CHK(eq_eps(desc.mesh.coords[8], 0.003142, 1e-8)); + + igeometry++; + CHK(sphin_surface_get_geometry(surface, igeometry, &geom) == RES_OK); + CHK(sphin_geometry_get_desc(geom, &desc) == RES_OK); + CHK(eq_eps(desc.mesh.coords[3], 1935, 1e-3)); + CHK(eq_eps(desc.mesh.coords[8], 3142, 1e-3)); + CHK(sphin_geometry_ref_get(NULL) == RES_BAD_ARG); CHK(sphin_geometry_ref_put(NULL) == RES_BAD_ARG); CHK(sphin_geometry_ref_get(geom) == RES_OK);