commit ceb0df63346897338b9aca0a6221307459a01f4b
parent eca24493f249ca8cb459814e53236b227489c90a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 15 Oct 2025 16:21:16 +0200
Merge branch 'release_0.6_r1'
Diffstat:
6 files changed, 439 insertions(+), 66 deletions(-)
diff --git a/README.md b/README.md
@@ -27,15 +27,15 @@ Edit config.mk as needed, then run:
### Version 0.6
+This version breaks the API and brings an huge performance improvement (10 times
+and more on complex scenes).
- Add `scad_add_cone' and `scad_add_torus' API calls.
- API changes for geometry creation: geometry name is no longer provided to the
various add_<something> functions, that now create unnamed geometries; instead
names have to be set after geometry creation through `scad_geometry_set_name'.
-- API change for `scad_geometries_boundaries' and
- `scad_geometries_common_boundaries': now return a list of geometries
- (that could be grouped through `scad_collect_geometries'); used to return a
- single geometry containing the (possibly empty) boundary elements (that could
- be ungrouped using `scad_geometry_explode').
+- Add `scad_geometries_boundaries' and `scad_geometries_common_boundaries' that
+ return a list of geometries instead of a (possibly empty) single geometry
+ containing all the boundary elements.
- API uniformization (involving args order, naming, etc.).
- Fix geometry naming. Now get_name returns NULL if name was set to NULL or
let unset (used to return ""). Allow to set same name again (to the same
@@ -45,14 +45,14 @@ Edit config.mk as needed, then run:
point, fixing a memleak in the process.
- Fix `scad_scene_clear' (geometries with multiple references where not
released).
-- Fix `scad_geometries_common_boundaries'. Used to trigger OccIntersect that, as
+- Fix `scad_geometries_common_boundary'. Used to trigger OccIntersect that, as
a side effet, partitionned geometries.
- Fix `scad_step_import' (arguments where inverted).
- Change `scad_geometry_get_centerofmass'. Now returns the unique center of mass
of all the entities involved in the geometry, regardless of their count (used
to return one center of mass per entity in the geometry).
- Rework the auto-sync feature (that manages sync events between gmsh and
- Open Cascade); this should greatly improve performance.
+ Open Cascade); this is the cause of the performance improvement.
- Rename enum members in capital letters.
- Upgrade gmsh dependency (to 1.14.1) and Open-Cascade dependency (to 7.9.1).
- Improve code robustness.
diff --git a/src/scad.h b/src/scad.h
@@ -581,6 +581,17 @@ scad_geometries_common_boundaries
struct scad_geometry*** out_boundaries,
size_t *out_count);
+/* Same as above, with the boundary entities collected in a single geometry.
+ * Note that there is always an output geometry returned is `out_boundary', that
+ * can be empty (scad_geometry_get_count = 0). */
+SCAD_API res_T
+scad_geometries_common_boundary
+ (struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_boundary);
+
/* Get the boundaries of the geometries in `geometries', considered as a whole.
* The output geometries are created unnamed.
* The result `out_boundaries' being allocated using the allocator provided when
@@ -592,6 +603,15 @@ scad_geometries_boundaries
struct scad_geometry*** out_boundaries,
size_t *out_count);
+/* Same as above, with the boundary entities collected in a single geometry.
+ * Note that there is always an output geometry returned is `out_boundary', that
+ * can be empty (scad_geometry_get_count = 0). */
+SCAD_API res_T
+scad_geometries_boundary
+ (struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** out_boundary);
+
/* Copy the geometry `geometry', except for its name.
* The new geometry remains unnamed. */
SCAD_API res_T
diff --git a/src/scad_device.c b/src/scad_device.c
@@ -28,63 +28,76 @@
#include <rsys/rsys.h>
/*******************************************************************************
+ * The unique device in scad-cad
+ ******************************************************************************/
+static struct scad_device* g_device = NULL;
+
+/*******************************************************************************
* Local functions
******************************************************************************/
static res_T
-device_release(struct scad_device* dev)
+device_release(void)
{
res_T res = RES_OK;
- struct htable_geometries tmp;
- struct htable_geometries_iterator it, end;
int log, empty;
- enum scad_log_refcounting option;
+ enum scad_log_refcounting option_ref;
+ int option_dec;
enum log_type log_type;
+ struct mem_allocator* allocator;
- ASSERT(dev);
+ ASSERT(g_device);
- option = dev->options.Misc.LogRefCounting;
- empty = htable_geometries_is_empty(&dev->allgeom);
+ allocator = g_device->allocator;
+ option_ref = g_device->options.Misc.LogRefCounting;
+ option_dec = g_device->options.Misc.DebugEmptyContext;
+ empty = htable_geometries_is_empty(&g_device->allgeom);
log_type = empty ? LOG_OUTPUT : LOG_WARNING;
- log = (option & SCAD_LOG_DIMTAGS_ALL)
- || (!empty && (option & SCAD_LOG_DIMTAGS_ONLY_UNDELETED));
- dev->log = log;
- dev->log_type = log_type;
-
- /* Duplicate the htable we iterate on as dev->allgeom will be altered during
- * the process (through calls to geometry_release) */
- htable_geometries_init(dev->allocator, &tmp);
- CHK(RES_OK == htable_geometries_copy(&tmp, &dev->allgeom));
- htable_geometries_begin(&tmp, &it);
- htable_geometries_end(&tmp, &end);
- if(log && empty) {
- logger_print(dev->logger, log_type, "No scad geometry.\n");
- }
- while(!htable_geometries_iterator_eq(&it, &end)) {
- struct scad_geometry* geom = *htable_geometries_iterator_key_get(&it);
- while(geom->ref > 0) {
- SCAD(geometry_ref_put(geom));
+ log = (option_ref & SCAD_LOG_DIMTAGS_ALL)
+ || (!empty && (option_ref & SCAD_LOG_DIMTAGS_ONLY_UNDELETED));
+ g_device->log = log;
+ g_device->log_type = log_type;
+
+ if(empty) {
+ if(log) logger_print(g_device->logger, log_type, "No scad geometry.\n");
+ } else {
+ struct htable_geometries tmp;
+ struct htable_geometries_iterator it, end;
+ /* Duplicate the htable we iterate on as dev->allgeom will be altered during
+ * the process (through calls to geometry_release) */
+ htable_geometries_init(allocator, &tmp);
+ CHK(RES_OK == htable_geometries_copy(&tmp, &g_device->allgeom));
+ htable_geometries_begin(&tmp, &it);
+ htable_geometries_end(&tmp, &end);
+ while(!htable_geometries_iterator_eq(&it, &end)) {
+ struct scad_geometry* geom = *htable_geometries_iterator_key_get(&it);
+ long cpt = geom->ref;
+ while(cpt-- > 0) {
+ SCAD(geometry_ref_put(geom));
+ }
+ htable_geometries_iterator_next(&it);
}
- htable_geometries_iterator_next(&it);
- }
- htable_names_release(&dev->geometry_names);
- htable_geometries_release(&dev->allgeom);
- htable_tags2desc_release(dev->tags2desc);
- htable_tags2desc_release(dev->tags2desc+1);
- htable_size_modifiers_release(&dev->size_modifiers_by_dim[0]);
- htable_size_modifiers_release(&dev->size_modifiers_by_dim[1]);
- htable_size_modifiers_release(&dev->size_modifiers_by_dim[2]);
- htable_size_modifiers_release(&dev->size_modifiers_by_dim[3]);
+ htable_geometries_release(&tmp);
+ }
+ htable_names_release(&g_device->geometry_names);
+ htable_geometries_release(&g_device->allgeom);
+ htable_tags2desc_release(g_device->tags2desc);
+ htable_tags2desc_release(g_device->tags2desc+1);
+ htable_size_modifiers_release(&g_device->size_modifiers_by_dim[0]);
+ htable_size_modifiers_release(&g_device->size_modifiers_by_dim[1]);
+ htable_size_modifiers_release(&g_device->size_modifiers_by_dim[2]);
+ htable_size_modifiers_release(&g_device->size_modifiers_by_dim[3]);
if(log) {
- logger_print(dev->logger, log_type, "End finalizing scad.\n");
+ logger_print(g_device->logger, log_type, "End finalizing scad.\n");
}
- MEM_RM(dev->allocator, dev);
- htable_geometries_release(&tmp);
- if(dev->options.Misc.DebugEmptyContext) {
+ if(option_dec) {
/* After releasing all star-cad stuff, gmsh and OCC contexts must be empty */
- return check_empty_gmsh_occ(dev);
+ res = check_empty_gmsh_occ(g_device);
}
+ MEM_RM(allocator, g_device);
+ g_device = NULL;
+
return res;
}
@@ -123,11 +136,6 @@ log_message(struct scad_device* dev, const char* msg, ...)
}
/*******************************************************************************
- * The unique device in scad-cad
- ******************************************************************************/
-static struct scad_device* g_device = NULL;
-
-/*******************************************************************************
* Exported scad_device functions
******************************************************************************/
res_T
@@ -661,8 +669,7 @@ exit:
return res;
error:
if(g_device) {
- device_release(g_device);
- g_device = NULL;
+ device_release();
}
goto exit;
}
@@ -690,8 +697,7 @@ scad_finalize
"Finalizing scad; undeleted tags will be automatically unregistered.\n");
}
- tmp_res = device_release(g_device);
- g_device = NULL;
+ tmp_res = device_release();
gmshFinalize(&ierr);
ERR(gmsh_err_to_res_T(ierr));
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -654,7 +654,8 @@ scad_scene_clear
}
while(!htable_geometries_iterator_eq(&it, &end)) {
struct scad_geometry* geom = *htable_geometries_iterator_key_get(&it);
- while(geom->ref > 0) {
+ long cpt = geom->ref;
+ while(cpt-- > 0) {
ERR(scad_geometry_ref_put(geom));
}
htable_geometries_iterator_next(&it);
@@ -2012,7 +2013,7 @@ scad_geometries_common_boundaries
c = tagoutn / 2;
if(tagoutn == 0) {
- log_message(dev, "Common boundary list is empty.\n");
+ log_message(dev, "Common boundaries list is empty.\n");
goto exit;
}
@@ -2087,8 +2088,8 @@ exit:
error:
if(ierr) {
int dim = INT_MAX;
- if(!mixed_dim_err_msg("common boundary", geometries, geometries_count, &dim))
- mixed_dim_err_msg("common boundary", tools, tools_count, &dim);
+ if(!mixed_dim_err_msg("common boundaries", geometries, geometries_count, &dim))
+ mixed_dim_err_msg("common boundaries", tools, tools_count, &dim);
}
if(out_geom) {
for(i = 0; i < c; i++) {
@@ -2103,6 +2104,134 @@ error:
}
res_T
+scad_geometries_common_boundary
+ (struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_boundary)
+{
+ res_T res = RES_OK;
+ int* tagout = NULL;
+ size_t tagoutn, sz1, sz2, u_sz;
+ int* data1 = NULL;
+ int* data2 = NULL;
+ int* unique = NULL;
+ int ierr = 0;
+ int* bound1 = NULL;
+ int* bound2 = NULL;
+ size_t n1, n2;
+ struct scad_geometry* out_geom = NULL;
+ struct mem_allocator* allocator = NULL;
+ struct scad_device* dev = get_device();
+ int log;
+ enum log_type log_type;
+ size_t i, n;
+ struct str msg;
+ int msg_initialized = 0;
+
+ if(!geometries || !geometries_count || !tools || !tools_count || !out_boundary) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ERR(check_device(FUNC_NAME));
+ allocator = dev->allocator;
+
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, &data2, &sz2));
+
+ /* data1 and data2 can have tags in common: deduplicate them!
+ * (even if the refcounting stuff can manage duplicates) */
+ ERR(process_tag_list(data1, sz1, data2, sz2, UNIQUE_TAGS, &unique, &u_sz));
+
+ ERR(sync_device());
+ gmshModelGetBoundary(data1, sz1, &bound1, &n1, 1, 0, 0, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+ gmshModelGetBoundary(data2, sz2, &bound2, &n2, 1, 0, 0, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+
+ ERR(process_tag_list(bound1, n1, bound2, n2, COMMON_TAGS, &tagout, &tagoutn));
+ ASSERT(tagoutn % 2 == 0);
+
+ if(tagoutn == 0) {
+ log_message(dev, "Common boundary list is empty.\n");
+ } else {
+ log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
+ log_type = dev->log_type;
+ if(log) {
+ str_init(allocator, &msg);
+ msg_initialized = 1;
+ logger_print(dev->logger, log_type,
+ "Common boundary specific tag management:\n");
+ ERR(str_printf(&msg, " tags ["));
+ for(i = 0; i < tagoutn; i += 2) {
+ const int dim = tagout[i];
+ const int tag = tagout[i+1];
+ ERR(str_append_printf(&msg, (i ? ", %d.%d" : "%d.%d"), dim, tag));
+ }
+ ERR(str_append_printf(&msg, "] getting a ref to tags ["));
+ for(i = 0; i < u_sz; i += 2) {
+ const int dim = unique[i];
+ const int tag = unique[i+1];
+ ERR(str_append_printf(&msg, (i ? ", %d.%d" : "%d.%d"), dim, tag));
+ }
+ logger_print(dev->logger, log_type, "%s].\n", str_cget(&msg));
+ }
+ }
+
+ ERR(geometry_create(&out_geom));
+ out_geom->gmsh_dimTags_n = tagoutn;
+ out_geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout));
+ if(!out_geom->gmsh_dimTags) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ memcpy(out_geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout));
+ ERR(device_register_tags(out_geom));
+
+ for(i = 0, n = 0; i < tagoutn; i += 2, n++) {
+ int dim = tagout[i];
+ int tag = tagout[i+1];
+ struct tag_desc* desc = device_get_description(dim, tag);
+ ASSERT(desc);
+ ASSERT(dim == 2);
+ /* Need to protect out_geometry's tags by getting a ref on input tags or
+ * deleting input geometry will possibly delete them */
+ ERR(device_register_ref_to_tags(dim, tag, unique, u_sz));
+ /* As the 2D tags will be deleted when the 3D tag they are part of are
+ * deleted, they shouldn't be deleted when the geometry they belongs to are
+ * released. */
+ desc->delete_policy = Scad_do_not_delete;
+ }
+
+exit:
+ if(msg_initialized) str_release(&msg);
+ if(out_boundary) *out_boundary = out_geom;
+ if(allocator) {
+ MEM_RM(allocator, data1);
+ MEM_RM(allocator, data2);
+ MEM_RM(allocator, unique);
+ MEM_RM(allocator, tagout);
+ }
+ gmshFree(bound1);
+ gmshFree(bound2);
+ return res;
+error:
+ if(ierr) {
+ int dim = INT_MAX;
+ if(!mixed_dim_err_msg("common boundary", geometries, geometries_count, &dim))
+ mixed_dim_err_msg("common boundary", tools, tools_count, &dim);
+ }
+ if(out_geom) {
+ SCAD(geometry_ref_put(out_geom));
+ out_geom = NULL;
+ }
+ if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ goto exit;
+}
+
+res_T
scad_geometry_rotate
(const struct scad_geometry* geom,
const double pt[3],
@@ -3022,6 +3151,101 @@ error:
goto exit;
}
+
+res_T
+scad_geometries_boundary
+ (struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** out_boundary)
+{
+ res_T res = RES_OK;
+ int* tagout = NULL;
+ size_t tagoutn, sz;
+ int* data = NULL;
+ int ierr = 0;
+ struct scad_geometry* out_geom = NULL;
+ struct mem_allocator* allocator = NULL;
+ struct scad_device* dev = get_device();
+ int log;
+ enum log_type log_type;
+ size_t i;
+ struct str msg;
+ int msg_initialized = 0;
+
+ if(!geometries || geometries_count == 0 || !out_boundary) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ERR(check_device(FUNC_NAME));
+ allocator = dev->allocator;
+
+ ERR(gather_tags(geometries, geometries_count, &data, &sz));
+ ERR(sync_device());
+ gmshModelGetBoundary(data, sz, &tagout, &tagoutn, 1, 0, 0, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+ ASSERT(tagoutn % 2 == 0);
+
+ log = (dev->options.Misc.LogRefCounting & SCAD_LOG_DIMTAGS_ALL);
+ log_type = dev->log_type;
+ if(log) {
+ str_init(allocator, &msg);
+ msg_initialized = 1;
+ logger_print(dev->logger, log_type, "Boundary specific tag management:\n");
+ ERR(str_printf(&msg, " tags ["));
+ for(i = 0; i < tagoutn; i += 2) {
+ const int dim = tagout[i];
+ const int tag = tagout[i+1];
+ ERR(str_append_printf(&msg, (i ? ", %d.%d" : "%d.%d"), dim, tag));
+ }
+ ERR(str_append_printf(&msg, "] getting a ref to tags ["));
+ for(i = 0; i < sz; i += 2) {
+ const int dim = data[i];
+ const int tag = data[i+1];
+ ERR(str_append_printf(&msg, (i ? ", %d.%d" : "%d.%d"), dim, tag));
+ }
+ logger_print(dev->logger, log_type, "%s].\n", str_cget(&msg));
+ }
+
+ ERR(geometry_create(&out_geom));
+ out_geom->gmsh_dimTags_n = tagoutn;
+ out_geom->gmsh_dimTags = MEM_ALLOC(allocator, tagoutn * sizeof(*tagout));
+ if(!out_geom->gmsh_dimTags) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ memcpy(out_geom->gmsh_dimTags, tagout, tagoutn * sizeof(*tagout));
+ ERR(device_register_tags(out_geom));
+ for(i = 0; i < out_geom->gmsh_dimTags_n; i += 2) {
+ const int dim = out_geom->gmsh_dimTags[i];
+ const int tag = out_geom->gmsh_dimTags[i+1];
+ struct tag_desc* desc = device_get_description(dim, tag);
+ ASSERT(dim == 2);
+ ASSERT(desc != NULL);
+ /* Need to protect input geometry's tags by getting a ref on output tags or
+ * deleting out_geometry will possibly delete them */
+ ERR(device_register_ref_to_tags(dim, tag, data, sz));
+ /* As the 2D tags will be deleted when the 3D tag they are part of are
+ * deleted, they shouldn't be deleted when the geometry they belongs to is
+ * released. */
+ desc->delete_policy = Scad_do_not_delete;
+ }
+
+exit:
+ if(msg_initialized) str_release(&msg);
+ if(allocator) MEM_RM(allocator, data);
+ if(out_boundary) *out_boundary = out_geom;
+ gmshFree(tagout);
+ return res;
+error:
+ if(out_geom) {
+ SCAD(geometry_ref_put(out_geom));
+ out_geom = NULL;
+ }
+ if(tagout) gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ goto exit;
+}
+
res_T
scad_step_import
(const char* filename,
@@ -3389,8 +3613,8 @@ scad_geometries_set_periodic
}
allocator = dev->allocator;
- src_tags = MEM_ALLOC(allocator, src_tagsn);
- tgt_tags = MEM_ALLOC(allocator, tgt_tagsn);
+ src_tags = MEM_ALLOC(allocator, src_tagsn * sizeof(*src_tags));
+ tgt_tags = MEM_ALLOC(allocator, tgt_tagsn * sizeof(*tgt_tags));
if(!src_tags || !tgt_tags) {
res = RES_MEM_ERR;
goto error;
diff --git a/src/test_api.c b/src/test_api.c
@@ -134,7 +134,9 @@ main(int argc, char* argv[])
BAD(scad_geometries_intersect(&geom1, 1, &geom2, 1, &geom));
BAD(scad_geometries_partition(&geom1, 1, 0, &geom));
BAD(scad_geometries_common_boundaries(&geom1, 1, &geom2, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundary(&geom1, 1, &geom2, 1, &geom));
BAD(scad_geometries_boundaries(&geom1, 1, &geom_array, &c));
+ BAD(scad_geometries_boundary(&geom1, 1, &geom));
BAD(scad_geometry_copy(geom1, &geom2));
BAD(scad_geometry_set_visibility(geom1, 0, 0));
BAD(scad_geometries_set_periodic(&geom1, 1, &geom2, 1, affine));
@@ -202,7 +204,9 @@ main(int argc, char* argv[])
BAD(scad_geometries_intersect(&geom1, 1, &geom2, 1, &geom));
BAD(scad_geometries_partition(&geom1, 1, 0, &geom));
BAD(scad_geometries_common_boundaries(&geom1, 1, &geom2, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundary(&geom1, 1, &geom2, 1, &geom));
BAD(scad_geometries_boundaries(&geom1, 1, &geom_array, &c));
+ BAD(scad_geometries_boundary(&geom1, 1, &geom));
BAD(scad_geometry_copy(geom1, &geom2));
BAD(scad_geometry_set_visibility(geom1, 0, 0));
BAD(scad_geometries_set_periodic(&geom1, 1, &geom2, 1, affine));
@@ -1265,11 +1269,71 @@ main(int argc, char* argv[])
OK(scad_geometries_swap(geoms, out_geoms, 2, SCAD_SWAP_GEOMETRY));
OK(scad_geometry_ref_put(out_geoms[0]));
OK(scad_geometry_ref_put(out_geoms[1]));
- BAD(scad_geometries_common_boundaries(geoms, 2, NULL, 0, &geom_array, &c));
+
+
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 1, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, NULL, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 1, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 0, geoms+1, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 1, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, NULL, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 1, &geom_array, NULL));
BAD(scad_geometries_common_boundaries(NULL, 1, geoms+1, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 1, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, NULL, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 1, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 0, geoms+1, 1, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 1, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 1, &geom_array, NULL));
BAD(scad_geometries_common_boundaries(geoms, 1, NULL, 1, &geom_array, &c));
- BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 1, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 0, NULL, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 0, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 0, &geom_array, NULL));
+ BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 0, &geom_array, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 1, NULL, NULL));
BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 1, NULL, &c));
+ BAD(scad_geometries_common_boundaries(geoms, 1, geoms+1, 1, &geom_array, NULL));
OK(scad_geometries_common_boundaries(geoms, 1, geoms+1, 1, &geom_array, &c));
CHK(c == 0);
MEM_RM(&allocator, geom_array);
@@ -1315,6 +1379,51 @@ main(int argc, char* argv[])
OK(scad_scene_count(&c));
CHK(c == 0);
+ OK(scad_add_sphere(p1, 0.1, &geoms[0]));
+ OK(scad_add_sphere(p3, 0.1, &geoms[1]));
+ OK(scad_geometries_partition(geoms, 2, SCAD_ALLOW_OVERLAPPING, out_geoms));
+ OK(scad_geometries_swap(geoms, out_geoms, 2, SCAD_SWAP_GEOMETRY));
+ OK(scad_geometry_ref_put(out_geoms[0]));
+ OK(scad_geometry_ref_put(out_geoms[1]));
+ BAD(scad_geometries_common_boundary(NULL, 0, NULL, 0, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 0, NULL, 0, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 0, NULL, 1, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 0, NULL, 1, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 0, geoms+1, 0, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 0, geoms+1, 0, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 0, geoms+1, 1, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 0, geoms+1, 1, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 1, NULL, 0, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 1, NULL, 0, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 1, NULL, 1, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 1, NULL, 1, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 1, geoms+1, 0, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 1, geoms+1, 0, &geom));
+ BAD(scad_geometries_common_boundary(NULL, 1, geoms+1, 1, NULL));
+ BAD(scad_geometries_common_boundary(NULL, 1, geoms+1, 1, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 0, NULL, 0, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 0, NULL, 0, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 0, NULL, 1, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 0, NULL, 1, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 0, geoms+1, 0, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 0, geoms+1, 0, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 0, geoms+1, 1, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 0, geoms+1, 1, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 1, NULL, 0, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 1, NULL, 0, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 1, NULL, 1, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 1, NULL, 1, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 1, geoms+1, 0, NULL));
+ BAD(scad_geometries_common_boundary(geoms, 1, geoms+1, 0, &geom));
+ BAD(scad_geometries_common_boundary(geoms, 1, geoms+1, 1, NULL));
+ OK(scad_geometries_common_boundary(geoms, 1, geoms+1, 1, &geom));
+ OK(scad_geometry_ref_put(geoms[0]));
+ OK(scad_geometry_ref_put(geoms[1]));
+ OK(scad_geometry_ref_put(geom));
+
+ OK(scad_scene_count(&c));
+ CHK(c == 0);
+
OK(scad_add_sphere(p1, 0.1, &geom1));
BAD(scad_geometries_boundaries(NULL, 0, NULL, NULL));
BAD(scad_geometries_boundaries(NULL, 0, NULL, &c));
@@ -1332,6 +1441,7 @@ main(int argc, char* argv[])
BAD(scad_geometries_boundaries(&geom1, 0, &geom_array, &c));
BAD(scad_geometries_boundaries(NULL, 1, &geom_array, &c));
OK(scad_geometries_boundaries(&geom1, 1, &geom_array, &c));
+ CHK(c == 1);
for(i = 0; i < c; i++) {
OK(scad_geometry_ref_put(geom_array[i]));
}
@@ -1342,6 +1452,21 @@ main(int argc, char* argv[])
CHK(c == 0);
OK(scad_add_sphere(p1, 0.1, &geom1));
+ BAD(scad_geometries_boundary(NULL, 0, NULL));
+ BAD(scad_geometries_boundary(NULL, 0, &geom));
+ BAD(scad_geometries_boundary(NULL, 1, NULL));
+ BAD(scad_geometries_boundary(&geom1, 0, NULL));
+ BAD(scad_geometries_boundary(NULL, 1, &geom));
+ BAD(scad_geometries_boundary(&geom1, 0, &geom));
+ BAD(scad_geometries_boundary(&geom1, 1, NULL));
+ OK(scad_geometries_boundary(&geom1, 1, &geom));
+ OK(scad_geometry_ref_put(geom1));
+ OK(scad_geometry_ref_put(geom));
+
+ OK(scad_scene_count(&c));
+ CHK(c == 0);
+
+ OK(scad_add_sphere(p1, 0.1, &geom1));
BAD(scad_geometry_copy(NULL, &geom));
BAD(scad_geometry_copy(geom1, NULL));
OK(scad_geometry_copy(geom1, &geom));
diff --git a/src/test_sync.c b/src/test_sync.c
@@ -133,7 +133,6 @@ main(int argc, char* argv[])
OK(scad_stl_get_data(geom, &trg));
c = darray_double_size_get(&trg);
darray_double_clear(&trg);
- printf("%ld trg\n", c/9);
OK(scad_geometries_clear_mesh(&geom, 1));
OK(scad_stl_get_data(geom, &trg));
@@ -142,7 +141,6 @@ main(int argc, char* argv[])
OK(scad_geometries_set_mesh_size_modifier(&geom, 1, SCAD_SIZE_FACTOR, 0.25));
OK(scad_scene_mesh());
OK(scad_stl_get_data(geom, &trg));
- printf("%ld trg\n", darray_double_size_get(&trg)/9);
CHK(c < darray_double_size_get(&trg));
darray_double_release(&trg);
OK(scad_geometry_ref_put(geom));