commit 4a3ae9f33326829ae5e52efb1eb0f275a58b9b63
parent 9091d955c1d2c520c31c48a3242b1cae3d10e01d
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 2 Sep 2022 18:11:33 +0200
Add an API function to help partition geometries from a loop
Diffstat:
2 files changed, 138 insertions(+), 87 deletions(-)
diff --git a/src/scad.h b/src/scad.h
@@ -231,6 +231,23 @@ scad_geometries_partition
const int allow_overlapping,
struct scad_geometry** out_geometry);
+/* Compute the boolean fragments (general fuse) resulting from the
+ * intersection of the geometry `geometries[not_tool_index]' and the other
+ * geometries in `geometries' used as tools, making all interfaces conformal.
+ * This function may be best suited than scad_geometries_partition when used
+ * from a loop.
+ * When applied to geometries of different dimensions, the lower dimensional
+ * geometries will be automatically embedded in the higher dimensional
+ * geometries if they are not on their boundary. */
+SCAD_API res_T
+scad_geometries_partition_one
+ (const char* name, /* Can be NULL */
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ const size_t not_tool_index,
+ const int allow_overlapping,
+ struct scad_geometry** out_geometry);
+
/* Get the boundary of the geometry `geom'. */
SCAD_API res_T
scad_geometry_boundary
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -91,6 +91,7 @@ static res_T
gather_tags
(struct scad_geometry** geometries,
const size_t geometries_count,
+ const size_t except, /* if not SIZE_MAX, this one is not gathered */
int** out_dimTags,
size_t* out_dimTags_n)
{
@@ -99,6 +100,7 @@ gather_tags
size_t i, j, c, sz;
ASSERT(geometries && geometries_count && out_dimTags && out_dimTags_n);
+ ASSERT(except == SIZE_MAX || except < geometries_count);
for(sz = 0, i = 0; i < geometries_count; i++) {
sz += geometries[i]->gmsh_dimTags_n;
@@ -109,6 +111,7 @@ gather_tags
goto error;
}
for(i = 0, c = 0; i < geometries_count; i++) {
+ if(i == except) continue;
for(j = 0; j < geometries[i]->gmsh_dimTags_n; j++, c++) {
tags[c] = geometries[i]->gmsh_dimTags[j];
}
@@ -123,6 +126,97 @@ error:
goto exit;
}
+static res_T
+scad_geometries_partition_core
+ (const char* name,
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ const size_t except,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ const int allow_overlapping,
+ struct scad_geometry** out_geometry)
+{
+ int* tagout = NULL;
+ int** map = NULL;
+ size_t* mapn = NULL;
+ size_t tagoutn = 0, mapnn, sz1, sz2 = 0;
+ int* data1 = NULL;
+ int* data2 = NULL;
+ int ierr = 0;
+ struct scad_geometry* geom = NULL;
+ res_T res = RES_OK;
+
+ if(!geometries || !out_geometry) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ERR(check_device());
+ if(get_device()->need_synchro) {
+ ERR(scad_synchronize());
+ }
+
+ ERR(gather_tags(geometries, geometries_count, except, &data1, &sz1));
+ if(tools) {
+ ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
+ }
+
+ /* We don't remove gmsh objects here; they are only removed when their tags are
+ * no longuer used by any star-cad geometry */
+ gmshModelOccFragment(data1, sz1, data2, sz2, &tagout, &tagoutn, &map, &mapn,
+ &mapnn, -1, 0, 0, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+ ASSERT(sz1 + sz2 == 2*mapnn);
+ if(!allow_overlapping) {
+ /* Each tag in geometries must have been translated to a single tag in map */
+ size_t i, err;
+ for(i = 0, err = SIZE_MAX; i < mapnn; i++) {
+ int dim = (2*i >= sz1) ? data2[i*2-sz1] : data1[i*2];
+ int tag = (2*i >= sz1) ? data2[i*2+1-sz1] : data1[i*2+1];
+ if(mapn[i] != 2) {
+ err = i;
+ break;
+ }
+ ASSERT(dim == map[i][0]); (void)dim; (void)tag;
+ }
+ if(err != SIZE_MAX) {
+ struct scad_geometry* problem = geometries[err];
+ res = RES_BAD_ARG;
+ if(str_is_empty(&problem->name)) {
+ log_error(get_device(), "Unnamed geometry overlapping tools.\n");
+ } else {
+ log_error(get_device(), "Geometry '%s' overlapping tools.\n",
+ str_cget(&problem->name));
+ }
+ goto error;
+ }
+ }
+
+ ERR(scad_geometry_create(name, &geom));
+ geom->gmsh_dimTags_n = tagoutn;
+ geom->gmsh_dimTags = tagout;
+
+ ERR(device_register_tags(geom));
+
+exit:
+ *out_geometry = geom;
+ if(data1) free(data1);
+ if(data2) free(data2);
+ if(mapn) free(mapn);
+ if(map) free(map);
+ return res;
+error:
+ if(geom) {
+ CHK(RES_OK == geometry_release(geom));
+ geom = NULL;
+ }
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
+ goto exit;
+}
/*******************************************************************************
* Local functions
******************************************************************************/
@@ -539,8 +633,8 @@ scad_fuse_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -601,8 +695,8 @@ scad_cut_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -663,8 +757,8 @@ scad_intersect_geometries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -728,8 +822,8 @@ scad_geometries_common_boundaries
ERR(scad_synchronize());
}
- ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
- ERR(gather_tags(tools, tools_count, &data2, &sz2));
+ ERR(gather_tags(geometries, geometries_count, SIZE_MAX, &data1, &sz1));
+ ERR(gather_tags(tools, tools_count, SIZE_MAX, &data2, &sz2));
/* We don't remove gmsh objects here; they are only removed when their tags are
* no longuer used by any star-cad geometry */
@@ -938,6 +1032,22 @@ error:
}
res_T
+scad_geometries_partition_one
+ (const char* name, /* Can be NULL */
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ const size_t not_tool_index,
+ const int allow_overlapping,
+ struct scad_geometry** out_geometry)
+{
+ if(not_tool_index >= geometries_count)
+ return RES_BAD_ARG;
+ return scad_geometries_partition_core(name, geometries, geometries_count,
+ not_tool_index, geometries+not_tool_index, 1, allow_overlapping,
+ out_geometry);
+}
+
+res_T
scad_geometries_partition
(const char* name,
struct scad_geometry** geometries,
@@ -947,87 +1057,11 @@ scad_geometries_partition
const int allow_overlapping,
struct scad_geometry** out_geometry)
{
- int* tagout = NULL;
- int** map = NULL;
- size_t* mapn = NULL;
- size_t tagoutn = 0, mapnn, sz1, sz2 = 0;
- int* data1 = NULL;
- int* data2 = NULL;
- int ierr = 0;
- struct scad_geometry* geom = NULL;
- res_T res = RES_OK;
-
- if(!geometries || !out_geometry) {
- res = RES_BAD_ARG;
- goto error;
- }
-
- ERR(check_device());
- if(get_device()->need_synchro) {
- ERR(scad_synchronize());
- }
-
- ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
- if(tools) {
- ERR(gather_tags(tools, tools_count, &data2, &sz2));
- }
-
- /* We don't remove gmsh objects here; they are only removed when their tags are
- * no longuer used by any star-cad geometry */
- gmshModelOccFragment(data1, sz1, data2, sz2, &tagout, &tagoutn, &map, &mapn,
- &mapnn, -1, 0, 0, &ierr);
- ERR(gmsh_err_to_res_T(ierr));
- ASSERT(sz1 + sz2 == 2*mapnn);
- if(!allow_overlapping) {
- /* Each tag in geometries must have been translated to a single tag in map */
- size_t i, err;
- for(i = 0, err = SIZE_MAX; i < mapnn; i++) {
- int dim = (2*i >= sz1) ? data2[i*2-sz1] : data1[i*2];
- int tag = (2*i >= sz1) ? data2[i*2+1-sz1] : data1[i*2+1];
- if(mapn[i] != 2) {
- err = i;
- break;
- }
- ASSERT(dim == map[i][0]); (void)dim; (void)tag;
- }
- if(err != SIZE_MAX) {
- struct scad_geometry* problem = geometries[err];
- res = RES_BAD_ARG;
- if(str_is_empty(&problem->name)) {
- log_error(get_device(), "Unnamed geometry overlapping tools.\n");
- } else {
- log_error(get_device(), "Geometry '%s' overlapping tools.\n",
- str_cget(&problem->name));
- }
- goto error;
- }
- }
-
- ERR(scad_geometry_create(name, &geom));
- geom->gmsh_dimTags_n = tagoutn;
- geom->gmsh_dimTags = tagout;
-
- ERR(device_register_tags(geom));
-
-exit:
- *out_geometry = geom;
- if(data1) free(data1);
- if(data2) free(data2);
- if(mapn) free(mapn);
- if(map) free(map);
- return res;
-error:
- if(geom) {
- CHK(RES_OK == geometry_release(geom));
- geom = NULL;
- }
- if(tagout) {
- gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
- free(tagout);
- }
- goto exit;
+ return scad_geometries_partition_core(name, geometries, geometries_count,
+ SIZE_MAX, tools, tools_count, allow_overlapping, out_geometry);
}
+
res_T
scad_geometry_boundary
(const char* name,