star-cad

Geometric operators for computer-aided design
git clone git://git.meso-star.fr/star-cad.git
Log | Files | Refs | README | LICENSE

commit 0f882001d4232e7adee2a901b58eebdc7714385a
parent 7dc0f8b4dfcabf20183834e53fac1e4a219c2ea8
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 10 Apr 2024 10:42:24 +0200

Merge branch 'release_0.3.1'

Diffstat:
MREADME.md | 6++++++
Mcmake/CMakeLists.txt | 6+++---
Msrc/scad.c | 11++++++-----
Msrc/scad.h | 10+++++++++-
Msrc/scad_geometry.c | 65++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
5 files changed, 78 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md @@ -21,6 +21,12 @@ project from the `cmake/CMakeLists.txt` file by appending to the ## Release notes +### Version 0.3.1 + +- Add a flag allowing to dump overlapping geometries +- Improve some log messages +- Sets required version of star-enclosures-3d to 0.6 + ### Version 0.3 This release largely breaks the API. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -26,8 +26,8 @@ option(NO_TEST "Disable the test" OFF) find_package(gmsh 4.9.5 REQUIRED) find_package(RCMake 0.4.1 REQUIRED) find_package(RSys 0.12.1 REQUIRED) -find_package(StarGeom3D 0.1 REQUIRED) -find_package(StarEnc3D 0.5 REQUIRED) +find_package(StarGeom3D 0.1.3 REQUIRED) +find_package(StarEnc3D 0.6 REQUIRED) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) @@ -44,7 +44,7 @@ include_directories( ################################################################################ set(VERSION_MAJOR 0) set(VERSION_MINOR 3) -set(VERSION_PATCH 0) +set(VERSION_PATCH 1) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SCAD_FILES_SRC diff --git a/src/scad.c b/src/scad.c @@ -524,8 +524,7 @@ scad_stl_sort_orientation if(tcount != tcount_in) { ASSERT(tcount_in > tcount); log_warning(get_device(), - "Triangles duplicates were found when sorting out normals (%u / %u) " - "in set '%s'.\n", + "Triangles duplicates found when sorting out normals (%u / %u) in set '%s'.\n", tcount_in - tcount, tcount_in, set_name); } if(orientation == Scad_force_normals_outward) @@ -543,7 +542,7 @@ scad_stl_sort_orientation ERR(senc3d_scene_get_overlapping_triangles_count(senc3d_scn, &ocount)); if(ocount) { logger_print(logger, LOG_ERROR, - "Overlapping triangles where found when sorting out normals (%u / %u) " + "Overlapping triangles found when sorting out normals (%u / %u) " "in set '%s'.\n", tcount_in - ocount, tcount_in, set_name); res = RES_BAD_ARG; @@ -581,8 +580,10 @@ scad_stl_sort_orientation if(header.primitives_count != header.unique_primitives_count) { log_error(get_device(), "Triangle set '%s' define an invalid closed volume " - "(both sides of a triangle are in).\n", - set_name); + "(both sides of %u / %u triangles are in).\n", + set_name, + header.primitives_count - header.unique_primitives_count, + header.unique_primitives_count); res = RES_BAD_ARG; goto error; } diff --git a/src/scad.h b/src/scad.h @@ -135,6 +135,12 @@ enum scad_normals_orientation { Scad_force_normals_inward }; +/* A type to specify how partitioning is done. */ +enum scad_partition_flags { + Scad_allow_overlapping = BIT(0), + Scad_dump_on_overlapping_error = BIT(1) +}; + BEGIN_DECLS /******************************************************************************* @@ -363,6 +369,8 @@ scad_geometries_common_boundaries /* Compute the boolean fragments (general fuse) resulting from the * intersection of the geometries in `geometries', making all interfaces * conformal. + * `flags' should be made by Oring values from enum scad_partition_flags to + * enable non default behaviours (default is to disallow overlapping). * The output geometries are created unnamed. * When applied to geometries of different dimensions, the lower dimensional * geometries will be automatically embedded in the higher dimensional @@ -371,7 +379,7 @@ SCAD_API res_T scad_geometries_partition (struct scad_geometry** geometries, const size_t geometries_count, - const int allow_overlapping, + const int flags, struct scad_geometry** out_geometries); /* Get the boundary of the geometry `geom'. */ diff --git a/src/scad_geometry.c b/src/scad_geometry.c @@ -1794,7 +1794,7 @@ res_T scad_geometries_partition (struct scad_geometry** geometries, const size_t geometries_count, - const int allow_overlapping, + const int flags, struct scad_geometry** out_geometries) { res_T res = RES_OK; @@ -1810,18 +1810,25 @@ scad_geometries_partition struct scad_device* dev = get_device(); struct htable_tags t2, t3; struct htable_tags_iterator it, end; - int ht_initialized = 0; + int ht_initialized = 0, tmp_initialized = 0; struct mem_allocator* allocator = NULL; int dont_call_fragment = 0; char* overlap = NULL; + const int invalid_flags = + ~(Scad_allow_overlapping | Scad_dump_on_overlapping_error); + const int dump_overlapping_err = flags & Scad_dump_on_overlapping_error; + static size_t err_cpt = 0; + struct str tmp; - if(!geometries || !geometries_count || !out_geometries) { + if(!geometries || !geometries_count || !out_geometries || flags & invalid_flags) { res = RES_BAD_ARG; goto error; } ERR(check_device(FUNC_NAME)); allocator = dev->allocator; + str_init(allocator, &tmp); + tmp_initialized = 1; ERR(gather_tags(geometries, geometries_count, &data, &sz)); @@ -1861,7 +1868,7 @@ scad_geometries_partition get_device()->need_synchro = 1; /* Check first if there was an overlapping problem */ - if(!allow_overlapping) { + if(!(flags & Scad_allow_overlapping)) { /* No overlapping means that each tag in geometries is translated into a * single tag in map */ size_t ov = 0; @@ -1884,18 +1891,53 @@ scad_geometries_partition } } if(ov) { - size_t k; + size_t k, item_cpt = 0; + res_T tmp_err; + if(dump_overlapping_err) { + ERR(scad_scene_mesh()); + } for(k = 0; k < geometries_count; k++) { struct scad_geometry* g = geometries[k]; if(!overlap[k]) continue; - if(str_is_empty(&g->name)) { - log_error(get_device(), "Unnamed geometry '%p' overlapping.\n", - (void*)g); - } else { - log_error(get_device(), "Geometry '%s' overlapping.\n", - str_cget(&g->name)); + tmp_err = RES_BAD_OP; + if(dump_overlapping_err) { + if(str_is_empty(&g->name)) { + str_printf(&tmp, "unamed_partition_error_%lu_%lu.stl", + err_cpt, (long unsigned)item_cpt++); + tmp_err = + scad_stl_export(g, str_cget(&tmp), Scad_keep_normals_unchanged, 0); + if(tmp_err == RES_OK) { + log_error(get_device(), + "Unnamed geometry '%p' overlapping (dumped in '%s).\n", + (void*)g, str_cget(&tmp)); + } else { + log_error(get_device(), "Could not dump geoemtry.\n"); + } + } else { + str_printf(&tmp, "%s_partition_error_%lu_%lu.stl", + str_cget(&g->name), err_cpt, (long unsigned)item_cpt++); + tmp_err = + scad_stl_export(g, str_cget(&tmp), Scad_keep_normals_unchanged, 0); + if(tmp_err == RES_OK) { + log_error(get_device(), + "Geometry '%s' overlapping (dumped in '%s).\n", + str_cget(&g->name), str_cget(&tmp)); + } else { + log_error(get_device(), "Could not dump geoemtry.\n"); + } + } + } + if(tmp_err != RES_OK) { /* not dumped */ + if(str_is_empty(&g->name)) { + log_error(get_device(), "Unnamed geometry '%p' overlapping.\n", + (void*)g); + } else { + log_error(get_device(), "Geometry '%s' overlapping.\n", + str_cget(&g->name)); + } } } + err_cpt++; } if(ov) { res = RES_BAD_ARG; @@ -1986,6 +2028,7 @@ exit: htable_tags_release(&t2); htable_tags_release(&t3); } + if(tmp_initialized) str_release(&tmp); if(allocator) { MEM_RM(allocator, data); MEM_RM(allocator, geoms);