CAD: picking a face for a Coord Sys must also make it a face-based frame

A mate between two connectors committed cleanly, recomputed without error, and
moved nothing. apply_mate was reached and computed a translation of exactly
(0, 0, 0).

The connectors were the cause, not the mate. Picking a face stores
coordsys_face and coordsys_body but left the Type combo on its default,
Point (world) — and datum_frame ignores the pick entirely for that type,
resolving the connector to coordsys_point, which is (0,0,0) unless the user
typed otherwise. Two connectors built that way share one frame, so the mate
between them is an identity transform: everything reports success and the
assembly never moves.

Capturing a face or an edge now switches the type to FaceAndDirection. Picking
a face IS the choice of a face-based frame; asking for it twice, with no hint
that the second half is required, is what made every mate a silent no-op.

Verified on the rig, two bodies with a face-based connector each:
  before  Extrude4 [-71.6, 402.6, 156.5] .. [-8.8, 412.6, 237.3]
  after   Extrude4 [-31.4, -40.4, -10.0] .. [ 31.4,  40.4,  -0.0]
with the mate transform now (40.19, -196.88, 402.56) instead of (0, 0, 0).
That is the first mate in this tree that assembles anything.

Not the kernel: recompute applies mates exactly as preview does, proven by an
A/B harness over all five kinds — the two paths give identical bounding boxes.
This commit is contained in:
Tommaso Bianchi
2026-08-14 10:01:28 +02:00
parent c45f84edf4
commit 03fb81020e
+13 -1
View File
@@ -3502,7 +3502,19 @@ DesignPanel::DesignPanel(wxWindow* parent)
case CoordSysPick::Edge: if (m_sel_solid_edge >= 0) { m_cs_face_body = m_sel_solid_body; m_cs_edge = m_sel_solid_edge; got = true; } break;
default: break;
}
if (got) { m_coordsys_pick = CoordSysPick::None; refresh_coordsys_labels(); }
if (got) {
// A picked face or edge is only meaningful to FaceAndDirection. Left on the
// default Point (world), datum_frame ignores the pick entirely and resolves the
// connector to coordsys_point — which is (0,0,0) unless the user typed
// otherwise. Two such connectors then share one frame, so a mate between them
// computes an IDENTITY transform: the feature commits, the recompute succeeds,
// and nothing moves. Picking a face IS the choice of a face-based frame, so make
// the type follow the pick rather than asking for it twice.
if (m_coordsys_type && m_coordsys_type->GetSelection() != (int)CoordSysType::FaceAndDirection)
m_coordsys_type->SetSelection((int)CoordSysType::FaceAndDirection);
m_coordsys_pick = CoordSysPick::None;
refresh_coordsys_labels();
}
if (got && m_viewport) m_viewport->set_escalate_on_repick(true);
}
m_status->SetForegroundColour(wxNullColour);