CAD: a sheet body reports no volume, instead of a confident wrong one

mass_properties on an open shell returned volume 96000 with an inertia diagonal
of [-4.2e7, -4.2e7, -6.9e7] for a 60x60x40 four-walled box — negative principal
moments, which no real body can have. BRepGProp::VolumeProperties integrates the
divergence theorem over whatever faces exist; on an open shell that is not a
volume at all, and the old code hid the only obvious tell by taking std::abs()
of the mass. "valid: true" then asserted the number was trustworthy.

This matters because mass_properties is what an agent or a user reaches for to
confirm a cut removed the right material. Silent nonsense there means the check
passes on garbage.

MassProps gains is_solid. For a sheet we compute surface area only — that stays
exact — and report volume 0 with the inertia left zeroed. The MCP verb returns
is_solid plus a note saying volume and inertia are not defined for an open
shell; the GUI's Mass command says "sheet body — N cm² of surface, no volume"
rather than quoting material that is not there.

Verified on the rig: the sheet now returns volume 0.0, surface_area 9600.0
(exactly 4 x 60 x 40), is_solid false. The solid controls are unchanged and
exact — a 60 mm cube reports 216000.0 and 21600.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tommaso Bianchi
2026-08-14 13:35:03 +02:00
co-authored by Claude Opus 5
parent 1545fb7946
commit 9013f530fa
4 changed files with 43 additions and 0 deletions
+15
View File
@@ -470,6 +470,21 @@ GeometryEngine::MassProps GeometryEngine::mass_properties(const TopoDS_Shape& sh
MassProps p;
if (shape.IsNull()) return p;
try {
// A sheet body (open shell, no solid) encloses nothing, and BRepGProp::VolumeProperties
// integrates the divergence theorem over whatever faces exist — on an open shell that is
// not a volume at all. It came back as 96000 with an inertia diagonal of
// [-4.2e7, -4.2e7, -6.9e7] for a 60x60x40 four-walled box: negative principal moments,
// which no real body can have. The old code then hid the only obvious tell by taking
// std::abs() of the mass. Report the honest answer instead — surface area is still
// meaningful, so this is not a failure, just not a solid.
p.is_solid = TopExp_Explorer(shape, TopAbs_SOLID).More();
if (!p.is_solid) {
GProp_GProps sonly;
BRepGProp::SurfaceProperties(shape, sonly);
p.surface_area = sonly.Mass();
p.valid = true; // the area IS trustworthy; volume/inertia stay zero
return p;
}
GProp_GProps vprops;
BRepGProp::VolumeProperties(shape, vprops);
double mass = vprops.Mass();
+3
View File
@@ -100,6 +100,9 @@ public:
Vec3d center_of_mass{Vec3d::Zero()};
std::array<double, 9> inertia{};
bool valid{false};
// False for a sheet body (an open shell with no solid). Volume and inertia are then
// meaningless and are reported as zero; surface_area stays meaningful. See the .cpp.
bool is_solid{false};
};
static MassProps mass_properties(const TopoDS_Shape& shape);