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:
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;
+}