star-cad

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

commit 2580f7a37551a32d2de624b989b01c55c5b28782
parent 86c188aa026fbccd9e8cd399e722299b653d91bb
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 20 Dec 2024 11:16:33 +0100

Add an API call to declare periodic surfaces

Flags some target surfaces as being the result of applying an affine
transform to some source surfaces.
As a result the target surfaces are meshed in the same way as the source
surfaces (i.e. the target mesh is the affine transform of the source
mesh).

Diffstat:
Msrc/scad.h | 15+++++++++++++++
Msrc/scad_geometry.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 88 insertions(+), 8 deletions(-)

diff --git a/src/scad.h b/src/scad.h @@ -563,6 +563,21 @@ SCAD_API res_T scad_scene_mesh (void); +/* Flag `target' geometries as being the result of applying the `affine' + * tranform to `source' geometries. + * The result is that the mesh generated for `target' is the image on the mesh + * generated for `source' through the `affine' transform. + * Only apply to surfaces (dimension 2). If called on a volume, it applies to + * its 2D constituents. + * The two sets of surfaces must match exactly (same number of points, etc.). */ +SCAD_API res_T +scad_geometries_set_periodic + (struct scad_geometry** source, + const size_t source_count, + struct scad_geometry** target, + const size_t target_count, + double affine[16]); + /* Set a size modifier for geometries in `geometries'. * When meshing these geometries, triangles' size will be either size*modifier, * or modifier where size would be the size of the triangle in the absence of a diff --git a/src/scad_geometry.c b/src/scad_geometry.c @@ -278,6 +278,7 @@ static res_T gather_tags_recursive (struct scad_geometry** geometries, const size_t geometries_count, + const int down_to_dim, int* out_dimTags[4], size_t out_dimTags_n[4]) { @@ -291,8 +292,9 @@ gather_tags_recursive int dim; ASSERT((geometries || geometries_count == 0) && out_dimTags && out_dimTags_n); + ASSERT(0 <= down_to_dim && down_to_dim <= 3); - for(i = 0; i < 4; i++) { + for(i = (size_t)down_to_dim; i < 4; i++) { htable_tags_init(allocator, t+i); } @@ -305,11 +307,12 @@ gather_tags_recursive ERR(store_tags(geometries[i]->gmsh_dimTags, geometries[i]->gmsh_dimTags_n, t)); } - /* Recursively build result by dimension and list constituants, + /* Recursively build result by dimension and list constituents, * begining with dim==3 */ - for(dim = 3; dim >= 0; dim--) { + for(dim = 3; dim >= down_to_dim; dim--) { size_t c = 0; sz[dim] = 2 * htable_tags_size_get(t+dim); + if(sz[dim] == 0) continue; dimTags[dim] = MEM_ALLOC(allocator, sz[dim] * sizeof(*dimTags)); if(!dimTags[dim]) { res = RES_MEM_ERR; @@ -322,7 +325,7 @@ gather_tags_recursive dimTags[dim][c++] = *htable_tags_iterator_key_get(&it); htable_tags_iterator_next(&it); } - if(dim > 0) { + if(dim > down_to_dim) { int ierr; size_t subn; gmshModelGetBoundary(dimTags[dim], sz[dim], &sub, &subn, 0, 0, 0, &ierr); @@ -333,19 +336,19 @@ gather_tags_recursive ASSERT(sz[dim] == c); } - for(i = 0; i < 4; i++) { + for(i = (size_t)down_to_dim; i < 4; i++) { out_dimTags_n[i] = sz[i]; out_dimTags[i] = dimTags[i]; } exit: if(sub) gmshFree(sub); - for(i = 0; i < 4; i++) { + for(i = (size_t)down_to_dim; i < 4; i++) { htable_tags_release(t+i); } return res; error: - for(i = 0; i < 4; i++) { + for(i = (size_t)down_to_dim; i < 4; i++) { MEM_RM(allocator, dimTags[i]); } goto exit; @@ -2767,8 +2770,8 @@ scad_geometries_set_mesh_size_modifier ERR(check_device(FUNC_NAME)); - ERR(gather_tags_recursive(geometries, geometries_count, tagout, tagoutn)); if(type == Scad_absolute_size) modifier = -modifier; + ERR(gather_tags_recursive(geometries, geometries_count, 0, tagout, tagoutn)); for(dim = 0; dim < 4; dim++) { for(i = 0; i < tagoutn[dim]; i += 2) { int d = tagout[dim][i]; @@ -2804,3 +2807,65 @@ exit: error: goto exit; } + +res_T +scad_geometries_set_periodic + (struct scad_geometry** source, + const size_t source_count, + struct scad_geometry** target, + const size_t target_count, + double affine[16]) +{ + res_T res = RES_OK; + struct scad_device* dev = get_device(); + struct mem_allocator* allocator = dev->allocator; + int ierr; + int* src_dimTagout[4] = { NULL, NULL, NULL, NULL }; + int* tgt_dimTagout[4] = { NULL, NULL, NULL, NULL }; + int* src_tags = NULL, *tgt_tags = NULL; + size_t src_dimTagoutn[4], tgt_dimTagoutn[4], src_tagsn = 0, tgt_tagsn = 0, i; + + if(!source || source_count == 0 || !target || target_count == 0 || !affine) { + res = RES_BAD_ARG; + goto error; + } + + ERR(check_device(FUNC_NAME)); + + ERR(gather_tags_recursive(source, source_count, 2, src_dimTagout, src_dimTagoutn)); + ERR(gather_tags_recursive(target, target_count, 2, tgt_dimTagout, tgt_dimTagoutn)); + ASSERT(src_dimTagoutn[2] % 2 == 0 && tgt_dimTagoutn[2] % 2 == 0); + src_tagsn = src_dimTagoutn[2] / 2; + tgt_tagsn = tgt_dimTagoutn[2] / 2; + if(src_tagsn == 0 || tgt_tagsn == 0) { + res = RES_BAD_ARG; + goto error; + } + + src_tags = MEM_ALLOC(allocator, src_tagsn); + tgt_tags = MEM_ALLOC(allocator, tgt_tagsn); + if(!src_tags || !tgt_tags) { + res = RES_MEM_ERR; + goto error; + } + for(i = 0; i < src_tagsn; i += 2) { + src_tags[i] = src_dimTagout[2][i+1]; + } + for(i = 0; i < tgt_tagsn; i += 2) { + tgt_tags[i] = tgt_dimTagout[2][i+1]; + } + gmshModelMeshSetPeriodic(2, tgt_tags, tgt_tagsn, src_tags, src_tagsn, + affine, 16, &ierr); + ERR(gmsh_err_to_res_T(ierr)); + +exit: + for(i = 2; i < 4; i++) { + MEM_RM(dev->allocator, src_dimTagout[i]); + MEM_RM(dev->allocator, tgt_dimTagout[i]); + } + MEM_RM(dev->allocator, src_tags); + MEM_RM(dev->allocator, tgt_tags); + return res; +error: + goto exit; +}