mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 10:51:22 +00:00
The connector work has lived outside the code since 2026-08-05, in a workspace repo with no
remote. It is the basis of a decision that now shapes the Design tab, so it belongs here.
docs/design/mate-connectors/
DESIGN_MATE_CONNECTORS.md seven CAD systems surveyed; the frame-pair model this kernel
already matches; sections 8b/8c on the glyph, and section 9's
four open decisions (D1-D4) still awaiting Tommaso.
bear.step the male, Onshape 2026-08-05T08:27Z, md5 faf228326ee3f971
BearConnector_Female*.step/.stl, BearConnector_Cutter.step
built by make_female.py FROM the real male B-rep rather than
re-modelled, so the pocket is complementary by construction
including every deliberate asymmetry. Fit measured at exactly
0.2000 mm, zero interference, mated hosts proven coplanar.
BEAR_CONNECTOR_REVIEW.md the symmetry-group result: identity 81/81 edges, mirror-x 0/81,
mirror-y 0/81, rot180Z 0/81, rot90Z 0/81, diagonal 0/81 at
0.1 mm. Trivial group, so every PARTIAL view fixes orientation.
extract_outline.py, simplify_study.py, relief_sheet.py, handedness.py, make_female.py,
trim_female.py, fit_check.py, verify_trimmed.py, coplanar_test.py + their sheets
THE DECISION THIS SUPPORTS (snaporca-x0kd): the mate connector is drawn as a simplified BEAR
FACE by default, with the standard disc + roll quadrant + Z arrow kept behind a preference.
Face orientation is hardwired perception -- a toddler reads a face's roll and verse with no
instruction -- and no abstract glyph earns that. Measured against the alternative: the disc's
gold quadrant+tick falls 89 -> 66 -> 37 -> 20 -> 3 -> 0 lit pixels as the camera drops from
47 deg to edge-on, and is a shapeless blob by 16 deg.
WHAT THE SIMPLIFICATION STUDY SETTLED (snaporca-wi3z), all measured off the real B-rep:
The eyes are load-bearing. Same outline and muzzle with the eyes removed stops reading as
a face at every size. Whatever else goes, they stay.
45 -> 22 outline vertices with no loss of read at 22 / 32 / 48 px; the muzzle reduces to
one filled triangle. Three marks plus a cheek dot.
Drawn FLAT the face fails exactly where the disc fails: in the connector's plane everything
foreshortens by sin(elevation). Rendered as its real relief instead, lit pixels at 32 px go
164 -> 210 at 16 deg and 69 -> 120 at 6 deg, and the snout ridge stands proud as a profile
rather than smearing. The glyph must be a shaded relief, not an outline.
Handedness already reads without any added mark -- 32 to 35 % of lit pixels differ from the
mirror, and re-registering by best whole-pixel translation returns offset (0,0), so it is
real shape asymmetry. But it reads only BY COMPARISON. A dot on one cheek makes it local:
34.5 / 37.0 / 36.4 %, and unlike uneven eyes (42 %) it does not read as a defect.
Tommaso's calls: it stays a bear, and handedness must read.
The scripts were repointed at the co-located male and extract_outline.py re-run from here to
prove it -- same 45 outline points, same three inner wires, same 3829.5 mm2 back plate.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
141 lines
6.8 KiB
OpenSCAD
141 lines
6.8 KiB
OpenSCAD
// Faceted ridge key — asymmetric male/female alignment feature, flat facets only.
|
|
//
|
|
// 6 vertices, 7 faces, one closed manifold. Euler check: V - E + F = 6 - 11 + 7 = 2.
|
|
// No spheres, no cylinders, no splines, no fillets.
|
|
//
|
|
// THE FLANKS ARE TRIANGULATED EXPLICITLY, and that is not cosmetic. Written as quads
|
|
// [0,3,5,4] and [1,4,5,2] they are NOT planar — the base edge and the ridge edge are
|
|
// skew, so the four corners do not share a plane. A checker caught this after the first
|
|
// draft claimed the opposite. Left as quads, the tessellator picks the fold direction for
|
|
// you, which means the "flat facet" promise is broken by an unspecified crease and two
|
|
// exporters can disagree about the shape. Splitting them here fixes the crease at
|
|
// back-bottom -> front-ridge, which keeps the rear peak's triangle large and clean.
|
|
//
|
|
// FRAME CONVENTION (matches the CAD mate connector it is derived from):
|
|
// +Z the mating axis — the feature protrudes along it
|
|
// +X the roll reference — the ridge runs along it, low end forward
|
|
// +Y completes the right-handed frame
|
|
//
|
|
// WHAT BREAKS WHICH SYMMETRY
|
|
// rotational about Z ....... the ridge (elongation along X)
|
|
// 180 deg about Z .......... the ridge SLOPE: tall steep back, long shallow front
|
|
// mirror across XZ ......... deliberately NOT broken. Handedness is fixed by convention,
|
|
// so +Y is implied once Z and X are known. Breaking it would
|
|
// add a facet and buy nothing.
|
|
//
|
|
// KNOWN AMBIGUITY, stated rather than hidden: viewed exactly ALONG the ridge (+/-X,
|
|
// orthographic), the silhouette is the same isoceles triangle from front and back. Front
|
|
// and back are then distinguished by SHADING only — the long shallow front face catches
|
|
// light differently from the steep back face. If the target renderer is flat-shaded with a
|
|
// single headlight, verify this case before committing to the shape.
|
|
|
|
// ---------------------------------------------------------------- parameters
|
|
L = 12.0; // overall length along the ridge (X)
|
|
W = 4.0; // half-width at the BACK
|
|
tf = 0.45; // front taper: front half-width = W * tf
|
|
H = 4.5; // peak height at the rear <-- the single dimension controlling asymmetry
|
|
pr = 0.22; // rear ridge position, fraction of L from the back
|
|
pf = 0.62; // front ridge position, fraction of L from the back
|
|
hf = 0.35; // front ridge height, fraction of H
|
|
|
|
// Clearance is a PHYSICAL quantity and only means anything if this is a printed part.
|
|
// See the note at the bottom: for a viewport glyph it is meaningless.
|
|
clr = 0.20; // per-face clearance, mm
|
|
depth = 0.40; // extra pocket depth so the male never bottoms out before it seats
|
|
|
|
Wf = W * tf;
|
|
xr0 = -L/2 + L * pr;
|
|
xr1 = -L/2 + L * pf;
|
|
Hf = H * hf;
|
|
|
|
// ---------------------------------------------------------------- geometry
|
|
// Vertex order is fixed and referenced by the face table; do not reorder.
|
|
// 0 back-left 1 back-right 2 front-right 3 front-left
|
|
// 4 REAR PEAK (tall) 5 front ridge (low)
|
|
function ridge_pts(l, w, wf, h, hfr, x0, x1) = [
|
|
[-l/2, -w, 0 ], // 0
|
|
[-l/2, w, 0 ], // 1
|
|
[ l/2, wf, 0 ], // 2
|
|
[ l/2, -wf, 0 ], // 3
|
|
[ x0, 0, h ], // 4 rear peak
|
|
[ x1, 0, hfr] // 5 front ridge, low
|
|
];
|
|
|
|
// OpenSCAD wants each face wound CLOCKWISE seen from OUTSIDE. The right-hand-rule
|
|
// outward-normal (CCW) form is given in the comment for anyone porting to STL/OCC,
|
|
// where the opposite convention is the usual one.
|
|
RIDGE_FACES = [
|
|
[3, 2, 1, 0], // base (CCW-outward: [0,1,2,3]) planar, all z=0
|
|
[1, 4, 0], // back (CCW-outward: [0,4,1]) steep
|
|
[5, 3, 0], // flank -Y a (CCW-outward: [0,3,5])
|
|
[4, 5, 0], // flank -Y b (CCW-outward: [0,5,4])
|
|
[5, 4, 1], // flank +Y a (CCW-outward: [1,4,5])
|
|
[2, 5, 1], // flank +Y b (CCW-outward: [1,5,2])
|
|
[5, 2, 3] // front (CCW-outward: [3,2,5]) long, shallow
|
|
];
|
|
|
|
module ridge_key(l = L, w = W, wf = Wf, h = H, hfr = Hf, x0 = xr0, x1 = xr1) {
|
|
polyhedron(points = ridge_pts(l, w, wf, h, hfr, x0, x1),
|
|
faces = RIDGE_FACES,
|
|
convexity = 3);
|
|
}
|
|
|
|
// MALE: the protrusion, nominal size.
|
|
module ridge_key_male() { ridge_key(); }
|
|
|
|
// FEMALE: the pocket. Grown by `clr` on every side and sunk `depth` deeper.
|
|
//
|
|
// HONEST LIMITATION: this grows the key by scaling its defining dimensions, which is NOT a
|
|
// true uniform surface offset — on the shallow front face the normal clearance comes out
|
|
// smaller than `clr`, because that face is far from perpendicular to every axis it is
|
|
// scaled along. A true offset needs minkowski() with a small cube, which is exact and slow,
|
|
// or an explicit per-face plane push, which is exact and fiddly. For a keying feature whose
|
|
// job is angular registration rather than a press fit, the approximation is the right trade
|
|
// — but do not quote this pocket as holding 0.2 mm everywhere, because it does not.
|
|
module ridge_key_female() {
|
|
translate([0, 0, -depth])
|
|
ridge_key(l = L + 2*clr,
|
|
w = W + clr,
|
|
wf = Wf + clr,
|
|
h = H + clr + depth,
|
|
hfr = Hf + clr + depth,
|
|
x0 = xr0,
|
|
x1 = xr1);
|
|
}
|
|
|
|
// ---------------------------------------------------------------- demo
|
|
// Left: the male key on its plate. Right: the plate with the pocket cut.
|
|
PLATE = [30, 18, 3];
|
|
|
|
module plate_with_male() {
|
|
translate([-PLATE[0]/2, -PLATE[1]/2, -PLATE[2]]) cube(PLATE);
|
|
ridge_key_male();
|
|
}
|
|
|
|
module plate_with_female() {
|
|
difference() {
|
|
translate([-PLATE[0]/2, -PLATE[1]/2, -PLATE[2]]) cube(PLATE);
|
|
ridge_key_female();
|
|
}
|
|
}
|
|
|
|
translate([-20, 0, 0]) plate_with_male();
|
|
translate([ 20, 0, 0]) plate_with_female();
|
|
|
|
// ---------------------------------------------------------------- note on the two readings
|
|
// This file is written for the PHYSICAL reading: a printable alignment key, where `clr` and
|
|
// `depth` are real millimetres and flat facets genuinely help — they slice without the
|
|
// stair-stepping a tessellated curve produces, and they print without support on the
|
|
// shallow front face.
|
|
//
|
|
// If the intent is instead the VIEWPORT GLYPH for a CAD mate connector, then:
|
|
// - `clr` and `depth` are meaningless: a symbol does not mate with anything;
|
|
// - all dimensions must become SCREEN PIXELS scaled by upp = 1/zoom, because every gizmo
|
|
// in that viewport is screen-constant and must not shrink with the model;
|
|
// - "low-poly for rendering performance" is not a real reason at ~2-20 glyphs per frame.
|
|
// The real reason to keep flat facets there is LEGIBILITY: hard normals give distinct
|
|
// value steps between facets, and that is what lets a 22-px solid read as an oriented
|
|
// object instead of a grey blob.
|
|
// The vertex logic above is identical under both readings. Only the units and the clearance
|
|
// change.
|