mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +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)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class CadFeatureType { Sketch, Extrude, Fillet, Chamfer, Hole, Thread, Shell, Revolve, Sweep, Pattern, Plane, Loft, Draft, Import, Boolean, Cut, Mirror, Axis, CoordSys, Helix, Transform, Thicken, Project, DeleteFace };
|
||||
enum class CadFeatureType { Sketch, Extrude, Fillet, Chamfer, Hole, Thread, Shell, Revolve, Sweep, Pattern, Plane, Loft, Draft, Import, Boolean, Cut, Mirror, Axis, CoordSys, Helix, Transform, Thicken, Project, DeleteFace, Rib };
|
||||
enum class SketchShape { Rectangle, Circle };
|
||||
enum class PlaneType { Offset, Angle, Midplane, Tangent, TwoEdges, Coincident };
|
||||
enum class AxisType { TwoPoints, FaceNormal, CylinderCenterline, PlaneIntersection, AlongEdge };
|
||||
@@ -276,6 +276,12 @@ struct CadFeature {
|
||||
// healed via BRepAlgoAPI_Defeaturing.
|
||||
std::vector<int> delete_faces;
|
||||
|
||||
// Rib: a thin wall grown from an open sketch line, fused to the body.
|
||||
int rib_sketch_ref{-1}; // feature index of the Sketch holding the profile
|
||||
int rib_entity{-1}; // index of the open Line entity within that sketch
|
||||
double rib_thickness{2}; // wall thickness (mm), centred on the line
|
||||
double rib_depth{10}; // extrude distance along the sketch-plane normal (mm)
|
||||
|
||||
template<class Archive>
|
||||
void save(Archive& ar) const {
|
||||
std::string brep = (type == CadFeatureType::Import) ? brep_to_string(imported_solid) : std::string();
|
||||
@@ -308,7 +314,8 @@ struct CadFeature {
|
||||
project_source_body, project_edges, project_face,
|
||||
delete_faces,
|
||||
hole_style, hole_cbore_diameter, hole_cbore_depth,
|
||||
hole_csink_diameter, hole_csink_angle, hole_standard);
|
||||
hole_csink_diameter, hole_csink_angle, hole_standard,
|
||||
rib_sketch_ref, rib_entity, rib_thickness, rib_depth);
|
||||
}
|
||||
template<class Archive>
|
||||
void load(Archive& ar) {
|
||||
@@ -340,9 +347,10 @@ struct CadFeature {
|
||||
thicken_face, thicken_thickness, thicken_flip,
|
||||
cut_face_body, cut_face,
|
||||
project_source_body, project_edges, project_face,
|
||||
delete_faces,
|
||||
hole_style, hole_cbore_diameter, hole_cbore_depth,
|
||||
hole_csink_diameter, hole_csink_angle, hole_standard);
|
||||
delete_faces,
|
||||
hole_style, hole_cbore_diameter, hole_cbore_depth,
|
||||
hole_csink_diameter, hole_csink_angle, hole_standard,
|
||||
rib_sketch_ref, rib_entity, rib_thickness, rib_depth);
|
||||
imported_solid = brep_from_string(brep);
|
||||
}
|
||||
};
|
||||
@@ -449,6 +457,10 @@ public:
|
||||
int add_loft(const std::vector<int>& profile_refs, bool ruled, BooleanMode mode,
|
||||
const std::string& name);
|
||||
int add_shell(double thickness, int face, int target_body, const std::string& name);
|
||||
// Grow a thin rib wall (thickness, depth) from the open Line entity `entity` inside sketch
|
||||
// feature `sketch_ref`, fused to `target_body`. Returns the new feature index.
|
||||
int add_rib(int sketch_ref, int entity, double thickness, double depth,
|
||||
int target_body, const std::string& name);
|
||||
int add_draft(double angle, int face, int target_body, const std::string& name);
|
||||
// Boolean between two existing bodies. op reuses BooleanMode (Add=union, Cut=subtract,
|
||||
// Intersect=common; New invalid). target survives, tool is consumed unless keep_tool.
|
||||
|
||||
Reference in New Issue
Block a user