commit 236a298488e28830eaa8e98eb552f9e8789ebdd1
parent 27846f944494b5fff41bd2783896bb4e5038c6cd
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 6 Mar 2024 15:43:46 +0100
Change scad_geometries_partition
Replace the boolean int argument by a flags argument.
The two values 0 and 1 that where the basic values for this arg still
produce the same behaviour: API is not broken.
A new capability is to use the Scad_dump_on_overlapping_error which, as
the name implies, requests that overlapping geometries are dumped (as
STL files).
Diffstat:
2 files changed, 63 insertions(+), 12 deletions(-)
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);