commit 15b3a36c563d9851b3e9718bc675bc182880afa0
parent 8d5936d783ab11fa6f293c985753373d345d704a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 10 Oct 2025 10:16:41 +0200
Rename scad_geometries_boundary API call
New name is scad_geometries_boundaries, to be consistent with
scad_geometries_common_boundaries.
Diffstat:
7 files changed, 226 insertions(+), 30 deletions(-)
diff --git a/src/scad.h b/src/scad.h
@@ -563,7 +563,7 @@ scad_geometries_partition
const int flags,
struct scad_geometry** out_geometries);
-/* compute boundary intersection (the common part) of the geometries in
+/* Compute boundaries' intersection (the common part) of the geometries in
* `geometries' and `tools'.
* The output geometries are created unnamed.
* The result `out_boundaries' being allocated using the allocator provided when
@@ -581,12 +581,12 @@ scad_geometries_common_boundaries
struct scad_geometry*** out_boundaries,
size_t *out_count);
-/* Get the boundary of the geometries in `geometries', considered as a whole.
+/* 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
* initializing star-cad, it should be freed accordingly. */
SCAD_API res_T
-scad_geometries_boundary
+scad_geometries_boundaries
(struct scad_geometry** geometries,
const size_t geometries_count,
struct scad_geometry*** out_boundaries,
@@ -697,8 +697,8 @@ scad_stl_export_partial
const int binary);
/* Export the geometry `geometry' in as many files than its count.
- * The files are named <base>_<rank>.stl, where <base> is either filename (first
- * choice) or geom's name, <rank> counting from 0. */
+ * The files are named <base>_<rank>.stl, where <base> is either `filename'
+ * (first choice) or `geometry's name, <rank> counting from 0. */
SCAD_API res_T
scad_stl_export_split
(struct scad_geometry* geometry,
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -2912,7 +2912,7 @@ error:
}
res_T
-scad_geometries_boundary
+scad_geometries_boundaries
(struct scad_geometry** geometries,
const size_t geometries_count,
struct scad_geometry*** out_boundaries,
diff --git a/src/test_api.c b/src/test_api.c
@@ -134,7 +134,7 @@ 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_boundary(&geom1, 1, &geom_array, &c));
+ BAD(scad_geometries_boundaries(&geom1, 1, &geom_array, &c));
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 +202,7 @@ 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_boundary(&geom1, 1, &geom_array, &c));
+ BAD(scad_geometries_boundaries(&geom1, 1, &geom_array, &c));
BAD(scad_geometry_copy(geom1, &geom2));
BAD(scad_geometry_set_visibility(geom1, 0, 0));
BAD(scad_geometries_set_periodic(&geom1, 1, &geom2, 1, affine));
@@ -1316,22 +1316,22 @@ main(int argc, char* argv[])
CHK(c == 0);
OK(scad_add_sphere(p1, 0.1, &geom1));
- BAD(scad_geometries_boundary(NULL, 0, NULL, NULL));
- BAD(scad_geometries_boundary(NULL, 0, NULL, &c));
- BAD(scad_geometries_boundary(NULL, 0, &geom_array, NULL));
- BAD(scad_geometries_boundary(NULL, 1, NULL, NULL));
- BAD(scad_geometries_boundary(&geom1, 0, NULL, NULL));
- BAD(scad_geometries_boundary(NULL, 0, &geom_array, &c));
- BAD(scad_geometries_boundary(NULL, 1, NULL, &c));
- BAD(scad_geometries_boundary(&geom1, 0, NULL, &c));
- BAD(scad_geometries_boundary(NULL, 1, &geom_array, NULL));
- BAD(scad_geometries_boundary(&geom1, 0, &geom_array, NULL));
- BAD(scad_geometries_boundary(&geom1, 1, NULL, NULL));
- BAD(scad_geometries_boundary(&geom1, 1, &geom_array, NULL));
- BAD(scad_geometries_boundary(&geom1, 1, NULL, &c));
- BAD(scad_geometries_boundary(&geom1, 0, &geom_array, &c));
- BAD(scad_geometries_boundary(NULL, 1, &geom_array, &c));
- OK(scad_geometries_boundary(&geom1, 1, &geom_array, &c));
+ BAD(scad_geometries_boundaries(NULL, 0, NULL, NULL));
+ BAD(scad_geometries_boundaries(NULL, 0, NULL, &c));
+ BAD(scad_geometries_boundaries(NULL, 0, &geom_array, NULL));
+ BAD(scad_geometries_boundaries(NULL, 1, NULL, NULL));
+ BAD(scad_geometries_boundaries(&geom1, 0, NULL, NULL));
+ BAD(scad_geometries_boundaries(NULL, 0, &geom_array, &c));
+ BAD(scad_geometries_boundaries(NULL, 1, NULL, &c));
+ BAD(scad_geometries_boundaries(&geom1, 0, NULL, &c));
+ BAD(scad_geometries_boundaries(NULL, 1, &geom_array, NULL));
+ BAD(scad_geometries_boundaries(&geom1, 0, &geom_array, NULL));
+ BAD(scad_geometries_boundaries(&geom1, 1, NULL, NULL));
+ BAD(scad_geometries_boundaries(&geom1, 1, &geom_array, NULL));
+ BAD(scad_geometries_boundaries(&geom1, 1, NULL, &c));
+ 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));
for(i = 0; i < c; i++) {
OK(scad_geometry_ref_put(geom_array[i]));
}
diff --git a/src/test_lifetime.c b/src/test_lifetime.c
@@ -78,7 +78,7 @@ main(int argc, char* argv[])
/* Check that 2D constituants of a deleted 3D object are alive and well */
OK(scad_add_box(p1, diago, &geom));
- OK(scad_geometries_boundary(&geom, 1, &list, &list_n));
+ OK(scad_geometries_boundaries(&geom, 1, &list, &list_n));
OK(scad_geometries_set_name(list, list_n, "boundary", 0));
OK(scad_geometry_ref_put(geom));
for(i = 0; i < list_n; i++) {
@@ -90,7 +90,7 @@ main(int argc, char* argv[])
OK(scad_add_rectangle(p1, base, &geom));
OK(scad_geometry_extrude(geom, dir1, &geom1));
OK(scad_geometry_ref_put(geom));
- OK(scad_geometries_boundary(&geom1, 1, &list, &list_n));
+ OK(scad_geometries_boundaries(&geom1, 1, &list, &list_n));
OK(scad_geometries_set_name(list, list_n, "boundary", 0));
OK(scad_geometry_ref_put(geom1));
for(i = 0; i < list_n; i++) {
@@ -105,7 +105,7 @@ main(int argc, char* argv[])
alive_and_well(geom, &allocator);
OK(scad_add_box(p1, diago, &geom1));
- OK(scad_geometries_boundary(&geom1, 1, &list, &list_n));
+ OK(scad_geometries_boundaries(&geom1, 1, &list, &list_n));
OK(scad_geometries_set_name(list, list_n, "bcavity", 0));
for(i = 0; i < list_n; i++) {
OK(scad_geometry_get_count(list[i], ¢er_n));
@@ -124,8 +124,8 @@ main(int argc, char* argv[])
* a partition */
OK(scad_add_box(p1, diago, geoms+0));
OK(scad_add_box(p1, diago_, geoms+1));
- OK(scad_geometries_boundary(geoms+0, 1, &list, &list_n));
- OK(scad_geometries_boundary(geoms+1, 1, &list2, &list_n2));
+ OK(scad_geometries_boundaries(geoms+0, 1, &list, &list_n));
+ OK(scad_geometries_boundaries(geoms+1, 1, &list2, &list_n2));
OK(scad_geometries_partition(geoms, 2, 0, out_geoms));
OK(scad_geometry_ref_put(geoms[0]));
OK(scad_geometry_ref_put(geoms[1]));
diff --git a/src/test_normals.c b/src/test_normals.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2022 |Meso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "scad.h"
+#include "scad_geometry.h"
+#include "test_common.h"
+
+#include <rsys/rsys.h>
+#include <rsys/str.h>
+#include <rsys/math.h>
+#include <rsys/mem_allocator.h>
+#include <rsys/dynamic_array_double.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+int
+main(int argc, char* argv[])
+{
+ res_T res = RES_OK;
+ double p1[3] = {0, 0, 0};
+ double s1[3] = {1, 1, 0};
+ double c[3] = {0.5, 0.5, 0};
+ double scale[3] = {0.5, 0.5, 0.5};
+ double d1[3] = {0, 0, 1};
+ double d1_[3] = {0, 0, -1};
+ double m1, m2;
+ struct scad_geometry* base = NULL;
+ struct scad_geometry* sbase = NULL;
+ struct scad_geometry* geom1 = NULL;
+ struct scad_geometry* geom2 = NULL;
+ struct scad_geometry* geoms[2];
+ struct scad_geometry* part[2];
+ struct mem_allocator allocator;
+ struct scad_options options = SCAD_DEFAULT_OPTIONS;
+ struct darray_double trg;
+
+ (void)argc; (void)argv;
+
+ OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
+ darray_double_init(&allocator, &trg);
+ OK(scad_initialize(NULL, &allocator, 3));
+ OK(scad_set_options(NULL));
+ OK(scad_set_options(&options));
+
+ OK(scad_add_rectangle("base", p1, s1, &base));
+ OK(scad_geometry_extrude(base, "top", d1, &geom1));
+ OK(scad_geometry_get_mass(geom1, &m1));
+
+ OK(scad_geometry_dilate(base, c, scale, "small_base", &sbase));
+ OK(scad_geometry_extrude(sbase, "bottom", d1_, &geom2));
+ OK(scad_geometry_get_mass(geom2, &m2));
+
+ geoms[0] = geom1;
+ geoms[1] = geom2;
+ OK(scad_synchronize());
+ OK(scad_geometries_partition(geoms, 2, 0, part));
+ OK(scad_synchronize());
+ OK(scad_scene_mesh());
+ OK(scad_synchronize());
+
+ CHK(eq_eps(m1, 1, 1e-10));
+ CHK(eq_eps(m2, 0.25, 1e-10));
+
+ OK(scad_stl_export(part[0], "/tmp/geom1", SCAD_FORCE_NORMALS_OUTWARD, 0));
+ OK(scad_stl_export(part[1], "/tmp/geom2", SCAD_FORCE_NORMALS_OUTWARD, 0));
+
+ OK(scad_stl_get_data(geom2, &trg));
+ OK(scad_stl_data_write(&trg, "/tmp/test", 0, 0));
+ OK(scad_stl_data_write(&trg, "/tmp/test", 1, 1));
+
+ OK(scad_stl_export(geom2, "/tmp/test", SCAD_FORCE_NORMALS_OUTWARD, 0));
+ OK(scad_stl_export(geom2, "/tmp/test", SCAD_FORCE_NORMALS_OUTWARD, 1));
+ OK(scad_stl_export(geom1, NULL, SCAD_FORCE_NORMALS_OUTWARD, 0));
+ OK(scad_stl_export(geom1, NULL, SCAD_FORCE_NORMALS_OUTWARD, 1));
+
+ OK(scad_finalize());
+ darray_double_release(&trg);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+
+ return (res == RES_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/test_periodic.c b/src/test_periodic.c
@@ -52,7 +52,7 @@ main(int argc, char* argv[])
OK(scad_geometries_cut(&cyl2, 1, &cyl1, 1, &cyl));
OK(scad_geometry_ref_put(cyl1));
OK(scad_geometry_ref_put(cyl2));
- OK(scad_geometries_boundary(&cyl, 1, &faces, &facesn));
+ OK(scad_geometries_boundaries(&cyl, 1, &faces, &facesn));
ASSERT(facesn == 4);
d3_add(p2, p1, d2);
len = d3_len(d2);
diff --git a/src/test_tolerance.c b/src/test_tolerance.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2022-2024 |Méso|Star> (contact@meso-star.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#define _POSIX_C_SOURCE 200112L
+
+#include "scad.h"
+#include "scad_geometry.h"
+#include "test_common.h"
+
+#include <rsys/rsys.h>
+#include <rsys/math.h>
+#include <rsys/mem_allocator.h>
+#include <rsys/double3.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/*
+ * +-------+ +-------+ +------+
+ * | | +----+ | +----+ | +----+
+ * | | | | | | | | || |
+ * | | +----+ | +----+ | +----+
+ * +-------+ +-------+ +------+
+ * x = 1.1 x = 1 x = 0.9
+ */
+
+static int
+tolerance
+ (double x,
+ double tol,
+ size_t expected_count,
+ struct mem_allocator* allocator)
+{
+ double p1[3] = {0, 0, 0};
+ double d[3] = {1, 1, 1};
+ double p2[3];
+ struct scad_geometry* geoms[2];
+ struct scad_geometry* out_geom;
+ size_t c;
+
+ ASSERT(tol > 0 && (expected_count == 1 || expected_count == 2));
+
+ OK(scad_initialize(NULL, allocator, 3));
+
+ /* set position for cube #2 */
+ d3(p2, x, 0, 0);
+
+ OK(scad_add_box("cube1", p1, d, geoms+0));
+ OK(scad_add_box("cube2", p2, d, geoms+1));
+
+ /* Try to fuse the 2 cubes and count resulting connex components */
+ OK(scad_fuse_geometries("fused", geoms, 1, geoms+1, 1, &out_geom));
+ OK(scad_geometry_get_count(out_geom, &c));
+
+ OK(scad_finalize());
+
+ return (c == expected_count) ? RES_OK : RES_BAD_ARG;
+}
+
+int
+main(int argc, char* argv[])
+{
+ struct mem_allocator allocator;
+ res_T res = RES_OK;
+
+ (void)argc; (void)argv;
+
+ OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
+
+ /* With contacting geometries */
+ OK(tolerance(1, 0.01, 1, &allocator));
+ OK(tolerance(1, 0.1, 1, &allocator));
+
+ /* With overlapping geometries */
+ OK(tolerance(0.9, 0.01, 1, &allocator));
+ OK(tolerance(0.9, 0.1, 1, &allocator));
+
+ /* With distant geometries */
+ OK(tolerance(1.1, 0.01, 2, &allocator));
+ OK(tolerance(1.1, 0.1, 1, &allocator));
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+
+ return (res == RES_OK) ? EXIT_SUCCESS : EXIT_FAILURE;
+}