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 03236cd03926792d7ca6ed9ffb80100848304273
parent b854926a3731f2bc175b7d00b3e7fe54f22779d9
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu,  2 Mar 2017 14:50:25 +0100

Introduce anchors to hyperbols' image focal point.

Diffstat:
Mdoc/input | 16+++++++++++++++-
Msrc/parser/solparser.c | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/parser/solparser_shape.h | 16+++++++++++-----
Msrc/parser/test_solparser3.c | 48+++++++++++++++++++++++++++++++++++++++++++++---
Msrc/parser/test_solparser6.c | 7+++----
Msrc/parser/yaml/test_ko_0.yaml | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/solstice_args.c | 2+-
Msrc/solstice_object.c | 4++--
8 files changed, 252 insertions(+), 62 deletions(-)

diff --git a/doc/input b/doc/input @@ -130,6 +130,7 @@ # | <obj> # | <parabol> # | <parabolic-cylinder> +# | <hyperbol> # | <plane> # | <sphere> # | <stl> @@ -158,6 +159,16 @@ # focal: REAL # in ]0, INF) # clip: <polyclip-list> # +# <hyperbol> ::= # (x^2 + y^2) / a^2 - (z + z0 - g/2)^2 / b^2 + 1 = 0 +# hyperbol: # with g = img_focal + real_focal; f = real_focal / g; +# # a^2 = g^2(f - f^2); b = g(f - 1/2); z0 = |b| + g/2 +# focals: <hyperboloid_focals>- +# clip: <polyclip-list> +# +# <hyperboloid_focals> ::= +# real: REAL # in ]0, INF) +# image: REAL # in ]0, INF) +# # <plane> ::= # plane: # clip: <polyclip-list> @@ -247,7 +258,10 @@ # # <anchor-data> ::= # name: STRING -# position: <real3> +# <position-description> +# +# <position-description> ::= +# position: <real3> | hyperboloid_image_focal: <hyperboloid_focals> # # # "self" references the first level entity # <entity-identifier> ::= diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -1941,13 +1941,84 @@ error: } static res_T +parse_focals_description + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* desc, + struct hyperboloid_focals* focals) +{ + enum { REAL, IMAGE }; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(doc && desc && focals); + + if (desc->type != YAML_MAPPING_NODE) { + log_err(parser, desc, "expect a mapping of focal parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + + n = desc->data.mapping.pairs.top - desc->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, desc->data.mapping.pairs.start[i].value); + if (key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect focal parameters.\n"); + res = RES_BAD_ARG; + goto error; + } + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the focal parameter `"Name"' is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if (!strcmp((char*) key->data.scalar.value, "real")) { + SETUP_MASK(REAL, "real"); + res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &focals->real); + } + else if (!strcmp((char*) key->data.scalar.value, "image")) { + SETUP_MASK(IMAGE, "image"); + res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &focals->image); + } + 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, desc, \ + "the focal parameter `"Name"' is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(REAL, "real"); + CHECK_PARAM(IMAGE, "image"); + #undef CHECK_PARAM + +exit: + return res; +error: + goto exit; +} + +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 }; + enum { CLIP, FOCAL }; struct solparser_shape_hyperboloid* shape = NULL; size_t ishape = SIZE_MAX; intptr_t i, n; @@ -1995,13 +2066,9 @@ parse_hyperboloid 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 if (!strcmp((char*) key->data.scalar.value, "focals")) { + SETUP_MASK(FOCAL, "focals"); + res = parse_focals_description(parser, doc, val, &shape->focals); } else { log_err(parser, key, "unknown hyperbol parameter `%s'.\n", @@ -2023,8 +2090,7 @@ parse_hyperboloid goto error; \ } (void)0 CHECK_PARAM(CLIP, "clip"); - CHECK_PARAM(REAL_FOCAL, "real_focal"); - CHECK_PARAM(IMG_FOCAL, "img_focal"); + CHECK_PARAM(FOCAL, "focals"); #undef CHECK_PARAM exit : @@ -2585,8 +2651,16 @@ parse_anchor SETUP_MASK(NAME, "name"); res = parse_identifier_string(parser, val, &solanchor->name); } else if(!strcmp((char*)key->data.scalar.value, "position")) { - SETUP_MASK(POSITION, "position"); + SETUP_MASK(POSITION, "position description"); res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solanchor->position); + } + else if (!strcmp((char*) key->data.scalar.value, "hyperboloid_image_focals")) + { + struct hyperboloid_focals focals; + SETUP_MASK(POSITION, "position description"); + res = parse_focals_description(parser, doc, val, &focals); + if (res != RES_OK) goto error; + d3(solanchor->position, 0, 0, focals.image); } else { log_err(parser, key, "unknown anchor parameter `%s'.\n", key->data.scalar.value); @@ -2607,7 +2681,7 @@ parse_anchor goto error; \ } (void)0 CHECK_PARAM(NAME, "name"); - CHECK_PARAM(POSITION, "position"); + CHECK_PARAM(POSITION, "position description"); #undef CHECK_PARAM res = anchor_register_name(parser, anchor, htable, isolanchor); diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h @@ -201,8 +201,16 @@ solparser_shape_paraboloid_copy_and_release /******************************************************************************* * Hyperboloid shape ******************************************************************************/ +struct hyperboloid_focals { + double real, image; +}; + +#define HYPERBOLOID_FOCALS_NULL__ { 0, 0 } +static const struct hyperboloid_focals +HYPERBOLOID_FOCALS_NULL = HYPERBOLOID_FOCALS_NULL__; + struct solparser_shape_hyperboloid { - double real_focal, img_focal; + struct hyperboloid_focals focals; struct darray_polyclip polyclips; }; @@ -228,8 +236,7 @@ solparser_shape_hyperboloid_copy const struct solparser_shape_hyperboloid* src) { ASSERT(dst && src); - dst->real_focal = src->real_focal; - dst->img_focal = src->img_focal; + dst->focals = src->focals; return darray_polyclip_copy(&dst->polyclips, &src->polyclips); } @@ -239,8 +246,7 @@ solparser_shape_hyperboloid_copy_and_release struct solparser_shape_hyperboloid* src) { ASSERT(dst && src); - dst->real_focal = src->real_focal; - dst->img_focal = src->img_focal; + dst->focals = src->focals; return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips); } diff --git a/src/parser/test_solparser3.c b/src/parser/test_solparser3.c @@ -25,6 +25,13 @@ static const char* input[] = { "- geometry: &cylinder2\n", " - cylinder: { radius: 1, height: 10 }\n", " material: *lambertian\n", + "- geometry: &hyperbol1\n", + " - hyperbol:\n", + " focals: &hyp1_focals { real: 4, image: 1 }\n", + " clip:\n", + " - operation : AND\n", + " vertices : [[1, 2],[3, 4],[6, 7]]\n", + " material: *lambertian\n", "- sun: \n", " dni: 1\n", " spectrum: [{wavelength: 1, data: 1}]\n", @@ -37,6 +44,8 @@ static const char* input[] = { " position: [1, 2, 3]\n", " - name: anchor1\n", " position: [4, 5, 6]\n", + " - name: anchor2\n", + " hyperboloid_image_focals: *hyp1_focals\n", " children:\n", " - name: entity0a\n", " primary: 1\n", @@ -49,6 +58,9 @@ static const char* input[] = { " position: [4, 5, 6]\n", " - name: entity0b\n", " position: [7, 8, 9]\n", + " - name: entity0c\n", + " primary: 0\n", + " geometry: *hyperbol1\n", "- entity:\n", " name: entity1\n", " x_pivot:\n", @@ -60,6 +72,11 @@ static const char* input[] = { " spacing: 1\n", " ref_point: [1, 2, 3]\n", " target: { anchor: \"entity0.entity0b.anchor0\" }\n", + "- entity:\n", + " name: entity3\n", + " x_pivot:\n", + " ref_point: [4, 2, 3]\n", + " target: { anchor: \"entity0.anchor2\" }\n", NULL }; @@ -120,8 +137,8 @@ check_entity0 matte = solparser_get_material_matte(parser, mtl->data.matte); CHECK(matte->reflectivity, 0.5); - CHECK(solparser_entity_get_children_count(entity0), 2); - CHECK(solparser_entity_get_anchors_count(entity0), 2); + CHECK(solparser_entity_get_children_count(entity0), 3); + CHECK(solparser_entity_get_anchors_count(entity0), 3); anchor_id = solparser_entity_get_anchor(entity0, 0); entity0_anchor0 = solparser_get_anchor(parser, anchor_id); @@ -186,13 +203,14 @@ check_entity1 CHECK(solparser_entity_get_children_count(entity1), 0); x_pivot = solparser_get_x_pivot(parser, entity1->data.x_pivot); + NCHECK(x_pivot, NULL); CHECK(d3_eq(x_pivot->ref_point, d3(tmp, 1, 2, 3)), 1); CHECK(x_pivot->target.type, SOLPARSER_TARGET_ANCHOR); } static void check_entity2 -(struct solparser* parser, const struct solparser_entity* entity2) + (struct solparser* parser, const struct solparser_entity* entity2) { double tmp[3]; @@ -205,11 +223,32 @@ check_entity2 CHECK(solparser_entity_get_children_count(entity2), 0); zx_pivot = solparser_get_zx_pivot(parser, entity2->data.zx_pivot); + NCHECK(zx_pivot, NULL); CHECK(zx_pivot->spacing, 1); CHECK(d3_eq(zx_pivot->ref_point, d3(tmp, 1, 2, 3)), 1); CHECK(zx_pivot->target.type, SOLPARSER_TARGET_ANCHOR); } +static void +check_entity3 + (struct solparser* parser, const struct solparser_entity* entity3) +{ + double tmp[3]; + + NCHECK(parser, NULL); + NCHECK(entity3, NULL); + + CHECK(strcmp(str_cget(&entity3->name), "entity3"), 0); + CHECK(entity3->type, SOLPARSER_ENTITY_X_PIVOT); + CHECK(solparser_entity_get_anchors_count(entity3), 0); + CHECK(solparser_entity_get_children_count(entity3), 0); + + x_pivot = solparser_get_x_pivot(parser, entity3->data.x_pivot); + NCHECK(x_pivot, NULL); + CHECK(d3_eq(x_pivot->ref_point, d3(tmp, 4, 2, 3)), 1); + CHECK(x_pivot->target.type, SOLPARSER_TARGET_ANCHOR); +} + int main(int argc, char** argv) { @@ -256,6 +295,9 @@ main(int argc, char** argv) } else if(!strcmp(str_cget(&entity->name), "entity2")) { check_entity2(parser, entity); + } + else if (!strcmp(str_cget(&entity->name), "entity3")) { + check_entity3(parser, entity); } else { FATAL("Unexpected entity name.\n"); } diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c @@ -57,8 +57,7 @@ main(int argc, char** argv) 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, " focals: { real: 10, image: 2 }\n"); fprintf(stream, " clip :\n"); fprintf(stream, " - operation : AND\n"); fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n"); @@ -101,8 +100,8 @@ main(int argc, char** argv) 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); + CHECK(hyperbol->focals.real, 10); + CHECK(hyperbol->focals.image, 2); mtl2 = solparser_get_material_double_sided(parser, obj->mtl2); CHECK(mtl2->front.i, mtl2->back.i); diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml @@ -627,12 +627,17 @@ 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) +# hyperbol: # (x^2 + y^2) / a^2 - (z + z0 - 1/2)^2 / b^2 + 1 = 0 +# # with g = img_focal + real_focal; f = real_focal / g; +# # a^2 = g^2(f - f^2); b = g(f - 1/2); z0 = |b| + g/2 +# focals: <hyperboloid_focals> # clip: <polyclip-list> +# +# <hyperboloid_focals> ::= +# real: REAL # in ]0, INF) +# image: REAL # in ]0, INF) # # missing hyperbol definition - geometry: [ { hyperbol: } ] @@ -640,57 +645,66 @@ # unknown dummy parameter - geometry: [ { hyperbol: { dummy: 1 } } ] --- -# missing real_focal value -- geometry: [ { hyperbol: { real_focal: } } ] +# missing focals definition +- geometry: [ { hyperbol: { focals: } } ] +--- +# missing real value +- geometry: [ { hyperbol: { focals: { real: } } } ] --- -# missing img_focal value -- geometry: [ { hyperbol: { img_focal: } } ] +# missing image value +- geometry: [ { hyperbol: { focals: { image: } } } ] --- # missing clip value - geometry: [ { hyperbol: { clip: } } ] --- -# real_focal should be a number -- geometry: [ { hyperbol: { real_focal: "dummy" } } ] +# real should be a number +- geometry: [ { hyperbol: { focals: { real: "dummy" } } } ] --- # -1 invalid -- geometry: [ { hyperbol: { real_focal: -1 } } ] +- geometry: [ { hyperbol: { focals: { real: -1 } } } ] --- # 0 invalid -- geometry: [ { hyperbol: { real_focal: 0 } } ] +- geometry: [ { hyperbol: { focals: { real: 0 } } } ] --- -# img_focal should be a number -- geometry: [ { hyperbol: { img_focal: "dummy" } } ] +# image should be a number +- geometry: [ { hyperbol: { focals: { image: "dummy" } } } ] --- # -1 invalid -- geometry: [ { hyperbol: { img_focal: -1 } } ] +- geometry: [ { hyperbol: { focals: { image: -1 } } } ] --- # 0 invalid -- geometry: [ { hyperbol: { img_focal: 0 } } ] +- geometry: [ { hyperbol: { focals: { image: 0 } } } ] --- # missing clip parameter -- geometry: [ { hyperbol: { real_focal: 10, img_focal: 10 } } ] +- geometry: [ { hyperbol: { focals: { real: 1, image: 1 } } } ] --- -# missing real_focal parameter +# missing real parameter - geometry: - hyperbol: - img_focal: 10 + focals: { image: 1 } clip: - operation: AND vertices: [ [1, 2], [3, 4], [6, 7] ] --- -# missing img_focal parameter +# missing image parameter - geometry: - hyperbol: - real_focal: 10 + focals: { real: 10 } clip: - operation: AND vertices: [ [1, 2], [3, 4], [6, 7] ] --- -# 2x real_focal -- geometry: [ { hyperbol: { real_focal: 10, real_focal: 10 } } ] +# 2x focals +- geometry: + - hyperbol: + focals: { real: 1, image: 1 } + focals: { real: 1, image: 1 } --- -# 2x img_focal -- geometry: [ { hyperbol: { img_focal: 10, img_focal: 10 } } ] +# 2x real +- geometry: [ { hyperbol: { focals: { real: 1, real: 1 } } } ] +--- +# 2x image +- geometry: [ { hyperbol: { focals: { image: 1, image: 1 } } } ] --- # 2x clip - geometry: @@ -1146,30 +1160,71 @@ # # <anchor-data> ::= # name: STRING -# position: <real3> +# <position-description> # +# <position-description> ::= +# position: <real3> | hyperboloid_image_focals: <hyperboloid_focals> +# # missing anchors definition - entity: anchors: --- -# missing position +# missing name definition - entity: - anchors: - - name: "anchor" + anchors: [ name: ] +--- +# missing position definition +- entity: + anchors: [ position: ] +--- +# missing hyperboloid_image_focals definition +- entity: + anchors: [ { hyperboloid_image_focals: } ] +--- +# missing position-description +- entity: + anchors: [ { name: "anchor" } ] +--- +# position should have 3 values +- entity: + anchors: [ { name: "anchor", position: [ -4, 5.2 ] } ] +--- +# position should have 3 values +- entity: + anchors: [ { name: "anchor", position: [ -4, 5.2, 0, 5 ] } ] --- # missing name - entity: + anchors: [ { position: [ -4, 5.2, 0 ] } ] +--- +# 2x name +- entity: + anchors: [ { name: "anchor", name: "anchor" } ] +--- +# 2x position-description +- entity: + anchors: [ { position: [ -4, 5.2, 0 ], position: [ -4, 5.2, 0 ] } ] +--- +# 2x position-description +- entity: + anchors: + - hyperboloid_image_focals: { real: 1, image: 1 } + hyperboloid_image_focals: { real: 1, image: 1 } +--- +# 2x position-description +- entity: anchors: - - position: [ -4, 5.2, 0 ] + - hyperboloid_image_focals: { real: 1, image: 1 } + position: [ -4, 5.2, 0 ] --- # 2 anchors with same name - entity: anchors: - - name: "anchor" - position: [ -4, 5.2, 0 ] - - name: "anchor" - position: [ -4, 5.2, 0 ] + - name: "anchor" + position: [ -4, 5.2, 0 ] + - name: "anchor" + position: [ -4, 5.2, 0 ] --- # diff --git a/src/solstice_args.c b/src/solstice_args.c @@ -256,7 +256,7 @@ parse_rendering_option(const char* str, struct solstice_args* args) fprintf(stderr, "Invalid rendering option `%s'.\n", val); /* TODO remove this. The man page will be sufficient */ fprintf(stderr, -"Valid options are: fov=FOV:img=WIDTHxHEIGHT:pos=X,Y,Z:tgt=X,Y,Z:up=X,Y,Z\n"); + "Valid options are: fov=FOV:img=WIDTHxHEIGHT:pos=X,Y,Z:tgt=X,Y,Z:up=X,Y,Z\n"); res = RES_BAD_ARG; goto error; } diff --git a/src/solstice_object.c b/src/solstice_object.c @@ -447,8 +447,8 @@ create_hyperbol 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; + quadric.data.hyperbol.real_focal = hyperboloid->focals.real; + quadric.data.hyperbol.img_focal = hyperboloid->focals.image; d33_set(quadric.transform, transform); d3_set(quadric.transform + 9, transform + 9);