M4: delete-face direct edit — remove faces and heal via OCCT defeaturing

New CadFeatureType::DeleteFace: removes a set of global face ids from target_body
and heals the gap via BRepAlgoAPI_Defeaturing (TKBO, already linked), mirroring the
Shell/Draft body-modifying pattern. delete_faces appended to both symmetric cereal
lists (recipe version stays 2, golden fixture regenerated 27913->28161). MCP
delete_face method (pure additions). 3 new [CadDocument][deleteface] tests: remove a
fillet face restores the sharp-box volume, bad index fails safely, round-trip.
Full kernel suite green (79 cases, 1309 asserts).

Move-face / replace-face deferred to snaporca-3c4 / snaporca-tc6 (no clean shipping
OCCT direct-modeling primitive; need research, and replace-face depends on M7 surfaces).

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-25 03:28:25 +02:00
co-authored by Claude Opus 4.8
parent 65caa2ea6e
commit e19e51b150
5 changed files with 179 additions and 10 deletions
+29
View File
@@ -13,6 +13,7 @@
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepAlgoAPI_Cut.hxx>
#include <BRepAlgoAPI_Common.hxx>
#include <BRepAlgoAPI_Defeaturing.hxx>
#include <BRepAlgoAPI_BooleanOperation.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
#include <BRepOffsetAPI_MakePipeShell.hxx>
@@ -680,6 +681,18 @@ int CadDocument::add_shell(double thickness, int face, int target_body, const st
return int(features.size()) - 1;
}
int CadDocument::add_delete_face(int target_body, const std::vector<int>& faces,
const std::string& name)
{
CadFeature f;
f.type = CadFeatureType::DeleteFace;
f.name = name;
f.target_body = target_body;
f.delete_faces = faces;
features.push_back(f);
return int(features.size()) - 1;
}
int CadDocument::add_draft(double angle, int face, int target_body, const std::string& name)
{
CadFeature f;
@@ -1873,6 +1886,22 @@ void CadDocument::apply_feature(TopoDS_Shape& result, bool& have_body,
if (result.IsNull()) throw std::runtime_error("draft produced no geometry");
break;
}
case CadFeatureType::DeleteFace: {
if (!have_body) throw std::runtime_error("delete_face needs a body");
if (f.delete_faces.empty()) throw std::runtime_error("delete_face needs at least one face");
BRepAlgoAPI_Defeaturing df;
df.SetShape(result);
for (int fi : f.delete_faces) {
TopoDS_Face fc = GeometryEngine::face_by_index(result, fi);
if (fc.IsNull()) throw std::runtime_error("delete_face: face not found");
df.AddFaceToRemove(fc);
}
df.Build();
if (!df.IsDone()) throw std::runtime_error("delete_face failed");
result = df.Shape();
if (result.IsNull()) throw std::runtime_error("delete_face produced no geometry");
break;
}
}
}