[Bug]: [freecad] measure center-of-mass wrong for sphere/cylinder/cone/torus
Affected Software/Harness
freecad (cli-anything-freecad)
Version / Commit
cli-anything-freecad 1.1.0 (via cli-hub info freecad), cli-anything-hub 0.4.1
Operating System
Windows
Python Version
3.13.13
Steps to Reproduce
cli-anything-freecad document new -o doc.json
cli-anything-freecad --project doc.json part add sphere -pos 0,0,0 -P radius=10
cli-anything-freecad --project doc.json measure position 0
cli-anything-freecad --project doc.json measure center-of-mass 0
# control case, same origin
cli-anything-freecad --project doc.json part add box -pos 0,0,0 -P length=10 -P width=10 -P height=10
cli-anything-freecad --project doc.json measure center-of-mass 1
Expected Behavior
For a sphere, measure center-of-mass should return the same point as measure position (a sphere is centrally symmetric about its own placement — its center of mass is its placement position, by definition, independent of any external convention). This is self-consistent within the harness's own data model, not an assumption about FreeCAD internals.
Actual Behavior
measure position 0 -> position: [0.0, 0.0, 0.0]
measure center-of-mass 0 -> center_of_mass: [10.0, 10.0, 10.0]
The reported center of mass is ~17.3 units from the origin — outside the sphere's own surface (radius 10) — for a sphere the harness's own measure position says is placed exactly at the origin. The box control at the same origin correctly returns [5.0, 5.0, 5.0] (its true geometric center, since a FreeCAD box's placement is its min corner), confirming the harness's box-center math is fine and the bug is specific to the other primitive types.
Relevant Logs / Tracebacks
$ cli-anything-freecad --project doc.json measure center-of-mass 0
Center of mass: [10.0, 10.0, 10.0]
id: 1
kind: center_of_mass
part_index: 0
center_of_mass: [10.0, 10.0, 10.0]
No exception — this is a silent, wrong-value bug, not a crash.
Root cause
cli_anything/freecad/core/measure.py, function _bbox_center() (called by measure_center_of_mass()), computes every primitive's bounding-box center by adding a min-corner offset to Placement.position:
elif t == "sphere":
r = p["radius"]
return [pos[0] + r, pos[1] + r, pos[2] + r]
and the analogous pos[i] + r/pos[2] + height/2 pattern for cylinder, cone, and torus. This is only correct for box and wedge, whose placement really is their bounding-box min corner. For sphere, cylinder, cone, and torus, the harness's own measure position / part add -pos treats the placement as the shape's own center (sphere, cylinder, cone) or torus center — so adding the radius again double-counts the offset and produces a point that is wrong (and, as in the sphere case above, physically outside the solid).
Affects: sphere, cylinder, cone, torus. Confirmed box is correct; did not test wedge.
Suggested Fix
In _bbox_center(), for sphere/cylinder/cone/torus, return pos (or pos with only the z-offset already used for height, where applicable) directly rather than adding the radius — matching what measure_position() already reports for the same part. box/wedge can keep their current min-corner-based math.
Source: HKUDS/CLI-Anything