commit c3753064e265d477fb9f1f223eec125a05e70b86
parent 415cd34acdeb8e57bae6321587d1a5798d5ad94f
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 27 Feb 2017 18:49:31 +0100
Add hyperboloids.
Diffstat:
6 files changed, 321 insertions(+), 3 deletions(-)
diff --git a/src/parser/solparser.c b/src/parser/solparser.c
@@ -99,6 +99,16 @@ struct target_alias {
solparser_shape_paraboloid_copy_and_release
#include <rsys/dynamic_array.h>
+/* Declare the array of hyperboloids */
+#define DARRAY_NAME hyperboloid
+#define DARRAY_DATA struct solparser_shape_hyperboloid
+#define DARRAY_FUNCTOR_INIT solparser_shape_hyperboloid_init
+#define DARRAY_FUNCTOR_RELEASE solparser_shape_hyperboloid_release
+#define DARRAY_FUNCTOR_COPY solparser_shape_hyperboloid_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE \
+ solparser_shape_hyperboloid_copy_and_release
+#include <rsys/dynamic_array.h>
+
/* Declare the array of planes */
#define DARRAY_NAME plane
#define DARRAY_DATA struct solparser_shape_plane
@@ -186,6 +196,7 @@ struct solparser {
struct darray_impgeom objs;
struct darray_paraboloid parabols;
struct darray_paraboloid parabolic_cylinders;
+ struct darray_hyperboloid hyperbols;
struct darray_plane planes;
struct darray_sphere spheres;
struct darray_impgeom stls;
@@ -383,6 +394,7 @@ parser_clear(struct solparser* parser)
darray_impgeom_clear(&parser->objs);
darray_paraboloid_clear(&parser->parabols);
darray_paraboloid_clear(&parser->parabolic_cylinders);
+ darray_hyperboloid_clear(&parser->hyperbols);
darray_plane_clear(&parser->planes);
darray_sphere_clear(&parser->spheres);
darray_impgeom_clear(&parser->stls);
@@ -434,6 +446,7 @@ parser_release(ref_T* ref)
darray_impgeom_release(&parser->objs);
darray_paraboloid_release(&parser->parabols);
darray_paraboloid_release(&parser->parabolic_cylinders);
+ darray_hyperboloid_release(&parser->hyperbols);
darray_plane_release(&parser->planes);
darray_sphere_release(&parser->spheres);
darray_impgeom_release(&parser->stls);
@@ -1815,6 +1828,104 @@ error:
}
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 };
+ struct solparser_shape_hyperboloid* shape = NULL;
+ size_t ishape = SIZE_MAX;
+ intptr_t i, n;
+ int mask = 0; /* Register the parsed attributes */
+ res_T res = RES_OK;
+ ASSERT(doc && hyperboloid && out_ishape);
+
+ if (hyperboloid->type != YAML_MAPPING_NODE) {
+ log_err(parser, hyperboloid, "expect a mapping of hyperbol parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ /* Allocate a hyperboloid shape */
+ ishape = darray_hyperboloid_size_get(&parser->hyperbols);
+ res = darray_hyperboloid_resize(&parser->hyperbols, ishape + 1);
+ if (res != RES_OK) {
+ log_err(parser, hyperboloid, "could not allocate the hyperbol shape.\n");
+ goto error;
+ }
+ shape = darray_hyperboloid_data_get(&parser->hyperbols) + ishape;
+
+ n = hyperboloid->data.mapping.pairs.top - hyperboloid->data.mapping.pairs.start;
+ FOR_EACH(i, 0, n) {
+ yaml_node_t* key;
+ yaml_node_t* val;
+
+ key = yaml_document_get_node(doc, hyperboloid->data.mapping.pairs.start[i].key);
+ val = yaml_document_get_node(doc, hyperboloid->data.mapping.pairs.start[i].value);
+ if (key->type != YAML_SCALAR_NODE) {
+ log_err(parser, key, "expect hyperbol parameters.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ #define SETUP_MASK(Flag, Name) { \
+ if(mask & BIT(Flag)) { \
+ log_err(parser, key, \
+ "the hyperbol parameter `"Name"' is already defined.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } \
+ mask |= BIT(Flag); \
+ } (void)0
+ if (!strcmp((char*) key->data.scalar.value, "clip")) {
+ 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 {
+ log_err(parser, key, "unknown hyperbol 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, hyperboloid, \
+ "the hyperbol parameter `"Name"' is missing.\n"); \
+ res = RES_BAD_ARG; \
+ goto error; \
+ } (void)0
+ CHECK_PARAM(CLIP, "clip");
+ CHECK_PARAM(REAL_FOCAL, "real_focal");
+ CHECK_PARAM(IMG_FOCAL, "img_focal");
+ #undef CHECK_PARAM
+
+exit :
+ out_ishape->i = ishape;
+ return res;
+error:
+ if (shape) {
+ darray_hyperboloid_pop_back(&parser->hyperbols);
+ ishape = SIZE_MAX;
+ }
+ goto exit;
+}
+
+static res_T
parse_plane
(struct solparser* parser,
yaml_document_t* doc,
@@ -2087,6 +2198,11 @@ parse_object
shape->type = SOLPARSER_SHAPE_PARABOLIC_CYLINDER;
res = parse_paraboloid
(parser, doc, val, shape->type, &shape->data.parabolic_cylinder);
+ }
+ else if (!strcmp((char*) key->data.scalar.value, "hyperbol")) {
+ SETUP_MASK(SHAPE, "shape");
+ shape->type = SOLPARSER_SHAPE_HYPERBOL;
+ res = parse_hyperboloid(parser, doc, val, &shape->data.hyperbol);
} else if(!strcmp((char*)key->data.scalar.value, "plane")) {
SETUP_MASK(SHAPE, "shape");
shape->type = SOLPARSER_SHAPE_PLANE;
@@ -3339,6 +3455,7 @@ solparser_create
darray_impgeom_init(mem_allocator, &parser->objs);
darray_paraboloid_init(mem_allocator, &parser->parabols);
darray_paraboloid_init(mem_allocator, &parser->parabolic_cylinders);
+ darray_hyperboloid_init(mem_allocator, &parser->hyperbols);
darray_plane_init(mem_allocator, &parser->planes);
darray_sphere_init(mem_allocator, &parser->spheres);
darray_impgeom_init(mem_allocator, &parser->stls);
@@ -3762,6 +3879,15 @@ solparser_get_shape_parabolic_cylinder
return darray_paraboloid_cdata_get(&parser->parabolic_cylinders)+paraboloid.i;
}
+const struct solparser_shape_hyperboloid*
+solparser_get_shape_hyperbol
+ (const struct solparser* parser,
+ const struct solparser_shape_hyperboloid_id hyperboloid)
+{
+ ASSERT(parser && hyperboloid.i < darray_hyperboloid_size_get(&parser->hyperbols));
+ return darray_hyperboloid_cdata_get(&parser->hyperbols) + hyperboloid.i;
+}
+
const struct solparser_shape_plane*
solparser_get_shape_plane
(const struct solparser* parser,
diff --git a/src/parser/solparser.h b/src/parser/solparser.h
@@ -157,6 +157,11 @@ solparser_get_shape_parabolic_cylinder
(const struct solparser* parser,
const struct solparser_shape_paraboloid_id paraboloid);
+extern LOCAL_SYM const struct solparser_shape_hyperboloid*
+solparser_get_shape_hyperbol
+ (const struct solparser* parser,
+ const struct solparser_shape_hyperboloid_id hyperboloid);
+
extern LOCAL_SYM const struct solparser_shape_plane*
solparser_get_shape_plane
(const struct solparser* parser,
diff --git a/src/parser/solparser_shape.h b/src/parser/solparser_shape.h
@@ -32,6 +32,7 @@ enum solparser_shape_type {
SOLPARSER_SHAPE_OBJ, /* Imported Alias Wavefront obj */
SOLPARSER_SHAPE_PARABOL,
SOLPARSER_SHAPE_PARABOLIC_CYLINDER,
+ SOLPARSER_SHAPE_HYPERBOL,
SOLPARSER_SHAPE_PLANE,
SOLPARSER_SHAPE_SPHERE,
SOLPARSER_SHAPE_STL /* Imported STereo Lithography */
@@ -198,6 +199,52 @@ solparser_shape_paraboloid_copy_and_release
}
/*******************************************************************************
+* Hyperboloid shape
+******************************************************************************/
+struct solparser_shape_hyperboloid {
+ double real_focal, img_focal;
+ struct darray_polyclip polyclips;
+};
+
+static INLINE void
+solparser_shape_hyperboloid_init
+ (struct mem_allocator* allocator,
+ struct solparser_shape_hyperboloid* hyperboloid)
+{
+ ASSERT(hyperboloid);
+ darray_polyclip_init(allocator, &hyperboloid->polyclips);
+}
+
+static INLINE void
+solparser_shape_hyperboloid_release(struct solparser_shape_hyperboloid* hyperboloid)
+{
+ ASSERT(hyperboloid);
+ darray_polyclip_release(&hyperboloid->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_hyperboloid_copy
+ (struct solparser_shape_hyperboloid* dst,
+ const struct solparser_shape_hyperboloid* src)
+{
+ ASSERT(dst && src);
+ dst->real_focal = src->real_focal;
+ dst->img_focal = src->img_focal;
+ return darray_polyclip_copy(&dst->polyclips, &src->polyclips);
+}
+
+static INLINE res_T
+solparser_shape_hyperboloid_copy_and_release
+ (struct solparser_shape_hyperboloid* dst,
+ struct solparser_shape_hyperboloid* src)
+{
+ ASSERT(dst && src);
+ dst->real_focal = src->real_focal;
+ dst->img_focal = src->img_focal;
+ return darray_polyclip_copy_and_release(&dst->polyclips, &src->polyclips);
+}
+
+/*******************************************************************************
* Plane shape
******************************************************************************/
struct solparser_shape_plane {
@@ -260,6 +307,7 @@ struct solparser_shape_cuboid_id { size_t i; };
struct solparser_shape_cylinder_id { size_t i; };
struct solparser_shape_imported_geometry_id { size_t i; };
struct solparser_shape_paraboloid_id { size_t i; };
+struct solparser_shape_hyperboloid_id { size_t i; };
struct solparser_shape_plane_id { size_t i; };
struct solparser_shape_sphere_id { size_t i; };
@@ -271,6 +319,7 @@ struct solparser_shape {
struct solparser_shape_imported_geometry_id obj;
struct solparser_shape_paraboloid_id parabol;
struct solparser_shape_paraboloid_id parabolic_cylinder;
+ struct solparser_shape_hyperboloid_id hyperbol;
struct solparser_shape_plane_id plane;
struct solparser_shape_sphere_id sphere;
struct solparser_shape_imported_geometry_id stl;
diff --git a/src/parser/test_solparser6.c b/src/parser/test_solparser6.c
@@ -31,6 +31,9 @@ main(int argc, char** argv)
const struct solparser_material* mtl;
const struct solparser_object* obj;
const struct solparser_shape* shape;
+ const struct solparser_shape_sphere* sphere;
+ const struct solparser_shape_paraboloid* parabol;
+ const struct solparser_shape_hyperboloid* hyperbol;
FILE* stream;
(void)argc, (void)argv;
@@ -45,8 +48,21 @@ main(int argc, char** argv)
fprintf(stream, " name: test\n");
fprintf(stream, " primary: 0\n");
fprintf(stream, " geometry:\n");
- fprintf(stream, " - sphere: { radius: 1 }\n");
- fprintf(stream, " material: { ?virtual }\n");
+ fprintf(stream, " - sphere: { radius: 1 }\n");
+ fprintf(stream, " material: { ?virtual }\n");
+ fprintf(stream, " - parabol:\n");
+ fprintf(stream, " focal: 10\n");
+ fprintf(stream, " clip :\n");
+ fprintf(stream, " - operation : AND\n");
+ 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, " clip :\n");
+ fprintf(stream, " - operation : AND\n");
+ fprintf(stream, " vertices : [[1, 2], [3, 4], [6, 7]]\n");
+ fprintf(stream, " material: { ?virtual }\n");
rewind(stream);
CHECK(solparser_setup(parser, NULL, stream), RES_OK);
@@ -63,11 +79,31 @@ main(int argc, char** argv)
CHECK(solparser_entity_get_children_count(entity), 0);
CHECK(entity->type, SOLPARSER_ENTITY_GEOMETRY);
geom = solparser_get_geometry(parser, entity->data.geometry);
- CHECK(solparser_geometry_get_objects_count(geom), 1);
+ CHECK(solparser_geometry_get_objects_count(geom), 3);
+
obj_id = solparser_geometry_get_object(geom, 0);
obj = solparser_get_object(parser, obj_id);
shape = solparser_get_shape(parser, obj->shape);
CHECK(shape->type, SOLPARSER_SHAPE_SPHERE);
+ sphere = solparser_get_shape_sphere(parser, shape->data.sphere);
+ CHECK(sphere->radius, 1);
+ CHECK(sphere->nslices, 16);
+
+ obj_id = solparser_geometry_get_object(geom, 1);
+ obj = solparser_get_object(parser, obj_id);
+ shape = solparser_get_shape(parser, obj->shape);
+ CHECK(shape->type, SOLPARSER_SHAPE_PARABOL);
+ parabol = solparser_get_shape_parabol(parser, shape->data.parabol);
+ CHECK(parabol->focal, 10);
+
+ obj_id = solparser_geometry_get_object(geom, 2);
+ obj = solparser_get_object(parser, obj_id);
+ 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);
+
mtl2 = solparser_get_material_double_sided(parser, obj->mtl2);
CHECK(mtl2->front.i, mtl2->back.i);
mtl = solparser_get_material(parser, mtl2->front);
diff --git a/src/parser/yaml/test_ko_0.yaml b/src/parser/yaml/test_ko_0.yaml
@@ -598,6 +598,82 @@
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)
+# clip: <polyclip-list>
+#
+# missing hyperbol definition
+- geometry: [ { hyperbol: } ]
+---
+# unknown dummy parameter
+- geometry: [ { hyperbol: { dummy: 1 } } ]
+---
+# missing real_focal value
+- geometry: [ { hyperbol: { real_focal: } } ]
+---
+# missing img_focal value
+- geometry: [ { hyperbol: { img_focal: } } ]
+---
+# missing clip value
+- geometry: [ { hyperbol: { clip: } } ]
+---
+# real_focal should be a number
+- geometry: [ { hyperbol: { real_focal: "dummy" } } ]
+---
+# -1 invalid
+- geometry: [ { hyperbol: { real_focal: -1 } } ]
+---
+# 0 invalid
+- geometry: [ { hyperbol: { real_focal: 0 } } ]
+---
+# img_focal should be a number
+- geometry: [ { hyperbol: { img_focal: "dummy" } } ]
+---
+# -1 invalid
+- geometry: [ { hyperbol: { img_focal: -1 } } ]
+---
+# 0 invalid
+- geometry: [ { hyperbol: { img_focal: 0 } } ]
+---
+# missing clip parameter
+- geometry: [ { hyperbol: { real_focal: 10, img_focal: 10 } } ]
+---
+# missing real_focal parameter
+- geometry:
+ - hyperbol:
+ img_focal: 10
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+---
+# missing img_focal parameter
+- geometry:
+ - hyperbol:
+ real_focal: 10
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+---
+# 2x real_focal
+- geometry: [ { hyperbol: { real_focal: 10, real_focal: 10 } } ]
+---
+# 2x img_focal
+- geometry: [ { hyperbol: { img_focal: 10, img_focal: 10 } } ]
+---
+# 2x clip
+- geometry:
+ - hyperbol:
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+ clip:
+ - operation: AND
+ vertices: [ [1, 2], [3, 4], [6, 7] ]
+---
+
#
# <plane> ::=
# plane:
diff --git a/src/solstice_object.c b/src/solstice_object.c
@@ -434,6 +434,29 @@ create_parabolic_cylinder
}
static res_T
+create_hyperbol
+ (struct solstice* solstice,
+ const double transform[12],
+ const struct solparser_shape_hyperboloid_id id,
+ struct ssol_shape** out_ssol_shape)
+{
+ const struct solparser_shape_hyperboloid* hyperboloid;
+ struct ssol_quadric quadric = SSOL_QUADRIC_DEFAULT;
+ ASSERT(solstice);
+
+ 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;
+ d33_set(quadric.transform, transform);
+ d3_set(quadric.transform + 9, transform + 9);
+
+ return create_ssol_shape_punched_surface
+ (solstice, &hyperboloid->polyclips, &quadric, out_ssol_shape);
+}
+
+static res_T
create_plane
(struct solstice* solstice,
const double transform[12],
@@ -503,6 +526,9 @@ create_shaded_shape
res = create_parabolic_cylinder
(solstice, transform, shape->data.parabol, ssol_shape);
break;
+ case SOLPARSER_SHAPE_HYPERBOL:
+ res = create_hyperbol(solstice, transform, shape->data.hyperbol, ssol_shape);
+ break;
case SOLPARSER_SHAPE_PLANE:
res = create_plane(solstice, transform, shape->data.plane, ssol_shape);
break;