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 8b3a01bfe49ec6870a8293c174db2f699976ec4b
parent ac865761ffd7007d8ac75386dc4a3ac46d1213fc
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 22 Nov 2016 15:38:08 +0100

Parse and load the anchors of an entity

Diffstat:
Mcmake/parser/CMakeLists.txt | 1+
Msrc/parser/solstice_entity.h | 53+++++++++++++++++++++++++++++++++++++++++++----------
Msrc/parser/solstice_parser.c | 256++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/parser/solstice_parser.h | 4+++-
Asrc/parser/solstice_pivot.h | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 352 insertions(+), 46 deletions(-)

diff --git a/cmake/parser/CMakeLists.txt b/cmake/parser/CMakeLists.txt @@ -35,6 +35,7 @@ set(PARSER_FILES_INC solstice_entity.h solstice_material.h solstice_parser.h + solstice_pivot.h solstice_shape.h solstice_sun.h) diff --git a/src/parser/solstice_entity.h b/src/parser/solstice_entity.h @@ -16,8 +16,9 @@ #ifndef SOLSTICE_ENTITY_H #define SOLSTICE_ENTITY_H -#include "solstice_shape.h" #include "solstice_geometry.h" +#include "solstice_pivot.h" +#include "solstice_shape.h" #include <rsys/double3.h> #include <rsys/dynamic_array.h> @@ -27,10 +28,14 @@ struct solstice_entity_id { size_t i; }; -#define DARRAY_NAME child +#define DARRAY_NAME child_id #define DARRAY_DATA struct solstice_entity_id #include <rsys/dynamic_array.h> +#define DARRAY_NAME anchor_id +#define DARRAY_DATA struct solstice_anchor_id +#include <rsys/dynamic_array.h> + /* Declare the hash table that map an entity name to the index of its in memory * solstice representation. */ #define HTABLE_NAME str2sols @@ -41,7 +46,7 @@ struct solstice_entity_id { size_t i; }; #define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release #define HTABLE_KEY_FUNCTOR_EQ str_eq #define HTABLE_KEY_FUNCTOR_HASH str_hash -#define HTABLE_DATA struct solstice_entity_id +#define HTABLE_DATA size_t #include <rsys/hash_table.h> struct solstice_entity { @@ -52,8 +57,10 @@ struct solstice_entity { struct solstice_geometry_id geometry; /* Internal data. Should not be acceded directly. */ + struct htable_str2sols str2anchors; struct htable_str2sols str2children; - struct darray_child children; /* List of children nodes */ + struct darray_anchor_id anchors; /* List of anchors */ + struct darray_child_id children; /* List of children nodes */ }; static INLINE void @@ -65,8 +72,10 @@ solstice_entity_init d3_splat(entity->translation, 0); entity->geometry.i = SIZE_MAX; str_init(allocator, &entity->name); + htable_str2sols_init(allocator, &entity->str2anchors); htable_str2sols_init(allocator, &entity->str2children); - darray_child_init(allocator, &entity->children); + darray_anchor_id_init(allocator, &entity->anchors); + darray_child_id_init(allocator, &entity->children); } static INLINE void @@ -74,8 +83,10 @@ solstice_entity_release(struct solstice_entity* entity) { ASSERT(entity); str_release(&entity->name); + htable_str2sols_release(&entity->str2anchors); htable_str2sols_release(&entity->str2children); - darray_child_release(&entity->children); + darray_anchor_id_release(&entity->anchors); + darray_child_id_release(&entity->children); } static INLINE res_T @@ -89,9 +100,13 @@ solstice_entity_copy dst->geometry = src->geometry; res = str_copy(&dst->name, &src->name); if(res != RES_OK) return res; + res = htable_str2sols_copy(&dst->str2anchors, &src->str2anchors); + if(res != RES_OK) return res; res = htable_str2sols_copy(&dst->str2children, &src->str2children); if(res != RES_OK) return res; - res = darray_child_copy(&dst->children, &src->children); + res = darray_anchor_id_copy(&dst->anchors, &src->anchors); + if(res != RES_OK) return res; + res = darray_child_id_copy(&dst->children, &src->children); if(res != RES_OK) return res; return RES_OK; } @@ -107,25 +122,43 @@ solstice_entity_copy_and_release dst->geometry = src->geometry; res = str_copy_and_release(&dst->name, &src->name); if(res != RES_OK) return res; + res = htable_str2sols_copy_and_release(&dst->str2anchors, &src->str2anchors); + if(res != RES_OK) return res; res = htable_str2sols_copy_and_release(&dst->str2children, &src->str2children); if(res != RES_OK) return res; - res = darray_child_copy_and_release(&dst->children, &src->children); + res = darray_anchor_id_copy_and_release(&dst->anchors, &src->anchors); + if(res != RES_OK) return res; + res = darray_child_id_copy_and_release(&dst->children, &src->children); if(res != RES_OK) return res; return RES_OK; } static INLINE size_t +solstice_entity_get_anchors_count(const struct solstice_entity* entity) +{ + ASSERT(entity); + return darray_anchor_id_size_get(&entity->anchors); +} + +static INLINE struct solstice_anchor_id +solstice_entity_get_anchor(const struct solstice_entity* entity, const size_t i) +{ + ASSERT(entity && i < solstice_entity_get_anchors_count(entity)); + return darray_anchor_id_cdata_get(&entity->anchors)[i]; +} + +static INLINE size_t solstice_entity_get_children_count(const struct solstice_entity* entity) { ASSERT(entity); - return darray_child_size_get(&entity->children); + return darray_child_id_size_get(&entity->children); } static INLINE struct solstice_entity_id solstice_entity_get_child(const struct solstice_entity* entity, const size_t i) { ASSERT(entity && i < solstice_entity_get_children_count(entity)); - return darray_child_cdata_get(&entity->children)[i]; + return darray_child_id_cdata_get(&entity->children)[i]; } #endif /* SOLSTICE_ENTITY_H */ diff --git a/src/parser/solstice_parser.c b/src/parser/solstice_parser.c @@ -18,6 +18,7 @@ #include "solstice_entity.h" #include "solstice_material.h" #include "solstice_parser.h" +#include "solstice_pivot.h" #include "solstice_shape.h" #include "solstice_sun.h" @@ -125,6 +126,15 @@ #define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_entity_copy_and_release #include <rsys/dynamic_array.h> +/* Declare the array of anchors */ +#define DARRAY_NAME anchor +#define DARRAY_DATA struct solstice_anchor +#define DARRAY_FUNCTOR_INIT solstice_anchor_init +#define DARRAY_FUNCTOR_RELEASE solstice_anchor_release +#define DARRAY_FUNCTOR_COPY solstice_anchor_copy +#define DARRAY_FUNCTOR_COPY_AND_RELEASE solstice_anchor_copy_and_release +#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 @@ -169,6 +179,9 @@ struct solstice_parser { struct htable_str2sols str2entities; struct darray_entity entities; + /* Anchors */ + struct darray_anchor anchors; + ref_T ref; struct mem_allocator* allocator; }; @@ -256,10 +269,13 @@ parser_clear(struct solstice_parser* parser) solstice_sun_clear(&parser->sun); parser->sun_key = 0; - /* Tree */ + /* Entitiies */ htable_yaml2sols_clear(&parser->yaml2entities); htable_str2sols_clear(&parser->str2entities); darray_entity_clear(&parser->entities); + + /* Anchors */ + darray_anchor_clear(&parser->anchors); } static void @@ -298,11 +314,14 @@ parser_release(ref_T* ref) /* Sun */ solstice_sun_release(&parser->sun); - /* Tree */ + /* Entities */ htable_yaml2sols_release(&parser->yaml2entities); htable_str2sols_release(&parser->str2entities); darray_entity_release(&parser->entities); + /* Anchors */ + darray_anchor_release(&parser->anchors); + MEM_RM(parser->allocator, parser); } @@ -1932,8 +1951,7 @@ entity_register_name const size_t isolent) { struct solstice_entity* solent; - struct solstice_entity_id* pisolent; - struct solstice_entity_id id; + size_t* pisolent; res_T res = RES_OK; ASSERT(parser && htable); ASSERT(isolent < darray_entity_size_get(&parser->entities)); @@ -1948,8 +1966,7 @@ entity_register_name return RES_BAD_ARG; } - id.i = isolent; - res = htable_str2sols_set(htable, &solent->name, &id); + res = htable_str2sols_set(htable, &solent->name, &isolent); if(res != RES_OK) { log_err(parser, entity, "could not register the entity.\n"); return res; @@ -1958,67 +1975,229 @@ entity_register_name } static res_T -parse_children +anchor_register_name + (struct solstice_parser* parser, + const yaml_node_t* anchor, + struct htable_str2sols* htable, + const size_t isolanchor) +{ + struct solstice_anchor* solanchor; + size_t* pisolanchor; + res_T res = RES_OK; + ASSERT(parser && htable); + ASSERT(isolanchor < darray_anchor_size_get(&parser->anchors)); + + solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor; + + pisolanchor = htable_str2sols_find(htable, &solanchor->name); + if(pisolanchor) { + log_err(parser, anchor, + "an anchor with the name `%s' is already defined in the cunrrent context.\n", + str_cget(&solanchor->name)); + return RES_BAD_ARG; + } + + res = htable_str2sols_set(htable, &solanchor->name, &isolanchor); + if(res != RES_OK) { + log_err(parser, anchor, "could not register the anchor.\n"); + return res; + } + return RES_OK; +} + +static res_T +parse_identifier_string + (struct solstice_parser* parser, + yaml_node_t* name, + struct str* str) +{ + res_T res = RES_OK; + ASSERT(parser && name && str); + + res = parse_string(parser, name, str); + if(res != RES_OK) goto error; + + if(strchr(str_cget(str), '.')) { + log_err(parser, name, "invalid character `.' in the name `%s'.\n", + str_cget(str)); + goto error; + } + +exit: + return res; +error: + goto exit; +} + +static res_T +parse_anchor (struct solstice_parser* parser, yaml_document_t* doc, - const yaml_node_t* children, + const yaml_node_t* anchor, struct htable_str2sols* htable, - struct darray_child* entities) + struct solstice_anchor_id* out_isolanchor) { + enum { NAME, POSITION }; + struct solstice_anchor* solanchor = NULL; + size_t isolanchor = SIZE_MAX; intptr_t i, n; + int mask = 0; /* Register the parsed attributes */ res_T res = RES_OK; - ASSERT(doc && children && htable && entities); + ASSERT(parser && anchor && out_isolanchor); - if(children->type != YAML_SEQUENCE_NODE) { - log_err(parser, children, "expect a list of entities.\n"); + if(anchor->type == YAML_MAPPING_NODE) { + log_err(parser, anchor, "expect an anchor definition.\n"); res = RES_BAD_ARG; goto error; } - n = children->data.sequence.items.top - children->data.sequence.items.start; - res = darray_child_resize(entities, (size_t)n); + /* Allocate the anchor */ + isolanchor = darray_anchor_size_get(&parser->anchors); + res = darray_anchor_resize(&parser->anchors, isolanchor + 1); if(res != RES_OK) { - log_err(parser, children, "could not allocate the children list.\n"); + log_err(parser, anchor, "could not allocate the anchor.\n"); goto error; } + solanchor = darray_anchor_data_get(&parser->anchors) + isolanchor; + n = anchor->data.mapping.pairs.top - anchor->data.mapping.pairs.start; FOR_EACH(i, 0, n) { - struct solstice_entity_id* entity_id = darray_child_data_get(entities) + i; - yaml_node_t* child; + yaml_node_t* key; + yaml_node_t* val; - child = yaml_document_get_node(doc, children->data.sequence.items.start[i]); - res = parse_entity(parser, doc, child, htable, entity_id); + key = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].key); + val = yaml_document_get_node(doc, anchor->data.mapping.pairs.start[i].value); + if(key->type != YAML_SCALAR_NODE) { + log_err(parser, key, "expect an anchor attribute.\n"); + res = RES_BAD_ARG; + goto error; + } + + #define SETUP_MASK(Flag, Name) { \ + if(mask & BIT(Flag)) { \ + log_err(parser, key, "the anchor "Name" is already defined.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } \ + mask |= BIT(Flag); \ + } (void)0 + if(!strcmp((char*)key->data.scalar.value, "name")) { + 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"); + res = parse_real3(parser, doc, val, -DBL_MAX, DBL_MAX, solanchor->position); + } else { + log_err(parser, key, "unknown anchor parameter `%s'.\n", + key->data.scalar.value); + res = RES_BAD_ARG; + } if(res != RES_OK) goto error; + #undef SETUP_MASK } + #define CHECK_PARAM(Flag, Name) \ + if(!(mask & BIT(Flag))) { \ + log_err(parser, anchor, "the anchor "Name" is missing.\n"); \ + res = RES_BAD_ARG; \ + goto error; \ + } (void)0 + CHECK_PARAM(NAME, "name"); + CHECK_PARAM(POSITION, "position"); + #undef CHECK_PARAM + + res = anchor_register_name(parser, anchor, htable, isolanchor); + if(res != RES_OK) goto error; + exit: + out_isolanchor->i = isolanchor; return res; error: - darray_child_clear(entities); + if(solanchor) { + darray_anchor_pop_back(&parser->anchors); + isolanchor = SIZE_MAX; + } goto exit; } static res_T -parse_entity_name +parse_anchors (struct solstice_parser* parser, - yaml_node_t* name, - struct str* str) + yaml_document_t* doc, + const yaml_node_t* anchors, + struct htable_str2sols* htable, + struct darray_anchor_id* solanchors) { + intptr_t i, n; res_T res = RES_OK; - ASSERT(parser && name && str); + ASSERT(parser && anchors); - res = parse_string(parser, name, str); - if(res != RES_OK) goto error; + if(anchors->type != YAML_SEQUENCE_NODE) { + log_err(parser, anchors, "expect a list of anchors.\n"); + res = RES_BAD_ARG; + goto error; + } - if(strchr(str_cget(str), '.')) { - log_err(parser, name, "invalid character `.' in the entity name `%s'.\n", - str_cget(str)); + n = anchors->data.sequence.items.top - anchors->data.sequence.items.start; + res = darray_anchor_id_resize(solanchors, (size_t)n); + if(res != RES_OK) { + log_err(parser, anchors, "could not allocate the anchors list.\n"); + goto error; + } + + FOR_EACH(i, 0, n) { + struct solstice_anchor_id* anchor_id; + yaml_node_t* anchor; + + anchor_id = darray_anchor_id_data_get(solanchors)+i; + anchor = yaml_document_get_node(doc, anchors->data.sequence.items.start[i]); + res = parse_anchor(parser, doc, anchor, htable, anchor_id); + if(res != RES_OK) goto error; + } +exit: + return res; +error: + goto exit; +} + +static res_T +parse_children + (struct solstice_parser* parser, + yaml_document_t* doc, + const yaml_node_t* children, + struct htable_str2sols* htable, + struct darray_child_id* entities) +{ + intptr_t i, n; + res_T res = RES_OK; + ASSERT(parser && children && htable && entities); + + if(children->type != YAML_SEQUENCE_NODE) { + log_err(parser, children, "expect a list of entities.\n"); + res = RES_BAD_ARG; goto error; } + n = children->data.sequence.items.top - children->data.sequence.items.start; + res = darray_child_id_resize(entities, (size_t)n); + if(res != RES_OK) { + log_err(parser, children, "could not allocate the children list.\n"); + goto error; + } + + FOR_EACH(i, 0, n) { + struct solstice_entity_id* entity_id = darray_child_id_data_get(entities) + i; + yaml_node_t* child; + + child = yaml_document_get_node(doc, children->data.sequence.items.start[i]); + res = parse_entity(parser, doc, child, htable, entity_id); + if(res != RES_OK) goto error; + } + exit: return res; error: + darray_child_id_clear(entities); goto exit; } @@ -2030,7 +2209,7 @@ parse_entity struct htable_str2sols* htable, struct solstice_entity_id* out_isolent) { - enum { CHILDREN, DATA, NAME, TRANSFORM }; + enum { ANCHORS, CHILDREN, DATA, NAME, TRANSFORM }; struct solstice_entity* solent = NULL; const size_t *pisolent; size_t isolent = SIZE_MAX; @@ -2085,7 +2264,11 @@ parse_entity } \ mask |= BIT(Flag); \ } (void)0 - if(!strcmp((char*)key->data.scalar.value, "children")) { + if(!strcmp((char*)key->data.scalar.value, "anchors")) { + SETUP_MASK(ANCHORS, "anchors"); + res = parse_anchors + (parser, doc, val, &solent->str2anchors, &solent->anchors); + } else if(!strcmp((char*)key->data.scalar.value, "children")) { SETUP_MASK(CHILDREN, "children"); res = parse_children (parser, doc, val, &solent->str2children, &solent->children); @@ -2094,7 +2277,7 @@ parse_entity res = parse_geometry(parser, doc, val, &solent->geometry); } else if(!strcmp((char*)key->data.scalar.value, "name")) { SETUP_MASK(NAME, "name"); - res = parse_entity_name(parser, val, &solent->name); + res = parse_identifier_string(parser, val, &solent->name); } else if(!strcmp((char*)key->data.scalar.value, "pivot")) { SETUP_MASK(DATA, "data"); res = parse_pivot(parser, doc, val); @@ -2650,11 +2833,14 @@ solstice_parser_create solstice_sun_init(mem_allocator, &parser->sun); - /* Tree */ + /* Entities */ htable_yaml2sols_init(mem_allocator, &parser->yaml2entities); htable_str2sols_init(mem_allocator, &parser->str2entities); darray_entity_init(mem_allocator, &parser->entities); + /* Anchors */ + darray_anchor_init(mem_allocator, &parser->anchors); + exit: *out_parser = parser; return res; @@ -2820,14 +3006,14 @@ solstice_parser_find_entity tk = strtok(cstr, "."); htable = &parser->str2entities; while(tk) { - struct solstice_entity_id* pientity; + size_t* pientity; str_set(&str_tk, tk); pientity = htable_str2sols_find(htable, &str_tk); if(!pientity) { tk = NULL; } else { tk = strtok(NULL, "."); - entity = darray_entity_data_get(&parser->entities) + pientity->i; + entity = darray_entity_data_get(&parser->entities) + *pientity; htable = &entity->str2children; } } diff --git a/src/parser/solstice_parser.h b/src/parser/solstice_parser.h @@ -187,8 +187,10 @@ solstice_entity_iterator_eq static FINLINE struct solstice_entity_id solstice_entity_iterator_get(struct solstice_entity_iterator* it) { + struct solstice_entity_id id; ASSERT(it); - return *htable_str2sols_iterator_data_get(&it->it__); + id.i = *htable_str2sols_iterator_data_get(&it->it__); + return id; } /******************************************************************************* diff --git a/src/parser/solstice_pivot.h b/src/parser/solstice_pivot.h @@ -0,0 +1,84 @@ +/* Copyright (C) CNRS 2016 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SOLSTICE_PIVOT_H +#define SOLSTICE_PIVOT_H + +#include <rsys/double3.h> + +enum solstice_target_type { + SOLSTICE_TARGET_ANCHOR, + SOLSTICE_TARGET_DIRECTION, + SOLSTICE_TARGET_POSITION, + SOLSTICE_TARGET_SUN +}; + +struct solstice_anchor_id { size_t i; }; + +struct solstice_anchor { + struct str name; + double position[3]; +}; + +static INLINE void +solstice_anchor_init + (struct mem_allocator* allocator, struct solstice_anchor* anchor) +{ + ASSERT(anchor); + str_init(allocator, &anchor->name); +} + +static INLINE void +solstice_anchor_release(struct solstice_anchor* anchor) +{ + ASSERT(anchor); + str_release(&anchor->name); +} + +static INLINE res_T +solstice_anchor_copy + (struct solstice_anchor* dst, const struct solstice_anchor* src) +{ + ASSERT(dst && src); + d3_set(dst->position, src->position); + return str_copy(&dst->name, &src->name); +} + +static INLINE res_T +solstice_anchor_copy_and_release + (struct solstice_anchor* dst, struct solstice_anchor* src) +{ + ASSERT(dst && src); + d3_set(dst->position, src->position); + return str_copy_and_release(&dst->name, &src->name); +} + +struct solstice_pivot { + double point[3]; + double normal[3]; + double position[3]; + double rotation[3]; + enum solstice_target_type target_type; + union { + double position[3]; /* World space position */ + double direction[3]; /* World space direction */ + struct solstice_anchor_id anchor; + } target; +}; + +struct solstice_pivot_id { size_t i; }; + +#endif /* SOLSTICE_PIVOT_H */ +