solstice

Compute collected power and efficiencies of a solar plant
git clone git://git.meso-star.com/solstice.git
Log | Files | Refs | README | LICENSE

commit c3753064e265d477fb9f1f223eec125a05e70b86
parent 415cd34acdeb8e57bae6321587d1a5798d5ad94f
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Mon, 27 Feb 2017 18:49:31 +0100

Add hyperboloids.

Diffstat:
Msrc/parser/solparser.c | 126+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/solparser.h | 5+++++
Msrc/parser/solparser_shape.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/parser/test_solparser6.c | 42+++++++++++++++++++++++++++++++++++++++---
Msrc/parser/yaml/test_ko_0.yaml | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/solstice_object.c | 26++++++++++++++++++++++++++
6 files changed, 321 insertions(+), 3 deletions(-)

diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -99,6 +99,16 @@ struct target_alias { solparser_shape_paraboloid_copy_and_release #include <rsys/dynamic_array.h> +/* Declare the array of hyperboloids */ +#define DARRAY_NAME hyperboloid +#define DARRAY_DATA struct solparser_shape_hyperboloid +#define DARRAY_FUNCTOR_INIT solparser_shape_hyperboloid_init +#define DARRAY_FUNCTOR_RELEASE solparser_shape_hyperboloid_release +#define DARRAY_FUNCTOR_COPY solparser_shape_hyperboloid_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE \ + solparser_shape_hyperboloid_copy_and_release +#include <rsys/dynamic_array.h> + /* Declare the array of planes */ #define DARRAY_NAME plane #define DARRAY_DATA struct solparser_shape_plane @@ -186,6 +196,7 @@ struct solparser { struct darray_impgeom objs; struct darray_paraboloid parabols; struct darray_paraboloid parabolic_cylinders; + struct darray_hyperboloid hyperbols; struct darray_plane planes; struct darray_sphere spheres; struct darray_impgeom stls; @@ -383,6 +394,7 @@ parser_clear(struct solparser* parser) darray_impgeom_clear(&parser->objs); darray_paraboloid_clear(&parser->parabols); darray_paraboloid_clear(&parser->parabolic_cylinders); + darray_hyperboloid_clear(&parser->hyperbols); darray_plane_clear(&parser->planes); darray_sphere_clear(&parser->spheres); darray_impgeom_clear(&parser->stls); @@ -434,6 +446,7 @@ parser_release(ref_T* ref) darray_impgeom_release(&parser->objs); darray_paraboloid_release(&parser->parabols); darray_paraboloid_release(&parser->parabolic_cylinders); + darray_hyperboloid_release(&parser->hyperbols); darray_plane_release(&parser->planes); darray_sphere_release(&parser->spheres); darray_impgeom_release(&parser->stls); @@ -1815,6 +1828,104 @@ error: } static res_T +parse_hyperboloid + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* hyperboloid, + struct solparser_shape_hyperboloid_id* out_ishape) +{ + enum { CLIP, REAL_FOCAL, IMG_FOCAL }; + struct solparser_shape_hyperboloid* shape = NULL; + size_t ishape = SIZE_MAX; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(doc && hyperboloid && out_ishape); + + if (hyperboloid->type != YAML_MAPPING_NODE) { + log_err(parser, hyperboloid, "expect a mapping of hyperbol parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Allocate a hyperboloid shape */ + ishape = darray_hyperboloid_size_get(&parser->hyperbols); + res = darray_hyperboloid_resize(&parser->hyperbols, ishape + 1); + if (res != RES_OK) { + log_err(parser, hyperboloid, "could not allocate the hyperbol shape.\n"); + goto error; + } + shape = darray_hyperboloid_data_get(&parser->hyperbols) + ishape; + + n = hyperboloid->data.mapping.pairs.top - hyperboloid->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, hyperboloid->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, hyperboloid->data.mapping.pairs.start[i].value); + if (key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect hyperbol parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the hyperbol parameter `"Name"' is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if (!strcmp((char*) key->data.scalar.value, "clip")) { + SETUP_MASK(CLIP, "clip"); + res = parse_clip(parser, doc, val, &shape->polyclips); + } + else if (!strcmp((char*) key->data.scalar.value, "real_focal")) { + SETUP_MASK(REAL_FOCAL, "real_focal"); + res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &shape->real_focal); + } + else if (!strcmp((char*) key->data.scalar.value, "img_focal")) { + SETUP_MASK(IMG_FOCAL, "img_focal"); + res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &shape->img_focal); + } + else { + log_err(parser, key, "unknown hyperbol parameter `%s'.\n", + key->data.scalar.value); + res = RES_BAD_ARG; + goto error; + } + if (res != RES_OK) { + log_node(parser, key); + goto error; + } + #undef SETUP_MASK + } + #define CHECK_PARAM(Flag, Name) \ + if(!(mask & BIT(Flag))) { \ + log_err(parser, hyperboloid, \ + "the hyperbol parameter `"Name"' is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(CLIP, "clip"); + CHECK_PARAM(REAL_FOCAL, "real_focal"); + CHECK_PARAM(IMG_FOCAL, "img_focal"); + #undef CHECK_PARAM + +exit : + out_ishape->i = ishape; + return res; +error: + if (shape) { + darray_hyperboloid_pop_back(&parser->hyperbols); + ishape = SIZE_MAX; + } + goto exit; +} + +static res_T parse_plane (struct solparser* parser, yaml_document_t* doc, @@ -2087,6 +2198,11 @@ parse_object shape->type = SOLPARSER_SHAPE_PARABOLIC_CYLINDER; res = parse_paraboloid (parser, doc, val, shape->type, &shape->data.parabolic_cylinder); + } + else if (!strcmp((char*) key->data.scalar.value, "hyperbol")) { + SETUP_MASK(SHAPE, "shape"); + shape->type = SOLPARSER_SHAPE_HYPERBOL; + res = parse_hyperboloid(parser, doc, val, &shape->data.hyperbol); } else if(!strcmp((char*)key->data.scalar.value, "plane")) { SETUP_MASK(SHAPE, "shape"); shape->type = SOLPARSER_SHAPE_PLANE; @@ -3339,6 +3455,7 @@ solparser_create darray_impgeom_init(mem_allocator, &parser->objs); darray_paraboloid_init(mem_allocator, &parser->parabols); darray_paraboloid_init(mem_allocator, &parser->parabolic_cylinders); + darray_hyperboloid_init(mem_allocator, &parser->hyperbols); darray_plane_init(mem_allocator, &parser->planes); darray_sphere_init(mem_allocator, &parser->spheres); darray_impgeom_init(mem_allocator, &parser->stls); @@ -3762,6 +3879,15 @@ solparser_get_shape_parabolic_cylinder return darray_paraboloid_cdata_get(&parser->parabolic_cylinders)+paraboloid.i; } +const struct solparser_shape_hyperboloid* +solparser_get_shape_hyperbol + (const struct solparser* parser, + const struct solparser_shape_hyperboloid_id hyperboloid) +{ + ASSERT(parser && hyperboloid.i < darray_hyperboloid_size_get(&parser->hyperbols)); + return darray_hyperboloid_cdata_get(&parser->hyperbols) + hyperboloid.i; +} + const struct solparser_shape_plane* solparser_get_shape_plane (const struct solparser* parser, diff --git a/src/parser/solparser.h b/src/parser/solparser.h @@ -157,6 +157,11 @@ solparser_get_shape_parabolic_cylinder (const struct solparser* parser, const struct solparser_shape_paraboloid_id paraboloid); +extern LOCAL_SYM const struct solparser_shape_hyperboloid* +solparser_get_shape_hyperbol + (const struct solparser* parser, + const struct solparser_shape_hyperboloid_id hyperboloid); + extern LOCAL_SYM const struct solparser_shape_plane* solparser_get_shape_plane (const struct solparser* parser, diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h @@ -32,6 +32,7 @@ enum solparser_shape_type { SOLPARSER_SHAPE_OBJ, /* Imported Alias Wavefront obj */ SOLPARSER_SHAPE_PARABOL, SOLPARSER_SHAPE_PARABOLIC_CYLINDER, + SOLPARSER_SHAPE_HYPERBOL, SOLPARSER_SHAPE_PLANE, SOLPARSER_SHAPE_SPHERE, SOLPARSER_SHAPE_STL /* Imported STereo Lithography */ @@ -198,6 +199,52 @@ solparser_shape_paraboloid_copy_and_release } /******************************************************************************* +* Hyperboloid shape +******************************************************************************/ +struct solparser_shape_hyperboloid { + double real_focal, img_focal; + struct darray_polyclip polyclips; +}; + +static INLINE void +solparser_shape_hyperboloid_init + (struct mem_allocator* allocator, + struct solparser_shape_hyperboloid* hyperboloid) +{ + ASSERT(hyperboloid); + darray_polyclip_init(allocator, &hyperboloid->polyclips); +} + +static INLINE void +solparser_shape_hyperboloid_release(struct solparser_shape_hyperboloid* hyperboloid) +{ + ASSERT(hyperboloid); + darray_polyclip_release(&hyperboloid->polyclips); +} + +static INLINE res_T +solparser_shape_hyperboloid_copy + (struct solparser_shape_hyperboloid* dst, + const struct solparser_shape_hyperboloid* src) +{ + ASSERT(dst && src); + dst->real_focal = src->real_focal; + dst->img_focal = src->img_focal; + return darray_polyclip_copy(&dst->polyclips, &src->polyclips); +} + +static INLINE res_T +solparser_shape_hyperboloid_copy_and_release + (struct solparser_shape_hyperboloid* dst, + struct solparser_shape_hyperboloid* src) +{ + ASSERT(dst && src); + dst->real_focal = src->real_focal; + dst->img_focal = src->img_focal; + return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips); +} + +/******************************************************************************* * Plane shape ******************************************************************************/ struct solparser_shape_plane { @@ -260,6 +307,7 @@ struct solparser_shape_cuboid_id { size_t i; }; struct solparser_shape_cylinder_id { size_t i; }; struct solparser_shape_imported_geometry_id { size_t i; }; struct solparser_shape_paraboloid_id { size_t i; }; +struct solparser_shape_hyperboloid_id { size_t i; }; struct solparser_shape_plane_id { size_t i; }; struct solparser_shape_sphere_id { size_t i; }; @@ -271,6 +319,7 @@ struct solparser_shape { struct solparser_shape_imported_geometry_id obj; struct solparser_shape_paraboloid_id parabol; struct solparser_shape_paraboloid_id parabolic_cylinder; + struct solparser_shape_hyperboloid_id hyperbol; struct solparser_shape_plane_id plane; struct solparser_shape_sphere_id sphere; struct solparser_shape_imported_geometry_id stl; diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c @@ -31,6 +31,9 @@ main(int argc, char** argv) const struct solparser_material* mtl; const struct solparser_object* obj; const struct solparser_shape* shape; + const struct solparser_shape_sphere* sphere; + const struct solparser_shape_paraboloid* parabol; + const struct solparser_shape_hyperboloid* hyperbol; FILE* stream; (void)argc, (void)argv; @@ -45,8 +48,21 @@ main(int argc, char** argv) fprintf(stream, " name: test\n"); fprintf(stream, " primary: 0\n"); fprintf(stream, " geometry:\n"); - fprintf(stream, " - sphere: { radius: 1 }\n"); - fprintf(stream, " material: { ?virtual }\n"); + fprintf(stream, " - sphere: { radius: 1 }\n"); + fprintf(stream, " material: { ?virtual }\n"); + fprintf(stream, " - parabol:\n"); + fprintf(stream, " focal: 10\n"); + fprintf(stream, " clip :\n"); + fprintf(stream, " - operation : AND\n"); + fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n"); + fprintf(stream, " material: { ?virtual }\n"); + fprintf(stream, " - hyperbol:\n"); + fprintf(stream, " real_focal: 10\n"); + fprintf(stream, " img_focal: 2\n"); + fprintf(stream, " clip :\n"); + fprintf(stream, " - operation : AND\n"); + fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n"); + fprintf(stream, " material: { ?virtual }\n"); rewind(stream); CHECK(solparser_setup(parser, NULL, stream), RES_OK); @@ -63,11 +79,31 @@ main(int argc, char** argv) CHECK(solparser_entity_get_children_count(entity), 0); CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY); geom = solparser_get_geometry(parser, entity->data.geometry); - CHECK(solparser_geometry_get_objects_count(geom), 1); + CHECK(solparser_geometry_get_objects_count(geom), 3); + obj_id = solparser_geometry_get_object(geom, 0); obj = solparser_get_object(parser, obj_id); shape = solparser_get_shape(parser, obj->shape); CHECK(shape->type, SOLPARSER_SHAPE_SPHERE); + sphere = solparser_get_shape_sphere(parser, shape->data.sphere); + CHECK(sphere->radius, 1); + CHECK(sphere->nslices, 16); + + obj_id = solparser_geometry_get_object(geom, 1); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_PARABOL); + parabol = solparser_get_shape_parabol(parser, shape->data.parabol); + CHECK(parabol->focal, 10); + + obj_id = solparser_geometry_get_object(geom, 2); + obj = solparser_get_object(parser, obj_id); + shape = solparser_get_shape(parser, obj->shape); + CHECK(shape->type, SOLPARSER_SHAPE_HYPERBOL); + hyperbol = solparser_get_shape_hyperbol(parser, shape->data.hyperbol); + CHECK(hyperbol->real_focal, 10); + CHECK(hyperbol->img_focal, 2); + mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); CHECK(mtl2->front.i, mtl2->back.i); mtl = solparser_get_material(parser, mtl2->front); diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml @@ -598,6 +598,82 @@ vertices: [ [1, 2], [3, 4], [6, 7] ] --- +# <hyperbol> ::= +# hyperbol: #(x^2 + y^2) / a^2 - (z - 1/2)^2 / b^2 + 1 = 0 +# with a^2 = f - f^2; b = f -1/2; f = real_focal / (img_focal + real_focal) +# real_focal: REAL # in ]0, INF) +# img_focal: REAL # in ]0, INF) +# clip: <polyclip-list> +# +# missing hyperbol definition +- geometry: [ { hyperbol: } ] +--- +# unknown dummy parameter +- geometry: [ { hyperbol: { dummy: 1 } } ] +--- +# missing real_focal value +- geometry: [ { hyperbol: { real_focal: } } ] +--- +# missing img_focal value +- geometry: [ { hyperbol: { img_focal: } } ] +--- +# missing clip value +- geometry: [ { hyperbol: { clip: } } ] +--- +# real_focal should be a number +- geometry: [ { hyperbol: { real_focal: "dummy" } } ] +--- +# -1 invalid +- geometry: [ { hyperbol: { real_focal: -1 } } ] +--- +# 0 invalid +- geometry: [ { hyperbol: { real_focal: 0 } } ] +--- +# img_focal should be a number +- geometry: [ { hyperbol: { img_focal: "dummy" } } ] +--- +# -1 invalid +- geometry: [ { hyperbol: { img_focal: -1 } } ] +--- +# 0 invalid +- geometry: [ { hyperbol: { img_focal: 0 } } ] +--- +# missing clip parameter +- geometry: [ { hyperbol: { real_focal: 10, img_focal: 10 } } ] +--- +# missing real_focal parameter +- geometry: + - hyperbol: + img_focal: 10 + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] +--- +# missing img_focal parameter +- geometry: + - hyperbol: + real_focal: 10 + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] +--- +# 2x real_focal +- geometry: [ { hyperbol: { real_focal: 10, real_focal: 10 } } ] +--- +# 2x img_focal +- geometry: [ { hyperbol: { img_focal: 10, img_focal: 10 } } ] +--- +# 2x clip +- geometry: + - hyperbol: + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] + clip: + - operation: AND + vertices: [ [1, 2], [3, 4], [6, 7] ] +--- + # # <plane> ::= # plane: diff --git a/src/solstice_object.c b/src/solstice_object.c @@ -434,6 +434,29 @@ create_parabolic_cylinder } static res_T +create_hyperbol + (struct solstice* solstice, + const double transform[12], + const struct solparser_shape_hyperboloid_id id, + struct ssol_shape** out_ssol_shape) +{ + const struct solparser_shape_hyperboloid* hyperboloid; + struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT; + ASSERT(solstice); + + hyperboloid = solparser_get_shape_hyperbol(solstice->parser, id); + + quadric.type = SSOL_QUADRIC_HYPERBOL; + quadric.data.hyperbol.real_focal = hyperboloid->real_focal; + quadric.data.hyperbol.img_focal = hyperboloid->img_focal; + d33_set(quadric.transform, transform); + d3_set(quadric.transform + 9, transform + 9); + + return create_ssol_shape_punched_surface + (solstice, &hyperboloid->polyclips, &quadric, out_ssol_shape); +} + +static res_T create_plane (struct solstice* solstice, const double transform[12], @@ -503,6 +526,9 @@ create_shaded_shape res = create_parabolic_cylinder (solstice, transform, shape->data.parabol, ssol_shape); break; + case SOLPARSER_SHAPE_HYPERBOL: + res = create_hyperbol(solstice, transform, shape->data.hyperbol, ssol_shape); + break; case SOLPARSER_SHAPE_PLANE: res = create_plane(solstice, transform, shape->data.plane, ssol_shape); break;