mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-26 10:21:00 +00:00
CAD: split a body by a picked face; add the missing both-halves cut test
Split-by-face reuses the existing Cut feature rather than adding a new type: two appended fields (cut_face_body, cut_face) let apply_cut derive the cut plane from a picked face via SketchPlane::from_face when cut_face >= 0, otherwise it keeps using the base `plane`. cut_offset / cut_flip still apply along the derived normal, so the same square-wire split machinery handles both cases. add_split_by_face() is the convenience entry point; MCP gains a `split` method (body / face_body / face / keep_upper / keep_lower). Serialization stays append-only — cut_face_body, cut_face appended to save/load, recipe version unchanged at 2. Tests: the previously-missing both-halves plane cut (keep_upper && keep_lower => two bodies whose volumes sum to the original), split-by-face via a top-face plane offset into the interior, keep-upper-only, and a round-trip. Golden fixture regenerated with a GoldenSplit cut-by-face feature and exact field-value assertions. Suite 63 -> 67 cases, 1119 -> 1178 assertions. 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
9da5851534
commit
07b39d45cb
@@ -240,6 +240,14 @@ json describe_tools()
|
||||
json{{"name", "thickness"}, {"type", "number"}, {"unit", "mm"}, {"default", 2}, {"min", 0.01}},
|
||||
json{{"name", "flip"}, {"type", "boolean"}, {"default", false}},
|
||||
})}},
|
||||
json{{"name", "split"}, {"summary", "Split a body along the plane of a picked face."},
|
||||
{"params", json::array({
|
||||
json{{"name", "body"}, {"type", "integer"}, {"default", -1}, {"description", "target body; omit for the last body"}},
|
||||
json{{"name", "face_body"}, {"type", "integer"}, {"default", -1}, {"description", "body that owns the face; -1 = target"}},
|
||||
json{{"name", "face"}, {"type", "integer"}, {"description", "face id to split along (query_topology)"}},
|
||||
json{{"name", "keep_upper"},{"type", "boolean"}, {"default", true}},
|
||||
json{{"name", "keep_lower"},{"type", "boolean"}, {"default", true}},
|
||||
})}},
|
||||
json{{"name", "query_topology"}, {"summary", "Measured faces (centroid/normal/cylinder) and edges (length/circle) of a body."},
|
||||
{"params", json::array({
|
||||
json{{"name", "body"}, {"type", "integer"}, {"default", 0}},
|
||||
@@ -906,6 +914,24 @@ json action_thicken(DesignPanel* panel, const json& params)
|
||||
return json{{"ok", ok}, {"thicken_index", idx}, {"bodies", int(doc.bodies.size())}, {"error", doc.error}};
|
||||
}
|
||||
|
||||
json action_split(DesignPanel* panel, const json& params)
|
||||
{
|
||||
if (!params.contains("face")) throw std::runtime_error("split needs 'face' (id from query_topology)");
|
||||
CadDocument& doc = panel->mcp_doc();
|
||||
if (doc.bodies.empty()) throw std::runtime_error("no body to split");
|
||||
int bi = target_body_arg(params, doc);
|
||||
int face_body = params.value("face_body", -1);
|
||||
int face = params["face"].get<int>();
|
||||
bool keep_upper = params.value("keep_upper", true);
|
||||
bool keep_lower = params.value("keep_lower", true);
|
||||
doc.checkpoint();
|
||||
int idx = doc.add_split_by_face(bi, face_body, face, keep_upper, keep_lower, "Split");
|
||||
bool ok = doc.recompute();
|
||||
if (!ok) doc.undo();
|
||||
panel->mcp_after_change();
|
||||
return json{{"ok", ok}, {"split_index", idx}, {"bodies", int(doc.bodies.size())}, {"error", doc.error}};
|
||||
}
|
||||
|
||||
json action_axis(DesignPanel* panel, const json& params)
|
||||
{
|
||||
CadDocument& doc = panel->mcp_doc();
|
||||
@@ -1006,6 +1032,7 @@ std::string handle_on_main(const std::string& method, const json& params, const
|
||||
if (method == "mirror") return rpc_result(id, action_mirror(panel, params));
|
||||
if (method == "transform") return rpc_result(id, action_transform(panel, params));
|
||||
if (method == "thicken") return rpc_result(id, action_thicken(panel, params));
|
||||
if (method == "split") return rpc_result(id, action_split(panel, params));
|
||||
if (method == "axis") return rpc_result(id, action_axis(panel, params));
|
||||
if (method == "coordsys") return rpc_result(id, action_coordsys(panel, params));
|
||||
if (method == "helix") return rpc_result(id, action_helix(panel, params));
|
||||
|
||||
Reference in New Issue
Block a user