mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-19 15:03:05 +00:00
M8a: assembly mates — Fastened + Planar (recipe v3)
An assembly is a multi-body document. An instance is already expressible as Transform with xf_copy=true, and a mate connector is already a CoordSys feature, so this adds exactly one feature type: Mate. No constraint solver. A mate rigidly transforms the body carrying connector B so that B's frame lands on connector A's, applied in feature order like every other feature. Chains resolve by composition; closed kinematic loops do not converge (last mate wins) and are out of scope. The vendored SolveSpace in src/libslic3r/slvs/ was evaluated for 3D extension and rejected: it is built and linked but has zero callers, and SketchEngine's solver is hand-rolled. Extending it would mean adopting a dependency to write more code than the alternative. - CadFeatureType::Mate appended; six fields (mate_kind, mate_cs_a, mate_cs_b, mate_offset, mate_angle, mate_flip) appended at the END of both cereal lists - SNAPORCA_CAD_RECIPE_VERSION 2 -> 3; v2 blobs are rejected, as by design there is no migration path. Golden fixture renamed to cad_recipe_v3.bin and regenerated once, extended with two CoordSys + one Mate so the new fields are tripwired by the field-order assertions - datum_frame() extracted from resolve_datum_coordsys() so a mate can resolve its connectors against the in-progress bodies vector during replay - apply_mate dispatched early-return, so Mate is deliberately absent from starts_new (unreachable for that dispatch style) - Planar: the degenerate branch splits on the sign of zB.z_target — antiparallel needs a 180 deg rotation about a perpendicular axis, which an earlier revision silently skipped, leaving the body's normal inverted - MCP: mate command, named bare to match the other 38 methods Drive-by: feature_type_name() was missing Mirror, ThickenSurface, SurfaceOffset, SurfaceLoft and SurfaceFill, which reported as "Unknown" to MCP clients. Suite 122 cases / 1741 assertions green. Note that kernel-test.sh builds only libslic3r_tests, so McpControl.cpp is reviewed but not compiled here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9c28be5860
commit
b13ca01ccc
@@ -71,6 +71,7 @@ const char* feature_type_name(CadFeatureType t)
|
||||
case CadFeatureType::Import: return "Import";
|
||||
case CadFeatureType::Boolean: return "Boolean";
|
||||
case CadFeatureType::Cut: return "Cut";
|
||||
case CadFeatureType::Mirror: return "Mirror";
|
||||
case CadFeatureType::Axis: return "Axis";
|
||||
case CadFeatureType::CoordSys: return "CoordSys";
|
||||
case CadFeatureType::Helix: return "Helix";
|
||||
@@ -81,6 +82,11 @@ const char* feature_type_name(CadFeatureType t)
|
||||
case CadFeatureType::Rib: return "Rib";
|
||||
case CadFeatureType::SurfaceExtrude: return "SurfaceExtrude";
|
||||
case CadFeatureType::SurfaceRevolve: return "SurfaceRevolve";
|
||||
case CadFeatureType::ThickenSurface: return "ThickenSurface";
|
||||
case CadFeatureType::SurfaceOffset: return "SurfaceOffset";
|
||||
case CadFeatureType::SurfaceLoft: return "SurfaceLoft";
|
||||
case CadFeatureType::SurfaceFill: return "SurfaceFill";
|
||||
case CadFeatureType::Mate: return "Mate";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -324,6 +330,15 @@ json describe_tools()
|
||||
json{{"name", "angle"}, {"type", "number"}, {"unit", "deg"}, {"default", 360}},
|
||||
json{{"name", "axis"}, {"type", "integer"}, {"enum", json::array({0, 1})}, {"default", 0}},
|
||||
})}},
|
||||
json{{"name", "mate"}, {"summary", "Mate two bodies: transform the moving body (cs_b) so its connector lands on the fixed one (cs_a). kind: 0=Fastened, 1=Planar."},
|
||||
{"params", json::array({
|
||||
json{{"name", "kind"}, {"type", "integer"}, {"default", 0}, {"description", "0=Fastened (full align), 1=Planar (normal only)"}},
|
||||
json{{"name", "cs_a"}, {"type", "integer"}, {"description", "feature index of the fixed CoordSys (mate connector A)"}},
|
||||
json{{"name", "cs_b"}, {"type", "integer"}, {"description", "feature index of the CoordSys on the body that moves"}},
|
||||
json{{"name", "offset"}, {"type", "number"}, {"unit", "mm"}, {"default", 0}},
|
||||
json{{"name", "angle"}, {"type", "number"}, {"unit", "deg"}, {"default", 0}},
|
||||
json{{"name", "flip"}, {"type", "boolean"}, {"default", false}},
|
||||
})}},
|
||||
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}},
|
||||
@@ -1310,6 +1325,25 @@ json action_helix(DesignPanel* panel, const json& params)
|
||||
return json{{"ok", true}, {"helix_index", idx}, {"bodies", int(doc.bodies.size())}, {"error", doc.error}};
|
||||
}
|
||||
|
||||
json action_mate(DesignPanel* panel, const json& params)
|
||||
{
|
||||
if (!params.contains("cs_a")) throw std::runtime_error("mate needs 'cs_a' (CoordSys feature index)");
|
||||
if (!params.contains("cs_b")) throw std::runtime_error("mate needs 'cs_b' (CoordSys feature index)");
|
||||
const int kind = params.value("kind", 0);
|
||||
const int cs_a = params["cs_a"].get<int>();
|
||||
const int cs_b = params["cs_b"].get<int>();
|
||||
const double offset = params.value("offset", 0.0);
|
||||
const double angle = params.value("angle", 0.0);
|
||||
const bool flip = params.value("flip", false);
|
||||
CadDocument& doc = panel->mcp_doc();
|
||||
doc.checkpoint();
|
||||
int idx = doc.add_mate(kind, cs_a, cs_b, offset, angle, flip, "Mate");
|
||||
bool ok = doc.recompute();
|
||||
if (!ok) doc.undo();
|
||||
panel->mcp_after_change();
|
||||
return json{{"ok", ok}, {"mate_index", idx}, {"bodies", int(doc.bodies.size())}, {"error", doc.error}};
|
||||
}
|
||||
|
||||
json action_set_variable(DesignPanel* panel, const json& params)
|
||||
{
|
||||
if (!params.contains("name")) throw std::runtime_error("set_variable needs 'name'");
|
||||
@@ -1394,6 +1428,7 @@ std::string handle_on_main(const std::string& method, const json& params, const
|
||||
if (method == "surface_offset") return rpc_result(id, action_surface_offset(panel, params));
|
||||
if (method == "surface_loft") return rpc_result(id, action_surface_loft(panel, params));
|
||||
if (method == "surface_fill") return rpc_result(id, action_surface_fill(panel, params));
|
||||
if (method == "mate") return rpc_result(id, action_mate(panel, params));
|
||||
return rpc_error(id, -32601, "Unknown method: " + method);
|
||||
} catch (const Standard_Failure& ex) { // OCCT errors are NOT std::exception
|
||||
return rpc_error(id, -32000, std::string("OCCT: ") + (ex.GetMessageString() ? ex.GetMessageString() : "failure"));
|
||||
|
||||
Reference in New Issue
Block a user