"""The 39 parts of the user's reference sheet (2026-10-14), one builder each, in sheet order (rows A to E, left to right). Numbers here are SHEET PIXELS (1 px = 3 mm, see mpk_lib.U), relative to the item's centre; z is height above the floor in the same units. The sheet is a single top view, so heights are my reading of its shading. Each builder gets a Kit and returns a list of moving parts: (suffix, Kit, pivot_px, axis) - built as separate objects with their origin on the hinge or spin axis (memory: separate-objects-for-moving-parts). """ import math from mathutils import Matrix, Vector from mpk_lib import Kit, U, PAINT, DARK, STEEL, rrect ITEMS = [] # (key, name, sheet centre (px), builder) def item(key, name, cx, cy): def deco(fn): ITEMS.append((key, name, (cx, cy), fn)) return fn return deco def m(v): return [x * U for x in v] # px wrappers --------------------------------------------------------------- def bx(k, c, s, r=2.0, mat=PAINT, rx=0.0, ry=0.0, rz=0.0): rot = None if rx or ry or rz: rot = (Matrix.Rotation(math.radians(rz), 4, 'Z') @ Matrix.Rotation(math.radians(ry), 4, 'Y') @ Matrix.Rotation(math.radians(rx), 4, 'X')) return k.box(m(c), m(s), r * U, mat, rot) def cy(k, c, r, h, axis='Z', segs=24, bev=1.5, mat=PAINT): return k.cyl(m(c), r * U, h * U, axis, segs, bev * U, mat) def cn(k, c, r, L, axis='Z', grooves=(), ends=(True, True), end=0.35, segs=32, mat=PAINT): return k.can(m(c), r * U, L * U, axis, end, segs, [g * U for g in grooves], mat, ends) def tb(k, pts, r, bend=None, segs=12, mat=PAINT, closed=False): return k.tube([m(p) for p in pts], r * U, None if bend is None else bend * U, segs, mat, closed) def hd(k, a, b, up, h, r=2.2, mat=PAINT): return k.handle(m(a), m(b), up, h * U, r * U, mat) def bt(k, c, r=2.2, h=1.6, axis='Z'): return k.bolt(m(c), r * U, h * U, axis) def dt(k, c, r, axis='Z', mat=DARK): return k.dot(m(c), r * U, axis, 0.0015, mat) def sk(k, c, r, depth, axis='Z', rim=2.0): return k.socket(m(c), r * U, depth * U, axis, rim * U) def ring(k, c, r, w, h, axis='Z', mat=PAINT, segs=32): """band of outer radius r centred on c along axis""" d = Vector({'X': (1, 0, 0), 'Y': (0, 1, 0), 'Z': (0, 0, 1)}[axis.strip('-')]) return k.ring([x - y for x, y in zip(m(c), d * (h * U / 2))], r * U, w * U, h * U, axis, segs, mat) def bolts4(k, cx, cy_, w, h, z, r=2.0): for sx in (-1, 1): for sy in (-1, 1): bt(k, (cx + sx * w / 2, cy_ + sy * h / 2, z), r) def plate_holes(k, xs, ys, holes, t, z0, kk=6, mat=PAINT): return k.holed_plate([x * U for x in xs], [y * U for y in ys], {c: (a * U, b * U, n) for c, (a, b, n) in holes.items()}, t * U, z0 * U, kk, mat, wall_mat=DARK) def slab(k, outline_px, t, z0, r=1.5, mat=PAINT): return k.slab([(p[0] * U, p[1] * U) for p in outline_px], t * U, z0 * U, mat, None, r * U) # ============================================================== row A @item("A01", "HoleFrame", 227, 140) def a01(k): plate_holes(k, [-120, -97, -27, 27, 97, 120], [-46, -35, 35, 46], {(1, 1): (27, 27, 2), (3, 1): (27, 27, 2)}, 8, 2) for sy in (-1, 1): bx(k, (0, sy * 53, 9), (232, 14, 18), 2.5) for x in (-80, -40, 0, 40, 80): bt(k, (x, sy * 53, 18)) for sx in (-1, 1): # corner hinge brackets with their pins bx(k, (sx * 124, sy * 52, 12), (22, 30, 24), 2.5) cy(k, (sx * 124, sy * 52 - 17, 15), 5, 34, 'Y', 12, 1) bx(k, (sx * 108, sy * 60, 6), (14, 12, 12), 1.5) for sx in (-1, 1): bx(k, (sx * 131, 0, 6), (14, 40, 12), 2.5) bt(k, (sx * 131, 10, 12)); bt(k, (sx * 131, -10, 12)) return [] @item("A02", "WinchMotor", 460, 150) def a02(k): bx(k, (0, 0, 4), (132, 112, 8), 2) for sx in (-1, 1): bx(k, (sx * 52, 10, 26), (8, 80, 40), 2) cn(k, (-44, 22, 34), 22, 82, 'X', grooves=(12, 22, 60, 70), ends=(False, False)) for x in (-44, 38): cy(k, (x, 22, 34), 10, 4, '-X' if x < 0 else 'X', 20, 1, STEEL) bx(k, (8, -28, 22), (60, 36, 28), 3) # gear case under the drum bx(k, (8, -28, 37), (44, 24, 3), 1) bolts4(k, 8, -28, 48, 26, 36) tb(k, [(-60, -26, 10), (-60, -50, 10), (40, -50, 10), (40, -38, 16)], 4.5) tb(k, [(60, -20, 12), (62, 40, 12)], 4) for sx in (-1, 1): for sy in (-1, 1): bt(k, (sx * 58, sy * 48, 8), 2.6) return [] @item("A03", "StackBox", 616, 151) def a03(k): bx(k, (0, 0, 30), (80, 104, 60), 3) bx(k, (0, 24, 61), (66, 42, 4), 1.5) bx(k, (0, -25, 61), (66, 44, 4), 1.5) bolts4(k, 0, 24, 56, 32, 63); bolts4(k, 0, -25, 56, 34, 63) bx(k, (0, 56, 36), (86, 8, 34), 2) # top flange for sx in (-1, 1): bx(k, (sx * 43, -46, 7), (10, 16, 14), 2) bx(k, (sx * 43, 30, 30), (6, 30, 40), 1.5) bx(k, (0, -56, 10), (50, 8, 20), 2) for sx in (-1, 1): for y in (-30, -10, 10): bx(k, (sx * 41, y, 30), (4, 6, 50), 1) for x in (-30, 0, 30): bt(k, (x, 60, 53), 2) hd(k, (-16, 52, 60), (16, 52, 60), 'Z', 8, 2) return [] @item("A04", "DomeCanister", 800, 152) def a04(k): k.lathe([(0, 0), (48 * U, 0), (50 * U, 3 * U), (50 * U, 40 * U), (47 * U, 44 * U), (44 * U, 44 * U), (44 * U, 48 * U), (40 * U, 52 * U), (24 * U, 56 * U), (0, 57 * U)], m((-28, 0, 0)), 'Z', 40) ring(k, (-28, 0, 47), 46, 3, 2) ring(k, (-28, 0, 54), 26, 2, 3) cy(k, (-28, 0, 55), 8, 5, 'Z', 20, 1.5) for a in range(0, 360, 45): r = math.radians(a) bt(k, (-28 + 42 * math.cos(r), 42 * math.sin(r), 44), 2) bx(k, (48, -18, 5), (64, 50, 10), 2.5) # side bracket plate for x, y in ((62, -30), (62, -6), (36, -30)): dt(k, (x, y, 10), 5) bx(k, (40, -8, 16), (26, 22, 14), 2) bx(k, (12, -18, 18), (16, 30, 30), 2) tb(k, [(40, 4, 18), (40, 30, 18), (20, 40, 26)], 3.5) return [] @item("A05", "HatchPanel", 1122, 152) def a05(k): bx(k, (0, 0, 8), (355, 108, 16), 3) hx, hy, hw, hh = 35, -6, 186, 76 # hatch frame knuckles = (-60, 0, 60) # hatch hinge knuckles (x from the hatch centre) bx(k, (hx, hy - (hh / 2 - 4), 19), (hw, 8, 6), 1.5) edges = [-hw / 2] + [e for x in knuckles for e in (x - 8, x + 8)] + [hw / 2] for a, b in zip(edges[0::2], edges[1::2]): # the top bar is notched where the knuckles turn bx(k, (hx + (a + b) / 2, hy + (hh / 2 - 4), 19), (b - a, 8, 6), 1.5) for sx in (-1, 1): bx(k, (hx + sx * (hw / 2 - 4), hy, 19), (8, hh - 16, 6), 1.5) bx(k, (hx, hy, 16.5), (hw - 16, hh - 16, 1), 0, DARK) # dark gap round the hatch bx(k, (150, -14, 21), (18, 30, 10), 2) # latch block beside the hatch bx(k, (150, -2, 27), (8, 30, 4), 1) bx(k, (-150, -10, 19), (26, 26, 6), 2) # lever box at the left cy(k, (-150, -10, 22), 6, 5, 'Z', 16, 1) hd(k, (95, 46, 16), (150, 46, 16), 'Z', 22, 3) tb(k, [(-172, -46, 18), (-165, -46, 18), (130, -46, 18), (138, -40, 16)], 3.5) for sx in (-1, 1): for sy in (-1, 1): bt(k, (sx * 168, sy * 44, 16), 2.4) # the hatch leaf (moving): hinged along X at its top edge, axis on the plate's top face so it lifts clear h = Kit() w_, d_ = hw - 18, hh - 18 h.box(m((0, -d_ / 2, -2.2)), m((w_, d_, 4.4)), 1.5 * U) # 1.8 mm over the gap plate h.box(m((-40, -d_ / 2, 1)), m((40, 24, 2)), 1 * U) h.handle(m((40, -d_ / 2 - 8, 0)), m((70, -d_ / 2 - 8, 0)), 'Z', 7 * U, 2 * U) for x in knuckles: h.cyl(m((x - 6, 0, 0)), 3.5 * U, 12 * U, 'X', 12, 0.5 * U) return [("Hatch", h, (hx, hy + d_ / 2, 22), 'X')] @item("A06", "PlugCapsule", 1400, 152) def a06(k): slab(k, rrect(46, 104, 21), 40, 0, 3) bx(k, (0, 0, 41), (30, 74, 3), 1.5) for y in (16, -16): bx(k, (0, y, 43), (14, 24, 1.6), 0.8, DARK) bx(k, (0, y, 43.6), (8, 18, 1.6), 0.5, PAINT) hd(k, (-12, 50, 22), (12, 50, 22), 'Y', 12, 2.6) for y in (-46, 46): bt(k, (0, y, 40), 2.2) return [] @item("A07", "PumpCan", 1535, 152) def a07(k): cn(k, (0, -52, 28), 26, 84, 'Y', grooves=(14, 22, 58), ends=(False, True)) for rr in (22, 15, 8): ring(k, (0, -53, 28), rr, 2, 3, 'Y', DARK) dt(k, (0, -53, 28), 5, 'Y') bx(k, (0, 44, 18), (46, 22, 36), 3) for sx in (-1, 1): bx(k, (sx * 30, 8, 18), (12, 28, 24), 2) bx(k, (0, 44, 37), (30, 14, 3), 1) return [] @item("A08", "FramedBay", 1780, 152) def a08(k): bx(k, (0, 0, 4), (250, 110, 8), 2) for sx in (-1, 1): bx(k, (sx * 119, 0, 14), (12, 110, 20), 2) bx(k, (sx * 100, 40, 22), (20, 20, 20), 2) bx(k, (0, 50, 14), (226, 10, 20), 2) bx(k, (0, 8, 22), (160, 52, 10), 3, rx=-14) # sloped hood bx(k, (0, 8, 30), (120, 4, 6), 1, rx=-14) bx(k, (0, -14, 14), (180, 14, 12), 2) tb(k, [(-112, -24, 22), (-100, -44, 13), (100, -44, 13), (112, -24, 22)], 7, bend=16) for sx in (-1, 1): cy(k, (sx * 100, -44, 13), 9, 10, 'X', 16, 1.5) for y in (56, 62): tb(k, [(-100, y, 30), (100, y, 30)], 2.4) for sx in (-1, 1): bx(k, (sx * 104, 59, 26), (8, 16, 12), 1.5) return [] # ============================================================== row B @item("B01", "PivotLid", 190, 300) def b01(k): bx(k, (-22, 0, 14), (112, 100, 28), 4) bx(k, (-22, -52, 8), (80, 8, 16), 2) cy(k, (-28, 0, 27), 46, 2, 'Z', 40, 0.5, DARK) # seat under the lid for y in (-30, 30): # hinge knuckles on the base cy(k, (34, y - 9, 36), 6, 18, 'Y', 16, 1) bx(k, (34, y, 31), (10, 18, 10), 1.5) bx(k, (62, -18, 6), (60, 44, 12), 2.5) # hinge arm to the right bx(k, (82, -30, 14), (20, 20, 8), 1.5) for y in (-30, -6): bt(k, (62, y, 12)) lid = Kit() # the lid (moving): hinged along Y on its right edge lid.lathe([(0, 0), (52 * U, 0), (55 * U, 3 * U), (55 * U, 9 * U), (52 * U, 12 * U), (0, 12 * U)], m((-62, 0, -6)), 'Z', 48) lid.ring(m((-62, 0, 6)), 40 * U, 3 * U, 2 * U) lid.cyl(m((-62, 0, 6)), 12 * U, 4 * U, 'Z', 24, 1 * U) lid.cyl(m((0, -9, 0)), 6 * U, 18 * U, 'Y', 16, 1 * U) lid.box(m((-7, 0, 0)), m((14, 16, 10)), 1.5 * U) return [("Lid", lid, (34, 0, 36), 'Y')] @item("B02", "SlimPanel", 352, 298) def b02(k): bx(k, (0, 0, 10), (42, 112, 20), 2) bx(k, (0, 0, 21), (30, 90, 2), 1) for y in (-30, 0, 30): bx(k, (0, y, 23), (34, 5, 3), 1) bolts4(k, 0, 0, 30, 100, 20) bx(k, (0, 59, 8), (20, 8, 12), 1.5) return [] @item("B03", "TwinCylinderEngine", 552, 298) def b03(k): bx(k, (10, 0, 5), (170, 104, 10), 2) for y in (22, -22): cn(k, (-58, y, 32), 20, 132, 'X', grooves=(14, 28, 104, 118), ends=(False, False)) cy(k, (-62, y, 32), 12, 4, '-X', 20, 1, STEEL) bx(k, (24, 0, 42), (40, 94, 30), 3) bx(k, (24, 0, 58), (28, 70, 3), 1) bolts4(k, 24, 0, 32, 84, 57) tb(k, [(-66, 30, 34), (-90, 30, 34), (-90, -30, 34), (-66, -30, 34)], 6, bend=14) tb(k, [(-66, 12, 40), (-80, 12, 40), (-80, -12, 40), (-66, -12, 40)], 3.5, bend=8) for sx in (60, 84): for y in (-40, 40): bx(k, (sx, y, 20), (14, 18, 30), 2) return [] @item("B04", "VentPlate", 810, 298) def b04(k): xs = [-92, -84, -12, 60, 132, 140] ys = [-52, -46, -16, 14, 44, 52] holes = {(i, j): (29, 9, 5) for i in (1, 2, 3) for j in (1, 2, 3)} plate_holes(k, xs, ys, holes, 8, 2, kk=5) bx(k, (24, 55, 8), (232, 8, 16), 2) bx(k, (24, -55, 8), (232, 8, 16), 2) bx(k, (-112, 0, 14), (24, 118, 28), 3) # side bracket with its handle hd(k, (-120, -36, 28), (-120, 36, 28), 'Z', 14, 2.8) bt(k, (-104, 44, 28), 2.6); bt(k, (-104, -44, 28), 2.6) for sx in (-1, 1): bx(k, (142, sx * 40, 10), (10, 20, 20), 2) return [] @item("B05", "FanPanel", 1150, 300) def b05(k): bx(k, (0, 0, 6), (300, 110, 12), 3) fx = -95 ring(k, (fx, 0, 21), 44, 7, 18) # fan shroud cy(k, (fx, 0, 12), 38, 2, 'Z', 40, 0, DARK) for a in (0, 60, 120): # guard bars over the fan bx(k, (fx, 0, 29), (84, 3, 3), 1, rz=a) ring(k, (fx, 0, 29), 24, 2.5, 3) bx(k, (10, 16, 24), (64, 52, 24), 3) bx(k, (10, 16, 37), (48, 36, 3), 1) bolts4(k, 10, 16, 56, 44, 36) bx(k, (10, -32, 18), (52, 22, 12), 2) bx(k, (100, 0, 20), (60, 72, 16), 3) for x in (85, 100, 115): bx(k, (x, 0, 29), (6, 60, 3), 1) for y in (-48, 48): tb(k, [(-150, y, 12), (-142, y, 22), (142, y, 22), (150, y, 12)], 4.5, bend=8) for sx in (-1, 1): bx(k, (sx * 146, 0, 16), (10, 104, 20), 2) rot = Kit() # fan rotor (moving): spins about Z rot.cyl(m((0, 0, 0)), 10 * U, 9 * U, 'Z', 20, 1.5 * U) for i in range(7): a = 2 * math.pi * i / 7 R = Matrix.Rotation(a, 4, 'Z') @ Matrix.Rotation(math.radians(28), 4, 'X') rot.box([c * U for c in (22 * math.cos(a), 22 * math.sin(a), 4.5)], m((26, 11, 1.6)), 0.5 * U, PAINT, R) return [("FanRotor", rot, (fx, 0, 15), 'Z')] # 3 mm over the fan well @item("B06", "Tank", 1372, 302) def b06(k): cn(k, (0, -46, 22), 21, 92, 'Y', grooves=(24, 68)) for y in (-22, 22): ring(k, (0, y, 22), 22, 2, 7, 'Y') bx(k, (0, 0, 3), (30, 70, 6), 2) return [] @item("B07", "ValveBlock", 1497, 298) def b07(k): bx(k, (6, -4, 25), (62, 92, 50), 4) bx(k, (6, 38, 52), (50, 20, 4), 1.5) bolts4(k, 6, 38, 40, 12, 54, 1.8) bx(k, (6, -14, 51), (40, 44, 3), 1.5) for y in (28, -28): cy(k, (-26, y, 30), 9, 10, '-X', 16, 1.5) tb(k, [(-30, 28, 30), (-42, 28, 30), (-42, -28, 30), (-30, -28, 30)], 6.5, bend=14) for sx in (-1, 1): bx(k, (6 + sx * 24, -50, 6), (14, 10, 12), 1.5) cy(k, (40, 10, 25), 8, 8, 'X', 16, 1.5) return [] @item("B08", "PortStrip", 1612, 300) def b08(k): slab(k, rrect(52, 108, 25), 14, 0, 2.5) for y in (-37, -12, 12, 37): k.ring(m((0, y, 14)), 9 * U, 2.5 * U, 2 * U) dt(k, (0, y, 14), 7) return [] @item("B09", "StepModule", 1812, 298) def b09(k): bx(k, (-55, 0, 30), (82, 104, 60), 3) bx(k, (-55, 8, 61), (60, 60, 3), 1.5) bolts4(k, -55, 8, 52, 52, 63) ang = math.degrees(math.atan2(52, 104)) bx(k, (58, 0, 26), (70, 116, 6), 2, rx=ang) # sloped back plate under the rungs for x in (26, 90): tb(k, [(x, -54, 4), (x, 54, 58)], 4) for i in range(6): t = (i + 0.5) / 6 y, z = -54 + 108 * t, 4 + 54 * t + 6 tb(k, [(26, y, z), (90, y, z)], 3) bx(k, (58, -56, 4), (76, 8, 8), 1.5) return [] # ============================================================== row C @item("C01", "RadiatorBar", 295, 470) def c01(k): bx(k, (0, 0, 24), (332, 90, 48), 4) for y in (-26, 0, 26): bx(k, (0, y, 48.6), (316, 5, 1.2), 0.4, DARK) bx(k, (0, y + 13, 49), (316, 8, 2.5), 1) for sx in (-1, 1): bx(k, (sx * 176, 0, 20), (22, 74, 40), 3) for y in (-22, 22): cy(k, (sx * 186, y, 16), 5, 20, 'X' if sx > 0 else '-X', 12, 1, STEEL) bx(k, (sx * 196, y, 14), (10, 14, 18), 1.5) bt(k, (sx * 176, 0, 40), 3) return [] @item("C02", "PipeTray", 675, 472) def c02(k): bx(k, (0, 0, 4), (310, 104, 8), 2) for sy in (-1, 1): bx(k, (0, sy * 49, 16), (310, 6, 24), 1.5) for sx in (-1, 1): bx(k, (sx * 152, 0, 16), (6, 92, 24), 1.5) tb(k, [(-140, 26, 16), (140, 26, 16)], 6) tb(k, [(-140, 8, 14), (-100, 8, 14), (-90, -10, 14), (90, -10, 14), (100, 8, 14), (140, 8, 14)], 4.5, bend=10) for x in (-60, 60): bx(k, (x, 14, 22), (20, 44, 22), 2) bt(k, (x, 26, 33)); bt(k, (x, 2, 33)) for x in (-110, 110): cy(k, (x - 14, -28, 14), 7, 28, 'X', 16, 1.5) bx(k, (0, -40, 8.4), (200, 6, 1), 0.3, DARK) return [] @item("C03", "CylinderTray", 1042, 472) def c03(k): bx(k, (0, 0, 6), (345, 100, 12), 3) for sx in (-1, 1): bx(k, (sx * 152, 0, 20), (40, 100, 28), 3) cn(k, (sx * 112, -32, 24), 12, 64, 'Y', grooves=(10, 54), ends=(False, False)) bx(k, (sx * 70, -20, 20), (30, 40, 18), 2) for y in (-30, 0, 30): bt(k, (sx * 152, y, 34), 2.6) bx(k, (0, 8, 15), (120, 62, 6), 2) bx(k, (0, 8, 18.6), (104, 48, 1), 0.3, DARK) bx(k, (0, 8, 19.4), (100, 44, 2), 1) hd(k, (-20, -14, 18), (20, -14, 18), 'Z', 8, 2.2) for x in range(-50, 60, 20): dt(k, (x, -40, 12), 3) return [] @item("C04", "TwinThruster", 1372, 472) def c04(k): bx(k, (0, 28, 8), (265, 46, 16), 3) for sx in (-1, 1): dt(k, (sx * 118, 28, 16), 7) bx(k, (sx * 100, 10, 16), (24, 20, 16), 2) bx(k, (0, 8, 34), (150, 64, 46), 5) bx(k, (0, 20, 58), (110, 30, 3), 1.5) for sx in (-1, 1): cn(k, (sx * 40, -18, 34), 26, 46, '-Y', grooves=(10, 18), ends=(False, False)) ring(k, (sx * 40, -65, 34), 22, 4, 2, 'Y') # nozzle lip, proud of the can's end dt(k, (sx * 40, -64, 34), 14, '-Y') return [] @item("C05", "ForkBracket", 1678, 472) def c05(k): bx(k, (0, 26, 14), (214, 22, 22), 3) for x in (-40, 0, 40): dt(k, (x, 26, 25), 4) for sx in (-1, 1): bx(k, (sx * 70, 8, 14), (34, 20, 24), 2) cn(k, (sx * 70, 0, 16), 14, 46, '-Y', grooves=(12, 30), ends=(False, True)) bx(k, (sx * 100, 26, 6), (16, 34, 12), 2) bt(k, (sx * 100, 36, 12)); bt(k, (sx * 100, 16, 12)) bx(k, (0, 10, 12), (36, 18, 18), 2) return [] @item("C06", "EndCap", 1860, 478) def c06(k): cn(k, (0, 40, 30), 28, 80, '-Y', grooves=(12, 22, 32), ends=(False, True), end=0.45) ring(k, (0, 39, 30), 31, 4, 6, 'Y') bx(k, (0, 30, 4), (40, 30, 8), 2) return [] # ============================================================== row D @item("D01", "TwinTankFrame", 215, 628) def d01(k): bx(k, (0, 10, 30), (100, 110, 60), 4) bx(k, (0, 10, 61), (76, 80, 3), 1.5) bolts4(k, 0, 10, 66, 70, 62) for sx in (-1, 1): cn(k, (sx * 86, -58, 28), 26, 124, 'Y', grooves=(20, 104)) for y in (-28, 36): ring(k, (sx * 86, y, 28), 27.5, 2.5, 8, 'Y') tb(k, [(sx * 50, 30, 44), (sx * 66, 30, 44), (sx * 72, 20, 44)], 4) bx(k, (sx * 70, -66, 8), (30, 14, 16), 2) bx(k, (0, -50, 10), (100, 14, 20), 2) return [] @item("D02", "CableBox", 430, 625) def d02(k): bx(k, (0, 12, 25), (76, 112, 50), 4) bx(k, (0, 28, 51), (62, 50, 3), 1.5) bx(k, (0, -14, 51), (40, 18, 4), 1.5) hd(k, (-14, 56, 30), (14, 56, 30), 'Y', 10, 2.4) cy(k, (0, -44, 20), 10, 8, '-Y', 16, 1.5) tb(k, [(0, -50, 20), (0, -62, 20), (6, -76, 8), (12, -82, 4)], 6, bend=12) for sx in (-1, 1): for y in (-20, 10, 40): bx(k, (sx * 38, y, 25), (4, 8, 40), 1) bx(k, (0, 2, 52.5), (14, 8, 4), 1) bolts4(k, 0, 28, 52, 40, 52.5, 1.8) return [] @item("D03", "PerforatedCan", 575, 635) def d03(k): cy(k, (0, -62, 30), 28, 128, 'Y', 32, 4) cy(k, (0, 66, 30), 18, 8, 'Y', 24, 2) for i in range(7): y = -40 + i * 14 for a in (-50, -25, 0, 25, 50): r = math.radians(a) d = Vector((math.sin(r), 0, math.cos(r))) c = Vector((0, y, 30)) + d * 27.6 k.dot(m(c), 4 * U, tuple(d), 0.0015, DARK, 12) for sx in (-1, 1): bx(k, (sx * 26, -58, 10), (10, 16, 20), 2) bx(k, (0, -58, 4), (62, 16, 8), 2) return [] @item("D04", "TriPortBlock", 707, 637) def d04(k): bx(k, (0, 0, 22), (80, 152, 44), 4) for y in (-46, 0, 46): sk(k, (0, y, 44), 17, 7, 'Z', 3) for sy in (-1, 1): bx(k, (0, sy * 72, 8), (90, 14, 16), 2) return [] @item("D05", "FrameBox", 900, 638) def d05(k): bx(k, (0, 8, 26), (130, 104, 52), 4) bx(k, (0, 8, 53), (100, 70, 3), 1.5) W, H = 86, 72 for z in (6, 58): tb(k, [(-W, -H, z), (W, -H, z), (W, H, z), (-W, H, z)], 4, bend=12, closed=True) for sx in (-1, 1): for sy in (-1, 1): tb(k, [(sx * (W - 2), sy * (H - 2), 6), (sx * (W - 2), sy * (H - 2), 58)], 4) bx(k, (sx * 74, 8, 26), (18, 30, 24), 2) bx(k, (0, -74, 6), (150, 10, 12), 2) return [] @item("D06", "SlimMechanism", 1107, 642) def d06(k): bx(k, (0, 0, 4), (60, 162, 8), 2) for sx in (-1, 1): tb(k, [(sx * 18, -60, 18), (sx * 18, 62, 18)], 4.5) bx(k, (sx * 18, 70, 16), (12, 18, 30), 2) bx(k, (0, 28, 22), (52, 40, 30), 3) bx(k, (0, -20, 14), (30, 24, 12), 2) for y in (-48, -64): k.ring(m((0, y, 8)), 9 * U, 2 * U, 2 * U) dt(k, (0, y, 8), 7) return [] @item("D07", "HandleBox", 1282, 640) def d07(k): bx(k, (0, 0, 35), (130, 140, 70), 5) bx(k, (0, -10, 71), (100, 92, 4), 2) bx(k, (0, -10, 73.6), (60, 30, 2), 1) hd(k, (-40, 54, 70), (40, 54, 70), 'Z', 16, 3) for sx in (-1, 1): hd(k, (sx * 65, -30, 40), (sx * 65, 30, 40), 'X' if sx > 0 else '-X', 12, 3) bx(k, (0, -74, 6), (110, 10, 12), 2) bolts4(k, 0, -10, 90, 82, 73) return [] @item("D08", "DrumUnit", 1595, 628) def d08(k): k.lathe([(0, 0), (60 * U, 0), (62 * U, 2 * U), (62 * U, 60 * U), (58 * U, 64 * U), (56 * U, 64 * U), (56 * U, 68 * U), (50 * U, 70 * U), (0, 70 * U)], m((-50, 0, 0)), 'Z', 48) for z in (16, 44): ring(k, (-50, 0, z), 63.5, 3, 6) ring(k, (-50, 0, 70), 40, 3, 2) cy(k, (-50, 0, 70), 14, 5, 'Z', 24, 1.5) bx(k, (62, -28, 6), (100, 60, 12), 3) bx(k, (76, -32, 22), (32, 32, 20), 2.5) bx(k, (40, -28, 16), (18, 40, 8), 1.5) tb(k, [(10, -10, 44), (40, -10, 44), (60, -24, 32)], 5, bend=12) return [] @item("D09", "CubeBox", 1828, 628) def d09(k): bx(k, (0, 0, 40), (152, 142, 80), 6) bx(k, (0, 0, 81), (122, 112, 3), 2) bx(k, (0, 0, 83.6), (96, 86, 2), 1.5) hd(k, (-24, 40, 84), (24, 40, 84), 'Z', 8, 2.4) for sx in (-1, 1): for sy in (-1, 1): bt(k, (sx * 66, sy * 60, 80), 2.8) for sx in (-1, 1): for sy in (-1, 1): bx(k, (sx * 72, sy * 67, 40), (12, 12, 76), 3) for sy in (-1, 1): bx(k, (0, sy * 71.5, 20), (110, 3, 10), 1) bx(k, (0, sy * 71.5, 60), (110, 3, 10), 1) return [] # ============================================================== row E @item("E01", "HorizontalTank", 212, 808) def e01(k): cn(k, (-102, 0, 60), 58, 192, 'X', grooves=(40, 152), ends=(True, False), end=0.45) cy(k, (90, 0, 60), 62, 8, 'X', 40, 2) cy(k, (98, 0, 60), 20, 6, 'X', 24, 2) for x in (-40, 40): ring(k, (x, 0, 60), 60, 3, 10, 'X') bx(k, (x, 0, 8), (20, 100, 16), 2) tb(k, [(104, 24, 70), (116, 24, 70), (116, -30, 40), (100, -46, 20)], 5, bend=14) return [] @item("E02", "FrameAssembly", 522, 800) def e02(k): bx(k, (0, -4, 5), (222, 140, 10), 2) bx(k, (0, 66, 20), (254, 14, 30), 3) for x in (-60, 60): hd(k, (x - 26, 68, 35), (x + 26, 68, 35), 'Z', 14, 3) bx(k, (0, -4, 26), (150, 82, 32), 3) bx(k, (0, -4, 43), (120, 60, 3), 1.5) for x in (-40, 0, 40): bx(k, (x, -4, 45.5), (6, 50, 3), 1) bolts4(k, 0, -4, 140, 72, 42) for sx in (-1, 1): for y in (-50, 40): bx(k, (sx * 95, y, 16), (20, 16, 12), 2) for sx in (-1, 1): bx(k, (sx * 116, -4, 25), (16, 128, 50), 2.5) tb(k, [(-110, -74, 12), (110, -74, 12)], 5) for sx in (-1, 1): bx(k, (sx * 110, -74, 10), (12, 14, 16), 1.5) return [] @item("E03", "GrilleBox", 772, 808) def e03(k): bx(k, (0, 8, 30), (92, 128, 60), 4) bx(k, (0, -14, 60.4), (72, 66, 1), 0.3, DARK) for i in range(10): bx(k, (0, -44 + i * 6.6, 61.5), (72, 2.6, 3), 0.6) for sx in (-1, 1): bx(k, (sx * 37.5, -14, 61.5), (3, 66, 3), 0.6) bx(k, (0, 46, 61.5), (72, 30, 3), 1.5) bx(k, (0, -60, 8), (80, 10, 16), 2) return [] @item("E04", "MotorHose", 1060, 810) def e04(k): bx(k, (-60, 10, 35), (110, 112, 70), 6) bx(k, (-60, 18, 71), (80, 70, 3), 2) for x in (-85, -60, -35): bx(k, (x, 18, 74), (6, 56, 3), 1) bx(k, (-2, -6, 34), (14, 50, 50), 3) cy(k, (4, -6, 34), 20, 22, 'X', 24, 2) ring(k, (24, -6, 34), 15, 3, 6, 'X') tb(k, [(24, -6, 34), (80, -6, 34), (106, -26, 28), (110, -62, 18)], 12, bend=30, segs=16) ring(k, (106, -40, 24), 13.5, 2, 6, 'Y') return [] @item("E05", "HingeMount", 1240, 810) def e05(k): bx(k, (0, -22, 10), (72, 96, 20), 3) bx(k, (0, -30, 21), (52, 56, 3), 1.5) bolts4(k, 0, -30, 40, 44, 22) for sx in (-1, 1): bx(k, (sx * 24, 26, 18), (16, 16, 18), 2) cy(k, (sx * 16, 30, 28), 9, 16, 'X' if sx > 0 else '-X', 16, 1.5) leaf = Kit() # hinge leaf (moving): swings about X leaf.cyl(m((-15, 0, 0)), 9 * U, 30 * U, 'X', 16, 1.5 * U) leaf.box(m((0, 22, -4)), m((30, 36, 8)), 2 * U) leaf.cyl(m((0, 28, 0)), 5 * U, 1.6 * U, 'Z', 16, 0.3 * U, DARK) return [("Leaf", leaf, (0, 30, 28), 'X')] @item("E06", "WidePipeBox", 1508, 810) def e06(k): bx(k, (0, 14, 30), (282, 100, 60), 5) bx(k, (0, 14, 61), (124, 70, 4), 2) bolts4(k, 0, 14, 112, 60, 63) for sx in (-1, 1): bx(k, (sx * 120, 30, 60.4), (36, 34, 1), 0.3, DARK) for i in range(5): bx(k, (sx * 120, 16 + i * 7, 61.4), (36, 3, 2.4), 0.6) for sx in (-1, 1): tb(k, [(sx * 140, 34, 30), (sx * 162, 34, 30), (sx * 162, -40, 22), (sx * 162, -62, 8)], 8.5, bend=18) bx(k, (sx * 126, -48, 15), (30, 28, 30), 2.5) for x in (60, 90): bx(k, (sx * x, 14, 61.5), (6, 70, 3), 1) return [] @item("E07", "TripleCanister", 1810, 810) def e07(k): bx(k, (0, -6, 6), (190, 120, 12), 3) for x in (-62, 0, 62): cn(k, (x, -2, 12), 27, 72, 'Z', grooves=(10, 44), ends=(False, True), end=0.3) cy(k, (x, -2, 82), 8, 5, 'Z', 16, 1.5) for x in (-31, 31): bx(k, (x, -2, 36), (10, 46, 46), 2) tb(k, [(-92, 56, 12), (-92, 56, 60), (92, 56, 60), (92, 56, 12)], 4, bend=10) for sx in (-1, 1): bx(k, (sx * 92, -60, 14), (12, 12, 16), 1.5) return []