star-cad

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

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:
Msrc/scad.h | 17+++++++++++++++++
Msrc/scad_geometry.c | 208++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
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,