star-geometry-3d

Clean and decorate 3D geometries
git clone git://git.meso-star.fr/star-geometry-3d.git
Log | Files | Refs | README | LICENSE

commit b54696785e585f5efa90954dd0df09f560f8bd4e
parent e8024de027ddbb370ca8b26aeef7a8b725f9681d
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 12 Dec 2019 19:13:14 +0100

Add dump geometry to VTK

Diffstat:
Msrc/sg3_geometry.c | 137+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/star-geometry.h | 40+++++++++++++++++++++++++++++-----------
Msrc/test_sg3_geometry.c | 9+++++++++
Msrc/test_sg3_geometry_2.c | 9+++++++--
4 files changed, 175 insertions(+), 20 deletions(-)

diff --git a/src/sg3_geometry.c b/src/sg3_geometry.c @@ -93,6 +93,39 @@ trg_make_key(struct unsigned3* k, const unsigned t[3]) } } +static void +dump_trg_property + (const struct sg3_geometry* geom, + FILE* stream, + const enum sg3_property_type type) +{ + size_t i; + const struct trg_descriptions* descriptions; + ASSERT(geom && stream && type < SG3_PROP_TYPES_COUNT__); + + descriptions + = darray_trg_descriptions_cdata_get(&geom->trg_descriptions); + FOR_EACH(i, 0, darray_triangle_size_get(&geom->unique_triangles)) { + unsigned property = SG3_UNDEFINED_PROPERTY; + size_t tdefs_count + = darray_definition_size_get(&descriptions[i].defs[type]); + if(tdefs_count && descriptions[i].property_defined[type]) { + const struct definition* tdefs + = darray_definition_cdata_get(&descriptions[i].defs[type]); + size_t j; + FOR_EACH(j, 0, tdefs_count) { + if(tdefs->property_value != SG3_UNDEFINED_PROPERTY) { + property = tdefs->property_value; + break; /* Found the defined value */ + } + tdefs++; /* Next value */ + } + } + /* Value is INT_MAX for both undefined and conflict */ + fprintf(stream, "%u\n", MMIN(property, INT_MAX)); + } +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -102,8 +135,6 @@ geometry_register_triangle const struct triangle* triangle, const unsigned triangle_unique_id, const unsigned set_id, - /* The conflict code as returned by user callback; if no callback provided - * set_id is 0 or 1 according to media equality / SG3_UNDEFINED_PROPERTY */ const int merge_conflict) { res_T res = RES_OK; @@ -223,6 +254,7 @@ dump_partition 1 + triangles[i].vertex_ids[2]); } } + /******************************************************************************* * Exported functions ******************************************************************************/ @@ -366,8 +398,8 @@ sg3_geometry_add || tmp.vertex_ids[0] == tmp.vertex_ids[2] || tmp.vertex_ids[1] == tmp.vertex_ids[2]) { - log_err(geom->dev, "%s: triangle %lu is degenerate.\n", - FUNC_NAME, (unsigned long)tmp.global_id); + log_err(geom->dev, "%s: triangle %u is degenerate.\n", + FUNC_NAME, tmp.global_id); res = RES_BAD_ARG; goto error; } @@ -648,9 +680,9 @@ sg3_geometry_dump_as_obj fprintf(stream, "v %f %f %f\n", SPLIT3(vertices[i].coord)); /* Dump triangles by groups */ - dump_partition(geom, stream, "Valid triangles", SG3_VALID_TRIANGLE); - dump_partition(geom, stream, "Merge conflicts", SG3_MERGE_CONFLICTS); - dump_partition(geom, stream, "Property conflicts", SG3_PROPERTY_CONFLICTS); + dump_partition(geom, stream, "Valid_triangles", SG3_VALID_TRIANGLE); + dump_partition(geom, stream, "Merge_conflicts", SG3_MERGE_CONFLICTS); + dump_partition(geom, stream, "Property_conflicts", SG3_PROPERTY_CONFLICTS); exit: return res; @@ -659,6 +691,97 @@ error: } res_T +sg3_geometry_dump_as_vtk + (const struct sg3_geometry* geom, + FILE* stream) +{ + res_T res = RES_OK; + const struct vertex* vertices; + const struct triangle* triangles; + const struct trg_descriptions* descriptions; + size_t vsz, tsz, i; + if(!geom || !stream || !geom->triangle_count_including_duplicates) { + if(geom && !geom->triangle_count_including_duplicates) + log_err(geom->dev, + "%s: cannot dump empty geometries as VTK\n", + FUNC_NAME); + res = RES_BAD_ARG; + goto error; + } + /* Headers */ + fprintf(stream, "# vtk DataFile Version 3.0\n"); + fprintf(stream, "Dump of star-geometry report\n"); + fprintf(stream, "ASCII\n"); + fprintf(stream, "DATASET POLYDATA\n"); + + /* Dump vertices */ + vsz = darray_vertex_size_get(&geom->unique_vertices); + ASSERT(vsz <= UINT_MAX); + fprintf(stream, "POINTS %u double\n", (unsigned)vsz); + vertices = darray_vertex_cdata_get(&geom->unique_vertices); + FOR_EACH(i, 0, vsz) + fprintf(stream, "%f %f %f\n", SPLIT3(vertices[i].coord)); + + /* Dump triangles */ + tsz = darray_triangle_size_get(&geom->unique_triangles); + ASSERT(4 * tsz <= UINT_MAX); + fprintf(stream, "POLYGONS %u %u\n", (unsigned)tsz, (unsigned)(4 * tsz)); + triangles = darray_triangle_cdata_get(&geom->unique_triangles); + FOR_EACH(i, 0, tsz) + fprintf(stream, "3 %u %u %u\n", SPLIT3(triangles[i].vertex_ids)); + + /* Start triangles properties */ + fprintf(stream, "CELL_DATA %u\n", (unsigned)tsz); + descriptions = darray_trg_descriptions_cdata_get(&geom->trg_descriptions); + + /* Dump front medium */ + fprintf(stream, "SCALARS Front_medium int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + dump_trg_property(geom, stream, SG3_FRONT); + + /* Dump back medium */ + fprintf(stream, "SCALARS Back_medium int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + dump_trg_property(geom, stream, SG3_BACK); + + /* Dump interface */ + fprintf(stream, "SCALARS Interface int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + dump_trg_property(geom, stream, SG3_INTFACE); + + /* Dump merge conflict status */ + fprintf(stream, "SCALARS Merge_conflict int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(i, 0, tsz) + fprintf(stream, "%d\n", descriptions[i].merge_conflict); + + /* Dump property property status */ + fprintf(stream, "SCALARS Property_conflict int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(i, 0, tsz) + fprintf(stream, "%d\n", descriptions[i].properties_conflict); + + /* Dump rank of the sg3_geometry_add that created the triangle */ + fprintf(stream, "SCALARS Created_at_sg3_geometry_add int\n"); + fprintf(stream, "LOOKUP_TABLE default\n"); + FOR_EACH(i, 0, tsz) { + size_t tdefs_count + = darray_definition_size_get(&descriptions[i].defs[SG3_FRONT]); + const struct definition* tdefs; + const unsigned* ranks; + ASSERT(tdefs_count); + /* Rank is the first set_id of the first definition of any property */ + tdefs = darray_definition_cdata_get(&descriptions[i].defs[SG3_FRONT]); + ranks = darray_uint_cdata_get(&tdefs[0].set_ids); + fprintf(stream, "%u\n", ranks[0]); + } + +exit: + return res; +error: + goto exit; +} +res_T sg3_geometry_dump_as_C_code (const struct sg3_geometry* geom, FILE* stream, diff --git a/src/star-geometry.h b/src/star-geometry.h @@ -144,13 +144,13 @@ sg3_geometry_create * callback is provided. In either case, sg3_geometry_add never stops * prematurely nor returns an error code due to a merge conflict. * - if provided, the callback must return the consistency status using the - * merge_conflict int* paramater (0 for consistent; any other value for - * inconsistent, this value being recorded); regardless of the - * merge_conflict status, the callback can change the properties of the + * merge_conflict_status int* paramater (0 for consistent; any other value + * for inconsistent, this value being recorded); regardless of + * merge_conflict_status, the callback can change the properties of the * triangle before the SG3_UNDEFINED_PROPERTY overwriting step; * - if not, a non-SG3_UNDEFINED_PROPERTY is only consistent with itself and - * with SG3_UNDEFINED_PROPERTY (if inconsistent, the merge_conflict status is - * set to 1 and recorded) ; regardless of the merge_conflict status, a + * with SG3_UNDEFINED_PROPERTY (if inconsistent, merge_conflict_status is set + * to 1 and recorded) ; regardless of merge_conflict_status, a * non-SG3_UNDEFINED_PROPERTY property is never overridden. * When deduplicating triangles, the first occurence remains (with its * original index in user world). After consistency being computed, a final @@ -182,15 +182,15 @@ sg3_geometry_add * recorded properties. * The reversed_triangle arg indicates if the triangle vertices' order is * the same it was when the triangle was first added. - * The merge_conflict argument can be set to any value. Any non-0 value - * is accounted for a conflict and is kept as-is in dumps, allowing + * The merge_conflict_status argument can be set to any value. Any non-0 + * value is accounted for a conflict and is kept as-is in dumps, allowing * different shades of conflict. * The triangle_properties and merged_properties args contain the involved * properties. */ res_T(*merge_triangle) /* Can be NULL */ (const unsigned global_id, const unsigned itri, const int reversed_triangle, unsigned triangle_properties[3], const unsigned merged_properties[3], - void* context, int* merge_conflict), + void* context, int* merge_conflict_status), void* context); /* Can be NULL */ /* Apply a validation callback on each triangle included in this geometry that @@ -253,15 +253,33 @@ sg3_geometry_get_properties_conflict_count * properties. The dumped triangles are defined by the flags argument, that * must be ORed enum sg3_dump_content values. * The dumped triangles are partitioned in the following groups: - * - Valid triangles - * - Merge conflicts - * - Property conflict */ + * - Valid_triangles + * - Merge_conflicts + * - Property_conflict */ SG3_API res_T sg3_geometry_dump_as_obj (const struct sg3_geometry* geometry, FILE* stream, int flags); +/* Dump a geometry in the provided stream in the VTK ascii format. + * The geometry can include conflicts, but cannot be empty. + * The dump is made of the vertices and triangles, with most of their + * properties: + * - Front_medium (medium ID of the front side, INT_MAX for both undefined and + * conflicted) + * - Back_medium (medium ID of the back side, INT_MAX for both undefined and + * conflicted) + * - Interface (interface ID, INT_MAX for both undefined and conflicted) + * - Merge_conflict (merge conflict status) + * - Property_conflict (property conflict status) + * - Created_at_sg3_geometry_add (rank of the sg3_geometry_add that created the + * triangle) */ +SG3_API res_T +sg3_geometry_dump_as_vtk + (const struct sg3_geometry* geometry, + FILE* stream); + /* Dump the geometry as C code. * The geometry cannot be empty and must be conflict-free. * The C code defines the 3 variables: diff --git a/src/test_sg3_geometry.c b/src/test_sg3_geometry.c @@ -120,6 +120,12 @@ main(int argc, char** argv) /* BA because geometry is empty */ BA(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + BA(sg3_geometry_dump_as_vtk(NULL, NULL)); + BA(sg3_geometry_dump_as_vtk(geom, NULL)); + BA(sg3_geometry_dump_as_vtk(NULL, stdout)); + /* BA because geometry is empty */ + BA(sg3_geometry_dump_as_vtk(geom, stdout)); + BA(sg3_geometry_dump_as_C_code(NULL, NULL, NULL)); BA(sg3_geometry_dump_as_C_code(geom, NULL, NULL)); BA(sg3_geometry_dump_as_C_code(NULL, stdout, NULL)); @@ -145,6 +151,7 @@ main(int argc, char** argv) OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, nvertices, get_position, NULL, NULL, &ctx)); OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + OK(sg3_geometry_dump_as_vtk(geom, stdout)); OK(sg3_geometry_dump_as_C_code(geom, stdout, NULL)); OK(sg3_geometry_dump_as_C_code(geom, stdout, "test")); @@ -155,6 +162,7 @@ main(int argc, char** argv) /* Due to merge_trg internals, all but the first triangle have conflict */ CHK(count == ntriangles - 1); OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + OK(sg3_geometry_dump_as_vtk(geom, stdout)); /* BA because of conflicts */ BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); OK(sg3_geometry_ref_put(geom)); @@ -170,6 +178,7 @@ main(int argc, char** argv) FOR_EACH(i, 0, ntriangles) if(medium0[i] != medium1_front0[i]) count--; CHK(count == 0); OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + OK(sg3_geometry_dump_as_vtk(geom, stdout)); /* BA because of conflicts */ BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); diff --git a/src/test_sg3_geometry_2.c b/src/test_sg3_geometry_2.c @@ -257,12 +257,15 @@ main(int argc, char** argv) SG3(geometry_ref_put(geom)); OK(sg3_geometry_create(dev, &geom)); - /* Successful add geometry with add callback */ + /* Successful add geometry with add callback + * First half of the triangles, then all of them */ add_geom_ctx.add_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles / 2, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, nvertices, get_position, add_trg, merge_trg, &ctx)); CHK(add_geom_ctx.add_cpt == ntriangles); - CHK(add_geom_ctx.merge_cpt == 0); + CHK(add_geom_ctx.merge_cpt == ntriangles / 2); add_geom_ctx.add_cpt = 0; OK(sg3_geometry_get_unique_vertices_count(geom, &count)); CHK(count == nvertices); @@ -276,10 +279,12 @@ main(int argc, char** argv) CHK(count == 0); OK(sg3_geometry_get_properties_conflict_count(geom, &count)); CHK(count == 0); + OK(sg3_geometry_dump_as_vtk(geom, stdout)); /* Clear geometry */ SG3(geometry_ref_put(geom)); OK(sg3_geometry_create(dev, &geom)); + add_geom_ctx.merge_cpt = 0; /* Successful add geometry with add callback and no defined properties */ add_geom_ctx.add_res = RES_OK;