mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
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:
co-authored by
Claude Opus 4.8
parent
8edc12c8f1
commit
b807be3c4a
@@ -1852,4 +1852,10 @@ bool CadDocument::export_step(const std::string& path,
|
||||
return true;
|
||||
}
|
||||
|
||||
GeometryEngine::MassProps CadDocument::body_mass_properties(int body_index) const
|
||||
{
|
||||
if (body_index < 0 || body_index >= int(bodies.size())) return {};
|
||||
return GeometryEngine::mass_properties(bodies[body_index].shape);
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -371,6 +371,8 @@ public:
|
||||
const std::vector<Transform3d>& body_xforms,
|
||||
std::string& err) const;
|
||||
|
||||
GeometryEngine::MassProps body_mass_properties(int body_index) const;
|
||||
|
||||
// Undo/redo of the feature recipe (Onshape-style Ctrl+Z). The caller marks a
|
||||
// user-action boundary by calling checkpoint() BEFORE the mutation(s) for that
|
||||
// action (add/delete/move/replace, or a direct features edit). undo()/redo() then
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -94,6 +94,15 @@ public:
|
||||
double merge_angle_deg,
|
||||
MeshBrepStats& stats);
|
||||
|
||||
struct MassProps {
|
||||
double volume{0.0};
|
||||
double surface_area{0.0};
|
||||
Vec3d center_of_mass{Vec3d::Zero()};
|
||||
std::array<double, 9> inertia{};
|
||||
bool valid{false};
|
||||
};
|
||||
static MassProps mass_properties(const TopoDS_Shape& shape);
|
||||
|
||||
struct Deviation { double max_mm{0}; double mean_mm{0}; double rms_mm{0}; int sample_count{0}; };
|
||||
static Deviation surface_deviation(const TopoDS_Shape& candidate,
|
||||
const TopoDS_Shape& reference,
|
||||
|
||||
Reference in New Issue
Block a user