commit 632e64b00f456d80a36c384f6334d6a49d5be1a4
parent db7bfdf1058db9ac8b05308281a218fdd679ac20
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 29 Jul 2025 13:47:24 +0200
Change the way get_centerofmass works
Now returns the true center of mass as a single point. Used to return a
list of centers, one by geometry's component.
The signature was changed accordingly.
Diffstat:
2 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/src/scad.h b/src/scad.h
@@ -386,13 +386,11 @@ scad_geometry_get_mass
(struct scad_geometry* geometry,
double* mass);
-/* Get the center of mass of the various components of geometry `geometry'.
- * Note that `center' must be allocated by the caller with enough room for (at
- * least) 3 times the count of geom (scad_geometry_get_count) doubles. */
+/* Get the center of mass of geometry `geometry' in `center'. */
SCAD_API res_T
scad_geometry_get_centerofmass
(struct scad_geometry* geometry,
- double* center);
+ double center[3]);
/* Get the `closest' point on geometry `geometry' from point `from'.
* Return the `closest' point and its `distance'.
diff --git a/src/scad_geometry.c b/src/scad_geometry.c
@@ -807,10 +807,13 @@ error:
res_T
scad_geometry_get_centerofmass
(struct scad_geometry* geom,
- double* center)
+ double center[3])
{
res_T res = RES_OK;
- size_t i = 0;
+ double *centers = NULL, *masses = NULL;
+ size_t i = 0, count;
+ struct mem_allocator* allocator;
+ int ierr;
if(!geom || !center) {
res = RES_BAD_ARG;
@@ -819,19 +822,39 @@ scad_geometry_get_centerofmass
ERR(check_device(FUNC_NAME));
- for(i = 0; i < geom->gmsh_dimTags_n; i += 2) {
- double x, y, z;
- int ierr = 0;
+ ASSERT(geom->gmsh_dimTags_n % 2 == 0);
+ count = geom->gmsh_dimTags_n / 2;
+ if(count == 1) {
int dim = geom->gmsh_dimTags[i];
int tag = geom->gmsh_dimTags[i + 1];
- gmshModelOccGetCenterOfMass(dim, tag, &x, &y, &z, &ierr);
+ gmshModelOccGetCenterOfMass(dim, tag, center, center+1, center+2, &ierr);
ERR(gmsh_err_to_res_T(ierr));
- center[3*i] = x;
- center[3*i + 1] = y;
- center[3*i + 2] = z;
+ } else {
+ double c[3] = { 0, 0, 0 }, tmp[3], m = 0;
+ allocator = get_device()->allocator;
+ centers = MEM_ALLOC(allocator, count * 3 * sizeof(*centers));
+ masses = MEM_ALLOC(allocator, count * sizeof(*masses));
+ if(!centers || !masses) {
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ for(i = 0; i < count; i++) {
+ int dim = geom->gmsh_dimTags[2*i];
+ int tag = geom->gmsh_dimTags[2*i + 1];
+ gmshModelOccGetCenterOfMass(dim, tag,
+ centers+3*i, centers+3*i+1, centers+3*i+2, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+ gmshModelOccGetMass(dim, tag, masses+i, &ierr);
+ ERR(gmsh_err_to_res_T(ierr));
+ d3_add(c, c, d3_muld(tmp, centers+3*i, masses[i]));
+ m += masses[i];
+ }
+ d3_muld(center, c, 1/m);
}
exit:
+ if(centers) MEM_RM(allocator, centers);
+ if(masses) MEM_RM(allocator, masses);
return res;
error:
goto exit;