commit 61b790042233aab17745d60e6920df097a599820
parent 620f2f62a2213e01f7c334e5ae0c1a8257c82e51
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 24 Apr 2017 14:31:08 +0200
Merge branch 'feature_contours' into develop
Diffstat:
12 files changed, 317 insertions(+), 17 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -157,6 +157,7 @@ if(NOT NO_TEST)
add_test_simulation(test05)
add_test_simulation(test06)
add_test_simulation(test07)
+ add_test_simulation(test08)
endif()
diff --git a/doc/input b/doc/input
@@ -146,7 +146,7 @@
cylinder:
height: REAL # in ]0, INF)
radius: REAL # in ]0, INF)
-[ slices: INTEGER # in [4, 4096]. Default 32 ]
+[ slices: INTEGER # in [4, 4096]. Default 16 ]
[ stacks: INTEGER # in [1, 4096]. Default 1 ]
<obj> ::=
@@ -197,12 +197,12 @@
<plane> ::=
plane:
clip: <polyclip-list>
-[ slices: INTEGER ] # in [1, 4096). Default 1
+[ slices: INTEGER # in [1, 4096). Default 1 ]
<sphere> ::=
sphere:
radius: REAL # in ]0, INF)
-[ slices: INTEGER # in [4, 4096). Default 32 ]
+[ slices: INTEGER # in [4, 4096). Default 16 ]
[ stacks: INTEGER # in [2, 4096]. Default slices/2 ]
<stl> ::=
@@ -216,8 +216,20 @@
<polyclip> ::=
operation: <AND|SUB>
+ <contour-descriptor>
+
+<contour-descriptor> ::=
+ <vertices-descriptor>
+ | <circle-descriptor>
+
+<vertices-descriptor> ::=
vertices: <vertices-list>
+<circle-descriptor> ::=
+ circle:
+ radius: REAL # in ]0, INF)
+[ segments: INTEGER # in [3, 4096). Default 64 ]
+
<vertices-list> ::=
- <real2>
- <real2>
diff --git a/src/parser/solparser_geometry.c b/src/parser/solparser_geometry.c
@@ -100,13 +100,92 @@ error:
}
static res_T
+parse_circle
+ (struct solparser* parser,
+ yaml_document_t* doc,
+ const yaml_node_t* circle,
+ struct solparser_circleclip* clip)
+{
+ enum { RADIUS, SEGMENTS };
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && circle && clip);
+
+ if(circle->type != YAML_MAPPING_NODE) {
+ log_err(parser, circle,
+ "expect a mapping of clipping circles parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ n = circle->data.mapping.pairs.top - circle->data.mapping.pairs.start;
+ clip->segments = 64; /* default value */
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, circle->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, circle->data.mapping.pairs.start[i].value);
+ if (key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect a clipping circle parameter.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the clipping circle parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if(!strcmp((char*)key->data.scalar.value, "radius")) {
+ SETUP_MASK(RADIUS, "radius");
+ res = parse_real(parser, val, nextafter(0, 1), DBL_MAX, &clip->radius);
+ }
+ else if (!strcmp((char*)key->data.scalar.value, "segments")) {
+ SETUP_MASK(SEGMENTS, "segments");
+ res = parse_integer(parser, val, 3, 4096, &clip->segments);
+ } else {
+ log_err(parser, key, "unknown clipping circle 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, circle, \
+ "the clipping circle parameter `"Name"' is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(RADIUS, "radius");
+ #undef CHECK_PARAM
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
parse_polyclip
(struct solparser* parser,
yaml_document_t* doc,
const yaml_node_t* polyclip,
struct solparser_polyclip* clip)
{
- enum { OPERATION, VERTICES };
+ enum { OPERATION, CONTOUR };
intptr_t i, n;
int mask = 0; /* Register the parsed attributes */
res_T res = RES_OK;
@@ -145,8 +224,14 @@ parse_polyclip
SETUP_MASK(OPERATION, "operation");
res = parse_clip_op(parser, val, &clip->op);
} else if(!strcmp((char*)key->data.scalar.value, "vertices")) {
- SETUP_MASK(VERTICES, "vertices");
+ SETUP_MASK(CONTOUR, "contour");
+ clip->contour_type = SOLPARSER_CLIP_CONTOUR_POLY;
res = parse_vertices(parser, doc, val, &clip->vertices);
+ }
+ else if(!strcmp((char*)key->data.scalar.value, "circle")) {
+ SETUP_MASK(CONTOUR, "contour");
+ clip->contour_type = SOLPARSER_CLIP_CONTOUR_CIRCLE;
+ res = parse_circle(parser, doc, val, &clip->circle);
} else {
log_err(parser, key, "unknown clipping polygon parameter `%s'.\n",
key->data.scalar.value);
@@ -168,7 +253,7 @@ parse_polyclip
goto error; \
} (void)0
CHECK_PARAM(OPERATION, "operation");
- CHECK_PARAM(VERTICES, "vertices");
+ CHECK_PARAM(CONTOUR, "contour");
#undef CHECK_PARAM
exit:
diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h
@@ -26,6 +26,11 @@ enum solparser_clip_op {
SOLPARSER_CLIP_OP_SUB
};
+enum solparser_clip_contour_type {
+ SOLPARSER_CLIP_CONTOUR_CIRCLE,
+ SOLPARSER_CLIP_CONTOUR_POLY
+};
+
enum solparser_shape_type {
SOLPARSER_SHAPE_CUBOID,
SOLPARSER_SHAPE_CYLINDER,
@@ -42,9 +47,16 @@ enum solparser_shape_type {
/*******************************************************************************
* Clipping polygon
******************************************************************************/
+struct solparser_circleclip {
+ double radius;
+ long segments;
+};
+
struct solparser_polyclip {
enum solparser_clip_op op;
+ enum solparser_clip_contour_type contour_type;
struct darray_double vertices;
+ struct solparser_circleclip circle;
};
static INLINE void
diff --git a/src/parser/test_solparser3.c b/src/parser/test_solparser3.c
@@ -37,7 +37,7 @@ static const char* input[] = {
" radius: 100\n",
" clip:\n",
" - operation : AND\n",
- " vertices : [[1, 2],[3, 4],[6, 7]]\n",
+ " circle: { radius: 4 }\n",
" material: *lambertian\n",
"- sun: \n",
" dni: 1\n",
diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c
@@ -71,13 +71,13 @@ main(int argc, char** argv)
fprintf(stream, " - plane:\n");
fprintf(stream, " clip :\n");
fprintf(stream, " - operation : AND\n");
- fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n");
+ fprintf(stream, " circle : { radius: 1, segments: 8 }\n");
fprintf(stream, " material: { ?virtual }\n");
fprintf(stream, " - hemisphere:\n");
fprintf(stream, " radius: 100\n");
fprintf(stream, " clip :\n");
fprintf(stream, " - operation : AND\n");
- fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n");
+ fprintf(stream, " circle : { radius: 1 }\n");
fprintf(stream, " material: { ?virtual }\n");
rewind(stream);
@@ -115,6 +115,7 @@ main(int argc, char** argv)
CHECK(darray_polyclip_size_get(¶bol->polyclips), 1);
polyclip = darray_polyclip_cdata_get(¶bol->polyclips);
CHECK(polyclip->op, SOLPARSER_CLIP_OP_AND);
+ CHECK(polyclip->contour_type, SOLPARSER_CLIP_CONTOUR_POLY);
CHECK(solparser_polyclip_get_vertices_count(polyclip), 3);
solparser_polyclip_get_vertex(polyclip, 0, pos);
CHECK(pos[0], 1);
@@ -146,6 +147,11 @@ main(int argc, char** argv)
CHECK(shape->type, SOLPARSER_SHAPE_PLANE);
plane = solparser_get_shape_plane(parser, shape->data.plane);
CHECK(plane->nslices, 1); /* Default value */
+ CHECK(darray_polyclip_size_get(&plane->polyclips), 1);
+ polyclip = darray_polyclip_cdata_get(&plane->polyclips);
+ CHECK(polyclip->contour_type, SOLPARSER_CLIP_CONTOUR_CIRCLE);
+ CHECK(polyclip->circle.radius, 1);
+ CHECK(polyclip->circle.segments, 8);
obj_id = solparser_geometry_get_object(geom, 4);
obj = solparser_get_object(parser, obj_id);
@@ -154,6 +160,11 @@ main(int argc, char** argv)
hemisphere = solparser_get_shape_hemisphere(parser, shape->data.hemisphere);;
CHECK(hemisphere->radius, 100);
CHECK(hemisphere->nslices, -1); /* Default value: auto */
+ CHECK(darray_polyclip_size_get(&hemisphere->polyclips), 1);
+ polyclip = darray_polyclip_cdata_get(&hemisphere->polyclips);
+ CHECK(polyclip->contour_type, SOLPARSER_CLIP_CONTOUR_CIRCLE);
+ CHECK(polyclip->circle.radius, 1);
+ CHECK(polyclip->circle.segments, 64); /* Default value */
solparser_entity_iterator_next(&it);
CHECK(solparser_entity_iterator_eq(&it, &end), 1);
diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml
@@ -394,7 +394,20 @@
#
# <polyclip> ::=
# operation: <AND|SUB>
-# vertices: <vertices-list>
+# <contour-descriptor>
+#
+# <contour-descriptor> ::=
+# <vertices-descriptor>
+# | <circle-descriptor>
+#
+# <vertices-descriptor> ::=
+# vertices: <vertices-list>
+#
+# <circle-descriptor> ::=
+# circle:
+# radius: REAL # in ]0, INF)
+# [ segments: INTEGER # in [3, 4096). Default 64 ]
+#
#
# <vertices-list> ::=
# - <real2>
@@ -432,7 +445,7 @@
clip:
- operation: dummy
---
-# missing vertices parameter
+# missing contour parameter
- geometry:
- plane:
clip:
@@ -471,6 +484,76 @@
- operation: AND
vertices: [ [0, 1, 2], [3, 4], [6, 7] ]
---
+# missing circle definition
+- geometry:
+ - plane:
+ clip:
+ - circle:
+---
+# missing radius value
+- geometry:
+ - plane:
+ clip:
+ - circle: { radius: }
+---
+# invalid number "dummy"
+- geometry:
+ - plane:
+ clip:
+ - operation: AND
+ circle: { radius: "dummy" }
+---
+# invalid number "dummy"
+- geometry:
+ - plane:
+ clip:
+ - operation: AND
+ circle: { segments: "dummy" }
+---
+# 0 invalid
+- geometry:
+ - plane:
+ clip:
+ - circle: { radius: 0 }
+---
+# 2 invalid
+- geometry:
+ - plane:
+ clip:
+ - circle: { segments: 2 }
+---
+# missing radius
+- geometry:
+ - plane:
+ clip:
+ - circle: { segments: 10 }
+---
+# 2x radius
+- geometry:
+ - plane:
+ clip:
+ - circle: { radius: 1, radius: 1 }
+---
+# 2x segments
+- geometry:
+ - plane:
+ clip:
+ - circle: { segments: 10, segments: 10 }
+---
+# 2x contour
+- geometry:
+ - plane:
+ clip:
+ - vertices: [ [1, 2], [3, 4], [6, 7] ]
+ circle: { radius: 1 }
+---
+# 2x operation
+- geometry:
+ - plane:
+ clip:
+ - operation: AND
+ operation: OR
+---
#
# <cuboid> ::=
diff --git a/src/parser/yaml/test_ok_6.yaml b/src/parser/yaml/test_ok_6.yaml
@@ -104,5 +104,27 @@
clip:
- operation: AND
vertices: [[-30.0, -20.0], [-30.0, 20.0], [30.0, 20.0], [30.0, -20.0]]
-
-
+---
+- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] }
+- entity:
+ name: entity
+ primary: 1
+ geometry:
+ - material: { mirror: { reflectivity: 0, roughness: 0.5 } }
+ hyperbol:
+ focals: { real: 1, image: 1 }
+ clip:
+ - operation: AND
+ circle: { radius: 1 }
+---
+- sun: { dni: 1, spectrum: [{wavelength: 1, data: 1}] }
+- entity:
+ name: entity
+ primary: 1
+ geometry:
+ - material: { mirror: { reflectivity: 0, roughness: 0.5 } }
+ hyperbol:
+ focals: { real: 1, image: 1 }
+ clip:
+ - operation: AND
+ circle: { radius: 1, segments: 32 }
diff --git a/src/solstice_object.c b/src/solstice_object.c
@@ -108,6 +108,16 @@ solparser_clip_op_to_ssol_clipping_op(const enum solparser_clip_op op)
}
}
+static void
+get_circular(const size_t ivert, double position[2], void* ctx)
+{
+ struct solparser_circleclip* data = (struct solparser_circleclip*)ctx;
+ const double a = (double)ivert * 2 * PI / (double)data->segments;
+ ASSERT(ivert < data->segments);
+ position[0] = data->radius * cos(a);
+ position[1] = data->radius * sin(a);
+}
+
static res_T
create_ssol_shape_mesh
(struct solstice* solstice,
@@ -353,10 +363,21 @@ create_ssol_shape_punched_surface
const struct solparser_polyclip* clip;
clip = darray_polyclip_cdata_get(clips) + iclip;
- carvings[iclip].get = get_carving_pos;
- carvings[iclip].nb_vertices = solparser_polyclip_get_vertices_count(clip);
- carvings[iclip].operation = solparser_clip_op_to_ssol_clipping_op(clip->op);
- carvings[iclip].context = (void*)clip;
+ switch(clip->contour_type) {
+ case SOLPARSER_CLIP_CONTOUR_POLY:
+ carvings[iclip].get = get_carving_pos;
+ carvings[iclip].nb_vertices = solparser_polyclip_get_vertices_count(clip);
+ carvings[iclip].operation = solparser_clip_op_to_ssol_clipping_op(clip->op);
+ carvings[iclip].context = (void*)clip;
+ break;
+ case SOLPARSER_CLIP_CONTOUR_CIRCLE:
+ carvings[iclip].get = get_circular;
+ carvings[iclip].nb_vertices = clip->circle.segments;
+ carvings[iclip].operation = solparser_clip_op_to_ssol_clipping_op(clip->op);
+ carvings[iclip].context = (void*)&clip->circle;
+ break;
+ default: FATAL("Unreachable code.\n");
+ }
}
punched_surf.quadric = quadric;
diff --git a/yaml/test08.ref b/yaml/test08.ref
@@ -0,0 +1,12 @@
+#--- Sun direction: 0 63 (-0.45399 -0 -0.891007)
+7 1 1 10000 0
+85.5109 0
+0 0
+0.917875 0.000431307
+0 0
+78.4137 2.52319e-08
+0 0
+0 0
+reflector.pivot.small_square 6 1 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 78.4137 2.52319e-08 0 0 0 0 0 0
+reflector.pivot.parabol 2 85.5109 10000 0 0 0 0
+6 2 FRONT: -1 -1 -1 -1 -1 -1 -1 -1 BACK: 0 0 78.4137 2.52319e-08 0 0 0 0
diff --git a/yaml/test08.yaml b/yaml/test08.yaml
@@ -0,0 +1,40 @@
+- sun: &sun { dni: 1 }
+
+- material: &lambertian
+ front:
+ matte: { reflectivity: 1 }
+ back:
+ matte: { reflectivity: 1 }
+
+- material: &specular
+ mirror: { reflectivity: 1, roughness: 0 }
+
+- template: &self_oriented_parabol
+ name: "pivot"
+ transform: { translation: [0, 0, 4], rotation: [0, 0, 90] }
+ x_pivot:
+ target: { sun: *sun }
+ children:
+ - name: "parabol"
+ primary: 1
+ geometry:
+ - material: *specular
+ parabol:
+ focal: 4
+ clip:
+ - operation: AND
+ circle: { radius: 5 }
+ - name: "small_square"
+ transform: { translation: [0, 0, 4] }
+ primary: 0
+ geometry:
+ - material: { virtual: }
+ plane:
+ clip:
+ - operation: AND
+ vertices: [ [-0.50, -0.50], [-0.50, 0.50], [0.50, 0.50], [0.50, -0.50] ]
+
+- entity:
+ name: "reflector"
+ transform: { rotation: [0, 0, 0], translation: [0, 0, 0] }
+ children: [ *self_oriented_parabol ]
diff --git a/yaml/test08_receiver.yaml b/yaml/test08_receiver.yaml
@@ -0,0 +1 @@
+- { name: "reflector.pivot.small_square", side: BACK }