Zhestokost kit and Nakovalnya emit schematic lines from their own frames (outline, step, seam, fitting)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
bd343b2a4e
commit
28ed24b28e
2 changed files with 54 additions and 19 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// Zhestokost fortress (boss) "Nakovalnya" (anvil). Built from the Zhestokost kit.
|
||||
// part = lang | brief | anchors | primary | secondary | accent | recess | marking | emit:<id> | rad:<id>
|
||||
// part = lang | brief | anchors | lines | primary | secondary | accent | recess | marking | emit:<id> | rad:<id>
|
||||
// Frame: Ship Root, metres, nose -Y, starboard -X, up +Z. Anchor yaw: 0 nose, 90 port, 180 aft, 270 starboard.
|
||||
include <zhestokost.scad>
|
||||
part = "primary";
|
||||
|
|
@ -46,10 +46,10 @@ zh_mass(M);
|
|||
zh_mass(T1);
|
||||
zh_mass(T2);
|
||||
zh_mass(APRON);
|
||||
for (x = CX) translate([x, 0, 0]) zh_mass(CAS);
|
||||
for (x = CX) lp_at(t=[x, 0, 0]) zh_mass(CAS);
|
||||
zh_mass(SPINE);
|
||||
zh_mass(KEEL);
|
||||
for (s = [-1, 1]) translate([s*DX, 0, 0]) zh_mass(DRV, "secondary");
|
||||
zh_mass(KEEL, lines=false); // under the hull: no top view sees it
|
||||
for (s = [-1, 1]) lp_at(t=[s*DX, 0, 0]) zh_mass(DRV, "secondary");
|
||||
|
||||
// ---- the casemate guns: lighter cast-steel barrels out of charcoal mantlets -----------------------------------------
|
||||
module casemate_gun() {
|
||||
|
|
@ -60,9 +60,11 @@ module casemate_gun() {
|
|||
}
|
||||
zh_z("primary") translate([0, GY - 0.7, GZ]) rotate([0, 0, 180]) tube(BR, BL, 8);
|
||||
zh_z("recess") translate([0, GY - 0.7 - BL - 0.81, GZ]) cube([BR*1.2, 0.05, BR*1.2], center=true);
|
||||
lp_line("fitting", [for (p = zh_rect(4.0, 1.2, GZ + 1.7)) p + [0, GY - 0.3, 0]], true);
|
||||
lp_line("fitting", [[0, GY - 0.7, GZ + BR], [0, GY - 0.7 - BL, GZ + BR]]);
|
||||
}
|
||||
for (x = CX) translate([x, 0, 0]) casemate_gun();
|
||||
for (x = CX) translate([x, 0, 0]) zh_on_top(CAS, -21.9, 0) zh_stripes(3.6, 0.6, 4);
|
||||
for (x = CX) lp_at(t=[x, 0, 0]) casemate_gun();
|
||||
for (x = CX) lp_at(t=[x, 0, 0]) zh_on_top(CAS, -21.9, 0) zh_stripes(3.6, 0.6, 4);
|
||||
// black reveals between the casemates, on the apron
|
||||
for (u = [-0.33, 0.33]) zh_on_top(APRON, -19.5, u) zh_reveal(2.3, 7.0);
|
||||
|
||||
|
|
@ -76,9 +78,10 @@ module flak(yaw) {
|
|||
zh_z("secondary") cylinder(r=FR, h=FH + ZH_SINK, $fn=8);
|
||||
zh_z("accent") translate([0, 0, FH*0.35]) cylinder(r=FR + 0.08, h=0.35, $fn=8); // oxide band round the drum
|
||||
zh_z("recess") translate([0, 0, FH - 0.06]) cylinder(r=FR*0.84, h=0.1, $fn=8);
|
||||
translate([0, 0, FH - 0.02]) rotate([0, 0, yaw]) zh_gun(FG[0], FG[1], FG[2], FG[3], "primary");
|
||||
lp_line("fitting", zh_oct(FR, FH), true);
|
||||
lp_at(t=[0, 0, FH - 0.02], r=[0, 0, yaw]) zh_gun(FG[0], FG[1], FG[2], FG[3], "primary");
|
||||
}
|
||||
for (f = FLAK) translate([f[0], f[1], DECK - ZH_SINK]) flak(f[2]);
|
||||
for (f = FLAK) lp_at(t=[f[0], f[1], DECK - ZH_SINK]) flak(f[2]);
|
||||
function rz(a, p) = [p[0]*cos(a) - p[1]*sin(a), p[0]*sin(a) + p[1]*cos(a), p[2]];
|
||||
|
||||
// ---- bow: cab with the slit high on the spine's front step ---------------------------------------------------------
|
||||
|
|
@ -87,7 +90,10 @@ zh_on_top(T2, -3.6, 0) zh_serial(0.7, 4);
|
|||
|
||||
// ---- dorsal magazine hatches: two rows of four on the mid-deck, clear of the rim -----------------------------------
|
||||
for (y = [-8.0, -3.4, 1.2, 5.6], u = [-0.78, 0.78]) zh_on_top(T1, y, u) zh_hatch(2.8, 3.0, dogs=false);
|
||||
for (y = [0.5, 4.5]) zh_on_top(T2, y, 0) zh_z("secondary") translate([0, 0, 0.06]) cube([8.4, 0.5, 0.2], center=true); // plate seams
|
||||
for (y = [0.5, 4.5]) zh_on_top(T2, y, 0) { // plate seams
|
||||
zh_z("secondary") translate([0, 0, 0.06]) cube([8.4, 0.5, 0.2], center=true);
|
||||
lp_line("seam", [[-4.2, 0, 0.16], [4.2, 0, 0.16]]);
|
||||
}
|
||||
|
||||
// Feed collar for an Oboz: a lighter cast-steel flange ring standing proud of the flank round the kit collar.
|
||||
module feed_collar() {
|
||||
|
|
@ -97,7 +103,7 @@ module feed_collar() {
|
|||
}
|
||||
// ---- flanks: feed collar, ammunition door, unit serial -------------------------------------------------------------
|
||||
for (s = [-1, 1]) {
|
||||
zh_on_belt(M, 1.5, s, 0.5) rotate([0, 0, 22.5]) feed_collar();
|
||||
zh_on_belt(M, 1.5, s, 0.5) lp_at(r=[0, 0, 22.5]) feed_collar();
|
||||
zh_on_wall(M, 7.0, s, 0.45) zh_hatch(2.6, 3.0);
|
||||
zh_on_wall(M, -9.0, s, 0.5) zh_serial(0.8, 5);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,22 @@ function zh_stern_at(secs, x, v, o, sink=ZH_SINK) = zh_stern_pt(secs, x, v) - [0
|
|||
|
||||
// ==== PRIMARY: masses that make the silhouette ========================================================================
|
||||
// Any section list as one faceted poured mass.
|
||||
module zh_mass(secs, zone="primary") zh_z(zone) for (i = [0:len(secs)-2]) hull() { _zh_slice(secs[i]); _zh_slice(secs[i+1]); }
|
||||
// Lines: the plan at the cast belt (outline), the deck edge (step) and, on a primary mass, a seam across the deck at each
|
||||
// interior station. lines=false for a mass no top view can see (a keel under the hull).
|
||||
module zh_mass(secs, zone="primary", lines=true) {
|
||||
zh_z(zone) for (i = [0:len(secs)-2]) hull() { _zh_slice(secs[i]); _zh_slice(secs[i+1]); }
|
||||
if (lines) {
|
||||
n = len(secs);
|
||||
lp_line("outline", concat([for (s = secs) [-s[1]/2, s[0], s[3] + s[2]*ZH_WU]],
|
||||
[for (i = [n-1:-1:0]) [secs[i][1]/2, secs[i][0], secs[i][3] + secs[i][2]*ZH_WU]]), true);
|
||||
lp_line("step", concat([for (s = secs) [-(s[1]/2 - s[4]), s[0], s[3] + s[2]]],
|
||||
[for (i = [n-1:-1:0]) [secs[i][1]/2 - secs[i][4], secs[i][0], secs[i][3] + secs[i][2]]]), true);
|
||||
if (zone == "primary") for (i = [1:n-2]) let(s = secs[i])
|
||||
lp_line("seam", [[-(s[1]/2 - s[4]), s[0], s[3] + s[2]], [s[1]/2 - s[4], s[0], s[3] + s[2]]]);
|
||||
}
|
||||
}
|
||||
function zh_rect(w, l, z) = [[-w/2, -l/2, z], [w/2, -l/2, z], [w/2, l/2, z], [-w/2, l/2, z]];
|
||||
function zh_oct(r, z) = [for (k = [0:7]) [r*cos(45*k), r*sin(45*k), z]];
|
||||
|
||||
// A core or whole hull: bow chamfered in plan and dropped (bow, as a fraction of L), stern a flat face with a cast lip.
|
||||
// bowW / bowH: nose width and height as fractions of W and H.
|
||||
|
|
@ -128,6 +143,7 @@ module zh_collar(r=ZH_COLLAR_R, proud=0.55, lugs=4) {
|
|||
zh_z("secondary") difference() {
|
||||
cylinder(r=r, h=proud + ZH_SINK, $fn=8); translate([0, 0, -0.1]) cylinder(r=r*0.6, h=proud + 1, $fn=8); }
|
||||
zh_z("recess") cylinder(r=r*0.62, h=0.08 + ZH_SINK, $fn=8);
|
||||
lp_line("fitting", zh_oct(r, proud), true);
|
||||
zh_z("accent") for (i = [0:lugs-1]) rotate(i*360/lugs) translate([r + 0.16, 0, (proud + 0.25)/2])
|
||||
cube([0.5, 0.6, proud + 0.25 + ZH_SINK], center=true);
|
||||
}
|
||||
|
|
@ -140,13 +156,17 @@ module zh_hatch(w=ZH_HATCH, l=ZH_HATCH, t=0.22, dogs=true) {
|
|||
for (x = [-1, 1]) translate([x*w*0.27, 0, t + 0.12]) cbox([0.5, l + 0.6, 0.34], 0.07);
|
||||
if (dogs) for (sx = [-1, 1], sy = [-1, 1]) translate([sx*(w/2 + 0.12), sy*l*0.3, t*0.6]) cube([0.36, 0.44, 0.4], center=true);
|
||||
}
|
||||
lp_line("fitting", zh_rect(w, l, t), true);
|
||||
translate([0, l/2 - 0.42, t]) zh_stripes(w*0.36, 0.5, dogs ? 3 : 2);
|
||||
}
|
||||
|
||||
// Armour plate (any frame): replaceable slab with four bolt bosses; leaves a seam to its neighbour.
|
||||
module zh_plate(w, l, t=0.3, zone="secondary") zh_z(zone) {
|
||||
translate([0, 0, t/2]) cbox([w, l, t + ZH_SINK], 0.07);
|
||||
for (sx = [-1, 1], sy = [-1, 1]) translate([sx*(w/2 - 0.25), sy*(l/2 - 0.25), t + 0.05]) cube([0.22, 0.22, 0.12], center=true);
|
||||
module zh_plate(w, l, t=0.3, zone="secondary") {
|
||||
zh_z(zone) {
|
||||
translate([0, 0, t/2]) cbox([w, l, t + ZH_SINK], 0.07);
|
||||
for (sx = [-1, 1], sy = [-1, 1]) translate([sx*(w/2 - 0.25), sy*(l/2 - 0.25), t + 0.05]) cube([0.22, 0.22, 0.12], center=true);
|
||||
}
|
||||
lp_line("fitting", zh_rect(w, l, t), true);
|
||||
}
|
||||
|
||||
// Radiator trough (top frame): cast frame round a black floor, split by a spine wall; vanes stand in it (zh_rad_vanes).
|
||||
|
|
@ -155,6 +175,8 @@ module zh_rad_trough(w=3.2, l=2.4, d=0.45, zone="secondary") {
|
|||
cbox([w + 0.7, l + 0.7, d + ZH_SINK], 0.1); cube([w, l, d*3], center=true); }
|
||||
zh_z(zone) translate([0, 0, d*0.6]) cube([0.3, l, d*1.2 + ZH_SINK], center=true);
|
||||
zh_z("recess") translate([0, 0, 0.04]) cube([w, l, 0.08 + ZH_SINK], center=true);
|
||||
lp_line("fitting", zh_rect(w + 0.7, l + 0.7, d), true);
|
||||
lp_line("fitting", zh_rect(w, l, d), true);
|
||||
}
|
||||
// radiator-mesh for one half of a trough (side 1 port, -1 starboard): transverse vanes rising out of it
|
||||
module zh_rad_vanes(w=3.2, l=2.4, side=1, n=5, h=1.0) {
|
||||
|
|
@ -173,17 +195,24 @@ module zh_tow_lug(s=ZH_LUG, zone="secondary") {
|
|||
// Ballistic mount (top frame): octagonal ring, battered mantlet block, n thick barrels with box brakes, pointing -Y.
|
||||
module zh_gun(n=2, cal=0.22, len=3.0, base=1.8, zone="secondary") {
|
||||
zh_z(zone) cylinder(r=base*0.56, h=0.35 + ZH_SINK, $fn=8);
|
||||
zh_mass([for (s = zh_block(0, base*0.95, base, base*0.5, 0.33, base*0.14, 0, 0.22)) s], zone);
|
||||
zh_z(zone) for (i = [0:n-1]) translate([(i - (n-1)/2)*cal*3.2, -base*0.4, 0.33 + base*0.25]) {
|
||||
rotate([0, 0, 180]) tube(cal, len, 8);
|
||||
translate([0, -len, 0]) cbox([cal*3, cal*3.5, cal*3], 0.04);
|
||||
lp_line("fitting", zh_oct(base*0.56, 0.35), true);
|
||||
zh_mass([for (s = zh_block(0, base*0.95, base, base*0.5, 0.33, base*0.14, 0, 0.22)) s], zone, lines=false);
|
||||
for (i = [0:n-1]) lp_at(t=[(i - (n-1)/2)*cal*3.2, -base*0.4, 0.33 + base*0.25]) {
|
||||
zh_z(zone) {
|
||||
rotate([0, 0, 180]) tube(cal, len, 8);
|
||||
translate([0, -len, 0]) cbox([cal*3, cal*3.5, cal*3], 0.04);
|
||||
}
|
||||
lp_line("fitting", [[0, 0, 0], [0, -len, 0]]);
|
||||
}
|
||||
}
|
||||
function zh_gun_muzzle(n=2, cal=0.22, len=3.0, base=1.8) = [0, -base*0.4 - len - cal*1.75, 0.33 + base*0.25];
|
||||
|
||||
// ==== TERTIARY: detail ===============================================================================================
|
||||
// Shadow-gap floor (top frame): the black bottom of a reveal between modules.
|
||||
module zh_reveal(w, l) zh_z("recess") translate([0, 0, 0.03]) cube([w, l, 0.06 + ZH_SINK], center=true);
|
||||
module zh_reveal(w, l) {
|
||||
zh_z("recess") translate([0, 0, 0.03]) cube([w, l, 0.06 + ZH_SINK], center=true);
|
||||
lp_line("seam", zh_rect(w, l, 0.06), true);
|
||||
}
|
||||
// Cream safety chevrons (any frame, +Z out): n diagonal bars clipped to w x l.
|
||||
module zh_stripes(w, l, n=3) zh_z("marking") intersection() {
|
||||
translate([0, 0, 0.04]) cube([w, l, 0.1], center=true);
|
||||
|
|
|
|||
Loading…
Reference in a new issue