mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-26 10:21:00 +00:00
M5b: rib — thin stiffening wall grown from an open sketch line
New CadFeatureType::Rib (appended). A straight open Line entity in a sketch is offset ±thickness/2 along its in-plane perpendicular into a thin rectangle, extruded rib_depth along the sketch-plane normal, and fused to the target body. Line-only for now (ponytail; polyline/arc ribs are a later extension) — a non-line entity fails cleanly at recompute. Four serialized fields (rib_sketch_ref/rib_entity/rib_thickness/rib_depth) appended to both symmetric cereal lists (version stays 2, golden fixture regenerated 29525->30269). MCP: rib. 3 new [CadDocument][rib] tests; suite 86/1376. 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
0bbf22ceae
commit
a606dfe00a
@@ -748,6 +748,21 @@ int CadDocument::add_shell(double thickness, int face, int target_body, const st
|
||||
return int(features.size()) - 1;
|
||||
}
|
||||
|
||||
int CadDocument::add_rib(int sketch_ref, int entity, double thickness, double depth,
|
||||
int target_body, const std::string& name)
|
||||
{
|
||||
CadFeature f;
|
||||
f.type = CadFeatureType::Rib;
|
||||
f.name = name;
|
||||
f.rib_sketch_ref = sketch_ref;
|
||||
f.rib_entity = entity;
|
||||
f.rib_thickness = thickness;
|
||||
f.rib_depth = depth;
|
||||
f.target_body = target_body;
|
||||
features.push_back(f);
|
||||
return int(features.size()) - 1;
|
||||
}
|
||||
|
||||
int CadDocument::add_delete_face(int target_body, const std::vector<int>& faces,
|
||||
const std::string& name)
|
||||
{
|
||||
@@ -1784,6 +1799,38 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CadFeatureType::Rib: {
|
||||
if (!have_body) throw std::runtime_error("rib needs a body");
|
||||
if (f.rib_sketch_ref < 0 || f.rib_sketch_ref >= (int)features.size())
|
||||
throw std::runtime_error("rib: bad sketch ref");
|
||||
const CadFeature& sk = features[f.rib_sketch_ref];
|
||||
if (sk.type != CadFeatureType::Sketch)
|
||||
throw std::runtime_error("rib: ref is not a sketch");
|
||||
if (f.rib_entity < 0 || f.rib_entity >= (int)sk.entities.size())
|
||||
throw std::runtime_error("rib: bad entity");
|
||||
const SketchEntity& ln = sk.entities[f.rib_entity];
|
||||
if (ln.type != SketchEntity::Type::Line)
|
||||
throw std::runtime_error("rib: entity must be a line"); // ponytail: line-only for now
|
||||
// Thin rectangle centred on the line, in the sketch plane: offset both endpoints by
|
||||
// +/-thickness/2 along the in-plane perpendicular of the line direction.
|
||||
const SketchPlane& pl = sk.plane;
|
||||
Vec2d a = ln.p0, b = ln.p1;
|
||||
Vec2d dir = (b - a); double L = dir.norm();
|
||||
if (L < 1e-9) throw std::runtime_error("rib: degenerate line");
|
||||
dir /= L;
|
||||
Vec2d perp(-dir.y(), dir.x());
|
||||
double h = f.rib_thickness * 0.5;
|
||||
Vec2d q0 = a + perp*h, q1 = b + perp*h, q2 = b - perp*h, q3 = a - perp*h;
|
||||
auto w3 = [&](const Vec2d& p){ Vec3d w = pl.to_world(p); return gp_Pnt(w.x(),w.y(),w.z()); };
|
||||
BRepBuilderAPI_MakePolygon poly(w3(q0), w3(q1), w3(q2), w3(q3), Standard_True);
|
||||
if (!poly.IsDone()) throw std::runtime_error("rib: profile failed");
|
||||
TopoDS_Shape wall = SketchEngine::make_extrude(poly.Wire(), pl, f.rib_depth, false, 0.0);
|
||||
if (wall.IsNull()) throw std::runtime_error("rib: extrude failed");
|
||||
BRepAlgoAPI_Fuse fuse(result, wall);
|
||||
if (!fuse.IsDone()) throw std::runtime_error("rib: fuse failed");
|
||||
result = fuse.Shape();
|
||||
break;
|
||||
}
|
||||
case CadFeatureType::Fillet:
|
||||
if (!have_body) throw std::runtime_error("fillet needs a body");
|
||||
if (f.dressup_edge >= 0)
|
||||
|
||||
Reference in New Issue
Block a user