commit 1a61e7a4d636fa754c5683c3024e572c4df05977
parent 83738eb1326404be7933accb4c3508cd9aa7a6c2
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Fri, 2 Sep 2022 17:19:46 +0200
Change API reflect groups removal
Internals change too, as the lifetime of gmsh entities is now implicitly managed by reference (from star-cad geometries)
Diffstat:
6 files changed, 514 insertions(+), 212 deletions(-)
diff --git a/src/scad.c b/src/scad.c
@@ -186,9 +186,14 @@ scad_synchronize
(void)
{
res_T res = RES_OK;
+ struct scad_device* dev = get_device();
int ierr;
- ERR(check_device());
+ /* Cannot use check_device to avoid an infinite loop! */
+ if(!dev) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
gmshModelOccSynchronize(&ierr);
get_device()->need_synchro = 0;
@@ -204,9 +209,18 @@ res_T
scad_run_ui(void)
{
res_T res = RES_OK;
+ struct scad_device* dev = get_device();
int ierr;
- ERR(check_device());
+ /* Cannot use check_device to avoid an infinite loop! */
+ if(!dev) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(dev->options.Misc.SynchronizeOnRunUI && get_device()->need_synchro) {
+ ERR(scad_synchronize());
+ }
gmshFltkRun(&ierr);
ERR(gmsh_err_to_res_T(ierr));
diff --git a/src/scad.h b/src/scad.h
@@ -52,10 +52,14 @@ struct scad_options {
double MinimumElementsPerTwoPi;
double MeshSizeExtendFromBoundary;
} Mesh;
+ struct {
+ int Step;
+ int SynchronizeOnRunUI;
+ } Misc;
};
#define SCAD_DEFAULT_OPTIONS__ \
- { { 2, 0, 1, 36, 0 } }
+ { { 2, 0, 1, 36, 0 }, { 0, 0 }}
static const struct scad_options SCAD_DEFAULT_OPTIONS = SCAD_DEFAULT_OPTIONS__;
@@ -93,6 +97,10 @@ scad_synchronize
******************************************************************************/
SCAD_API res_T
+scad_geometry_delete
+ (struct scad_geometry* geom);
+
+SCAD_API res_T
scad_scene_clear
(void);
@@ -169,20 +177,22 @@ scad_scene_mesh
SCAD_API res_T
scad_fuse_geometries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove);
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry);
/* Compute the boolean difference between the geometries `geom1' and `geom2'.
* Remove geom1 and geom2 from scene if `remove' is set. */
SCAD_API res_T
scad_cut_geometries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove);
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry);
/* Compute the boolean intersection (the common parts) of the geometries
* `geom1' and `geom2'.
@@ -190,34 +200,38 @@ scad_cut_geometries
SCAD_API res_T
scad_intersect_geometries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove);
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry);
/* compute boundary intersection (the common part) of geom1 and geom2
* Remove geom1 and geom2 from scene if `remove' is set. */
SCAD_API res_T
scad_geometries_common_boundaries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove);
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry);
/* Compute the boolean fragments (general fuse) resulting from the
- * intersection of the geometries `geom1' and `geom2', making all iterfaces
+ * intersection of the geometries `geom1' and `geom2', making all interfaces
* conformal. 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.
* Remove geom1 and geom2 from scene if `remove' is set. */
SCAD_API res_T
-scad_geometries_fragment
+scad_geometries_partition
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove);
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ const int allow_overlapping,
+ struct scad_geometry** out_geometry);
/* Get the boundary of the geometry `geom'. */
SCAD_API res_T
diff --git a/src/scad_device.c b/src/scad_device.c
@@ -16,6 +16,7 @@
#include "scad.h"
#include "scad_c.h"
#include "scad_device.h"
+#include "scad_geometry.h"
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
@@ -23,6 +24,7 @@
#include <rsys/cstr.h>
#include <gmshc.h>
+#include <rsys/rsys.h>
/*******************************************************************************
* Local functions
@@ -30,19 +32,26 @@
static void
device_release(struct scad_device* dev)
{
- struct htable_names_iterator it, end;
+ struct htable_geometries tmp;
+ struct htable_geometries_iterator it, end;
ASSERT(dev);
- htable_names_begin(&dev->geometry_names, &it);
- htable_names_end(&dev->geometry_names, &end);
- while(!htable_names_iterator_eq(&it, &end)) {
- struct scad_geometry* geom = *htable_names_iterator_data_get(&it);
- SCAD(geometry_release(geom));
- htable_names_iterator_next(&it);
+ 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);
+ while(!htable_geometries_iterator_eq(&it, &end)) {
+ struct scad_geometry* geom = *htable_geometries_iterator_key_get(&it);
+ CHK(RES_OK == geometry_release(geom));
+ htable_geometries_iterator_next(&it);
}
htable_names_release(&dev->geometry_names);
+ htable_tags2geom_release(&dev->tags2geom[0]);
+ htable_tags2geom_release(&dev->tags2geom[1]);
+ htable_geometries_release(&dev->allgeom);
MEM_RM(dev->allocator, dev);
+ htable_geometries_release(&tmp);
}
void
@@ -79,7 +88,21 @@ res_T
check_device
(void)
{
- return g_device ? RES_OK : RES_BAD_ARG;
+ res_T res = RES_OK;
+
+ if(!g_device) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(g_device->options.Misc.Step) {
+ ERR(scad_run_ui());
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
}
struct scad_device*
@@ -90,6 +113,96 @@ get_device
}
res_T
+device_register_tags
+ (struct scad_geometry* geom)
+{
+ res_T res = RES_OK;
+ int* dimTags;
+ size_t count;
+
+ size_t i;
+
+ ASSERT(geom);
+
+ dimTags = geom->gmsh_dimTags;
+ count = geom->gmsh_dimTags_n;
+ for(i = 0; i < count; i += 2) {
+ int dim = dimTags[i];
+ int tag = dimTags[i+1];
+ struct htable_tags2geom* t2g;
+ struct htable_geometries* geoms;
+ char one = 1;
+ if(dim != 2 && dim != 3) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ /* Add geom to the geometries that use tag@dim */
+ t2g = g_device->tags2geom + (dim-2);
+ geoms = htable_tags2geom_find(t2g, &tag);
+ if(!geoms) {
+ /* First geom using this tag: create the table */
+ struct htable_geometries g;
+ htable_geometries_init(g_device->allocator, &g);
+ ERR(htable_tags2geom_set(t2g, &tag, &g));
+ geoms = htable_tags2geom_find(t2g, &tag);
+ ASSERT(geoms);
+ }
+ ASSERT(!htable_geometries_find(geoms, &geom));
+ ERR(htable_geometries_set(geoms, &geom, &one));
+ }
+
+end:
+ return res;
+error:
+ goto end;
+}
+
+res_T
+device_unregister_tags
+ (struct scad_geometry* geom)
+{
+ res_T res = RES_OK;
+ int* dimTags;
+ size_t count;
+ size_t i;
+
+ ASSERT(geom);
+
+ dimTags = geom->gmsh_dimTags;
+ count = geom->gmsh_dimTags_n;
+
+ for(i = 0; i < count; i += 2) {
+ int dim = dimTags[i];
+ int tag = dimTags[i+1];
+ int ierr;
+ struct htable_tags2geom* t2g;
+ struct htable_geometries* geoms;
+ size_t n;
+ if(dim != 2 && dim != 3) {
+ /* other dims not managed yet */
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ t2g = g_device->tags2geom + (dim-2);
+ geoms = htable_tags2geom_find(t2g, &tag);
+ n = htable_geometries_erase(geoms, &geom);
+ ASSERT(geoms && n == 1); (void)n;
+ if(htable_geometries_size_get(geoms) > 0) continue;
+ /* The gmsh geometry with tag 'tag' is not in use anymore: release it */
+ gmshModelOccRemove(dimTags+i, 2, 1, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+ }
+
+end:
+ return res;
+error:
+ goto end;
+}
+
+/*******************************************************************************
+ * API scad_device functions
+ ******************************************************************************/
+res_T
scad_initialize
(struct logger* logger,
struct mem_allocator* mem_allocator,
@@ -118,6 +231,9 @@ scad_initialize
g_device->logger = logger ? logger : LOGGER_DEFAULT;
g_device->allocator = allocator;
htable_names_init(allocator, &g_device->geometry_names);
+ htable_geometries_init(allocator, &g_device->allgeom);
+ htable_tags2geom_init(allocator, &g_device->tags2geom[0]);
+ htable_tags2geom_init(allocator, &g_device->tags2geom[1]);
g_device->verbose = verbose;
/* Init to default */
scad_set_options(NULL);
@@ -160,9 +276,12 @@ scad_set_options
const struct scad_options* actual_options
= options ? options : &SCAD_DEFAULT_OPTIONS;
int ierr = 0;
+ struct scad_options keep;
ERR(check_device());
+ keep = get_device()->options;
+
gmshOptionSetNumber("Mesh.StlOneSolidPerSurface",
actual_options->Mesh.StlOneSolidPerSurface, &ierr);
ERR(gmsh_err_to_res_T(ierr));
@@ -179,10 +298,13 @@ scad_set_options
actual_options->Mesh.MeshSizeExtendFromBoundary, &ierr);
ERR(gmsh_err_to_res_T(ierr));
+ get_device()->options = *actual_options;
+
exit:
return res;
error:
fprintf(stderr, "%s: can't initialize gmsh -- %s\n",
FUNC_NAME, res_to_cstr(res));
+ if(get_device()) get_device()->options = keep;
goto exit;
}
diff --git a/src/scad_device.h b/src/scad_device.h
@@ -23,6 +23,7 @@
#include <rsys/ref_count.h>
#include <rsys/logger.h>
#include <rsys/hash_table.h>
+#include <rsys/dynamic_array.h>
#include <rsys/str.h>
static INLINE char
@@ -46,15 +47,30 @@ hash_str(const struct str* a)
#define HTABLE_KEY_FUNCTOR_COPY_AND_RELEASE str_copy_and_release
#define HTABLE_KEY_FUNCTOR_EQ eq_str
#define HTABLE_KEY_FUNCTOR_HASH hash_str
+#include <rsys/hash_table.h>
+
+#define HTABLE_NAME geometries
+#define HTABLE_DATA char
+#define HTABLE_KEY struct scad_geometry*
+#include <rsys/hash_table.h>
+#define HTABLE_NAME tags2geom
+#define HTABLE_DATA struct htable_geometries
+#define HTABLE_KEY int
+#define HTABLE_DATA_FUNCTOR_INIT htable_geometries_init
+#define HTABLE_DATA_FUNCTOR_RELEASE htable_geometries_release
+#define HTABLE_DATA_FUNCTOR_COPY htable_geometries_copy
+#define HTABLE_DATA_FUNCTOR_COPY_AND_RELEASE htable_geometries_copy_and_release
#include <rsys/hash_table.h>
struct scad_device {
struct logger* logger;
struct mem_allocator* allocator;
+ struct scad_options options;
struct htable_names geometry_names;
+ struct htable_geometries allgeom;
+ struct htable_tags2geom tags2geom[2];
int verbose;
- int is_meshed;
int need_synchro;
ref_T ref;
@@ -113,4 +129,19 @@ LOCAL_SYM struct scad_device*
get_device
(void);
+LOCAL_SYM res_T
+device_register_tags
+ (struct scad_geometry* geom);
+
+LOCAL_SYM res_T
+device_unregister_tags
+ (struct scad_geometry* geom);
+
+LOCAL_SYM res_T
+device_apply_mappings
+ (const int* original_dimTags,
+ int** mappings,
+ size_t* mappings_counts, /* Number of items in each mapping */
+ const size_t mappings_count); /* Number of mappings; count(original_dimTags)/2 */
+
#endif
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -35,90 +35,119 @@ scad_geometry_create
struct scad_geometry** out_geometry)
{
res_T res = RES_OK;
+ struct str str_name;
struct scad_geometry* geom = NULL;
+ struct scad_device* dev = get_device();
+ char one = 1;
ASSERT(out_geometry);
- if (name) {
- struct str str_name;
-
- str_init(get_device()->allocator, &str_name);
+ str_init(dev->allocator, &str_name);
+ if(name) {
+ if(strlen(name) == 0) {
+ res = RES_BAD_ARG;
+ log_error(get_device(), "Geometry name '' is invalid.\n");
+ goto error;
+ }
ERR(str_set(&str_name, name));
- if(name && htable_names_find(&get_device()->geometry_names, &str_name)) {
+ if(name && htable_names_find(&dev->geometry_names, &str_name)) {
/* if defined, names must be unique */
res = RES_BAD_ARG;
+ log_error(get_device(), "Geometry name '%s' is allready in use.\n",
+ name);
goto error;
}
- str_release(&str_name);
}
- geom = (struct scad_geometry*)MEM_CALLOC(get_device()->allocator, 1,
+ geom = (struct scad_geometry*)MEM_CALLOC(dev->allocator, 1,
sizeof(*geom));
if(!geom) {
res = RES_MEM_ERR;
goto error;
}
- str_init(get_device()->allocator, &geom->name);
- get_device()->need_synchro = 1;
- if(name) {
- struct str str_name;
+ ERR(htable_geometries_set(&dev->allgeom, &geom, &one));
- str_init(get_device()->allocator, &str_name);
- ERR(str_set(&str_name, name));
- ERR(str_copy(&geom->name, &str_name));
- ERR(htable_names_set(&get_device()->geometry_names, &str_name, &geom));
- str_release(&str_name);
+ str_init(dev->allocator, &geom->name);
+ dev->need_synchro = 1;
+ if(name) {
+ ERR(str_set(&geom->name, name));
+ ERR(htable_names_set(&dev->geometry_names, &geom->name, &geom));
}
end:
- if(out_geometry) *out_geometry = geom;
+ str_release(&str_name);
+ *out_geometry = geom;
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto end;
}
-static void
-remove_dimTags
- (struct scad_geometry* geom)
+static res_T
+gather_tags
+ (struct scad_geometry** geometries,
+ const size_t geometries_count,
+ int** out_dimTags,
+ size_t* out_dimTags_n)
{
- ASSERT(geom);
- geom->gmsh_dimTags_n = 0;
- if(geom->gmsh_dimTags) free(geom->gmsh_dimTags);
- geom->gmsh_dimTags = NULL;
+ res_T res = RES_OK;
+ int* tags;
+ size_t i, j, c, sz;
+
+ ASSERT(geometries && geometries_count && out_dimTags && out_dimTags_n);
+
+ for(sz = 0, i = 0; i < geometries_count; i++) {
+ sz += geometries[i]->gmsh_dimTags_n;
+ }
+ tags = malloc(sizeof(*tags) * sz);
+ if(!tags) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ for(i = 0, c = 0; i < geometries_count; i++) {
+ for(j = 0; j < geometries[i]->gmsh_dimTags_n; j++, c++) {
+ tags[c] = geometries[i]->gmsh_dimTags[j];
+ }
+ }
+ *out_dimTags_n = sz;
+ *out_dimTags = tags;
+
+exit:
+ return res;
+error:
+ if(tags) free(tags);
+ goto exit;
}
/*******************************************************************************
* Local functions
******************************************************************************/
res_T
-scad_geometry_release
+geometry_release
(struct scad_geometry* geom)
{
struct mem_allocator* allocator;
- size_t sz;
- int* data;
- int ierr;
+ struct scad_device* dev = get_device();
res_T res = RES_OK;
- ASSERT(geom);
+ size_t n;
+ ASSERT(geom); (void)n;
- ERR(check_device());
- allocator = get_device()->allocator;
- get_device()->need_synchro = 1;
+ allocator = dev->allocator;
+ dev->need_synchro = 1;
- sz = geom->gmsh_dimTags_n;
- data = geom->gmsh_dimTags;
- if(sz != 0) {
- gmshModelOccRemove(data, sz, 1, &ierr);
- ERR(gmsh_err_to_res_T(ierr));
- ASSERT(data);
- free(data);
+ ERR(device_unregister_tags(geom));
+ free(geom->gmsh_dimTags);
+ if(str_len(&geom->name) != 0) {
+ n = htable_names_erase(&dev->geometry_names, &geom->name);
+ ASSERT(n == 1);
}
str_release(&geom->name);
+ n = htable_geometries_erase(&dev->allgeom, &geom);
+ ASSERT(n == 1);
MEM_RM(allocator, geom);
end:
@@ -131,6 +160,27 @@ error:
* Exported functions
*****************************************************************************/
res_T
+scad_geometry_delete
+ (struct scad_geometry* geom)
+{
+ res_T res = RES_OK;
+
+ if(!geom) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ ERR(check_device());
+
+ ERR(geometry_release(geom));
+
+end:
+ return res;
+error:
+ goto end;
+}
+
+res_T
scad_scene_clear
(void)
{
@@ -184,7 +234,7 @@ scad_add_rectangle
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!xyz || !dxdy) {
+ if(!xyz || !dxdy || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
@@ -203,13 +253,14 @@ scad_add_rectangle
}
geom->gmsh_dimTags[0] = 2;
geom->gmsh_dimTags[1] = gmsh_ID;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto exit;
@@ -226,7 +277,7 @@ scad_add_disk
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!xyz || radius <= 0) {
+ if(!xyz || radius <= 0 || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
@@ -245,13 +296,14 @@ scad_add_disk
}
geom->gmsh_dimTags[0] = 2;
geom->gmsh_dimTags[1] = gmsh_ID;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto exit;
@@ -274,7 +326,7 @@ scad_add_polygon
int loop;
res_T res = RES_OK;
- if(!x || !y || count < 3) {
+ if(!x || !y || count < 3 || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
@@ -289,11 +341,11 @@ scad_add_polygon
lines = malloc(count * sizeof(int));
for (i=0; i<count-1; ++i) {
- lines[i] = gmshModelOccAddLine(points[i], points[i+1], -1, &ierr);
+ lines[i] = gmshModelOccAddLine(points[i], points[i+1], -1, &ierr);
ERR(gmsh_err_to_res_T(ierr));
}
/*and the last line*/
- lines[count-1] = gmshModelOccAddLine(points[count-1], points[0], -1, &ierr);
+ lines[count-1] = gmshModelOccAddLine(points[count-1], points[0], -1, &ierr);
ERR(gmsh_err_to_res_T(ierr));
loop = gmshModelOccAddCurveLoop(lines, count, -1, &ierr);
@@ -311,15 +363,16 @@ scad_add_polygon
}
geom->gmsh_dimTags[0] = 2;
geom->gmsh_dimTags[1] = gmsh_ID;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
if(points) free(points);
if(lines) free(lines);
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto exit;
@@ -336,7 +389,7 @@ scad_add_box
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!xyz || !dxdydz) {
+ if(!xyz || !dxdydz || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
@@ -355,13 +408,14 @@ scad_add_box
}
geom->gmsh_dimTags[0] = 3;
geom->gmsh_dimTags[1] = gmsh_ID;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto exit;
@@ -380,7 +434,7 @@ scad_add_cylinder
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!xyz || !axis || rad <= 0 || angle < 0 || angle > 2*PI) {
+ if(!xyz || !axis || rad <= 0 || angle < 0 || angle > 2*PI || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
@@ -400,13 +454,14 @@ scad_add_cylinder
}
geom->gmsh_dimTags[0] = 3;
geom->gmsh_dimTags[1] = gmsh_ID;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto exit;
@@ -423,7 +478,7 @@ scad_add_sphere
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!xyz || rad <= 0) {
+ if(!xyz || rad <= 0 || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
@@ -442,13 +497,14 @@ scad_add_sphere
}
geom->gmsh_dimTags[0] = 3;
geom->gmsh_dimTags[1] = gmsh_ID;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
goto exit;
@@ -457,191 +513,204 @@ error:
res_T
scad_fuse_geometries
(const char* name,
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove)
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry)
{
int* tagout = NULL;
int** map = NULL;
size_t* mapn = NULL;
size_t tagoutn, mapnn, sz1, sz2;
- int* data1;
- int* data2;
+ int* data1 = NULL;
+ int* data2 = NULL;
int ierr = 0;
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!geom1 || !geom2 || !out_geometry) {
+ if(!geometries || !tools || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- sz1 = geom1->gmsh_dimTags_n;
- sz2 = geom2->gmsh_dimTags_n;
- data1 = geom1->gmsh_dimTags;
- data2 = geom2->gmsh_dimTags;
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ 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 */
gmshModelOccFuse(data1, sz1, data2, sz2, &tagout, &tagoutn, &map, &mapn,
- &mapnn, -1, remove, remove, &ierr);
+ &mapnn, -1, 0, 0, &ierr);
ERR(gmsh_err_to_res_T(ierr));
ERR(scad_geometry_create(name, &geom));
geom->gmsh_dimTags_n = tagoutn;
geom->gmsh_dimTags = tagout;
- if(remove) { /* FIXME: not sure of this! */
- remove_dimTags(geom1);
- remove_dimTags(geom2);
- }
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
+ if(data1) free(data1);
+ if(data2) free(data2);
if(mapn) free(mapn);
if(map) free(map);
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
goto exit;
}
res_T
scad_cut_geometries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove)
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry)
{
int* tagout = NULL;
int** map = NULL;
size_t* mapn = NULL;
size_t tagoutn, mapnn, sz1, sz2;
- int* data1;
- int* data2;
+ int* data1 = NULL;
+ int* data2 = NULL;
int ierr = 0;
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!geom1 || !geom2 || !out_geometry) {
+ if(!geometries || !tools || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- sz1 = geom1->gmsh_dimTags_n;
- sz2 = geom2->gmsh_dimTags_n;
- data1 = geom1->gmsh_dimTags;
- data2 = geom2->gmsh_dimTags;
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ 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 */
gmshModelOccCut(data1, sz1, data2, sz2, &tagout, &tagoutn, &map, &mapn,
- &mapnn, -1, remove, remove, &ierr);
+ &mapnn, -1, 0, 0, &ierr);
ERR(gmsh_err_to_res_T(ierr));
ERR(scad_geometry_create(name, &geom));
geom->gmsh_dimTags_n = tagoutn;
geom->gmsh_dimTags = tagout;
- if(remove) { /* FIXME: not sure of this! */
- remove_dimTags(geom1);
- remove_dimTags(geom2);
- }
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
+ if(data1) free(data1);
+ if(data2) free(data2);
if(mapn) free(mapn);
if(map) free(map);
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
goto exit;
}
res_T
scad_intersect_geometries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove)
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry)
{
int* tagout = NULL;
int** map = NULL;
size_t* mapn = NULL;
size_t tagoutn, mapnn, sz1, sz2;
- int* data1;
- int* data2;
+ int* data1 = NULL;
+ int* data2 = NULL;
int ierr = 0;
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!geom1 || !geom2 || !out_geometry) {
+ if(!geometries || !tools || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- sz1 = geom1->gmsh_dimTags_n;
- sz2 = geom2->gmsh_dimTags_n;
- data1 = geom1->gmsh_dimTags;
- data2 = geom2->gmsh_dimTags;
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ 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 */
gmshModelOccIntersect(data1, sz1, data2, sz2, &tagout, &tagoutn, &map, &mapn,
- &mapnn, -1, remove, remove, &ierr);
+ &mapnn, -1, 0, 0, &ierr);
ERR(gmsh_err_to_res_T(ierr));
ERR(scad_geometry_create(name, &geom));
geom->gmsh_dimTags_n = tagoutn;
geom->gmsh_dimTags = tagout;
- if(remove) { /* FIXME: not sure of this! */
- remove_dimTags(geom1);
- remove_dimTags(geom2);
- }
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
+ if(data1) free(data1);
+ if(data2) free(data2);
if(mapn) free(mapn);
if(map) free(map);
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
goto exit;
}
res_T
-scad_geometries_common_boundaries
+scad_geometries_common_boundaries
(const char* name, /* Can be NULL */
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove)
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ struct scad_geometry** tools,
+ const size_t tools_count,
+ struct scad_geometry** out_geometry)
{
int* tagout = NULL;
int** map = NULL;
size_t* mapn = NULL;
size_t tagoutn, mapnn, sz1, sz2;
- int* data1;
- int* data2;
+ int* data1 = NULL;
+ int* data2 = NULL;
int ierr = 0;
int* bound1;
int* bound2;
@@ -649,21 +718,21 @@ scad_geometries_common_boundaries
struct scad_geometry* geom = NULL;
res_T res = RES_OK;
- if(!geom1 || !geom2 || !out_geometry) {
+ if(!geometries || !tools || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- sz1 = geom1->gmsh_dimTags_n;
- sz2 = geom2->gmsh_dimTags_n;
- data1 = geom1->gmsh_dimTags;
- data2 = geom2->gmsh_dimTags;
+ ERR(gather_tags(geometries, geometries_count, &data1, &sz1));
+ 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 */
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);
@@ -675,13 +744,12 @@ scad_geometries_common_boundaries
ERR(scad_geometry_create(name, &geom));
geom->gmsh_dimTags_n = tagoutn;
geom->gmsh_dimTags = tagout;
- if(remove) { /* FIXME: not sure of this! */
- remove_dimTags(geom1);
- remove_dimTags(geom2);
- }
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
+ if(data1) free(data1);
+ if(data2) free(data2);
if(bound1) free(bound1);
if(bound2) free(bound2);
if(mapn) free(mapn);
@@ -689,9 +757,13 @@ exit:
return res;
error:
if(geom) {
- SCAD(geometry_release(geom));
+ CHK(RES_OK == geometry_release(geom));
geom = NULL;
}
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
goto exit;
}
@@ -713,7 +785,6 @@ scad_geometry_rotate
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
@@ -753,7 +824,6 @@ scad_geometry_extrude
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
@@ -769,7 +839,7 @@ scad_geometry_extrude
/* keep only 3D entities */
/* TODO : NOT SURE OF THE CONCEPT */
for (i=0; i<tagoutn/2; ++i) {
- if (tagout[2*i] == 3) extrude_sz += 2;
+ if (tagout[2*i] == 3) extrude_sz += 2;
}
extrude_data = malloc(extrude_sz * sizeof(int));
j = 0;
@@ -782,14 +852,15 @@ scad_geometry_extrude
}
extrude_geom->gmsh_dimTags_n = extrude_sz;
extrude_geom->gmsh_dimTags = extrude_data;
+ ERR(device_register_tags(extrude_geom));
exit:
- if(out_geometry) *out_geometry = extrude_geom;
- if (tagout) free(tagout);
+ *out_geometry = extrude_geom;
+ if(tagout) free(tagout);
return res;
error:
if(extrude_geom) {
- SCAD(geometry_release(extrude_geom));
+ CHK(RES_OK == geometry_release(extrude_geom));
extrude_geom = NULL;
}
goto exit;
@@ -813,7 +884,6 @@ scad_geometry_copy
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
@@ -827,6 +897,7 @@ scad_geometry_copy
ERR(scad_geometry_create(name, copy));
(*copy)->gmsh_dimTags_n = sz2;
(*copy)->gmsh_dimTags = data2;
+ ERR(device_register_tags(*copy));
exit:
return res;
@@ -850,7 +921,6 @@ scad_geometry_translate
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
@@ -868,56 +938,93 @@ error:
}
res_T
-scad_geometries_fragment
+scad_geometries_partition
(const char* name,
- struct scad_geometry* geom1,
- struct scad_geometry* geom2,
- struct scad_geometry** out_geometry,
- const int remove)
+ struct scad_geometry** geometries,
+ const size_t geometries_count,
+ 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, mapnn, sz1, sz2;
- int* data1;
- int* data2;
+ 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(!geom1 || !geom2 || !out_geometry) {
+ if(!geometries || !out_geometry) {
res = RES_BAD_ARG;
goto error;
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- sz1 = geom1->gmsh_dimTags_n;
- sz2 = geom2->gmsh_dimTags_n;
- data1 = geom1->gmsh_dimTags;
- data2 = geom2->gmsh_dimTags;
+ 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, remove, remove, &ierr);
+ &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;
- if(remove) { /* FIXME: not sure of this! */
- remove_dimTags(geom1);
- remove_dimTags(geom2);
- }
+
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *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;
}
@@ -950,11 +1057,20 @@ scad_geometry_boundary
ERR(scad_geometry_create(name, &geom));
geom->gmsh_dimTags_n = tagoutn;
geom->gmsh_dimTags = tagout;
+ ERR(device_register_tags(geom));
exit:
- if(out_geometry) *out_geometry = geom;
+ *out_geometry = geom;
return res;
error:
+ if(geom) {
+ CHK(RES_OK == geometry_release(geom));
+ geom = NULL;
+ }
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
goto exit;
}
@@ -968,6 +1084,8 @@ scad_step_import
int ierr;
int* tagout = NULL;
size_t tagoutn, i;
+ struct str strname;
+ int name_initialized = 0;
res_T res = RES_OK;
if(!filename) {
@@ -976,38 +1094,41 @@ scad_step_import
}
ERR(check_device());
-
if(get_device()->need_synchro) {
ERR(scad_synchronize());
}
- gmshModelOccImportShapes(filename,
- &tagout, &tagoutn,
- 1,
- "step",
- &ierr);
+ gmshModelOccImportShapes(filename, &tagout, &tagoutn, 1, "step", &ierr);
ERR(gmsh_err_to_res_T(ierr));
*out_geometry = malloc(tagoutn/2 * sizeof(struct scad_geometry*));
+ str_init(get_device()->allocator, &strname);
+ name_initialized = 1;
for (i=0; i<tagoutn/2; ++i) {
- struct str strname;
-
- str_init(get_device()->allocator, &strname);
ERR(str_set(&strname, name));
- ERR(str_append_printf(&strname,"_%lu", (unsigned long)i));
+ ERR(str_append_printf(&strname,"_%lu", (unsigned long)i));
ERR(scad_geometry_create(str_cget(&strname), &(*out_geometry)[i]));
(*out_geometry)[i]->gmsh_dimTags_n = 2;
(*out_geometry)[i]->gmsh_dimTags = malloc(2 * sizeof(int));
(*out_geometry)[i]->gmsh_dimTags[0] = tagout[2*i];
(*out_geometry)[i]->gmsh_dimTags[1] = tagout[2*i+1];
- str_release(&strname);
+ ERR(device_register_tags((*out_geometry)[i]));
}
*out_geometry_n = tagoutn/2;
exit:
+ if(name_initialized) str_release(&strname);
return res;
error:
+ if(tagout) {
+ gmshModelOccRemove(tagout, tagoutn, 1, &ierr);
+ free(tagout);
+ }
+ if(out_geometry) {
+ free(out_geometry);
+ out_geometry = NULL;
+ }
goto exit;
}
diff --git a/src/scad_geometry.h b/src/scad_geometry.h
@@ -27,8 +27,8 @@ struct scad_geometry {
struct str name;
};
-extern LOCAL_SYM res_T
-scad_geometry_release
+LOCAL_SYM res_T
+geometry_release
(struct scad_geometry* geom);
#endif