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:
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);