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 d42657c6b741ad830e634d8f752ca7c2cfff6244
parent fd3f022892f49353b2cc04755d66e5f18a8c1f38
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 26 Jan 2017 18:35:41 +0100

Two axis pivots.

Diffstat:
Mdoc/input | 10+++++++++-
Msrc/parser/solparser.c | 273+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/parser/solparser.h | 5+++++
Msrc/parser/solparser_entity.h | 4+++-
Msrc/parser/solparser_pivot.h | 44++++++++++++++++++++++++++++++++++----------
Msrc/parser/test_solparser3.c | 37++++++++++++++++++++++++++++++++++---
Msrc/parser/test_solparser5.c | 4++--
Msrc/parser/yaml/test_ko_0.yaml | 228++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/solstice_entity.c | 71++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
9 files changed, 627 insertions(+), 49 deletions(-)

diff --git a/doc/input b/doc/input @@ -113,6 +113,12 @@ # normal: <real3> # <target> # +# <pivot2> ::= +# pivot2: +# spacing: REAL # in [0, INF) +# ref_point: <real3> +# <target> +# # <target> ::= # target: # anchor: <anchor-identifier> @@ -217,7 +223,7 @@ # # <entity-data> ::= # name: STRING -# [ <geometry-data> | <pivot> ] +# [ <geometry-data> | <pivot> | <pivot2> ] # [ <anchors> ] # [ <transform> ] # [ <children> ] @@ -293,3 +299,4 @@ # <spectrum-data> ::= # wavelength: REAL # in [0, INF) # data: REAL # in [0, INF) +# +\ No newline at end of file diff --git a/src/parser/solparser.c b/src/parser/solparser.c @@ -151,6 +151,12 @@ struct target_alias { #define DARRAY_FUNCTOR_INIT solparser_pivot_init #include <rsys/dynamic_array.h> +/* Declare the array of pivot2s */ +#define DARRAY_NAME pivot2 +#define DARRAY_DATA struct solparser_pivot2 +#define DARRAY_FUNCTOR_INIT solparser_pivot2_init +#include <rsys/dynamic_array.h> + /* Declare the hash table that maps the address of a YAML node to the id of its * in memory representation. */ #define HTABLE_NAME yaml2sols @@ -201,6 +207,7 @@ struct solparser { /* Miscellaneous */ struct darray_anchor anchors; struct darray_pivot pivots; + struct darray_pivot2 pivot2s; ref_T ref; struct mem_allocator* allocator; @@ -229,6 +236,13 @@ parse_pivot struct solparser_pivot_id* out_isolpivot); static res_T +parse_pivot2 + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* pivot2, + struct solparser_pivot_id* out_isolpivot); + +static res_T parse_sun (struct solparser* parser, yaml_document_t* doc, @@ -331,10 +345,10 @@ flush_deferred_target_aliases /* Define the targeted anchor of the pivot */ pivot = darray_pivot_data_get(&parser->pivots) + tgt->pivot.i; - ASSERT(pivot->target_type == SOLPARSER_TARGET_ANCHOR); + ASSERT(pivot->target.type == SOLPARSER_TARGET_ANCHOR); ianchor = (size_t)(anchor - darray_anchor_cdata_get(&parser->anchors)); ASSERT(ianchor < darray_anchor_size_get(&parser->anchors)); - pivot->target.anchor.i = ianchor; + pivot->target.data.anchor.i = ianchor; } darray_tgtalias_clear(&parser->tgtaliases); @@ -390,6 +404,7 @@ parser_clear(struct solparser* parser) /* Miscellaneous */ darray_anchor_clear(&parser->anchors); darray_pivot_clear(&parser->pivots); + darray_pivot2_clear(&parser->pivot2s); } static void @@ -439,6 +454,7 @@ parser_release(ref_T* ref) /* Miscellaneous */ darray_anchor_release(&parser->anchors); darray_pivot_release(&parser->pivots); + darray_pivot2_release(&parser->pivot2s); MEM_RM(parser->allocator, parser); } @@ -2527,6 +2543,11 @@ parse_entity SETUP_MASK(DATA, "data"); solent.type = SOLPARSER_ENTITY_PIVOT; res = parse_pivot(parser, doc, val, &solent.data.pivot); + } + else if (!strcmp((char*) key->data.scalar.value, "pivot2")) { + SETUP_MASK(DATA, "data"); + solent.type = SOLPARSER_ENTITY_PIVOT2; + res = parse_pivot2(parser, doc, val, &solent.data.pivot2); } else if(!strcmp((char*)key->data.scalar.value, "transform")) { SETUP_MASK(TRANSFORM, "transform"); res = parse_transform @@ -2652,35 +2673,32 @@ error: } static res_T -parse_target +parse_target_ (struct solparser* parser, yaml_document_t* doc, - const yaml_node_t* target, - struct solparser_pivot* pivot) + const yaml_node_t* target_node, + struct solparser_target* target, + struct solparser_pivot_id pivot_id) { enum { POLICY }; intptr_t i, n; int mask = 0; /* Register the parsed attributes */ - struct solparser_pivot_id pivot_id; res_T res = RES_OK; - ASSERT(doc && target && pivot); + ASSERT(doc && target_node && target); - if(target->type != YAML_MAPPING_NODE) { - log_err(parser, target, "expect a target definition.\n"); + if(target_node->type != YAML_MAPPING_NODE) { + log_err(parser, target_node, "expect a target definition.\n"); res = RES_BAD_ARG; goto error; } - /* Retrieve the pivot id */ - pivot_id.i = (size_t)(pivot - darray_pivot_cdata_get(&parser->pivots)); - - n = target->data.mapping.pairs.top - target->data.mapping.pairs.start; + n = target_node->data.mapping.pairs.top - target_node->data.mapping.pairs.start; FOR_EACH(i, 0, n) { yaml_node_t* key; yaml_node_t* val; - key = yaml_document_get_node(doc, target->data.mapping.pairs.start[i].key); - val = yaml_document_get_node(doc, target->data.mapping.pairs.start[i].value); + key = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].value); if(key->type != YAML_SCALAR_NODE) { log_err(parser, key, "expect a target parameter.\n"); res = RES_BAD_ARG; @@ -2697,18 +2715,18 @@ parse_target } (void)0 if(!strcmp((char*)key->data.scalar.value, "anchor")) { SETUP_MASK(POLICY, "policy"); - pivot->target_type = SOLPARSER_TARGET_ANCHOR; - res = parse_anchor_alias(parser, val, pivot_id, &pivot->target.anchor); + target->type = SOLPARSER_TARGET_ANCHOR; + res = parse_anchor_alias(parser, val, pivot_id, &target->data.anchor); } else if(!strcmp((char*)key->data.scalar.value, "direction")) { SETUP_MASK(POLICY, "policy"); - pivot->target_type = SOLPARSER_TARGET_DIRECTION; + target->type = SOLPARSER_TARGET_DIRECTION; res = parse_real3 - (parser, doc, val, -DBL_MAX, DBL_MAX, pivot->target.direction); + (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.direction); } else if(!strcmp((char*)key->data.scalar.value, "position")) { SETUP_MASK(POLICY, "policy"); - pivot->target_type = SOLPARSER_TARGET_POSITION; + target->type = SOLPARSER_TARGET_POSITION; res = parse_real3 - (parser, doc, val, -DBL_MAX, DBL_MAX, pivot->target.position); + (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.position); } else if(!strcmp((char*)key->data.scalar.value, "sun")) { /* There is only one sun per YAML file. It is thus sufficient to define * the target_type to SOLPARSER_TARGET_SUN to indentify which data is @@ -2716,7 +2734,7 @@ parse_target * to target */ struct solparser_sun* sun; SETUP_MASK(POLICY, "policy"); - pivot->target_type = SOLPARSER_TARGET_SUN; + target->type = SOLPARSER_TARGET_SUN; res = parse_sun(parser, doc, val, &sun); } else { log_err(parser, key, "unknown target parameter `%s'.\n", @@ -2732,7 +2750,100 @@ parse_target } if(!(mask & BIT(POLICY))) { - log_err(parser, target, "the target policy is missing.\n"); + log_err(parser, target_node, "the target policy is missing.\n"); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + +static res_T +parse_target + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* target_node, + const struct solparser_pivot_id pivot_id, + struct solparser_target* target) +{ + enum { POLICY }; + intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ + res_T res = RES_OK; + ASSERT(doc && target_node && target); + + if (target_node->type != YAML_MAPPING_NODE) { + log_err(parser, target_node, "expect a target definition.\n"); + res = RES_BAD_ARG; + goto error; + } + + n = target_node->data.mapping.pairs.top - target_node->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, target_node->data.mapping.pairs.start[i].value); + if (key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect a target parameter.\n"); + res = RES_BAD_ARG; + goto error; + } + +#define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, "the target "Name" is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if (!strcmp((char*) key->data.scalar.value, "anchor")) { + SETUP_MASK(POLICY, "policy"); + target->type = SOLPARSER_TARGET_ANCHOR; + res = parse_anchor_alias(parser, val, pivot_id, &target->data.anchor); + } + else if (!strcmp((char*) key->data.scalar.value, "direction")) { + SETUP_MASK(POLICY, "policy"); + target->type = SOLPARSER_TARGET_DIRECTION; + res = parse_real3 + (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.direction); + } + else if (!strcmp((char*) key->data.scalar.value, "position")) { + SETUP_MASK(POLICY, "policy"); + target->type = SOLPARSER_TARGET_POSITION; + res = parse_real3 + (parser, doc, val, -DBL_MAX, DBL_MAX, target->data.position); + } + else if (!strcmp((char*) key->data.scalar.value, "sun")) { + /* There is only one sun per YAML file. It is thus sufficient to define + * the target_type to SOLPARSER_TARGET_SUN to indentify which data is + * targeted, i.e. it is not necessary to store the identifier of the sun + * to target */ + struct solparser_sun* sun; + SETUP_MASK(POLICY, "policy"); + target->type = SOLPARSER_TARGET_SUN; + res = parse_sun(parser, doc, val, &sun); + } + else { + log_err(parser, key, "unknown target 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 + } + + if (!(mask & BIT(POLICY))) { + log_err(parser, target_node, "the target policy is missing.\n"); res = RES_BAD_ARG; goto error; } @@ -2802,8 +2913,10 @@ parse_pivot SETUP_MASK(NORMAL, "normal"); res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solpivot->normal); } else if(!strcmp((char*)key->data.scalar.value, "target")) { + struct solparser_pivot_id pivot_id; + pivot_id.i = (size_t) (solpivot - darray_pivot_cdata_get(&parser->pivots)); SETUP_MASK(TARGET, "target"); - res = parse_target(parser, doc, val, solpivot); + res = parse_target(parser, doc, val, pivot_id, &solpivot->target); } else { log_err(parser, key, "unknown pivot parameter `%s'.\n", key->data.scalar.value); @@ -2838,6 +2951,106 @@ error: goto exit; } +static res_T +parse_pivot2 + (struct solparser* parser, + yaml_document_t* doc, + const yaml_node_t* pivot2, + struct solparser_pivot_id* out_isolpivot) +{ + enum { SPACING, REF_POINT, TARGET }; + struct solparser_pivot2* solpivot2 = NULL; + size_t isolpivot = SIZE_MAX; + int mask = 0; /* Register the parsed attributes */ + intptr_t i, n; + res_T res = RES_OK; + ASSERT(doc && pivot2 && out_isolpivot); + + if (pivot2->type != YAML_MAPPING_NODE) { + log_err(parser, pivot2, "expect a pivot2 definition.\n"); + res = RES_BAD_ARG; + goto error; + } + + /* Allocate the solstice pivot */ + isolpivot = darray_pivot2_size_get(&parser->pivot2s); + res = darray_pivot2_resize(&parser->pivot2s, isolpivot + 1); + if (res != RES_OK) { + log_err(parser, pivot2, "could not allocate the pivot2.\n"); + res = RES_BAD_ARG; + goto error; + } + solpivot2 = darray_pivot2_data_get(&parser->pivot2s) + isolpivot; + + n = pivot2->data.mapping.pairs.top - pivot2->data.mapping.pairs.start; + FOR_EACH(i, 0, n) { + yaml_node_t* key; + yaml_node_t* val; + + key = yaml_document_get_node(doc, pivot2->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, pivot2->data.mapping.pairs.start[i].value); + if (key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect pivot2 parameters.\n"); + res = RES_BAD_ARG; + goto error; + } +#define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, \ + "the pivot2 parameter `"Name"' is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if (!strcmp((char*) key->data.scalar.value, "spacing")) { + SETUP_MASK(SPACING, "spacing"); + res = parse_real(parser, val, 0, DBL_MAX, &solpivot2->spacing); + } + else if (!strcmp((char*) key->data.scalar.value, "ref_point")) { + SETUP_MASK(REF_POINT, "ref_point"); + res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solpivot2->ref_point); + } + else if (!strcmp((char*) key->data.scalar.value, "target")) { + struct solparser_pivot_id pivot_id; + pivot_id.i = (size_t) (solpivot2 - darray_pivot2_cdata_get(&parser->pivot2s)); + SETUP_MASK(TARGET, "target"); + res = parse_target(parser, doc, val, pivot_id, &solpivot2->target); + } + else { + log_err(parser, key, "unknown pivot2 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, pivot2, "the pivot2 parameter `"Name"' is missing.\n");\ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(SPACING, "spacing"); + CHECK_PARAM(REF_POINT, "ref_point"); + CHECK_PARAM(TARGET, "target"); +#undef CHECK_PARAM + + exit : + out_isolpivot->i = isolpivot; + return res; + error: + if (solpivot2) { + darray_pivot2_pop_back(&parser->pivot2s); + isolpivot = SIZE_MAX; + } + goto exit; +} + /******************************************************************************* * Sun ******************************************************************************/ @@ -3206,9 +3419,10 @@ solparser_create htable_str2sols_init(mem_allocator, &parser->str2entities); darray_entity_init(mem_allocator, &parser->entities); - /* Anchors */ + /* Anchors and pivot(2)s */ darray_anchor_init(mem_allocator, &parser->anchors); darray_pivot_init(mem_allocator, &parser->pivots); + darray_pivot2_init(mem_allocator, &parser->pivot2s); exit: *out_parser = parser; @@ -3547,6 +3761,15 @@ solparser_get_pivot return darray_pivot_cdata_get(&parser->pivots) + pivot.i; } +const struct solparser_pivot2* +solparser_get_pivot2 + (const struct solparser* parser, + const struct solparser_pivot_id pivot2) +{ + ASSERT(parser && pivot2.i < darray_pivot2_size_get(&parser->pivot2s)); + return darray_pivot2_cdata_get(&parser->pivot2s) + pivot2.i; +} + const struct solparser_shape* solparser_get_shape (const struct solparser* parser, diff --git a/src/parser/solparser.h b/src/parser/solparser.h @@ -122,6 +122,11 @@ solparser_get_pivot (const struct solparser* parser, const struct solparser_pivot_id pivot); +extern LOCAL_SYM const struct solparser_pivot2* +solparser_get_pivot2 + (const struct solparser* parser, + const struct solparser_pivot_id pivot2); + extern LOCAL_SYM const struct solparser_shape* solparser_get_shape (const struct solparser* parser, diff --git a/src/parser/solparser_entity.h b/src/parser/solparser_entity.h @@ -29,7 +29,8 @@ enum solparser_entity_type { SOLPARSER_ENTITY_EMPTY, SOLPARSER_ENTITY_GEOMETRY, - SOLPARSER_ENTITY_PIVOT + SOLPARSER_ENTITY_PIVOT, + SOLPARSER_ENTITY_PIVOT2 }; struct solparser_entity_id { size_t i; }; @@ -67,6 +68,7 @@ struct solparser_entity { union { struct solparser_geometry_id geometry; struct solparser_pivot_id pivot; + struct solparser_pivot_id pivot2; } data; /* Internal data. Should not be acceded directly. */ diff --git a/src/parser/solparser_pivot.h b/src/parser/solparser_pivot.h @@ -67,33 +67,57 @@ solparser_anchor_copy_and_release return str_copy_and_release(&dst->name, &src->name); } -struct solparser_pivot { - double point[3]; - double normal[3]; - enum solparser_target_type target_type; +struct solparser_target { + enum solparser_target_type type; union { double position[3]; /* World space position */ double direction[3]; /* World space direction */ struct solparser_anchor_id anchor; - } target; + } data; +}; + +struct solparser_pivot_id { size_t i; }; + +struct solparser_pivot { + double point[3]; + double normal[3]; + struct solparser_target target; }; #define SOLPARSER_PIVOT_NULL__ { \ {0,0,0}, {0,0,0}, SOLPARSER_TARGET_TYPES_COUNT__, {{0,0,0}} \ } -static const struct solparser_pivot SOLPARSER_PIVOT_NULL = - SOLPARSER_PIVOT_NULL__; - -struct solparser_pivot_id { size_t i; }; +static const struct solparser_pivot SOLPARSER_PIVOT_NULL = +SOLPARSER_PIVOT_NULL__; static INLINE void solparser_pivot_init - (struct mem_allocator* allocator, struct solparser_pivot* pivot) +(struct mem_allocator* allocator, struct solparser_pivot* pivot) { (void) allocator; ASSERT(pivot); *pivot = SOLPARSER_PIVOT_NULL; } +struct solparser_pivot2 { + double spacing; + double ref_point[3]; + struct solparser_target target; +}; + +#define SOLPARSER_PIVOT2_NULL__ { \ + 0, {0,0,0}, SOLPARSER_TARGET_TYPES_COUNT__, {{0,0,0}} \ +} +static const struct solparser_pivot2 SOLPARSER_PIVOT2_NULL = + SOLPARSER_PIVOT2_NULL__; + +static INLINE void +solparser_pivot2_init + (struct mem_allocator* allocator, struct solparser_pivot2* pivot2) +{ + (void) allocator; + ASSERT(pivot2); + *pivot2 = SOLPARSER_PIVOT2_NULL; +} #endif /* SOLPARSER_PIVOT_H */ diff --git a/src/parser/test_solparser3.c b/src/parser/test_solparser3.c @@ -52,6 +52,12 @@ static const char* input[] = { " point: [1, 2, 3]\n", " normal: [4, 5, 6]\n", " target: { anchor: \"entity0.entity0b.anchor0\" }\n", + "- entity:\n", + " name: entity2\n", + " pivot2:\n", + " spacing: 1\n", + " ref_point: [1, 2, 3]\n", + " target: { anchor: \"entity0.entity0b.anchor0\" }\n", NULL }; @@ -61,6 +67,7 @@ const struct solparser_anchor* entity0_entity0b_anchor0; const struct solparser_anchor* entity0_entity0b_entity0b; const struct solparser_geometry* geom; const struct solparser_pivot* pivot; +const struct solparser_pivot2* pivot2; static void check_entity0 @@ -168,7 +175,27 @@ check_entity1 pivot = solparser_get_pivot(parser, entity1->data.pivot); CHECK(d3_eq(pivot->point, d3(tmp, 1, 2, 3)), 1); CHECK(d3_eq(pivot->normal, d3(tmp, 4, 5, 6)), 1); - CHECK(pivot->target_type, SOLPARSER_TARGET_ANCHOR); + CHECK(pivot->target.type, SOLPARSER_TARGET_ANCHOR); +} + +static void +check_entity2 +(struct solparser* parser, const struct solparser_entity* entity2) +{ + double tmp[3]; + + NCHECK(parser, NULL); + NCHECK(entity2, NULL); + + CHECK(strcmp(str_cget(&entity2->name), "entity2"), 0); + CHECK(entity2->type, SOLPARSER_ENTITY_PIVOT2); + CHECK(solparser_entity_get_anchors_count(entity2), 0); + CHECK(solparser_entity_get_children_count(entity2), 0); + + pivot2 = solparser_get_pivot2(parser, entity2->data.pivot2); + CHECK(pivot2->spacing, 1); + CHECK(d3_eq(pivot2->ref_point, d3(tmp, 1, 2, 3)), 1); + CHECK(pivot2->target.type, SOLPARSER_TARGET_ANCHOR); } int @@ -211,8 +238,12 @@ main(int argc, char** argv) if(!strcmp(str_cget(&entity->name), "entity0")) { check_entity0(parser, entity); - } else if(!strcmp(str_cget(&entity->name), "entity1")) { + } + else if (!strcmp(str_cget(&entity->name), "entity1")) { check_entity1(parser, entity); + } + else if(!strcmp(str_cget(&entity->name), "entity2")) { + check_entity2(parser, entity); } else { FATAL("Unexpected entity name.\n"); } @@ -220,7 +251,7 @@ main(int argc, char** argv) solparser_entity_iterator_next(&it); } - anchor = solparser_get_anchor(parser, pivot->target.anchor); + anchor = solparser_get_anchor(parser, pivot->target.data.anchor); CHECK(anchor, entity0_entity0b_anchor0); anchor = solparser_find_anchor(parser, "entity0"); diff --git a/src/parser/test_solparser5.c b/src/parser/test_solparser5.c @@ -71,9 +71,9 @@ check_entity(struct solparser* parser, const struct solparser_entity* entity) pivot = solparser_get_pivot(parser, entity->data.pivot); CHECK(d3_eq(pivot->point, d3(tmp, 1, 2, 3)), 1); CHECK(d3_eq(pivot->normal, d3(tmp, 4, 5, 6)), 1); - CHECK(pivot->target_type, SOLPARSER_TARGET_ANCHOR); + CHECK(pivot->target.type, SOLPARSER_TARGET_ANCHOR); - anchor = solparser_get_anchor(parser, pivot->target.anchor); + anchor = solparser_get_anchor(parser, pivot->target.data.anchor); CHECK(strcmp(str_cget(&anchor->name), "anchor0"), 0); CHECK(d3_eq(anchor->position, d3(tmp, 1, 2, 3)), 1); } diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml @@ -860,6 +860,179 @@ target: { sun: *sun } --- +# <pivot2> ::= +# pivot2: +# spacing: REAL # in [0, INF) +# ref_point: <real3> +# <target> +# +# <target> ::= +# target: +# anchor: <anchor-identifier> +# | direction: <real3> +# | position: <real3> +# | <sun> +# + +# missing pivot2 definition +- entity: + pivot2: +--- +# unknown dummy parameter +- entity: + pivot2: + dummy: 1 +--- +# missing spacing definition +- entity: + pivot2: + spacing: +--- +# missing ref_point definition +- entity: + pivot2: + ref_point: +--- +# missing target definition +- entity: + pivot2: + target: +--- +# spacing should be a number +- entity: + pivot2: + spacing: "dummy" +--- +# -1 invalid +- entity: + pivot2: + spacing: -1 +--- +# spacing should be a number +- entity: + pivot2: + ref_point: "dummy" +--- +# ref_point should have 3 values +- entity: + pivot2: + ref_point: [ -4, 5.2 ] +--- +# ref_point should have 3 values +- entity: + pivot2: + ref_point: [ -4, 5.2, 0, 1 ] +--- +# target should be a <target> +- entity: + pivot2: + target: "dummy" +--- +# missing anchor definition +- entity: + pivot2: + target: + anchor: +--- +# missing direction definition +- entity: + pivot2: + target: + direction: +--- +# missing position definition +- entity: + pivot2: + target: + position: +--- +# undefined anchor +- entity: + pivot2: + target: + anchor: dummy +--- +# direction should be a number +- entity: + pivot2: + target: + direction: "dummy" +--- +# direction should have 3 values +- entity: + pivot2: + target: + direction: [ -4, 5.2 ] +--- +# direction should have 3 values +- entity: + pivot2: + target: + direction: [ -4, 5.2, 0, 1 ] +--- +# position should be a number +- entity: + pivot2: + target: + position: "dummy" +--- +# position should have 3 values +- entity: + pivot2: + target: + position: [ -4, 5.2 ] +--- +# position should have 3 values +- entity: + pivot2: + target: + position: [ -4, 5.2, 0, 1 ] +--- +# sun should be a <sun> +- entity: + pivot2: + target: { sun: "dummy" } +--- +# missing point +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + pivot2: + normal: [ -4, 5.2, 0 ] + target: { sun: *sun } +--- +# missing normal +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + pivot2: + point: [ -4, 5.2, 0 ] + target: { sun: *sun } +--- +# missing target +- entity: + pivot2: + point: [ -4, 5.2, 0 ] + normal: [ -4, 5.2, 0 ] +--- +# 2x spacing +- entity: + pivot2: + spacing: 1 + spacing: 1 +--- +# 2x ref_point +- entity: + pivot2: + ref_point: [ 0, 5.2, 0 ] + ref_point: [ 0, 5.2, 0 ] +--- +# 2x target +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + pivot2: + target: { sun: *sun } + target: { sun: *sun } +--- + # # <anchors> ::= # anchors: @@ -901,7 +1074,7 @@ # # <entity-data> ::= # name: STRING -# [ <geometry-data> | <pivot> ] +# [ <geometry-data> | <pivot> | <pivot2> ] # [ <anchors> ] # [ <transform> ] # [ <children> ] @@ -929,6 +1102,9 @@ # missing pivot value - entity: { pivot: } --- +# missing pivot2 value +- entity: { pivot2: } +--- # missing anchors value - entity: { anchors: } --- @@ -981,6 +1157,27 @@ target: { sun: *sun } geometry: [ { stl: { path: "file" } } ] --- +# cannot define both geometry and pivot2 +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + pivot2: + spacing: 1 + ref_point: [ 0, 5.2, 0 ] + target: { sun: *sun } + geometry: [ { stl: { path: "file" } } ] +--- +# cannot define both pivot and pivot2 +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- entity: + pivot: + point: [ -4, 5.2, 0 ] + normal: [ -4, 5.2, 0 ] + target: { sun: *sun } + pivot2: + spacing: 1 + ref_point: [ 0, 5.2, 0 ] + target: { sun: *sun } +--- # 2x anchors - entity: anchors: @@ -1023,7 +1220,7 @@ # # <entity-data> ::= # name: STRING -# [ <geometry-data> | <pivot> ] +# [ <geometry-data> | <pivot> | <pivot2> ] # [ <anchors> ] # [ <transform> ] # [ <children> ] @@ -1057,6 +1254,10 @@ - template: &temp { pivot: } - entity: *temp --- +# missing pivot2 value +- template: &temp { pivot2: } +- entity: *temp +--- # missing anchors value - template: &temp { anchors: } - entity: *temp @@ -1119,6 +1320,29 @@ geometry: [ { stl: { path: "file" } } ] - entity: *temp --- +# cannot define both geometry and pivot2 +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- template: &temp + pivot2: + spacing: 1 + ref_point: [ 0, 5.2, 0 ] + target: { sun: *sun } + geometry: [ { stl: { path: "file" } } ] +- entity: *temp +--- +# cannot define both pivot and pivot2 +- sun: &sun { dni: 1, spectrum: [{wavelength: 1, data: 1}] } +- template: &temp + pivot: + point: [ -4, 5.2, 0 ] + normal: [ -4, 5.2, 0 ] + target: { sun: *sun } + pivot2: + spacing: 1 + ref_point: [ 0, 5.2, 0 ] + target: { sun: *sun } +- entity: *temp +--- # 2x anchors - template: &temp anchors: diff --git a/src/solstice_entity.c b/src/solstice_entity.c @@ -112,26 +112,25 @@ create_pivot_node parser_pivot = solparser_get_pivot(solstice->parser, entity->data.pivot); - /* Setup the pivot descriptor TODO: 2-axis pivots */ anim_pivot.type = PIVOT_SINGLE_AXIS; d3_set(anim_pivot.data.pivot1.ref_normal, parser_pivot->normal); d3_set(anim_pivot.data.pivot1.ref_point, parser_pivot->point); /* Setup the tracking descriptor */ - switch (parser_pivot->target_type) { + switch (parser_pivot->target.type) { case SOLPARSER_TARGET_ANCHOR: anim_tracking.policy = TRACKING_NODE_TARGET; target = *htable_anchor_find - (&solstice->anchors, &parser_pivot->target.anchor.i); + (&solstice->anchors, &parser_pivot->target.data.anchor.i); solstice_node_target_get_tracking(target, &anim_tracking); break; case SOLPARSER_TARGET_DIRECTION: anim_tracking.policy = TRACKING_OUT_DIR; - d3_set(anim_tracking.data.out_dir.u, parser_pivot->target.direction); + d3_set(anim_tracking.data.out_dir.u, parser_pivot->target.data.direction); break; case SOLPARSER_TARGET_POSITION: anim_tracking.policy = TRACKING_POINT; - d3_set(anim_tracking.data.point.target, parser_pivot->target.position); + d3_set(anim_tracking.data.point.target, parser_pivot->target.data.position); anim_tracking.data.point.target_is_local = 0; /* TODO */ break; case SOLPARSER_TARGET_SUN: @@ -158,6 +157,65 @@ error: } static struct solstice_node* +create_pivot2_node + (struct solstice* solstice, + const struct solparser_entity* entity) +{ + struct solstice_node* node = NULL; + struct solstice_node* target = NULL; + const struct solparser_pivot2* parser_pivot2 = NULL; + struct sanim_pivot anim_pivot = SANIM_PIVOT_NULL; + struct sanim_tracking anim_tracking = SANIM_TRACKING_NULL; + res_T res = RES_OK; + ASSERT(solstice && entity); + + parser_pivot2 = solparser_get_pivot2(solstice->parser, entity->data.pivot2); + + anim_pivot.type = PIVOT_TWO_AXIS; + anim_pivot.data.pivot2.spacing = parser_pivot2->spacing; + d3_set(anim_pivot.data.pivot2.ref_point, parser_pivot2->ref_point); + + /* Setup the tracking descriptor */ + switch (parser_pivot2->target.type) { + case SOLPARSER_TARGET_ANCHOR: + anim_tracking.policy = TRACKING_NODE_TARGET; + target = *htable_anchor_find + (&solstice->anchors, &parser_pivot2->target.data.anchor.i); + solstice_node_target_get_tracking(target, &anim_tracking); + break; + case SOLPARSER_TARGET_DIRECTION: + anim_tracking.policy = TRACKING_OUT_DIR; + d3_set(anim_tracking.data.out_dir.u, parser_pivot2->target.data.direction); + break; + case SOLPARSER_TARGET_POSITION: + anim_tracking.policy = TRACKING_POINT; + d3_set(anim_tracking.data.point.target, parser_pivot2->target.data.position); + anim_tracking.data.point.target_is_local = 0; /* TODO */ + break; + case SOLPARSER_TARGET_SUN: + anim_tracking.policy = TRACKING_SUN; + break; + default: FATAL("Unreachable code.\n"); break; + } + + res = solstice_node_pivot_create + (solstice->allocator, &anim_pivot, &anim_tracking, &node); + if (res != RES_OK) goto error; + + res = darray_nodes_push_back(&solstice->pivots, &node); + if (res != RES_OK) goto error; + +exit: + return node; +error: + if (node) { + solstice_node_ref_put(node); + node = NULL; + } + goto exit; +} + +static struct solstice_node* create_node(struct solstice* solstice, const struct solparser_entity* entity) { struct solstice_node* node = NULL; @@ -180,6 +238,9 @@ create_node(struct solstice* solstice, const struct solparser_entity* entity) case SOLPARSER_ENTITY_PIVOT: node = create_pivot_node(solstice, entity); break; + case SOLPARSER_ENTITY_PIVOT2: + node = create_pivot2_node(solstice, entity); + break; default: FATAL("Unreachable code.\n"); break; } if(!node) {