star-cad

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

commit 04d4f68ac87fccb2f8819e581a0dadd646760755
parent 455ce14a7685428dbc584f567c22407bc33272c4
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 25 Aug 2022 10:44:59 +0200

Remove the scad_scene type from user space: there is a single implicit scene

Diffstat:
Mcmake/CMakeLists.txt | 2--
Msrc/scad.c | 65++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/scad.h | 79+++++++++++++++++++++++++++++++------------------------------------------------
Msrc/scad_device.c | 23++++++++++-------------
Msrc/scad_device.h | 33++++++++++++++++++++++++++++-----
Msrc/scad_geometry.c | 217++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/scad_geometry.h | 4++--
Dsrc/scad_scene.c | 172-------------------------------------------------------------------------------
Dsrc/scad_scene.h | 61-------------------------------------------------------------
Msrc/test1.c | 25+++++++++++--------------
10 files changed, 234 insertions(+), 447 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -43,12 +43,10 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SCAD_FILES_SRC scad.c - scad_scene.c scad_device.c scad_geometry.c) set(SCAD_FILES_INC_API scad.h) set(SCAD_FILES_INC - scad_scene.h scad_device.h scad_geometry.h) set(SCAD_FILES_DOC COPYING README.md) diff --git a/src/scad.c b/src/scad.c @@ -16,7 +16,6 @@ #include "scad.h" #include "scad_c.h" #include "scad_device.h" -#include "scad_scene.h" #include "scad_geometry.h" #include <gmshc.h> @@ -230,17 +229,15 @@ scad_stl_export goto error; } - if(geometry->scene->device->need_synchro) { - ERR(scad_device_synchronize(geometry->scene->device)); + if(geometry->device->need_synchro) { + ERR(scad_device_synchronize(geometry->device)); } - ERR(device_set_current_scene(geometry->scene)); - sz = geometry->gmsh_dimTags_n; data = geometry->gmsh_dimTags; ASSERT(sz > 0 && sz % 2 == 0); - str_init(geometry->scene->device->allocator, &filename); + str_init(geometry->device->allocator, &filename); str_initialized = 1; if(prefix) { ERR(str_set(&filename, prefix)); @@ -257,7 +254,7 @@ scad_stl_export size_t dimTags_n; size_t tcount; - ERR(scad_device_synchronize(geometry->scene->device)); + ERR(scad_device_synchronize(geometry->device)); gmshModelOccGetEntities(&dimTags, &dimTags_n, 3, &ierr); ERR(gmsh_err_to_res_T(ierr)); if(dimTags_n > 100000) { @@ -280,13 +277,13 @@ scad_stl_export #endif } /* WARNING : an export may be prohibited without a prior conformal mesh*/ - if (!geometry->scene->is_meshed) { - ERR(scad_device_synchronize(geometry->scene->device)); + if (!geometry->device->is_meshed) { + ERR(scad_device_synchronize(geometry->device)); gmshModelMeshGenerate(2, &ierr); ERR(gmsh_err_to_res_T(ierr)); - geometry->scene->is_meshed = 1; + geometry->device->is_meshed = 1; } - ERR(scad_device_synchronize(geometry->scene->device)); + ERR(scad_device_synchronize(geometry->device)); gmshModelGetBoundary(data, sz, &tagout, &tagoutn, 1, 0, 0, &ierr); ERR(gmsh_err_to_res_T(ierr)); @@ -392,18 +389,16 @@ scad_stl_export_split goto error; } - if(geometry->scene->device->need_synchro) { - ERR(scad_device_synchronize(geometry->scene->device)); + if(geometry->device->need_synchro) { + ERR(scad_device_synchronize(geometry->device)); } - ERR(device_set_current_scene(geometry->scene)); - sz = geometry->gmsh_dimTags_n; data = geometry->gmsh_dimTags; ASSERT(sz % 2 == 0); - str_init(geometry->scene->device->allocator, &filename_root); - str_init(geometry->scene->device->allocator, &filename); + str_init(geometry->device->allocator, &filename_root); + str_init(geometry->device->allocator, &filename); str_initialized = 1; if(prefix) { ERR(str_set(&filename_root, prefix)); @@ -466,3 +461,39 @@ exit: error: goto exit; } + +res_T +scad_conformal_mesh + (struct scad_device* device) +{ + int* dimTags = NULL; + size_t dimTags_n; + int ierr = 0; + res_T res = RES_OK; + + device->need_synchro = 1; + gmshModelOccSynchronize(&ierr); + ERR(gmsh_err_to_res_T(ierr)); + gmshModelOccGetEntities(&dimTags, &dimTags_n, 3, &ierr); + ERR(gmsh_err_to_res_T(ierr)); + if(dimTags_n > 2) { + /* Remove all duplicate entities in the OpenCASCADE CAD representation + * (different entities at the same geometrical location) after intersecting + * (using boolean fragments) all highest dimensional entities. */ + gmshModelOccRemoveAllDuplicates(&ierr); + ERR(gmsh_err_to_res_T(ierr)); + } + gmshModelOccSynchronize(&ierr); + ERR(gmsh_err_to_res_T(ierr)); + gmshModelMeshGenerate(2, &ierr); + ERR(gmsh_err_to_res_T(ierr)); + device->is_meshed = 1; + +exit: + if(dimTags) free(dimTags); + return res; +error: + goto exit; +} + + diff --git a/src/scad.h b/src/scad.h @@ -42,7 +42,6 @@ struct logger; /* Forward declaration of scad opaque data types */ struct scad_device; /* Entry point of the library */ -struct scad_scene; /* Collection of geometry items */ struct scad_geometry; /* Wrapping of dimTags gmsh description */ /* A type to specify options for devices */ @@ -94,25 +93,9 @@ scad_device_ref_put (struct scad_device* dev); /******************************************************************************* - * Scene API - A scene is a collection of geometries. - ******************************************************************************/ -SCAD_API res_T -scad_scene_create - (struct scad_device* device, - struct scad_scene** out_scene); - -SCAD_API res_T -scad_scene_ref_get - (struct scad_scene* scene); - -SCAD_API res_T -scad_scene_ref_put - (struct scad_scene* scene); - -/******************************************************************************* * Geometry API - A geometry is a primitive, a group of primitives, or the * result of an operation on geometries. - * If provided, names must be unique by scene. + * If provided, names must be unique by device. ******************************************************************************/ /* `size' is the number of primitives of the geometry `geom' */ @@ -124,8 +107,8 @@ scad_geometry_get_size /* Add a rectangle to the scene, defined by a point `xyz' and * `dxdy' the extents along the x-, y-axes. */ SCAD_API res_T -scad_scene_add_rectangle - (struct scad_scene* scene, +scad_add_rectangle + (struct scad_device* device, const char* name, /* Can be NULL */ const double xyz[3], const double dxdy[2], @@ -134,8 +117,8 @@ scad_scene_add_rectangle /* Add a disk in (xy) plane to the scene, defined by a the center `xyz' and * `radius'. */ SCAD_API res_T -scad_scene_add_disk - (struct scad_scene* scene, +scad_add_disk + (struct scad_device* device, const char* name, /* Can be NULL */ const double xyz[3], const double radius, @@ -144,8 +127,8 @@ scad_scene_add_disk /* Add a polygonal surface in (xy) plane to the scene at elevation z, defined by * the list of points of coordinates x, y.*/ SCAD_API res_T -scad_scene_add_polygon - (struct scad_scene* scene, +scad_add_polygon + (struct scad_device* device, const char* name, /* Can be NULL */ const double* x, const double* y, @@ -156,8 +139,8 @@ scad_scene_add_polygon /* Add a parallelepipedic box to the scene, defined by a point `xyz' and * `dxdydz' the extents along the x-, y- and z-axes. */ SCAD_API res_T -scad_scene_add_box - (struct scad_scene* scene, +scad_add_box + (struct scad_device* device, const char* name, /* Can be NULL */ const double xyz[3], const double dxdydz[3], @@ -167,8 +150,8 @@ scad_scene_add_box * circular face, the vector `axis' defining its axis and its radius `rad'. The * `angle' argument defines the angular opening (from 0 to 2*Pi). */ SCAD_API res_T -scad_scene_add_cylinder - (struct scad_scene* scene, +scad_add_cylinder + (struct scad_device* device, const char* name, /* Can be NULL */ const double xyz[3], const double axis[3], @@ -178,8 +161,8 @@ scad_scene_add_cylinder /* Add a sphere of center `xyz' and radius `rad' to the scene. */ SCAD_API res_T -scad_scene_add_sphere - (struct scad_scene* scene, +scad_add_sphere + (struct scad_device* device, const char* name, /* Can be NULL */ const double xyz[3], const double rad, @@ -189,8 +172,8 @@ scad_scene_add_sphere * All of the geometries must have been added to scene and must have dimension * dim. */ SCAD_API res_T -scad_scene_create_group - (struct scad_scene* scene, +scad_create_group + (struct scad_device* device, const char* name, /* Can be NULL */ const int dim, struct scad_geometry** geometries, @@ -198,14 +181,14 @@ scad_scene_create_group struct scad_geometry** group); SCAD_API res_T -scad_scene_conformal_mesh - (struct scad_scene* scene); +scad_conformal_mesh + (struct scad_device* device); /* Compute the boolean union (the fusion) of the geometries `geom1' and `geom2'. * Remove geom1 and geom2 from scene if `remove' is set. */ SCAD_API res_T -scad_scene_fuse_geometries - (struct scad_scene* scene, +scad_fuse_geometries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -215,8 +198,8 @@ scad_scene_fuse_geometries /* 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_scene_cut_geometries - (struct scad_scene* scene, +scad_cut_geometries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -227,8 +210,8 @@ scad_scene_cut_geometries * `geom1' and `geom2'. * Remove geom1 and geom2 from scene if `remove' is set. */ SCAD_API res_T -scad_scene_intersect_geometries - (struct scad_scene* scene, +scad_intersect_geometries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -238,8 +221,8 @@ scad_scene_intersect_geometries /* 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_scene_geometries_common_boundaries - (struct scad_scene* scene, +scad_geometries_common_boundaries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -253,8 +236,8 @@ scad_scene_geometries_common_boundaries * dimensional geometries if they are not on their boundary. * Remove geom1 and geom2 from scene if `remove' is set. */ SCAD_API res_T -scad_scene_geometries_fragment - (struct scad_scene* scene, +scad_geometries_fragment + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -263,8 +246,8 @@ scad_scene_geometries_fragment /* Get the boundary of the geometry `geom'. */ SCAD_API res_T -scad_scene_geometry_boundary - (struct scad_scene* scene, +scad_geometry_boundary + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom, struct scad_geometry** out); @@ -303,8 +286,8 @@ scad_geometry_extrude /* Import a step model (`filename'). The imported geometries are recorded in * `out_geometry' handler. */ SCAD_API res_T -scad_scene_step_import - (struct scad_scene* scene, +scad_step_import + (struct scad_device* device, const char* filename, /* name of step file */ const char* name, /* Can be NULL */ struct scad_geometry*** out_geometry, diff --git a/src/scad_device.c b/src/scad_device.c @@ -16,7 +16,6 @@ #include "scad.h" #include "scad_c.h" #include "scad_device.h" -#include "scad_scene.h" #include <rsys/logger.h> #include <rsys/mem_allocator.h> @@ -35,9 +34,18 @@ static void device_release(ref_T* ref) { struct scad_device* dev; + struct htable_names_iterator it, end; int ierr = 0; ASSERT(ref); dev = CONTAINER_OF(ref, struct scad_device, ref); + 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_names_release(&dev->geometry_names); MEM_RM(dev->allocator, dev); if(--device_count == 0) { gmshFinalize(&ierr); @@ -67,18 +75,6 @@ log_warning(struct scad_device* dev, const char* msg, ...) va_end(vargs_list); } -res_T -device_set_current_scene(struct scad_scene* scene) -{ - int ierr = 0; - ASSERT(scene); - if(scene->device->current_scene == scene) return RES_OK; - gmshModelSetCurrent(scene->name, &ierr); - if(ierr) scene->device->current_scene = NULL; - else scene->device->current_scene = scene; - return gmsh_err_to_res_T(ierr); -} - /******************************************************************************* * Exported scad_device functions ******************************************************************************/ @@ -124,6 +120,7 @@ scad_device_create } dev->logger = logger ? logger : LOGGER_DEFAULT; dev->allocator = allocator; + htable_names_init(allocator, &dev->geometry_names); dev->verbose = verbose; ref_init(&dev->ref); device_count++; diff --git a/src/scad_device.h b/src/scad_device.h @@ -22,13 +22,39 @@ #include <rsys/rsys.h> #include <rsys/ref_count.h> #include <rsys/logger.h> +#include <rsys/hash_table.h> +#include <rsys/str.h> + +static INLINE char +eq_str(const struct str* a, const struct str* b) +{ + return !strcmp(str_cget(a), str_cget(b)); +} + +static INLINE size_t +hash_str(const struct str* a) +{ + return hash_fnv32(str_cget(a), str_len(a)); +} + +#define HTABLE_NAME names +#define HTABLE_DATA struct scad_geometry* +#define HTABLE_KEY struct str +#define HTABLE_KEY_FUNCTOR_INIT str_init +#define HTABLE_KEY_FUNCTOR_RELEASE str_release +#define HTABLE_KEY_FUNCTOR_COPY str_copy +#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> struct scad_device { struct logger* logger; struct mem_allocator* allocator; - struct scad_scene* current_scene; - unsigned next_scene_id; + struct htable_names geometry_names; int verbose; + int is_meshed; int need_synchro; ref_T ref; @@ -76,7 +102,4 @@ log_msg } } -extern LOCAL_SYM res_T -device_set_current_scene(struct scad_scene* scene); - #endif diff --git a/src/scad_geometry.c b/src/scad_geometry.c @@ -15,7 +15,6 @@ #include "scad.h" #include "scad_c.h" -#include "scad_scene.h" #include "scad_device.h" #include "scad_geometry.h" @@ -32,20 +31,20 @@ ******************************************************************************/ static res_T scad_geometry_create - (struct scad_scene* scene, + (struct scad_device* device, const char* name, struct scad_geometry** out_geometry) { res_T res = RES_OK; struct scad_geometry* geom = NULL; - ASSERT(scene && out_geometry); + ASSERT(device && out_geometry); if (name) { struct str str_name; - str_init(scene->device->allocator, &str_name); + str_init(device->allocator, &str_name); ERR(str_set(&str_name, name)); - if(name && htable_names_find(&scene->geometry_names, &str_name)) { + if(name && htable_names_find(&device->geometry_names, &str_name)) { /* if defined, names must be unique */ res = RES_BAD_ARG; goto error; @@ -53,23 +52,23 @@ scad_geometry_create str_release(&str_name); } - geom = (struct scad_geometry*)MEM_CALLOC(scene->device->allocator, 1, + geom = (struct scad_geometry*)MEM_CALLOC(device->allocator, 1, sizeof(*geom)); if(!geom) { res = RES_MEM_ERR; goto error; } - str_init(scene->device->allocator, &geom->name); - geom->scene = scene; - scene->device->need_synchro = 1; + str_init(device->allocator, &geom->name); + geom->device = device; + device->need_synchro = 1; if(name) { struct str str_name; - str_init(scene->device->allocator, &str_name); + str_init(device->allocator, &str_name); ERR(str_set(&str_name, name)); ERR(str_copy(&geom->name, &str_name)); - ERR(htable_names_set(&scene->geometry_names, &str_name, &geom)); + ERR(htable_names_set(&device->geometry_names, &str_name, &geom)); str_release(&str_name); } @@ -108,8 +107,8 @@ scad_geometry_release int ierr; res_T res = RES_OK; ASSERT(geom); - allocator = geom->scene->device->allocator; - geom->scene->device->need_synchro = 1; + allocator = geom->device->allocator; + geom->device->need_synchro = 1; sz = geom->gmsh_dimTags_n; data = geom->gmsh_dimTags; @@ -164,8 +163,8 @@ error: res_T -scad_scene_add_rectangle - (struct scad_scene* scene, +scad_add_rectangle + (struct scad_device* device, const char* name, const double xyz[3], const double dxdy[2], @@ -175,16 +174,15 @@ scad_scene_add_rectangle struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !xyz || !dxdy) { + if(!device || !xyz || !dxdy) { res = RES_BAD_ARG; goto error; } - ERR(device_set_current_scene(scene)); gmsh_ID = gmshModelOccAddRectangle(SPLIT3(xyz), SPLIT2(dxdy), -1, 0, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags = malloc(geom->gmsh_dimTags_n * sizeof(int)); if(! geom->gmsh_dimTags_n) { @@ -206,8 +204,8 @@ error: } res_T -scad_scene_add_disk - (struct scad_scene* scene, +scad_add_disk + (struct scad_device* device, const char* name, const double xyz[3], const double radius, @@ -217,16 +215,15 @@ scad_scene_add_disk struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !xyz || radius <= 0) { + if(!device || !xyz || radius <= 0) { res = RES_BAD_ARG; goto error; } - ERR(device_set_current_scene(scene)); gmsh_ID = gmshModelOccAddDisk(SPLIT3(xyz), radius, radius, -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags = malloc(geom->gmsh_dimTags_n * sizeof(int)); if(! geom->gmsh_dimTags_n) { @@ -248,8 +245,8 @@ error: } res_T -scad_scene_add_polygon - (struct scad_scene* scene, +scad_add_polygon + (struct scad_device* device, const char* name, const double* x, const double* y, @@ -265,13 +262,11 @@ scad_scene_add_polygon int loop; res_T res = RES_OK; - if(!scene || !x || !y || count < 3) { + if(!device || !x || !y || count < 3) { res = RES_BAD_ARG; goto error; } - ERR(device_set_current_scene(scene)); - points = malloc(count * sizeof(int)); for (i=0; i<count; ++i) { points[i] = gmshModelOccAddPoint(x[i], y[i], z, -1, -1, &ierr); @@ -293,7 +288,7 @@ scad_scene_add_polygon gmsh_ID = gmshModelOccAddPlaneSurface(&loop, 1, -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags = malloc(geom->gmsh_dimTags_n * sizeof(int)); if(! geom->gmsh_dimTags_n) { @@ -316,8 +311,8 @@ error: goto exit; } res_T -scad_scene_add_box - (struct scad_scene* scene, +scad_add_box + (struct scad_device* device, const char* name, const double xyz[3], const double dxdydz[3], @@ -327,16 +322,15 @@ scad_scene_add_box struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !xyz || !dxdydz) { + if(!device || !xyz || !dxdydz) { res = RES_BAD_ARG; goto error; } - ERR(device_set_current_scene(scene)); gmsh_ID = gmshModelOccAddBox(SPLIT3(xyz), SPLIT3(dxdydz), -1, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags = malloc(geom->gmsh_dimTags_n * sizeof(int)); if(! geom->gmsh_dimTags_n) { @@ -358,8 +352,8 @@ error: } res_T -scad_scene_add_cylinder - (struct scad_scene* scene, +scad_add_cylinder + (struct scad_device* device, const char* name, const double xyz[3], const double axis[3], @@ -371,17 +365,16 @@ scad_scene_add_cylinder struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !xyz || !axis || rad <= 0 || angle < 0 || angle > 2*PI) { + if(!device || !xyz || !axis || rad <= 0 || angle < 0 || angle > 2*PI) { res = RES_BAD_ARG; goto error; } - ERR(device_set_current_scene(scene)); gmsh_ID = gmshModelOccAddCylinder(SPLIT3(xyz), SPLIT3(axis), rad, -1, angle, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags = malloc(geom->gmsh_dimTags_n * sizeof(int)); if(! geom->gmsh_dimTags_n) { @@ -403,8 +396,8 @@ error: } int -scad_scene_add_sphere - (struct scad_scene* scene, +scad_add_sphere + (struct scad_device* device, const char* name, const double xyz[3], const double rad, @@ -414,16 +407,15 @@ scad_scene_add_sphere struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !xyz || rad <= 0) { + if(!device || !xyz || rad <= 0) { res = RES_BAD_ARG; goto error; } - ERR(device_set_current_scene(scene)); gmsh_ID = gmshModelOccAddSphere(SPLIT3(xyz), rad, -1, -PI/2, PI/2, 2*PI, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = 2; geom->gmsh_dimTags = malloc(geom->gmsh_dimTags_n * sizeof(int)); if(! geom->gmsh_dimTags_n) { @@ -445,8 +437,8 @@ error: } res_T -scad_scene_create_group - (struct scad_scene* scene, +scad_create_group + (struct scad_device* device, const char* name, const int dim, struct scad_geometry** geometries, @@ -459,13 +451,13 @@ scad_scene_create_group int* ids = NULL; res_T res = RES_OK; - if(!scene || !geometries || (count == 0) || !out_geometry) { + if(!device || !geometries || (count == 0) || !out_geometry) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz = 0; @@ -485,12 +477,11 @@ scad_scene_create_group } } ASSERT(n == sz); - ERR(device_set_current_scene(scene)); gid = gmshModelAddPhysicalGroup(dim, ids, count, -1, &ierr); ASSERT(gid > 0); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->is_group = gid; geom->group_dim = dim; geom->gmsh_dimTags_n = 2 * sz; @@ -521,8 +512,8 @@ error: } res_T -scad_scene_fuse_geometries - (struct scad_scene* scene, +scad_fuse_geometries + (struct scad_device* device, const char* name, struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -539,15 +530,15 @@ scad_scene_fuse_geometries struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !geom1 || !geom2 || !out_geometry - || geom1->scene != scene || geom2->scene != scene) + if(!device || !geom1 || !geom2 || !out_geometry + || geom1->device != device || geom2->device != device) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz1 = geom1->gmsh_dimTags_n; @@ -558,7 +549,7 @@ scad_scene_fuse_geometries &mapnn, -1, remove, remove, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = tagoutn; geom->gmsh_dimTags = tagout; if(remove) { /* FIXME: not sure of this! */ @@ -580,8 +571,8 @@ error: } res_T -scad_scene_cut_geometries - (struct scad_scene* scene, +scad_cut_geometries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -598,15 +589,15 @@ scad_scene_cut_geometries struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !geom1 || !geom2 || !out_geometry - || geom1->scene != scene || geom2->scene != scene) + if(!device || !geom1 || !geom2 || !out_geometry + || geom1->device != device || geom2->device != device) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz1 = geom1->gmsh_dimTags_n; @@ -617,7 +608,7 @@ scad_scene_cut_geometries &mapnn, -1, remove, remove, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = tagoutn; geom->gmsh_dimTags = tagout; if(remove) { /* FIXME: not sure of this! */ @@ -639,8 +630,8 @@ error: } res_T -scad_scene_intersect_geometries - (struct scad_scene* scene, +scad_intersect_geometries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -657,15 +648,15 @@ scad_scene_intersect_geometries struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !geom1 || !geom2 || !out_geometry - || geom1->scene != scene || geom2->scene != scene) + if(!device || !geom1 || !geom2 || !out_geometry + || geom1->device != device || geom2->device != device) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz1 = geom1->gmsh_dimTags_n; @@ -676,7 +667,7 @@ scad_scene_intersect_geometries &mapnn, -1, remove, remove, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = tagoutn; geom->gmsh_dimTags = tagout; if(remove) { /* FIXME: not sure of this! */ @@ -698,8 +689,8 @@ error: } res_T -scad_scene_geometries_common_boundaries - (struct scad_scene* scene, +scad_geometries_common_boundaries + (struct scad_device* device, const char* name, /* Can be NULL */ struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -719,15 +710,15 @@ scad_scene_geometries_common_boundaries struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !geom1 || !geom2 || !out_geometry - || geom1->scene != scene || geom2->scene != scene) + if(!device || !geom1 || !geom2 || !out_geometry + || geom1->device != device || geom2->device != device) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz1 = geom1->gmsh_dimTags_n; @@ -742,7 +733,7 @@ scad_scene_geometries_common_boundaries &mapn, &mapnn, -1, 0/*no delete*/, 0/*no delete*/, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = tagoutn; geom->gmsh_dimTags = tagout; if(remove) { /* FIXME: not sure of this! */ @@ -782,14 +773,14 @@ scad_geometry_rotate goto error; } - if(geom->scene->device->need_synchro) { - ERR(scad_device_synchronize(geom->scene->device)); + if(geom->device->need_synchro) { + ERR(scad_device_synchronize(geom->device)); } sz = geom->gmsh_dimTags_n; data = geom->gmsh_dimTags; gmshModelOccRotate(data, sz, SPLIT3(pt), SPLIT3(axis), angle, &ierr); - geom->scene->device->need_synchro = 1; + geom->device->need_synchro = 1; ERR(gmsh_err_to_res_T(ierr)); exit: @@ -820,18 +811,18 @@ scad_geometry_extrude goto error; } - if(geom->scene->device->need_synchro) { - ERR(scad_device_synchronize(geom->scene->device)); + if(geom->device->need_synchro) { + ERR(scad_device_synchronize(geom->device)); } sz = geom->gmsh_dimTags_n; data = geom->gmsh_dimTags; gmshModelOccExtrude(data, sz, SPLIT3(dxdydz), &tagout, &tagoutn, NULL, 0, NULL, 0, 0 , &ierr); - geom->scene->device->need_synchro = 1; + geom->device->need_synchro = 1; ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(geom->scene, name, &extrude_geom)); + ERR(scad_geometry_create(geom->device, name, &extrude_geom)); /* keep only 3D entities */ /* TODO : NOT SURE OF THE CONCEPT */ for (i=0; i<tagoutn/2; ++i) { @@ -878,17 +869,17 @@ scad_geometry_copy goto error; } - if(geom->scene->device->need_synchro) { - ERR(scad_device_synchronize(geom->scene->device)); + if(geom->device->need_synchro) { + ERR(scad_device_synchronize(geom->device)); } sz1 = geom->gmsh_dimTags_n; data1 = geom->gmsh_dimTags; gmshModelOccCopy(data1, sz1, &data2, &sz2, &ierr); - geom->scene->device->need_synchro = 1; + geom->device->need_synchro = 1; ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(geom->scene, name, copy)); + ERR(scad_geometry_create(geom->device, name, copy)); (*copy)->gmsh_dimTags_n = sz2; (*copy)->gmsh_dimTags = data2; @@ -913,14 +904,14 @@ scad_geometry_translate goto error; } - if(geom->scene->device->need_synchro) { - ERR(scad_device_synchronize(geom->scene->device)); + if(geom->device->need_synchro) { + ERR(scad_device_synchronize(geom->device)); } sz = geom->gmsh_dimTags_n; data = geom->gmsh_dimTags; gmshModelOccTranslate(data, sz, SPLIT3(dxdydz), &ierr); - geom->scene->device->need_synchro = 1; + geom->device->need_synchro = 1; ERR(gmsh_err_to_res_T(ierr)); exit: @@ -930,8 +921,8 @@ error: } res_T -scad_scene_geometries_fragment - (struct scad_scene* scene, +scad_geometries_fragment + (struct scad_device* device, const char* name, struct scad_geometry* geom1, struct scad_geometry* geom2, @@ -948,15 +939,15 @@ scad_scene_geometries_fragment struct scad_geometry* geom = NULL; res_T res = RES_OK; - if(!scene || !geom1 || !geom2 || !out_geometry - || geom1->scene != scene || geom2->scene != scene) + if(!device || !geom1 || !geom2 || !out_geometry + || geom1->device != device || geom2->device != device) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz1 = geom1->gmsh_dimTags_n; @@ -967,7 +958,7 @@ scad_scene_geometries_fragment &mapnn, -1, remove, remove, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = tagoutn; geom->gmsh_dimTags = tagout; if(remove) { /* FIXME: not sure of this! */ @@ -985,8 +976,8 @@ error: } res_T -scad_scene_geometry_boundary - (struct scad_scene* scene, +scad_geometry_boundary + (struct scad_device* device, const char* name, struct scad_geometry* geom, struct scad_geometry** out_geometry) @@ -997,13 +988,13 @@ scad_scene_geometry_boundary int ierr = 0; res_T res = RES_OK; - if(!scene || !geom || !out_geometry || geom->scene != scene) { + if(!device || !geom || !out_geometry || geom->device != device) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } sz = geom->gmsh_dimTags_n; @@ -1011,7 +1002,7 @@ scad_scene_geometry_boundary gmshModelGetBoundary(data, sz, &tagout, &tagoutn, 1, 0, 0, &ierr); ERR(gmsh_err_to_res_T(ierr)); - ERR(scad_geometry_create(scene, name, &geom)); + ERR(scad_geometry_create(device, name, &geom)); geom->gmsh_dimTags_n = tagoutn; geom->gmsh_dimTags = tagout; @@ -1023,8 +1014,8 @@ error: } res_T -scad_scene_step_import - (struct scad_scene* scene, +scad_step_import + (struct scad_device* device, const char* filename, const char* name, struct scad_geometry*** out_geometry, @@ -1035,13 +1026,13 @@ scad_scene_step_import size_t tagoutn, i; res_T res = RES_OK; - if(!scene || !filename) { + if(!device || !filename) { res = RES_BAD_ARG; goto error; } - if(scene->device->need_synchro) { - ERR(scad_device_synchronize(scene->device)); + if(device->need_synchro) { + ERR(scad_device_synchronize(device)); } gmshModelOccImportShapes(filename, @@ -1056,11 +1047,11 @@ scad_scene_step_import for (i=0; i<tagoutn/2; ++i) { struct str strname; - str_init(scene->device->allocator, &strname); + str_init(device->allocator, &strname); ERR(str_set(&strname, name)); ERR(str_append_printf(&strname,"_%lu", (unsigned long)i)); - ERR(scad_geometry_create(scene, str_cget(&strname), &(*out_geometry)[i])); + ERR(scad_geometry_create(device, 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]; diff --git a/src/scad_geometry.h b/src/scad_geometry.h @@ -21,12 +21,12 @@ #include <rsys/rsys.h> #include <rsys/str.h> -struct scad_scene; +struct scad_device; struct scad_geometry { int* gmsh_dimTags; size_t gmsh_dimTags_n; - struct scad_scene* scene; + struct scad_device* device; struct str name; int is_group, group_dim; }; diff --git a/src/scad_scene.c b/src/scad_scene.c @@ -1,172 +0,0 @@ -/* 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/>. */ - -#define _POSIX_C_SOURCE 200112L /* snprintf */ - -#include "scad.h" -#include "scad_c.h" -#include "scad_scene.h" -#include "scad_device.h" - -#include <rsys/rsys.h> - -#include <stdio.h> -#include <gmshc.h> - -/******************************************************************************* - * Helper functions - ******************************************************************************/ -static res_T -set_name - (struct scad_scene* scene) -{ - int n; - ASSERT(scene); - n = snprintf(scene->name, sizeof(scene->name), "%x", - scene->device->next_scene_id++); - if((size_t)n >= sizeof(scene->name)) return RES_BAD_ARG; - return RES_OK; -} - -static void -scene_release(ref_T* ref) -{ - struct scad_scene* scn; - struct mem_allocator* allocator; - struct htable_names_iterator it, end; - int ierr = 0; - res_T res; - ASSERT(ref); - scn = CONTAINER_OF(ref, struct scad_scene, ref); - allocator = scn->device->allocator; - htable_names_begin(&scn->geometry_names, &it); - htable_names_end(&scn->geometry_names, &end); - while(!htable_names_iterator_eq(&it, &end)) { - struct scad_geometry* geom = *htable_names_iterator_data_get(&it); - ASSERT(geom->scene == scn); - SCAD(geometry_release(geom)); - htable_names_iterator_next(&it); - } - htable_names_release(&scn->geometry_names); - res = device_set_current_scene(scn); - ASSERT(res == RES_OK); (void)res; - gmshModelRemove(&ierr); - ASSERT(!ierr); (void)ierr; - scn->device->current_scene = NULL; - SCAD(device_ref_put(scn->device)); - MEM_RM(allocator, scn); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ - -/******************************************************************************* - * Exported scad_scene functions - ******************************************************************************/ -res_T -scad_scene_create - (struct scad_device* device, - struct scad_scene** out_scene) -{ - struct scad_scene* scn = NULL; - int ierr = 0; - res_T res = RES_OK; - - if(!out_scene || !device) { - res = RES_BAD_ARG; - goto error; - } - - scn = (struct scad_scene*)MEM_CALLOC(device->allocator, 1, - sizeof(struct scad_scene)); - if(!scn) { - res = RES_MEM_ERR; - goto error; - } - htable_names_init(device->allocator, &scn->geometry_names); - scn->device = device; - set_name(scn); - scn->is_meshed = 0; - ref_init(&scn->ref); - SCAD(device_ref_get(scn->device)); - - gmshModelAdd(scn->name, &ierr); - ERR(gmsh_err_to_res_T(ierr)); - - device->current_scene = scn; - -exit: - if(out_scene) *out_scene = scn; - return res; -error: - if(scn) { - SCAD(scene_ref_put(scn)); - scn = NULL; - } - goto exit; -} - -res_T -scad_scene_conformal_mesh - (struct scad_scene* scene) -{ - int* dimTags = NULL; - size_t dimTags_n; - int ierr = 0; - res_T res = RES_OK; - - scene->device->need_synchro = 1; - device_set_current_scene(scene); - gmshModelOccSynchronize(&ierr); - ERR(gmsh_err_to_res_T(ierr)); - gmshModelOccGetEntities(&dimTags, &dimTags_n, 3, &ierr); - ERR(gmsh_err_to_res_T(ierr)); - if(dimTags_n > 2) { - /* Remove all duplicate entities in the OpenCASCADE CAD representation - * (different entities at the same geometrical location) after intersecting - * (using boolean fragments) all highest dimensional entities. */ - gmshModelOccRemoveAllDuplicates(&ierr); - ERR(gmsh_err_to_res_T(ierr)); - } - gmshModelOccSynchronize(&ierr); - ERR(gmsh_err_to_res_T(ierr)); - gmshModelMeshGenerate(2, &ierr); - ERR(gmsh_err_to_res_T(ierr)); - scene->is_meshed = 1; - -exit: - if(dimTags) free(dimTags); - return res; -error: - goto exit; -} - - -res_T -scad_scene_ref_get(struct scad_scene* scene) -{ - if(!scene) return RES_BAD_ARG; - ref_get(&scene->ref); - return RES_OK; -} - -res_T -scad_scene_ref_put(struct scad_scene* scene) -{ - if(!scene) return RES_BAD_ARG; - ref_put(&scene->ref, scene_release); - return RES_OK; -} diff --git a/src/scad_scene.h b/src/scad_scene.h @@ -1,61 +0,0 @@ -/* 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/>. */ - -#ifndef SCAD_SCENE_H -#define SCAD_SCENE_H - -#include "scad.h" - -struct scad_device; -struct scad_geometry; - -#include <rsys/ref_count.h> -#include <rsys/hash_table.h> -#include <rsys/str.h> - -static INLINE char -eq_str(const struct str* a, const struct str* b) -{ - return !strcmp(str_cget(a), str_cget(b)); -} - -static INLINE size_t -hash_str(const struct str* a) -{ - return hash_fnv32(str_cget(a), str_len(a)); -} - -#define HTABLE_NAME names -#define HTABLE_DATA struct scad_geometry* -#define HTABLE_KEY struct str -#define HTABLE_KEY_FUNCTOR_INIT str_init -#define HTABLE_KEY_FUNCTOR_RELEASE str_release -#define HTABLE_KEY_FUNCTOR_COPY str_copy -#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> - -struct scad_scene { - struct scad_device* device; - struct htable_names geometry_names; - char name[8]; - int is_meshed; - - ref_T ref; -}; - -#endif diff --git a/src/test1.c b/src/test1.c @@ -51,41 +51,38 @@ main(int argc, char* argv[]) struct scad_geometry* f2 = NULL; struct scad_geometry* sphere = NULL; struct scad_geometry* geoms[2]; - struct scad_device* dev = NULL; - struct scad_scene* scene = NULL; + struct scad_device* device = NULL; struct mem_allocator allocator; (void)argc; (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(scad_device_create(NULL, &allocator, 1, &dev)); - OK(scad_scene_create(dev, &scene)); + OK(scad_device_create(NULL, &allocator, 1, &device)); - OK(scad_scene_add_cylinder(scene, "c1", p1, d1, 2, PI, &geom1)); - OK(scad_scene_add_box(scene, "b1", p2, d2, &geom2)); + OK(scad_add_cylinder(device, "c1", p1, d1, 2, PI, &geom1)); + OK(scad_add_box(device, "b1", p2, d2, &geom2)); OK(scad_stl_export(geom1, NULL, 1)); OK(scad_stl_export(geom2, NULL, 1)); geoms[0] = geom1; geoms[1] = geom2; - OK(scad_scene_create_group(scene, "g1", 3, geoms, 2, &group1)); + OK(scad_create_group(device, "g1", 3, geoms, 2, &group1)); OK(scad_stl_export(group1, NULL, 1)); - OK(scad_scene_conformal_mesh(scene)); + OK(scad_conformal_mesh(device)); OK(scad_stl_export_split(group1, "conformal", 1)); - OK(scad_scene_add_cylinder(scene, "cyl", p1, d1, 1, 2*PI, &cyl)); + OK(scad_add_cylinder(device, "cyl", p1, d1, 1, 2*PI, &cyl)); OK(scad_stl_export(cyl, NULL, 1)); - OK(scad_scene_fuse_geometries(scene, "fused1", geom1, cyl, &f1, 0)); + OK(scad_fuse_geometries(device, "fused1", geom1, cyl, &f1, 0)); OK(scad_stl_export(f1, NULL, 1)); - OK(scad_scene_add_sphere(scene, "s1", p1, 1, &sphere)); - OK(scad_scene_fuse_geometries(scene, "fused2", group1, sphere, &f2, 0)); + OK(scad_add_sphere(device, "s1", p1, 1, &sphere)); + OK(scad_fuse_geometries(device, "fused2", group1, sphere, &f2, 0)); OK(scad_stl_export(f2, NULL, 0)); exit: - if(dev) SCAD(device_ref_put(dev)); - if(scene) SCAD(scene_ref_put(scene)); + if(device) SCAD(device_ref_put(device)); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator);