CAD mass properties: volume / area / centre of mass / inertia

Port of snaporca c2821af783. New GeometryEngine::mass_properties over BRepGProp
(separate VolumeProperties/SurfaceProperties), bounds-checked
CadDocument::body_mass_properties, and a mass_properties MCP method. Query-only:
no CadFeature, no serialization, no version change. Analytic tests
(WithinRel/WithinAbs): cube 8000/2400/COM(0,0,10)/inertia 533333, cylinder
500pi/300pi, hollow = solid-500pi, invalid index -> valid=false.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
This commit is contained in:
Tommaso Bianchi
2026-07-23 23:18:42 +02:00
co-authored by Claude Opus 4.8
parent 8edc12c8f1
commit b807be3c4a
6 changed files with 169 additions and 0 deletions
+27
View File
@@ -465,6 +465,33 @@ GeometryEngine::surface_deviation(const TopoDS_Shape& candidate,
return d;
}
GeometryEngine::MassProps GeometryEngine::mass_properties(const TopoDS_Shape& shape)
{
MassProps p;
if (shape.IsNull()) return p;
try {
GProp_GProps vprops;
BRepGProp::VolumeProperties(shape, vprops);
double mass = vprops.Mass();
if (std::abs(mass) < 1e-30) return p;
p.volume = std::abs(mass);
p.center_of_mass = Vec3d(vprops.CentreOfMass().X(), vprops.CentreOfMass().Y(), vprops.CentreOfMass().Z());
gp_Mat mat = vprops.MatrixOfInertia();
p.inertia = {{
mat(1,1), mat(1,2), mat(1,3),
mat(2,1), mat(2,2), mat(2,3),
mat(3,1), mat(3,2), mat(3,3),
}};
GProp_GProps sprops;
BRepGProp::SurfaceProperties(shape, sprops);
p.surface_area = sprops.Mass();
p.valid = true;
} catch (const Standard_Failure&) {
// leave valid = false
}
return p;
}
std::string GeometryEngine::primitive_name(PrimitiveType type)
{
switch (type) {