Kit frames: mates are lp_at placements that track the Ship Root frame; zone OFFs unchanged
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a18d3b812f
commit
bd343b2a4e
2 changed files with 33 additions and 7 deletions
|
|
@ -12,3 +12,28 @@ module cbox(s, c=0.2, center=true) {
|
|||
module tube(r, l, fn=8) { rotate([-90,0,0]) cylinder(r=r, h=l, $fn=fn); }
|
||||
// a straight strut between two points
|
||||
module strut(a, b, r=0.08, fn=6) { hull() { translate(a) sphere(r, $fn=fn); translate(b) sphere(r, $fn=fn); } }
|
||||
|
||||
// ==== Frames and schematic lines =====================================================================================
|
||||
// A kit part that draws schematic lines is placed with lp_at, never with raw translate/rotate/mirror: lp_at moves the
|
||||
// geometry (multmatrix) and tracks the same frame in $lp_m, so lp_line, called anywhere beneath it, emits its points in
|
||||
// the Ship Root frame. Placement has this one owner. A line is echoed (part "lines") only when the frame's local +Z
|
||||
// points up, so fittings on the belly, the walls and the belts, which a top view cannot see, emit nothing.
|
||||
$lp_m = [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]];
|
||||
function lp_T(t) = [[1,0,0,t[0]], [0,1,0,t[1]], [0,0,1,t[2]], [0,0,0,1]];
|
||||
function lp_R(r) = // Rz * Ry * Rx, as rotate() composes
|
||||
[[cos(r[2]), -sin(r[2]), 0, 0], [sin(r[2]), cos(r[2]), 0, 0], [0,0,1,0], [0,0,0,1]]
|
||||
* [[cos(r[1]), 0, sin(r[1]), 0], [0,1,0,0], [-sin(r[1]), 0, cos(r[1]), 0], [0,0,0,1]]
|
||||
* [[1,0,0,0], [0, cos(r[0]), -sin(r[0]), 0], [0, sin(r[0]), cos(r[0]), 0], [0,0,0,1]];
|
||||
lp_MX = [[-1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]; // mirror across x = 0
|
||||
function lp_ap(m, p) = let(v = m * [p[0], p[1], p[2], 1]) [v[0], v[1], v[2]];
|
||||
// Mirror (when mx), then translate by t, then rotate by r (as nested mirror, translate, rotate would).
|
||||
module lp_at(t=[0,0,0], r=[0,0,0], mx=false) {
|
||||
M = (mx ? lp_MX : [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]) * lp_T(t) * lp_R(r);
|
||||
$lp_m = $lp_m * M;
|
||||
multmatrix(M) children();
|
||||
}
|
||||
// One schematic line: layer (outline, step, seam or fitting), points in the local frame, cyclic when it closes.
|
||||
module lp_line(layer, pts, cyclic=false) {
|
||||
if (!is_undef(part) && part == "lines" && ($lp_m * [0, 0, 1, 0])[2] > 0.5)
|
||||
echo(line = [layer, cyclic, [for (p = pts) lp_ap($lp_m, p)]]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
// zh_on_stern, zh_on_nose. In the mate frame local +Z is the outward normal and the part is sunk ZH_SINK into
|
||||
// the skin, so nothing floats. Top/belly frames keep local +Y aft; wall/belt frames keep +Y aft with local +X
|
||||
// pointing down the wall on either side (starboard mates are mirrors of port); stern/nose frames have local +Y down.
|
||||
// Mates are lp_at frames: a part under a mate that draws lines (lp_line) emits them in the Ship Root frame.
|
||||
// 3. Zone routing: every zh_ module draws only the zone the global `part` names, so a hull writes its assembly once.
|
||||
// A hull on a Zhestokost donor (HULL_DONOR == "zhestokost") names a donor zone 'zhestokost:<zone>'.
|
||||
// Anchor meshes (zh_rad_vanes, zh_emitter) are not routed: call them inside the hull's rad:/emit: parts under
|
||||
|
|
@ -65,17 +66,17 @@ function zh_wall_tilt(secs, y) = let(s = zh_sec(secs, y)) atan2(s[4], s[2]*(1-ZH
|
|||
function zh_stern_pt(secs, x=0, v=0.5) = let(s = secs[len(secs)-1]) [x, s[0], s[3] + s[2]*v];
|
||||
function zh_nose_pt(secs, x=0, v=0.5) = let(s = secs[0]) [x, s[0], s[3] + s[2]*v];
|
||||
|
||||
module zh_on_top(secs, y, u=0, sink=ZH_SINK) translate(zh_top(secs, y, u) - [0, 0, sink]) children();
|
||||
module zh_on_belly(secs, y, u=0, sink=ZH_SINK) translate(zh_belly(secs, y, u) + [0, 0, sink]) rotate([0, 180, 0]) children();
|
||||
module _zh_port(side) { if (side < 0) mirror([1, 0, 0]) children(); else children(); }
|
||||
module zh_on_top(secs, y, u=0, sink=ZH_SINK) lp_at(t=zh_top(secs, y, u) - [0, 0, sink]) children();
|
||||
module zh_on_belly(secs, y, u=0, sink=ZH_SINK) lp_at(t=zh_belly(secs, y, u) + [0, 0, sink], r=[0, 180, 0]) children();
|
||||
module zh_on_belt(secs, y, side=1, v=0.5, sink=ZH_SINK)
|
||||
_zh_port(side) translate(zh_belt(secs, y, 1, v) - [sink, 0, 0]) rotate([0, 90, 0]) children();
|
||||
lp_at(t=zh_belt(secs, y, 1, v) - [sink, 0, 0], r=[0, 90, 0], mx=side < 0) children();
|
||||
module zh_on_wall(secs, y, side=1, v=0.5, sink=ZH_SINK) {
|
||||
t = zh_wall_tilt(secs, y);
|
||||
_zh_port(side) translate(zh_wall(secs, y, 1, v) - [cos(t), 0, sin(t)]*sink) rotate([0, 90 - t, 0]) children();
|
||||
lp_at(t=zh_wall(secs, y, 1, v) - [cos(t), 0, sin(t)]*sink, r=[0, 90 - t, 0], mx=side < 0) children();
|
||||
}
|
||||
module zh_on_stern(secs, x=0, v=0.5, sink=ZH_SINK) translate(zh_stern_pt(secs, x, v) - [0, sink, 0]) rotate([-90, 0, 0]) children();
|
||||
module zh_on_nose(secs, x=0, v=0.5, sink=ZH_SINK) translate(zh_nose_pt(secs, x, v) + [0, sink, 0]) rotate([90, 0, 0]) rotate([0, 0, 180]) children();
|
||||
module zh_on_stern(secs, x=0, v=0.5, sink=ZH_SINK) lp_at(t=zh_stern_pt(secs, x, v) - [0, sink, 0], r=[-90, 0, 0]) children();
|
||||
module zh_on_nose(secs, x=0, v=0.5, sink=ZH_SINK)
|
||||
lp_at(t=zh_nose_pt(secs, x, v) + [0, sink, 0], r=[90, 0, 0]) lp_at(r=[0, 0, 180]) children();
|
||||
// world point of a local offset under a mate (for anchors): top, belly, stern frames
|
||||
function zh_top_at(secs, y, u, o, sink=ZH_SINK) = zh_top(secs, y, u) - [0, 0, sink] + o;
|
||||
function zh_belly_at(secs, y, u, o, sink=ZH_SINK) = zh_belly(secs, y, u) + [0, 0, sink] + [-o[0], o[1], -o[2]];
|
||||
|
|
|
|||
Loading…
Reference in a new issue