Project: implement "(all edges)"; stop discarding the failure reason

Two defects found while driving the tools that Phase B wired but nobody had
exercised yet.

apply_project had no all-edges branch: with no face picked and no explicit
edge list it threw "no edges or face selected". That is precisely the state
the Project card opens in, and its label reads "(all edges)" — so the card's
default could never be confirmed. It now projects every edge of the source
body. Edges perpendicular to the target plane collapse to a point when
projected, so segments whose endpoints coincide are dropped instead of being
emitted as zero-length lines that would poison the sketch downstream.

The second defect is why the first one was invisible. 29 of the 31 rollback
sites in McpControl ran `if (!ok) doc.undo();`, and undo() recomputes the
restored feature list — which succeeds and clears doc.error. Every failing
command therefore reported `error: ""`. Yesterday's fix covered 2 sites and I
treated the file as done; it was not. All 31 now capture the reason before
the rollback and restore it after. Failures that read as `""` now read as
"rib: bad entity" / "surface-revolve: revolve failed".

Verified on the running GUI through the control socket: the Project call that
previously returned ok:false now returns ok:true, and failures carry a reason.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Tommaso Bianchi
2026-07-26 07:04:15 +02:00
co-authored by Claude Opus 5
parent 08e37296b9
commit 1cb80f7f9f
3 changed files with 76 additions and 45 deletions
+25
View File
@@ -3365,6 +3365,31 @@ TEST_CASE("project a cylinder top edge to 1 circle, extrudable", "[CadDocument][
REQUIRE_THAT(v, WithinRel(M_PI * 36.0 * 4.0, 1e-2));
}
TEST_CASE("project with no face and no edge selection projects every edge", "[CadDocument][project]")
{
// This is the state the Project card opens in — its label reads "(all edges)". Before the
// all-edges branch existed it threw "no edges or face selected", so the card's default
// could never be confirmed.
CadDocument doc;
int sk = doc.add_sketch(SketchShape::Rectangle, SketchPlane::XY(), 20, 20, 10, "Box");
doc.add_extrude(sk, 10.0, false, BooleanMode::New, "Ext");
REQUIRE(doc.recompute());
int proj = doc.add_project_edges(0, {}, -1, SketchPlane::XY(), "ProjAll");
REQUIRE(proj >= 0);
REQUIRE(doc.recompute());
REQUIRE(doc.error.empty());
// A box has 12 edges; the 4 running along Z collapse to points on XY and are dropped,
// leaving the 4 bottom and 4 top edges.
const auto& pf = doc.features[proj];
REQUIRE(pf.entities.size() == 8);
for (const auto& e : pf.entities) {
REQUIRE(e.type == SketchEntity::Type::Line);
REQUIRE((e.p1 - e.p0).norm() > 1e-6);
}
}
TEST_CASE("project bad face id returns error", "[CadDocument][project]")
{
CadDocument doc;