Gallery
Objects whose parts move, each one program. Pick one on the left, press Play, or move a joint
with its slider; click a part to light the code that builds it. The joints are the ones the program declares
with joint; export writes them to GLB, URDF and USD.
1"""A front-loading washing machine, articulated: what #82's vocabulary writes in one piece.2 3Millimetres; the front looks +X, Z up. Four joints, each on a frame read on the cabinet:4the door centred on the porthole, hinged at its outer -Y edge so that it clears the5cabinet (it opens outward about "-Z", 0–143°), the drum endless about the front's6normal, the detergent drawer sliding out 0–200 mm, the dial endless. The drawer's bay and the dial's seat are cut by `seat`, as they sit at rest;7the door's glass is seated in a groove of its ring. Built at rest; `washer_open()` poses it.8"""9import sand3d as s3d10 11 12def washer(w=600, d=600, h=850, porthole=440, door_d=480, drum_d=420):13 cab = s3d.box("cabinet", w, d, h)14 s3d.fillet(cab, 12, edges="side")15 front = cab.face("+X") # X is +Y, Y is up16 s3d.pocket(cab, s3d.circle(porthole), d - 100, on=front.move(0, 400))17 s3d.material(cab, "plastic", color="#f2f2f0")18 19 back = front.move(0, 400).offset(-(d - 200)) # a solid's height runs along its frame's normal20 drum = s3d.at(s3d.cylinder("drum", drum_d, d - 220), on=back)21 s3d.cut(drum, s3d.at(s3d.cylinder("bore", drum_d - 20, d - 229), on=back.offset(10)))22 s3d.join(drum, s3d.at(s3d.cylinder("axle", 40, 60), on=back.offset(-60)))23 s3d.material(drum, "brushed_steel")24 25 ring = s3d.at(s3d.tube("ring", door_d, 300, 45), on=front.move(0, 400)) # centred on the porthole26 glass = s3d.at(s3d.cylinder("glass", 320, 16), on=front.move(0, 400).offset(14))27 hinge = front.move(-door_d / 2, 400).offset(45) # the ring's outer -Y edge: it clears the cabinet28 s3d.seat(ring, glass)29 s3d.material(ring, "painted_metal", color="#3a3d42")30 s3d.material(glass, "glass", color="#cfe3e6", opacity=0.4)31 handle = s3d.at(s3d.box("handle", 24, 110, 30), on=s3d.bbox(ring, "+X").move(x=door_d / 2 - 40))32 door = s3d.group("door", ring, glass, handle) # the handle and the glass move with it33 34 top_band = front.move(0, h - 75)35 drawer = s3d.at(s3d.box("drawer", 200, 100, 231), on=top_band.move(150).offset(-230))36 s3d.join(drawer, s3d.at(s3d.box("drawer_front", 220, 120, 15), on=top_band.move(150)))37 s3d.seat(cab, drawer)38 dial = s3d.at(s3d.cylinder("dial", 60, 30), on=top_band.move(-150).offset(-10))39 s3d.seat(cab, dial)40 s3d.material([drawer, dial], "plastic", color="#e6e6e3")41 42 s3d.joint("door_hinge", door, hinge, axis="-Z", range=(0, 143))43 s3d.joint("drum_spin", drum, front.move(0, 400), kind="continuous")44 s3d.joint("drawer_slide", drawer, top_band.move(150), kind="prismatic", axis="+X", range=(0, 200))45 s3d.joint("dial_turn", dial, top_band.move(-150), kind="continuous")46 return s3d.assembly("washing_machine", cab, drum, door, drawer, dial, front=front)47 48 49def washer_open():50 machine = washer()51 s3d.pose(machine, 92, joint="door_hinge")52 s3d.pose(machine, 120, joint="drawer_slide")53 s3d.pose(machine, 30, joint="dial_turn")54 return machine
54 lines · 1038 tokens (o200k_base)
1"""A6 — a floor task lamp: a head that swivels on the column, an arm that lifts on the2head's yoke, a shade that tilts at the arm's tip — a revolute chain three deep.3 4Source: Articraft `rec_articulated_task_lamp_e3b37e132fda4a8b848be4c5ba370d7e`5(Articraft-10K, CC-BY-4.0; `ref/A6/`). Every link frame is a translation of the world's,6so the program is built in one frame: the swivel at z = 1168 (the column's top collar),7the shoulder 38 mm forward and 40 mm up from it, the shade's trunnion 439 mm along the8arm. The swivel turns about the stand's top face; the shoulder is read on the +X side9of a yoke cheek (x = 38, its origin 14 mm along the axis from Articraft's, which is the10same line); the tilt on the +X side of a tip cheek, offset 9 mm to the trunnion's axis.11Both lifts turn about -Y, as in the source: positive raises the arm and the shade's nose.12The lathed base and shade shell are `revolve`s of the source's profiles (the shade's13inner and outer profiles closed into one outline, the shell then laid along +X).14"""15import math16 17import sand3d as s3d18 19 20def build():21 # stand: the weighted base, the column and its collars22 base = s3d.revolve("weighted_base", [(0, 0), (106, 0), (132, 4), (145, 14), (143, 26), (118, 34),23 (50, 38), (0, 38)])24 s3d.material(base, "painted_metal", color=(0.12, 0.12, 0.13))25 collar = s3d.at(s3d.cylinder("base_collar", 54, 14), z=38)26 column = s3d.at(s3d.cylinder("column", 32, 1130), z=38)27 top = s3d.at(s3d.cylinder("top_collar", 48, 12), z=1156)28 s3d.material([collar, top], "steel", color=(0.28, 0.30, 0.32))29 s3d.material(column, "brushed_steel", color=(0.67, 0.69, 0.72))30 stand = s3d.group("stand", base, collar, column, top)31 32 # swivel head, on the top collar (z = 1168)33 z0 = 116834 disk = s3d.at(s3d.cylinder("swivel_disk", 80, 14), z=z0)35 stem = s3d.at(s3d.cylinder("swivel_stem", 36, 32), z=z0 + 10)36 bridge = s3d.at(s3d.box("shoulder_bridge", 30, 28, 18), x=12, z=z0 + 21)37 left = s3d.at(s3d.box("left_cheek", 40, 6, 28), x=18, y=14, z=z0 + 26)38 right = s3d.at(s3d.box("right_cheek", 40, 6, 28), x=18, y=-14, z=z0 + 26)39 s3d.material([disk, left, right], "steel", color=(0.28, 0.30, 0.32))40 s3d.material([stem, bridge], "brushed_steel", color=(0.67, 0.69, 0.72))41 swivel = s3d.group("swivel_head", disk, stem, bridge, left, right)42 43 # arm, from the shoulder axis (38, 0, 1208) along +X44 sx, sz = 38, z0 + 4045 barrel = s3d.at(s3d.cylinder("shoulder_barrel", 21, 22), x=sx, y=11, z=sz, rx=90)46 neck = s3d.at(s3d.box("shoulder_neck", 24, 16, 16), x=sx + 12, z=sz - 8)47 tube = s3d.at(s3d.cylinder("arm_tube", 22, 386), x=sx + 24, z=sz, ry=90)48 tip = s3d.at(s3d.box("tip_bridge", 28, 18, 16), x=sx + 414, z=sz - 8)49 tip_l = s3d.at(s3d.box("tip_left_cheek", 24, 5, 30), x=sx + 418, y=11.5, z=sz - 15)50 tip_r = s3d.at(s3d.box("tip_right_cheek", 24, 5, 30), x=sx + 418, y=-11.5, z=sz - 15)51 s3d.material([barrel, neck, tip, tip_l, tip_r], "steel", color=(0.28, 0.30, 0.32))52 s3d.material(tube, "brushed_steel", color=(0.67, 0.69, 0.72))53 arm = s3d.group("arm_link", barrel, neck, tube, tip, tip_l, tip_r)54 55 # shade, from the tilt axis (477, 0, 1208)56 tx = sx + 43957 trunnion = s3d.at(s3d.cylinder("shade_trunnion", 18, 18), x=tx, y=9, z=sz, rx=90)58 mount = s3d.at(s3d.box("shade_mount", 36, 16, 48), x=tx + 18, z=sz - 30)59 s3d.material([trunnion, mount], "steel", color=(0.28, 0.30, 0.32))60 shell = s3d.revolve("shade_shell", [(42, 0), (52, 16), (56, 50), (56, 170), (50, 200),61 (46, 200), (46, 50), (37, 26), (0, 10)])62 shell = s3d.at(shell, x=tx + 4, z=sz - 38, ry=90)63 s3d.material(shell, "plastic", color=(0.88, 0.87, 0.82))64 shade = s3d.group("shade", trunnion, mount, shell)65 66 s3d.joint("stand_to_swivel", swivel, s3d.bbox(stand, "+Z"), axis="+Z",67 range=(math.degrees(-1.91986), math.degrees(1.91986)))68 s3d.joint("swivel_to_arm", arm, s3d.bbox(left, "+X"), axis="-Y",69 range=(math.degrees(-0.698132), math.degrees(1.22173)))70 s3d.joint("arm_to_shade", shade, s3d.bbox(tip_l, "+X").offset(9), axis="-Y",71 range=(math.degrees(-1.13446), math.degrees(1.22173)))72 return s3d.assembly("floor_task_lamp", stand, swivel, arm, shade)
72 lines · 1695 tokens (o200k_base)
1"""A3 — a compact refrigerator: two doors on one hinge line, opening by negative angles,2and a thermostat dial turning in a control housing fixed under the divider.3 4Source: Articraft `rec_refrigerator_with_hinged_doors_eafdd7d9813b42fa80e8e2e8ff778665`5(Articraft-10K, CC-BY-4.0; `ref/A3/`). Every visual is an SDK box or cylinder; the cabinet's6link frame is the world, so each is placed by its centre in world millimetres. A door's link7frame sits on its hinge axis (x = 283, y = 271, at the door's mid-height): its visuals are8placed at that origin plus their offsets, at rest. The doors' limits are (-1.95, 0) rad: they9open clockwise seen from above, the hinge being on the +X side.10 11The source's `control_housing` is welded to the cabinet by a `fixed` joint: it is not a joint12here, its boxes and bezel join the cabinet's group, and the dial's joint is read on the13housing's front (+Y) face, so it hangs on the cabinet body. The door hinges are read on the14top of each door's upper hinge pin: the origin slides along the axis from Articraft's, which15is the same joint.16"""17import math18 19import sand3d as s3d20 21 22def _box(name, size, centre):23 """A box of size (x, y, z) centred on centre."""24 w, d, h = size25 x, y, z = centre26 return s3d.at(s3d.box(name, w, d, h), x=x, y=y, z=z - h / 2)27 28 29def _pin(name, d, length, centre):30 """A vertical cylinder centred on centre."""31 x, y, z = centre32 return s3d.at(s3d.cylinder(name, d, length), x=x, y=y, z=z - length / 2)33 34 35def build():36 w, d, h = 550, 530, 142037 hinge_x, hinge_y = 283, 27138 39 walls = [40 _box("left_wall", (28, d, h), (-261, 0, 710)),41 _box("right_wall", (28, d, h), (261, 0, 710)),42 _box("top_shell", (494, 518, 30), (0, 6, 1405)),43 _box("bottom_shell", (494, 518, 40), (0, 6, 20)),44 _box("back_panel", (494, 12, h), (0, -259, 710)),45 _box("center_face_rail", (494, 18, 24), (0, 256, 1080)),46 ]47 s3d.material(walls, "painted_metal", color=(0.92, 0.93, 0.94))48 shelf = _box("divider_shelf", (494, 518, 32), (0, 6, 1081))49 s3d.material(shelf, "plastic", color=(0.84, 0.86, 0.88))50 51 pins = {}52 hinge_parts = []53 for pin, z in (("upper_top", 1385), ("upper_center", 1100),54 ("lower_center", 1058), ("lower_bottom", 35)):55 hinge_parts.append(_box(f"{pin}_hinge_pin_bracket", (22, 18, 30), (275.5, 264.5, z)))56 pins[pin] = _pin(f"{pin}_hinge_pin", 14, 30, (hinge_x, hinge_y, z))57 hinge_parts.append(pins[pin])58 s3d.material(hinge_parts, "steel", color=(0.67, 0.69, 0.72))59 60 # The control housing, fixed to the cabinet: it welds into the cabinet's group.61 housing = _box("control_box", (160, 100, 50), (90, 100, 1030))62 tab = _box("mount_tab", (80, 60, 10), (90, 100, 1060))63 s3d.material([housing, tab], "plastic", color=(0.74, 0.76, 0.79))64 front = s3d.bbox(housing, "+Y") # y = 150; X is -X, Y is up65 dial_axis = front.move(-35, -4).offset(6) # (125, 156, 1026)66 bezel = s3d.at(s3d.cylinder("dial_bezel", 44, 6), on=front.move(-35, -4))67 s3d.material(bezel, "plastic", color=(0.28, 0.30, 0.33))68 69 cabinet = s3d.group("cabinet_body", walls, shelf, hinge_parts, housing, tab, bezel)70 71 def door(name, door_h, z, handle_h, handle_z):72 panel = _box(f"{name}_outer_panel", (575, 55, door_h), (hinge_x - 273.5, hinge_y + 34.5, z))73 flange = _box(f"{name}_hinge_flange", (14, 20, door_h - 100), (hinge_x + 11, hinge_y + 20, z))74 s3d.material([panel, flange], "glossy_plastic", color=(0.97, 0.97, 0.96))75 gasket = _box(f"{name}_door_gasket", (464, 10, door_h - 35), (hinge_x - 283, hinge_y + 1, z))76 s3d.material(gasket, "rubber", color=(0.76, 0.78, 0.80))77 liner = _box(f"{name}_inner_liner", (449, 28, door_h - 75), (hinge_x - 283, hinge_y + 19, z))78 s3d.material(liner, "plastic", color=(0.84, 0.86, 0.88))79 handle = _box(f"{name}_handle", (22, 20, handle_h), (hinge_x - 515, hinge_y + 67, z + handle_z))80 s3d.material(handle, "plastic", color=(0.28, 0.30, 0.33))81 k = door_h / 2 - 52.582 knuckles = [_pin(f"{name}_top_knuckle", 14, 45, (hinge_x, hinge_y, z + k)),83 _pin(f"{name}_bottom_knuckle", 14, 45, (hinge_x, hinge_y, z - k))]84 s3d.material(knuckles, "steel", color=(0.67, 0.69, 0.72))85 return s3d.group(name, panel, gasket, liner, flange, handle, knuckles)86 87 upper = door("upper_freezer_door", 315, 1242.5, 140, -55)88 lower = door("lower_main_door", 1053, 546.5, 240, 220)89 90 knob = s3d.at(s3d.cylinder("dial_body", 36, 12), on=dial_axis)91 s3d.material(knob, "plastic", color=(0.20, 0.22, 0.24))92 mark = _box("dial_indicator", (4, 3, 12), (125, 168.5, 1039))93 s3d.material(mark, "plastic", color=(0.93, 0.31, 0.18))94 dial = s3d.group("thermostat_dial", knob, mark)95 96 opening = (math.degrees(-1.95), 0)97 s3d.joint("upper_door_hinge", upper, s3d.bbox(pins["upper_top"], "+Z"), axis="+Z", range=opening)98 s3d.joint("lower_door_hinge", lower, s3d.bbox(pins["lower_center"], "+Z"), axis="+Z", range=opening)99 s3d.joint("thermostat_dial_joint", dial, dial_axis, axis="+Y",100 range=(math.degrees(-2.2), math.degrees(0.6)))101 return s3d.assembly("compact_apartment_refrigerator", cabinet, upper, lower, dial)
101 lines · 1917 tokens (o200k_base)
1"""A7 — an XYZ Cartesian stage: an X carriage on the base's rails, a Y stage on the2carriage, a column welded to the Y stage, and a table sliding up the column.3 4Source: Articraft `rec_xyz_cartesian_stage_9569f7654fbc435db20ac8bc588765a1`5(Articraft-10K, CC-BY-4.0; `ref/A7/`). Every visual is a box, centred on its origin in6its link frame; the links stack at z = 0, 57, 108, 174 and 199 mm, so each box here is7placed in the world at rest with its bottom at its centre minus half its height. Each8slide is read on the face its parent carries it on: the X carriage on the top of the9base's X rails (z = 57), the Y stage on the top of the carriage's cross plate10(z = 108), the table on the column's foot (its axis is vertical, so the origin may slide11along it from Articraft's z = 199). The source's `fixed` joint `y_to_column` is no joint12here: the column is a group welded inside the Y stage's group.13"""14import sand3d as s3d15 16 17def _block(name, w, d, h, x, y, zc, kind, color):18 """A box of w × d × h centred on (x, y, zc) in the world, as a URDF box visual."""19 ob = s3d.at(s3d.box(name, w, d, h), x=x, y=y, z=zc - h / 2)20 s3d.material(ob, kind, color=color)21 return ob22 23 24DARK, MILLED, RAIL, STOP, BLUE = "#14171a", "#b8bdc2", "#5c6166", "#050505", "#0d33d9"25 26 27def build():28 # base, link at z = 029 plate = _block("base_plate", 500, 320, 35, 0, 0, 17.5, "aluminium", DARK)30 x_rail_neg = _block("x_rail_neg", 400, 26, 22, 0, -90, 46, "steel", RAIL)31 x_rail_pos = _block("x_rail_pos", 400, 26, 22, 0, 90, 46, "steel", RAIL)32 stops = [_block(f"x_stop_{s}", 25, 240, 30, x, 0, 50, "plastic", STOP)33 for s, x in (("neg", -225), ("pos", 225))]34 base = s3d.group("base", plate, x_rail_neg, x_rail_pos, *stops)35 36 # x_carriage, link at z = 5737 z = 5738 cross = _block("x_cross_plate", 200, 220, 25, 0, 0, z + 38.5, "aluminium", MILLED)39 x_parts = [cross]40 for sx, x in (("neg", -65), ("pos", 65)):41 for sy, y in (("neg", -90), ("pos", 90)):42 x_parts.append(_block(f"x_bearing_{sx}_{sy}", 70, 46, 26, x, y, z + 13, "plastic", STOP))43 x_parts.append(_block("x_axis_cover", 70, 25, 10, 0, 0, z + 56, "painted_metal", BLUE))44 x_carriage = s3d.group("x_carriage", *x_parts)45 46 # y_stage, link at z = 10847 z = 10848 y_parts = [_block("y_carriage_plate", 220, 180, 25, 0, 0, z + 38.5, "aluminium", MILLED)]49 for s, x in (("neg", -70), ("pos", 70)):50 y_parts.append(_block(f"y_rail_{s}", 20, 205, 15, x, 0, z + 58.5, "steel", RAIL))51 for sx, x in (("neg", -65), ("pos", 65)):52 for sy, y in (("neg", -50), ("pos", 50)):53 y_parts.append(_block(f"y_bearing_{sx}_{sy}", 46, 70, 26, x, y, z + 13, "plastic", STOP))54 y_parts.append(_block("y_axis_cover", 160, 20, 10, 0, -92.5, z + 71, "painted_metal", BLUE))55 56 # z_column, link at z = 174: fixed to the Y stage, so welded into its group57 z = 17458 foot = _block("column_foot", 160, 160, 20, 0, 0, z + 10, "aluminium", DARK)59 column = s3d.group(60 "z_column",61 foot,62 _block("vertical_backbone", 120, 30, 220, 0, 65, z + 110, "aluminium", MILLED),63 _block("z_rail_neg", 18, 12, 180, -45, 44, z + 115, "steel", RAIL),64 _block("z_rail_pos", 18, 12, 180, 45, 44, z + 115, "steel", RAIL),65 _block("z_top_stop", 140, 35, 25, 0, 55, z + 232.5, "plastic", STOP),66 )67 y_stage = s3d.group("y_stage", *y_parts, column)68 69 # top_table, link at z = 19970 z = 19971 table = s3d.group(72 "top_table",73 _block("z_slide_plate", 130, 12, 100, 0, 24, z + 50, "plastic", STOP),74 _block("z_bearing_neg", 26, 8, 45, -45, 34, z + 60, "steel", RAIL),75 _block("z_bearing_pos", 26, 8, 45, 45, 34, z + 60, "steel", RAIL),76 _block("top_table_plate", 160, 120, 18, 0, -30, z + 109, "aluminium", MILLED),77 _block("table_neck", 90, 35, 20, 0, -2, z + 100, "aluminium", MILLED),78 )79 80 s3d.joint("base_to_x", x_carriage, x_rail_neg.face("+Z"), kind="prismatic", axis="+X",81 range=(-75, 75))82 s3d.joint("x_to_y", y_stage, cross.face("+Z"), kind="prismatic", axis="+Y", range=(-75, 75))83 s3d.joint("column_to_table", table, foot.face("+Z"), kind="prismatic", axis="+Z",84 range=(0, 120))85 return s3d.assembly("xyz_cartesian_stage", base, x_carriage, y_stage, table)
85 lines · 1644 tokens (o200k_base)
1"""A2 — a double-leaf garden gate: two leaves on hinges, a mirror pair, and a drop bolt2sliding down the right leaf into a socket in the foundation.3 4Source: Articraft `rec_garden_gate_30e6e784533b4583ac23a37b85f64c86` (Articraft-10K,5CC-BY-4.0; `ref/A2/`). Every visual is a box or a cylinder at a link-frame offset; the6link frames are all unturned, so each piece is placed here at its world centre (the posts7at x = ±800, the hinges at x = ±730, the bolt's origin at (40, −5.5, 840)). The two posts8are `fixed` to the foundation: their pieces are in the foundation's group, which welds9them. The right leaf is the left one mirrored across x = 0 (the source builds it with10`side_sign = −1`); it is mirrored before any joint is declared, because the source names11the two hinges differently and gives them opposite ranges about the same +Z: (0, 90°) on12the left, (−90°, 0) on the right. Only the right13leaf carries the bolt's two guides, added after the mirror. Each hinge is read on the14foot of its post's lower pin, the bolt's slide on the top of the upper guide (its origin15slides along the axis from Articraft's, which is the same joint); the bolt slides along16−Z, out of the leaf and down into the socket, 0 to 170 mm.17"""18import math19 20import sand3d as s3d21 22 23def piece(name, w, d, h, cx, cy, cz):24 """A box of w × d × h centred on (cx, cy, cz), as the source's `Box` visuals are."""25 return s3d.at(s3d.box(name, w, d, h), x=cx, y=cy, z=cz - h / 2)26 27 28def rod(name, r, length, cx, cy, cz):29 """A cylinder of radius r and length along Z, centred on (cx, cy, cz)."""30 return s3d.at(s3d.cylinder(name, 2 * r, length), x=cx, y=cy, z=cz - length / 2)31 32 33def post(prefix, x, side):34 """A post at x, its two hinge pins 70 mm towards the gate's centre (side: +1 left, -1 right)."""35 body = piece(f"{prefix}_body", 100, 120, 1600, x, 0, 660)36 cap = piece(f"{prefix}_cap", 120, 140, 25, x, 0, 1472.5)37 lower = piece(f"{prefix}_lower_pin", 40, 24, 120, x + side * 70, 0, 320)38 upper = piece(f"{prefix}_upper_pin", 40, 24, 120, x + side * 70, 0, 920)39 for p in (body, cap):40 s3d.material(p, "painted_metal", color=(0.18, 0.24, 0.17))41 for p in (lower, upper):42 s3d.material(p, "steel", color=(0.70, 0.72, 0.74))43 return [body, cap, lower, upper]44 45 46def leaf(prefix, x0):47 """The left leaf, its hinge line at x = x0: a frame, three bars, two hinge sleeves."""48 y, t = -35, 40 # the leaf's plane; its frame's section49 frame = [50 piece(f"{prefix}_outer_stile", t, 35, 1100, x0 + 24, y, 630),51 piece(f"{prefix}_inner_stile", t, 35, 1100, x0 + 690, y, 630),52 piece(f"{prefix}_bottom_rail", 665, 35, t, x0 + 357.5, y, 100),53 piece(f"{prefix}_top_rail", 665, 35, t, x0 + 357.5, y, 1160),54 ]55 frame += [piece(f"{prefix}_bar_{i}", 18, 18, 1020, x0 + bx, y, 630)56 for i, bx in enumerate((200, 360, 520), start=1)]57 hardware = [piece(f"{prefix}_latch_plate", 12, 20, 180, x0 + 696, y - 20, 680)]58 for name, z in (("lower_sleeve", 320), ("upper_sleeve", 920)):59 frame.append(piece(f"{prefix}_{name}_strap", 24, 28, 120, x0 + 32, -28, z))60 hardware.append(piece(f"{prefix}_{name}", 40, 22, 120, x0, -3, z))61 for p in frame:62 s3d.material(p, "painted_metal", color=(0.18, 0.24, 0.17))63 for p in hardware:64 s3d.material(p, "steel", color=(0.70, 0.72, 0.74))65 return s3d.group(f"{prefix}", frame, hardware)66 67 68def build():69 beam = piece("foundation_beam", 1960, 240, 200, 0, 0, -240)70 s3d.material(beam, "concrete", color=(0.55, 0.55, 0.53))71 socket = rod("drop_socket", 14, 220, 42, -5.5, -60)72 s3d.material(socket, "steel", color=(0.70, 0.72, 0.74))73 74 left_post = post("left_post", -800, 1)75 right_post = post("right_post", 800, -1)76 foundation = s3d.group("foundation", beam, socket, left_post, right_post)77 78 left_leaf = leaf("left_leaf", -730)79 right_leaf = s3d.transform(s3d.copy(left_leaf), mirror="x") # its image across x = 080 guides = [rod(f"right_leaf_{name}_guide", 12, 80, 40, -5.5, z) for name, z in (("upper", 780), ("lower", 270))]81 for g in guides:82 s3d.material(g, "steel", color=(0.70, 0.72, 0.74))83 right_leaf = s3d.group("right_leaf", right_leaf, guides)84 85 bolt = rod("bolt_rod", 8, 750, 40, -5.5, 465)86 s3d.material(bolt, "steel", color=(0.70, 0.72, 0.74))87 88 s3d.joint("left_leaf_hinge", left_leaf, s3d.bbox(left_post[2], "-Z"), axis="+Z",89 range=(0, math.degrees(1.5708)))90 s3d.joint("right_leaf_hinge", right_leaf, s3d.bbox(right_post[2], "-Z"), axis="+Z",91 range=(math.degrees(-1.5708), 0))92 s3d.joint("drop_bolt_slide", bolt, s3d.bbox(guides[0], "+Z"), kind="prismatic", axis="-Z", range=(0, 170))93 return s3d.group("double_leaf_garden_gate", foundation, left_leaf, right_leaf, bolt)
93 lines · 1714 tokens (o200k_base)
1"""A8 — a device on a tripod head: a pan, a tilt, a clamp that slides and its screw knob,2two lock knobs; the legs and the device are fixed.3 4Source: Articraft `rec_tripodmounted_device_a0b63454b90945138129d93d176264fc`5(Articraft-10K, CC-BY-4.0; `ref/A8/`). A chain of depth 4: tripod_base → pan_head6(`pan_axis`) → tilt_cradle (`tilt_axis`) → clamp_jaw (`clamp_slide`) → clamp_knob7(`clamp_adjust`), with the two lock knobs on the pan head. Every link frame of the8source is the world's turned by nothing, so the program builds each part in the world9where it rests: the pan head at z = 1120, the cradle on the trunnion at (0, 0, 1233),10the jaw at (0, -54, 1434), its knob 23 mm above. The source's four `fixed` joints are11groups: the three legs weld into the tripod base, the device into the cradle.12 13Each joint is read on the part that carries it: the pan on the top of the pan seat, the14tilt on the yoke's +X cheek moved up to the trunnion bores, each lock knob on the end of15its boss (the tilt lock 1.5 mm inside it, as the source has it), the slide and the screw16on the tops of the lower and the upper jaw. The pan and the clamp screw turn ±180°: the17source's ±math.pi, which its URDF prints as ±3.14159.18 19Departures: the source's primitives overlap, and so do these — they are separate solids20in a group, not fused, so that the hidden surfaces the reference keeps are here too.21The knob meshes (`KnobGeometry`) are a hexagonal prism (the faceted pan lock, its ribs22left out) and two cones (the lobed tilt and clamp knobs, their lobes, crowns and recess23left out), each with its bore. The yoke (`TrunnionYokeGeometry`) is a rounded block24with its span and its trunnion bore cut out.25"""26import math27 28import sand3d as s3d29 30GRAPHITE = (0.10, 0.11, 0.12)31ALUMINIUM = (0.22, 0.23, 0.24)32POLYMER = (0.025, 0.026, 0.028)33ELASTOMER = (0.012, 0.012, 0.011)34ACCENT = (0.70, 0.62, 0.48)35 36 37def paint(obs, kind, color, **kw):38 for ob in obs if isinstance(obs, list) else [obs]:39 s3d.material(ob, kind, color=color, **kw)40 return obs41 42 43def rod(name, d, a, b):44 """A cylinder of diameter d from point a to point b."""45 v = tuple(b[k] - a[k] for k in range(3))46 return s3d.at(s3d.cylinder(name, d, math.dist(a, b)), on=s3d.Frame(a, v))47 48 49def rod_about(name, d, length, centre, direction):50 """A cylinder of diameter d and that length, centred on a point, along a direction."""51 n = math.sqrt(sum(c * c for c in direction))52 u = tuple(c / n for c in direction)53 a = tuple(centre[k] - u[k] * length / 2 for k in range(3))54 b = tuple(centre[k] + u[k] * length / 2 for k in range(3))55 return rod(name, d, a, b)56 57 58def block(name, w, d, h, centre):59 x, y, z = centre60 return s3d.at(s3d.box(name, w, d, h), x=x, y=y, z=z - h / 2)61 62 63def rounded_block(name, w, d, h, r, centre):64 ob = block(name, w, d, h, centre)65 s3d.fillet(ob, r)66 return ob67 68 69def tripod():70 column = s3d.at(s3d.cylinder("center_column", 60, 470), z=650)71 hub = s3d.at(s3d.cylinder("leg_hub", 132, 75), z=587.5)72 collar = s3d.at(s3d.cylinder("column_lock_collar", 80, 48), z=1036)73 trim = s3d.at(s3d.cylinder("collar_trim_ring", 90, 10), z=1082)74 seat = s3d.at(s3d.cylinder("pan_seat", 68, 24), z=1096)75 paint([column], "aluminium", ALUMINIUM)76 paint([hub, seat], "painted_metal", GRAPHITE)77 paint(collar, "plastic", POLYMER)78 paint(trim, "brass", ACCENT)79 mounts, legs = [], []80 for i in range(3):81 a = i * 2 * math.pi / 3 + math.pi / 682 u = (math.cos(a), math.sin(a), 0.0)83 t = (-math.sin(a), math.cos(a), 0.0)84 mounts.append(rod(f"leg_mount_{i}", 28, (u[0] * 46, u[1] * 46, 612), (u[0] * 80, u[1] * 80, 612)))85 top = (u[0] * 94, u[1] * 94, 612)86 foot = (u[0] * 430, u[1] * 430, 34)87 barrel = rod_about(f"hinge_barrel_{i}", 36, 56, top, t)88 tube = rod(f"leg_tube_{i}", 28, top, foot)89 mid = tuple(top[k] * 0.58 + foot[k] * 0.42 for k in range(3))90 sleeve = rod_about(f"leg_collar_{i}", 36, 60, mid, tuple(foot[k] - top[k] for k in range(3)))91 socket = s3d.at(s3d.cylinder(f"foot_socket_{i}", 38, 32), x=foot[0], y=foot[1], z=18)92 rubber = s3d.at(s3d.cylinder(f"rubber_foot_{i}", 100, 18), x=foot[0], y=foot[1], z=0)93 paint([barrel, socket], "painted_metal", GRAPHITE)94 paint(tube, "aluminium", ALUMINIUM)95 paint(sleeve, "plastic", POLYMER)96 paint(rubber, "rubber", ELASTOMER)97 legs.append(s3d.group(f"leg_{i}", barrel, tube, sleeve, socket, rubber)) # fixed: welds98 paint(mounts, "painted_metal", GRAPHITE)99 base = s3d.group("tripod_base", column, hub, collar, trim, seat, mounts, legs)100 return base, seat101 102 103def pan_head():104 disc = s3d.at(s3d.cylinder("pan_disc", 132, 26), z=1120)105 trim = s3d.at(s3d.cylinder("pan_trim", 104, 14), z=1146)106 yoke = s3d.at(s3d.extrude("yoke_shell", s3d.rect(160, 64, r=4), 110), z=1158)107 s3d.cut(yoke, s3d.at(s3d.box("span", 102, 80, 100), z=1176))108 s3d.cut(yoke, rod_about("trunnion_bore", 30, 180, (0, 0, 1233), (1, 0, 0)))109 pan_boss = rod_about("pan_knob_boss", 20, 30, (78, 0, 1150), (1, 0, 0))110 tilt_boss = rod_about("tilt_knob_boss", 32, 38, (91, 0, 1233), (1, 0, 0))111 paint([disc, yoke, pan_boss, tilt_boss], "painted_metal", GRAPHITE)112 paint(trim, "brass", ACCENT)113 return s3d.group("pan_head", disc, trim, yoke, pan_boss, tilt_boss), yoke, pan_boss, tilt_boss114 115 116def tilt_cradle():117 axle = rod_about("tilt_axle", 30.8, 132, (0, 0, 1233), (1, 0, 0))118 neck = s3d.at(s3d.cylinder("cradle_neck", 40, 64), z=1233)119 plate = rounded_block("head_plate", 172, 92, 14, 6, (0, 0, 1299))120 spine = block("bracket_spine", 40, 12, 122, (0, -38, 1361))121 lower_jaw = block("fixed_lower_jaw", 155, 26, 18, (0, -54, 1316))122 lower_pad = block("lower_pad", 138, 30, 6, (0, -55, 1322))123 sleeves = [block(f"guide_sleeve_{i}", 14, 16, 112, (x, -40, 1379)) for i, x in enumerate((-83, 83))]124 bridge = block("top_bridge", 178, 10, 12, (0, -27, 1430))125 paint(axle, "aluminium", ALUMINIUM)126 paint([neck, plate], "painted_metal", GRAPHITE)127 paint([spine, lower_jaw, bridge] + sleeves, "plastic", POLYMER)128 paint(lower_pad, "rubber", ELASTOMER)129 130 shell = rounded_block("body_shell", 168, 20, 106, 8, (0, -55, 1378))131 glass = block("glass_face", 145, 2, 76, (-10, -65, 1378))132 ring = rod("lens_ring", 28, (60, -65, 1405), (60, -69, 1405))133 lens = rod("lens_glass", 16, (60, -66.5, 1405), (60, -71.5, 1405))134 paint(shell, "plastic", POLYMER)135 paint(glass, "glass", (0.015, 0.025, 0.035), opacity=0.92)136 paint(ring, "brass", ACCENT)137 paint(lens, "glass", (0.02, 0.04, 0.075))138 device = s3d.group("device", shell, glass, ring, lens) # fixed: welds139 cradle = s3d.group("tilt_cradle", axle, neck, plate, spine, lower_jaw, lower_pad, sleeves, bridge, device)140 return cradle, lower_jaw141 142 143def build():144 base, seat = tripod()145 head, yoke, pan_boss, tilt_boss = pan_head()146 147 pan_stem = rod("pan_knob_stem", 12, (93, 0, 1150), (123, 0, 1150))148 pan_cap = s3d.extrude("pan_knob_cap", s3d.polygon(6, 34), 20, on=s3d.Frame((118, 0, 1150), (1, 0, 0)))149 s3d.hole(pan_cap, 6, on=s3d.bbox(pan_cap, "+X"))150 paint(pan_stem, "painted_metal", GRAPHITE)151 paint(pan_cap, "plastic", POLYMER)152 pan_knob = s3d.group("pan_knob", pan_stem, pan_cap)153 154 tilt_stem = rod("tilt_knob_stem", 12, (108.5, 0, 1233), (142.5, 0, 1233))155 tilt_cap = s3d.at(s3d.cone("tilt_knob_cap", 42, 24, d2=38), on=s3d.Frame((137.5, 0, 1233), (1, 0, 0)))156 s3d.hole(tilt_cap, 6, on=s3d.bbox(tilt_cap, "+X"))157 paint(tilt_stem, "painted_metal", GRAPHITE)158 paint(tilt_cap, "plastic", POLYMER)159 tilt_knob = s3d.group("tilt_knob", tilt_stem, tilt_cap)160 161 cradle, lower_jaw = tilt_cradle()162 163 upper_jaw = block("upper_jaw", 180, 26, 14, (0, -54, 1444))164 upper_pad = block("upper_pad", 138, 30, 6, (0, -54, 1434))165 rods = [block(f"slide_rod_{i}", 8, 10, 70, (x, -40, 1404)) for i, x in enumerate((-83, 83))]166 paint(upper_jaw, "plastic", POLYMER)167 paint(upper_pad, "rubber", ELASTOMER)168 paint(rods, "aluminium", ALUMINIUM)169 jaw = s3d.group("clamp_jaw", upper_jaw, upper_pad, rods)170 171 screw = s3d.at(s3d.cylinder("threaded_screw", 9, 20), x=0, y=-54, z=1441)172 clamp_cap = s3d.at(s3d.cone("clamp_knob_cap", 38, 20, d2=34), x=0, y=-54, z=1459)173 s3d.hole(clamp_cap, 5, on=s3d.bbox(clamp_cap, "+Z"))174 paint(screw, "painted_metal", GRAPHITE)175 paint(clamp_cap, "plastic", POLYMER)176 clamp_knob = s3d.group("clamp_knob", screw, clamp_cap)177 178 s3d.joint("pan_axis", head, seat.face("+Z"), axis="+Z", range=(-180, 180))179 s3d.joint("pan_lock", pan_knob, s3d.bbox(pan_boss, "+X"), axis="+X",180 range=(math.degrees(-1.2), math.degrees(1.2)))181 s3d.joint("tilt_axis", cradle, s3d.bbox(yoke, "+X").move(0, 20), axis="+X",182 range=(math.degrees(-0.65), math.degrees(0.95)))183 s3d.joint("tilt_lock", tilt_knob, s3d.bbox(tilt_boss, "+X").offset(-1.5), axis="+X",184 range=(math.degrees(-1.4), math.degrees(1.4)))185 s3d.joint("clamp_slide", jaw, s3d.bbox(lower_jaw, "+Z").offset(109), kind="prismatic", axis="+Z",186 range=(0, 38))187 s3d.joint("clamp_adjust", clamp_knob, s3d.bbox(upper_jaw, "+Z").offset(6), axis="+Z", range=(-180, 180))188 return s3d.assembly("tripodmounted_device", base, head, pan_knob, cradle, tilt_knob, jaw, clamp_knob)
188 lines · 3551 tokens (o200k_base)
1"""A5 — a skateboard: two trucks steering on 45° kingpins, four endless wheels on the trucks.2 3Source: Articraft `rec_skateboard_b74cde82df474176b7005c584ba8eb13` (Articraft-10K, CC-BY-4.0;4`ref/A5/`). The deck is CadQuery's `box(800, 200, 15).edges("|Z").fillet(90)`: a rect with590 mm corners, centred on z = 100. Each truck turns about an axis tilted 45° in the XZ plane,6leaning toward the deck's centre, through (±250, 0, 27.5): that axis is read on the top of7its baseplate, offset down to the axle's height and turned 45° about the frame's Y. The8wheels are a chain: each one spins about +Y on its truck, read on the side of the axle's9bounding box (its end cap's centre; `face("+Y")` would start at the world origin's10projection, off the axle) and offset 20 mm in to the wheel's centre (y = ±160), so it11steers with the truck. Same bodies, joints and primitives as the source.12"""13import math14 15import sand3d as s3d16 17 18def truck(side, x):19 axle = s3d.at(s3d.cylinder(f"{side}_axle", 8, 360), rx=90, x=x, y=180, z=27.5)20 strut = s3d.at(s3d.box(f"{side}_strut", 30, 40, 56), x=x, z=27.5)21 s3d.material([axle, strut], "steel", color=(0.7, 0.7, 0.7))22 return axle, s3d.group(f"{side}_truck", axle, strut)23 24 25def wheel(name, x, y):26 w = s3d.at(s3d.cylinder(name, 55, 35), rx=90, x=x, y=y + 17.5, z=27.5)27 s3d.material(w, "rubber", color=(0.95, 0.9, 0.7))28 return w29 30 31def build():32 board = s3d.at(s3d.extrude("board", s3d.rect(800, 200, r=90), 15), z=92.5)33 s3d.material(board, "oak")34 front_plate = s3d.at(s3d.box("front_baseplate", 80, 60, 10), x=250, z=82.5)35 rear_plate = s3d.at(s3d.box("rear_baseplate", 80, 60, 10), x=-250, z=82.5)36 s3d.material([front_plate, rear_plate], "aluminium")37 deck = s3d.group("deck", board, front_plate, rear_plate)38 39 front_axle, front_truck = truck("front", 250)40 rear_axle, rear_truck = truck("rear", -250)41 steer = (math.degrees(-0.3), math.degrees(0.3))42 # The kingpin: through the axle centre (65 mm below the plate's top), tilted 45° inward.43 s3d.joint("front_truck_steer", front_truck,44 s3d.bbox(front_plate, "+Z").offset(-65).turn(ry=-45), range=steer)45 s3d.joint("rear_truck_steer", rear_truck,46 s3d.bbox(rear_plate, "+Z").offset(-65).turn(ry=45), range=steer)47 48 wheels = []49 for side, axle, x in (("front", front_axle, 250), ("rear", rear_axle, -250)):50 left = wheel(f"{side}_left_wheel", x, 160)51 right = wheel(f"{side}_right_wheel", x, -160)52 s3d.joint(f"{side}_left_spin", left, s3d.bbox(axle, "+Y").offset(-20), kind="continuous", axis="+Y")53 s3d.joint(f"{side}_right_spin", right, s3d.bbox(axle, "-Y").offset(-20), kind="continuous", axis="+Y")54 wheels += [left, right]55 56 return s3d.assembly("skateboard", deck, front_truck, rear_truck, *wheels)
56 lines · 1007 tokens (o200k_base)
1"""A9 — compact theatre binoculars: two housings on a central hinge, a focus wheel that2turns a full turn either way, two eyecups that twist.3 4Source: Articraft `rec_binoculars_fc9fc306c6f8437683635fccb0369257` (Articraft-10K,5CC-BY-4.0; `ref/A9/`). Its left housing is the root, at the world origin; the right6housing's link sits at the hinge (0, -11, 0) and its visuals are offset back by +11 in y,7so at rest both housings are mirror images across x = 0: the program builds both in the8world with one function, `side` -1 or +1. Cylinders whose URDF `rpy` is (π/2, 0, 0) lie9along Y and are built on a frame looking -Y; the focus wheel's (0, π/2, 0) lie along X.10The housing shell is the source's `section_loft` through four rounded rectangles in XZ11(y = -3 … -33); the eyecup its lathe shell (outer profile, inner profile back), turned12about Y from the eyecup's origin towards -Y.13 14Pivots: the hinge is read on the upper knuckle's top, the focus axle on the right focus15post's +X side, each eyecup's twist on its eyepiece barrel's back end (y = -45). The16focus wheel's range is the URDF's ±6.28319 rad (the source's ±2π, rounded up by 5e-6;17sky3d does not cap a revolute range at a turn): with ±2π exactly, the score's pose at the18reference's bound falls just outside the range and `pose` refuses it. Every19visual is its own solid in its body's group, unfused, as the URDF's visuals are.20"""21import math22 23import sand3d as s3d24 25BODY_X = 33 # each optical axis, off the hinge26HINGE_Y = -1127EYEPIECE_Y = -4528BLACK, ARMOR, GRAY, GLASS = (0.10, 0.10, 0.11), (0.16, 0.16, 0.17), (0.29, 0.30, 0.33), (0.12, 0.17, 0.22)29 30 31def along_y(name, d, length, x, y):32 """A cylinder along Y, centred on (x, y, 0)."""33 return s3d.at(s3d.cylinder(name, d, length), on=s3d.Frame((x, y + length / 2, 0), normal=(0, -1, 0)))34 35 36def block(name, w, d, h, x, y, z):37 """A box centred on (x, y, z)."""38 return s3d.at(s3d.box(name, w, d, h), x=x, y=y, z=z - h / 2)39 40 41def paint(color, *obs):42 for ob in obs:43 s3d.material(ob, "plastic", color=color)44 return list(obs)45 46 47def housing(side):48 """One housing, in the world at rest: its shell, barrels, rings and bridge arm."""49 cx = side * BODY_X50 sections = [(-3, 31, 34, 6), (-13, 32, 35, 6), (-23, 28, 31, 5), (-33, 23, 24, 4)]51 shell = s3d.loft("body_shell", *[s3d.at(s3d.rect(w, h, r=r), on=s3d.Frame((cx, y, 0), normal=(0, -1, 0)))52 for y, w, h, r in sections])53 barrel = along_y("objective_barrel", 27, 44, cx, 18)54 eyepiece = along_y("eyepiece_barrel", 22.4, 28, cx, -31)55 arm = block("bridge_arm", 26.4, 14, 12, side * 17.7, HINGE_Y, 0)56 trim = [along_y("objective_armor", 28.4, 13, cx, 12), along_y("objective_bezel", 29, 4, cx, 40),57 along_y("eyepiece_shoulder", 25.2, 8, cx, -19)]58 lens = along_y("objective_lens", 23, 1.2, cx, 42.5)59 return paint(BLACK, shell, barrel, eyepiece, arm) + paint(ARMOR, *trim) + paint(GLASS, lens), eyepiece60 61 62def eyecup(name, eyepiece_end):63 """The eyecup's lathe shell and its mount collar, from the eyepiece's end towards -Y."""64 outer = [(11.4, 0), (12.3, 2), (14.4, 7), (15.2, 14), (14.2, 17)]65 inner = [(10.8, 1), (11.0, 3), (12.6, 10), (13.0, 16)]66 shell = s3d.at(s3d.revolve("eyecup_shell", outer + inner[::-1]), on=eyepiece_end)67 collar = s3d.at(s3d.cylinder("eyecup_mount_collar", 22, 2), on=eyepiece_end)68 return s3d.group(name, *paint(ARMOR, shell, collar))69 70 71def build():72 left_parts, left_eyepiece = housing(-1)73 upper = s3d.at(s3d.cylinder("hinge_knuckle_upper", 9.4, 6), x=0, y=HINGE_Y, z=6)74 lower = s3d.at(s3d.cylinder("hinge_knuckle_lower", 9.4, 6), x=0, y=HINGE_Y, z=-12)75 post_r = block("focus_post_right", 4, 10, 18, 11, -12, 22)76 focus = [block("focus_stem", 6, 8, 24, -15, -12, 18), block("focus_arch", 32, 6, 4, 0, -12, 31),77 block("focus_post_left", 4, 10, 18, -11, -12, 22), post_r]78 left = s3d.group("left_housing", left_parts, paint(ARMOR, upper, lower), paint(BLACK, *focus))79 80 right_parts, right_eyepiece = housing(+1)81 center = s3d.at(s3d.cylinder("hinge_knuckle_center", 9.4, 12), x=0, y=HINGE_Y, z=-6)82 right = s3d.group("right_housing", right_parts, paint(ARMOR, center))83 84 axle = lambda name, d, length: s3d.at(s3d.cylinder(name, d, length), # noqa: E73185 on=s3d.Frame((-length / 2, -12, 22), normal=(1, 0, 0)))86 knob = s3d.group("focus_knob", paint(GRAY, axle("focus_wheel_core", 17, 18)),87 paint(ARMOR, axle("focus_wheel_tread", 20.4, 12)), paint(GRAY, axle("focus_axle_hub", 7, 20)))88 89 left_end = left_eyepiece.face("-Y").move(-BODY_X) # looking -Y, X is +X: (-33, -45, 0)90 right_end = right_eyepiece.face("-Y").move(BODY_X) # (33, -45, 0)91 left_cup = eyecup("left_eyecup", left_end)92 right_cup = eyecup("right_eyecup", right_end)93 94 s3d.joint("central_hinge", right, upper.face("+Z").move(0, HINGE_Y), axis="+Z",95 range=(math.degrees(-0.55), math.degrees(0.12)))96 s3d.joint("focus_knob_spin", knob, post_r.face("+X").move(-12, 22), axis="+X", # X is +Y, Y is up97 range=(math.degrees(-6.28319), math.degrees(6.28319)))98 s3d.joint("left_eyecup_twist", left_cup, left_end, axis="+Y", range=(0, math.degrees(4.2)))99 s3d.joint("right_eyecup_twist", right_cup, right_end, axis="+Y", range=(0, math.degrees(4.2)))100 return s3d.assembly("compact_theatre_binocular", left, right, knob, left_cup, right_cup)
100 lines · 2033 tokens (o200k_base)
1"""A10 — a compact pickup tailgate: a gate on a lower hinge, two latch knobs and a2work-stop bar that folds up from the gate's top edge.3 4Source: Articraft `rec_pickup_tailgate_be20bae3a83e40c386c21adab290f72d` (Articraft-10K,5CC-BY-4.0; `ref/A10/`). Every visual is a box or a cylinder, given by its centre in its6link's frame: `block` and `rod` take those centres, shifted by the link's origin at rest7(the bed's is the world's). The hinge line (x = -36, z = 100) is read on the top of a8sill pad, which it runs along (a face's frame starts above the world's origin, so the9moves are world coordinates); its barrels sit 6.5 mm off the bed, as in the source — a10clearance sky3d does not have to close. The knobs and the work stop hang on the moving11gate (a chain): their axles are read on the bezels and the stop pads they stand off.12Positive tailgate and stop angles turn about -Y, as declared: the gate falls outward.13"""14import math15 16import sand3d as s3d17 18PAINT, LINER, HARDWARE, METAL = (0.16, 0.24, 0.34), (0.17, 0.17, 0.18), (0.10, 0.10, 0.11), (0.65, 0.66, 0.68)19 20 21def block(name, size, centre, at=(0, 0, 0), color=PAINT):22 w, d, h = size23 x, y, z = (c + o for c, o in zip(centre, at))24 ob = s3d.at(s3d.box(name, w, d, h), x=x, y=y, z=z - h / 2)25 s3d.material(ob, "painted_metal", color=color)26 return ob27 28 29def rod(name, d, length, centre, along, at=(0, 0, 0), color=METAL):30 """A cylinder centred on `centre`, along -Y (Articraft's rpy (π/2, 0, 0)) or +X."""31 x, y, z = (c + o for c, o in zip(centre, at))32 cyl = s3d.cylinder(name, d, length)33 if along == "-Y":34 ob = s3d.at(cyl, x=x, y=y + length / 2, z=z, rx=90)35 else:36 ob = s3d.at(cyl, x=x - length / 2, y=y, z=z, ry=90)37 s3d.material(ob, "steel", color=color)38 return ob39 40 41def knob(side, origin):42 parts = [rod(f"{side}_shaft", 10, 12, (0, 0, 0), "+X", origin),43 rod(f"{side}_hub", 24, 10, (10, 0, 0), "+X", origin, HARDWARE),44 block(f"{side}_paddle", (8, 40, 14), (15, 0, 0), origin, HARDWARE),45 block(f"{side}_pointer", (6, 12, 10), (19, 0, 12), origin, HARDWARE)]46 return s3d.group(f"{side}_latch_knob", *parts)47 48 49def build():50 sill = block("left_sill_pad", (60, 160, 28), (-12, 180, 86), color=LINER)51 bed = s3d.group(52 "bed_frame",53 block("bed_floor", (610, 1280, 28), (322, 0, 86), color=LINER),54 sill,55 block("right_sill_pad", (60, 160, 28), (-12, -180, 86), color=LINER),56 block("left_bedside", (610, 60, 390), (322, 670, 295)),57 block("right_bedside", (610, 60, 390), (322, -670, 295)),58 block("left_rail_cap", (610, 88, 36), (322, 656, 492), color=LINER),59 block("right_rail_cap", (610, 88, 36), (322, -656, 492), color=LINER),60 block("left_hinge_support", (82, 40, 70), (-10, 655, 115)),61 block("right_hinge_support", (82, 40, 70), (-10, -655, 115)),62 block("front_bulkhead", (28, 1400, 420), (641, 0, 310)))63 64 t = (-36, 0, 100) # the tailgate's link, at rest65 bezels = [block(f"{s}_latch_bezel", (6, 56, 32), (37, y, 304), t, HARDWARE) for s, y in (("left", 435), ("right", -435))]66 pads = [block(f"{s}_work_stop_pad", (6, 45, 18), (35, y, 349), t, HARDWARE) for s, y in (("left", 340), ("right", -340))]67 gate = s3d.group(68 "tailgate",69 block("outer_skin", (18, 1240, 332), (15, 0, 206), t),70 block("bottom_rail", (45, 1240, 40), (23, 0, 20), t),71 block("top_cap", (34, 1240, 30), (20, 0, 347), t),72 block("left_side_frame", (45, 26, 338), (23, 607, 209), t),73 block("right_side_frame", (45, 26, 338), (23, -607, 209), t),74 rod("left_hinge_barrel", 26, 160, (10, 360, 0), "-Y", t),75 rod("center_hinge_barrel", 26, 120, (10, 0, 0), "-Y", t),76 rod("right_hinge_barrel", 26, 160, (10, -360, 0), "-Y", t),77 block("inner_panel", (6, 1130, 232), (41, 0, 192), t, LINER),78 block("left_inner_flange", (10, 22, 290), (37, 594, 190), t, LINER),79 block("right_inner_flange", (10, 22, 290), (37, -594, 190), t, LINER),80 block("top_inner_flange", (10, 1160, 22), (37, 0, 323), t, LINER),81 block("bottom_inner_flange", (10, 1160, 24), (37, 0, 50), t, LINER),82 block("upper_inner_rib", (12, 940, 56), (35, 0, 262), t, LINER),83 block("lower_inner_rib", (12, 940, 60), (35, 0, 122), t, LINER),84 block("center_inner_rib", (10, 660, 104), (34, 0, 192), t, LINER),85 bezels, pads)86 87 knobs = [knob(s, (10, y, 404)) for s, y in (("left", 435), ("right", -435))] # t + (46, ±435, 304)88 89 w = (9, 0, 449) # t + (45, 0, 349): the stop's link90 stop = s3d.group(91 "work_stop",92 rod("left_sleeve", 14, 40, (0, 340, 0), "-Y", w),93 rod("right_sleeve", 14, 40, (0, -340, 0), "-Y", w),94 block("left_arm", (10, 28, 84), (6, 340, -42), w, METAL),95 block("right_arm", (10, 28, 84), (6, -340, -42), w, METAL),96 block("stop_bar", (12, 1000, 18), (10, 0, -78), w, METAL))97 98 # The sill's top is z = 100; its frame starts above the world's origin.99 s3d.joint("bed_to_tailgate", gate, sill.face("+Z").move(-36, 0), axis="-Y", range=(0, math.degrees(1.50098)))100 for side, y, bezel, k in zip(("left", "right"), (435, -435), bezels, knobs):101 # The bezel's +X face is x = 4; on a face looking +X, X is +Y and Y is up.102 s3d.joint(f"tailgate_to_{side}_latch_knob", k, bezel.face("+X").move(y, 404).offset(6),103 axis="normal", range=(-math.degrees(1.2), math.degrees(1.2)))104 s3d.joint("tailgate_to_work_stop", stop, pads[0].face("+X").move(0, 449).offset(7), axis="-Y", range=(0, math.degrees(1.36136)))105 return s3d.assembly("compact_pickup_tailgate", bed, gate, knobs, stop)
105 lines · 2202 tokens (o200k_base)
1"""A11 — a rugged screw-cap bottle: a cap that turns and lifts on the neck.2 3Source: Articraft `rec_screwcap_bottle_aa1625790e9e4236941bc4c2650955de` (Articraft-10K,4CC-BY-4.0; `ref/A11/`). The body is a thin-wall lathe with a rubber bumper, a neck collar,5a helical neck thread, grip pads, side rails and four slotted fasteners; the cap a ribbed,6windowed shell with an internal thread, an index mark and a seal shadow. Articraft writes7the cap's two motions — a turn about +Z then an independent lift along +Z (no mimic) —8through an intermediate link `cap_axis` with no geometry; here they are two joints on the9cap, in that order, both read on the top of the neck collar (z = 242), and the URDF writes10the intermediate link itself. The threads are a trapezoid swept along a helix (Frenet, so11the section keeps its radial X): the section stands square to the path, tilted by the12helix angle (about 5°) where Articraft's stands in the (r, z) plane. The cap's 1.5 mm13fillet is left out.14"""15import math16 17import sand3d as s3d18 19 20def _thread(name, r, depth, z0, pitch=14, h=38, hw=3.5):21 """Articraft's helical ridge: a trapezoid from radius r, `depth` outward (< 0 inward)."""22 # Frenet: the section's X points to the axis, its Y up the coil23 section = s3d.poly([(0, -hw), (-depth, -0.16 * hw), (-depth, 0.16 * hw), (0, hw)])24 ridge = s3d.sweep(name, section, s3d.helix(2 * r, pitch, h), frenet=True)25 return s3d.at(ridge, z=z0)26 27 28def build():29 # ---- the bottle body: everything welds in one group30 shell = s3d.revolve("body_shell", [31 (82, 0), (82, 30), (70, 30), (77, 70), (77, 185), (45, 235), (25, 235), (25, 291),32 (31, 291), (31, 299), (18, 299), (18, 238), (56, 215), (56, 35), (65, 25), (65, 6), (75, 0)])33 s3d.material(shell, "plastic", color=(0.20, 0.27, 0.16))34 bumper = s3d.at(s3d.tube("base_bumper", 170, 120, 24), z=6)35 collar = s3d.at(s3d.tube("neck_collar", 110, 60, 16), z=226)36 s3d.material([bumper, collar], "rubber", color=(0.015, 0.017, 0.016))37 neck_thread = _thread("neck_thread", 24.6, 4.3, 247)38 s3d.material(neck_thread, "plastic", color=(0.45, 0.50, 0.42))39 pads = [s3d.at(s3d.box(f"{side}_grip_pad", 92, 8, 108), y=y, z=122 - 54)40 for side, y in (("front", -77), ("rear", 77))]41 rails = [s3d.at(s3d.box(f"side_rail_{i}", 12, 38, 150), x=x, z=112 - 75)42 for i, x in enumerate((77, -77))]43 s3d.material(pads, "rubber", color=(0.015, 0.017, 0.016))44 s3d.material(rails, "plastic", color=(0.20, 0.27, 0.16))45 fasteners = []46 for i, (x, y) in enumerate(((-38, -82), (38, -82), (-38, 82), (38, 82))):47 head = s3d.at(s3d.extrude(f"fastener_{i}", s3d.circle(12), 5, both=True), x=x, y=y, z=158, rx=90)48 slot = s3d.at(s3d.box(f"fastener_slot_{i}", 8, 1.2, 1.5),49 x=x, y=y + (-0.6 if y < 0 else 0.6), z=158 - 0.75)50 s3d.material(head, "steel", color=(0.78, 0.75, 0.68))51 s3d.material(slot, "plastic", color=(0.002, 0.002, 0.002))52 fasteners += [head, slot]53 body = s3d.group("body", shell, bumper, collar, neck_thread, pads, rails, fasteners)54 55 # ---- the cap, built in its own frame on top of the collar56 seat = collar.face("+Z") # (0, 0, 242), Z up57 cap = s3d.at(s3d.cylinder("cap_shell", 94, 66), on=seat)58 s3d.cut(cap, s3d.at(s3d.cylinder("bore", 68, 60), on=seat))59 s3d.join(cap, s3d.at(s3d.tube("crown", 82, 36, 7), on=seat.offset(66)))60 s3d.join(cap, s3d.at(s3d.box("rib", 6, 6, 52), on=s3d.ring(28, 49, on=seat.offset(8))))61 s3d.cut(cap, s3d.at(s3d.box("window", 32, 34, 28), on=s3d.ring(2, 50, on=seat.offset(16))))62 s3d.material(cap, "painted_metal", color=(0.025, 0.030, 0.033))63 cap_thread = _thread("cap_thread", 34.6, -4.1, 242 + 10)64 s3d.material(cap_thread, "plastic", color=(0.45, 0.50, 0.42))65 mark = s3d.at(s3d.box("cap_index_mark", 30, 6, 2), on=seat.move(21, 0).offset(73))66 s3d.material(mark, "plastic", color=(0.88, 0.86, 0.76))67 shadow = s3d.at(s3d.cylinder("seal_shadow", 40, 3), on=seat.offset(59.5))68 s3d.material(shadow, "plastic", color=(0.002, 0.002, 0.002))69 lid = s3d.group("cap", cap, cap_thread, mark, shadow)70 71 # ---- the two motions, turn first (nearest the body), both read on the collar72 s3d.joint("body_to_cap_turn", lid, seat, axis="normal", range=(0, math.degrees(6.28319))) # the URDF's 2π73 s3d.joint("cap_thread_lift", lid, seat, kind="prismatic", axis="normal", range=(0, 14))74 return s3d.assembly("rugged_screwcap_bottle", body, lid)
74 lines · 1724 tokens (o200k_base)
1"""A12 — a bevel-to-spur transfer: an endless vertical input shaft drives, through an218/18 bevel pair, a horizontal transfer shaft, which drives a parallel output shaft through3an 18/24 spur pair.4 5Source: Articraft `rec_gear_assemblies_65e1d6ce16ad4dd58dffa5c555c5680b` (Articraft-10K,6CC-BY-4.0; `ref/A12/`). The coupled joints are URDF mimics: `transfer_axis` follows7`input_axis` × −1, `output_axis` follows `transfer_axis` × −18/24 (degrees per degree).8Each joint is read on the bearing its shaft runs in, as a side of its bounding box (a9face's frame starts at the projected origin, off the axis): the input's on the lower10bearing's top, the two horizontal ones on the +X side of their first bearing; the11origins slide along the axes from Articraft's (160, 0, 205), (160, 0, 263.5),12(160, 127, 263.5), which are the same joints. Geometry along X is built on frames whose13normal is +X and up +Y: Articraft's rpy (0, 90°, 0).14 15The spur gears are `s3d.gear` with the source's module (6 mm), teeth (18, 24), widths (36,1640 mm) and 14 mm bores, a tooth on the local +X as in the source meshes; the source's17backlash (1.2 mm) and 1 mm chamfers are left out. The bevel gears (cq_gears' BevelGearPair,18module 6, 18/18 at 90°) have no sky3d verb: each is a loft of an 18-tooth outline measured19on the source's heel face (tip r 69.1, root r 48.5, teeth at 10° + 20° k) to the same20outline scaled toward the cone apex 59 mm away, stopped flat at 31.5 mm, with its 14 mm21bore; the source's toe cone (the tooth tips rising to 35.4 mm) is flattened. The pinion's22axis sits 0.52 mm above the transfer axis, as in the source mesh.23"""24import math25 26import sand3d as s3d27 28APEX = 59.02 # heel face to cone apex, mm29BEVEL_H = 31.5 # heel face to the flat toe30# One tooth of the bevel's heel outline: (radius, angle from the tooth's centre in degrees).31FLANK = [(48.6, 8.0), (50.0, 6.6), (52.5, 5.45), (57.5, 4.55), (62.1, 3.4), (65.2, 2.45), (69.08, 1.35)]32 33 34def bevel_outline(scale):35 pts = []36 for k in range(18):37 c = 10 + 20 * k38 side = [(r, c - a) for r, a in FLANK] + [(r, c + a) for r, a in reversed(FLANK)] + [(48.5, c + 10)]39 pts += [(scale * r * math.cos(math.radians(t)), scale * r * math.sin(math.radians(t))) for r, t in side]40 return s3d.poly(pts)41 42 43def bevel(name, heel):44 """A straight bevel gear standing on the frame `heel`, narrowing along its normal."""45 gear = s3d.loft(name, s3d.at(bevel_outline(1.0), on=heel),46 s3d.at(bevel_outline((APEX - BEVEL_H) / APEX), on=heel.offset(BEVEL_H)))47 s3d.cut(gear, s3d.at(s3d.cylinder(name + "_bore", 14, BEVEL_H + 2), on=heel.offset(-1)))48 return gear49 50 51def along_x(ob, x, y, z, length):52 """`ob`, built along +X, centred on x: Articraft's rpy (0, 90°, 0) at (x, y, z)."""53 return s3d.at(ob, on=s3d.Frame((x - length / 2, y, z), normal=(1, 0, 0), up=(0, 1, 0)))54 55 56def build():57 shaft_z = 263.558 out_y = 12759 60 # base: plate, the vertical bearing, four pillow blocks61 plate = s3d.at(s3d.box("base_plate", 860, 380, 40), x=360, y=70)62 lower = s3d.at(s3d.tube("lower_vertical_bearing", 72, 28, 52), x=160, y=0, z=40)63 blocks, bearings = [], {}64 for x, y, ped, brg in ((280, 0, "transfer_pedestal_0", "transfer_bearing_0"),65 (660, 0, "transfer_pedestal_1", "transfer_bearing_1"),66 (370, out_y, "output_pedestal_0", "output_bearing_0"),67 (640, out_y, "output_pedestal_1", "output_bearing_1")):68 blocks.append(s3d.at(s3d.box(ped, 52, 66, shaft_z - 78), x=x, y=y, z=40))69 bearings[brg] = along_x(s3d.tube(brg, 78, 31, 40), x, y, shaft_z, 40)70 s3d.material(plate, "painted_metal", color=(0.12, 0.14, 0.15))71 s3d.material(blocks, "painted_metal", color=(0.12, 0.14, 0.15))72 s3d.material([lower] + list(bearings.values()), "painted_metal", color=(0.025, 0.027, 0.03))73 base = s3d.group("base", plate, lower, blocks, list(bearings.values()))74 75 # input shaft, origin (160, 0, 205), vertical76 z0 = 20577 bar = s3d.at(s3d.cylinder("input_shaft_bar", 20, 194), x=160, y=0, z=z0 - 67 - 97)78 in_bevel = bevel("input_bevel", s3d.Frame((160, 0, z0)))79 hub = s3d.at(s3d.cylinder("input_hub", 42, 34), x=160, y=0, z=z0 + 32 - 17)80 collar = s3d.at(s3d.cylinder("input_bearing_collar", 40, 8), x=160, y=0, z=z0 - 109 - 4)81 s3d.material([bar, hub, collar], "brushed_steel")82 s3d.material(in_bevel, "brass")83 input_shaft = s3d.group("input_shaft", bar, in_bevel, hub, collar)84 85 # transfer shaft, origin (160, 0, 263.5), along +X86 x0 = 16087 t_bar = along_x(s3d.cylinder("transfer_shaft_bar", 20, 620), x0 + 230, 0, shaft_z, 620)88 t_bevel = bevel("transfer_bevel", s3d.Frame((x0 - APEX, 0, shaft_z + 0.52), normal=(1, 0, 0), up=(0, 0, 1)))89 t_hub = along_x(s3d.cylinder("bevel_hub", 40, 30), x0 - 41, 0, shaft_z, 30)90 t_collars = [along_x(s3d.cylinder(f"transfer_collar_{i}", 36, 8), x0 + x, 0, shaft_z, 8)91 for i, x in enumerate((96, 144, 476, 524))]92 t_spur = along_x(s3d.gear("transfer_spur", 18, 6, 36, bore=14), x0 + 340, 0, shaft_z, 36)93 t_spur_hub = along_x(s3d.cylinder("transfer_spur_hub", 42, 44), x0 + 340, 0, shaft_z, 44)94 s3d.material([t_bar, t_hub, t_collars, t_spur_hub], "brushed_steel")95 s3d.material([t_bevel, t_spur], "brass")96 transfer = s3d.group("transfer_shaft", t_bar, t_bevel, t_hub, t_collars, t_spur, t_spur_hub)97 98 # output shaft, origin (160, 127, 263.5), along +X99 o_bar = along_x(s3d.cylinder("output_shaft_bar", 20, 430), x0 + 300, out_y, shaft_z, 430)100 o_collars = [along_x(s3d.cylinder(f"output_collar_{i}", 36, 8), x0 + x, out_y, shaft_z, 8)101 for i, x in enumerate((186, 234, 456, 504))]102 o_spur = along_x(s3d.gear("output_spur", 24, 6, 40, bore=14), x0 + 340, out_y, shaft_z, 40)103 o_spur_hub = along_x(s3d.cylinder("output_spur_hub", 48, 50), x0 + 340, out_y, shaft_z, 50)104 s3d.material([o_bar, o_collars, o_spur_hub], "brushed_steel")105 s3d.material(o_spur, "painted_metal", color=(0.13, 0.25, 0.46))106 output = s3d.group("output_shaft", o_bar, o_collars, o_spur, o_spur_hub)107 108 s3d.joint("input_axis", input_shaft, s3d.bbox(lower, "+Z"), kind="continuous", axis="+Z")109 s3d.joint("transfer_axis", transfer, s3d.bbox(bearings["transfer_bearing_0"], "+X"),110 kind="continuous", axis="+X", follows="input_axis", ratio=-1)111 s3d.joint("output_axis", output, s3d.bbox(bearings["output_bearing_0"], "+X"),112 kind="continuous", axis="+X", follows="transfer_axis", ratio=-18 / 24)113 return s3d.assembly("bevel_to_spur_transfer", base, input_shaft, transfer, output)
113 lines · 2465 tokens (o200k_base)
1"""A4 — a compact keyboard: forty keys on plungers, a trackpoint on two crossed pivots, a2media wheel on a fixed shaft.3 4Source: Articraft `rec_keyboard_33e6828d32c148999830f99c31995d49` (Articraft-10K, CC-BY-4.0;5`ref/A4/`). Every link frame is world-aligned at rest, so a key's joint is read on the key6deck's top face (X is +X, Y is +Y there) moved to the key's origin; the trackpoint's tilt on7the deck top and its roll on the mount's top, both moved to y = -9 (a face's frame starts at8the world origin projected on it, not at the mount's own origin); the wheel's spin on the spindle's +Y end, its9origin slid along the axis from Articraft's (110, 45, 24), which is the same joint. The keys10stand 2.6 to 6.3 mm above the deck at rest: Articraft's plungers are guided "internally", and11sky3d needs no contact. The source's fixed `case_to_wheel_shaft` is no joint here: the shaft12is in the case's group, which welds it. Each keycap is the source's three-section loft of13rounded rectangles; sky3d's loft runs a spline through them where Articraft's is straight14between sections, a difference well under the tolerance.15"""16import math17 18import sand3d as s3d19 20COLUMNS = [-89.5, -70.5, -51.5, -32.5, -13.5, 13.5, 32.5, 51.5, 70.5, 89.5]21ROWS = [ # y, z of the joint, the top's shift toward +Y, the row's offset in x22 (-28.0, 14.6, 1.3, 6.0),23 (-9.0, 15.8, 0.5, 0.0),24 (10.0, 17.1, -0.4, -4.0),25 (29.0, 18.3, -1.2, -8.0),26]27CASE = (0.18, 0.19, 0.21)28DECK = (0.11, 0.12, 0.13)29 30 31def slab(name, w, d, h, x, y, zc, color):32 """A box given by its centre, as Articraft's are."""33 b = s3d.at(s3d.box(name, w, d, h), x=x, y=y, z=zc - h / 2)34 s3d.material(b, "plastic", color=color)35 return b36 37 38def keycap(name, h, shift, w=16.2):39 lower = s3d.rect(w, w, r=w * 0.15)40 middle = s3d.at(s3d.rect(w * 0.95, w * 0.92, r=w * 0.13), y=shift * 0.45, z=h * 0.55)41 upper = s3d.at(s3d.rect(w * 0.86, w * 0.79, r=w * 0.10), y=shift, z=h)42 return s3d.loft(name, lower, middle, upper)43 44 45def build():46 deck = slab("key_deck", 238, 90, 4, 0, -2, 10, DECK)47 top = deck.face("+Z") # (0, 0, 12); X is +X, Y is +Y48 shell = [49 slab("bottom_shell", 278, 118, 4, 0, 0, 2, CASE),50 slab("front_lip", 278, 10, 14, 0, -54, 7, CASE),51 slab("rear_wall", 278, 8, 31, 0, 55, 15.5, CASE),52 slab("left_wall", 8, 100, 25, -135, 0, 12.5, CASE),53 slab("right_wall", 8, 100, 25, 135, 0, 12.5, CASE),54 slab("rear_control_shelf", 238, 14, 6, 0, 45, 13, DECK),55 slab("media_pod_base", 36, 28, 6, 108, 45, 9, DECK),56 slab("media_pod_front_cheek", 22, 4, 20, 110, 33, 22, CASE),57 slab("media_pod_rear_cheek", 22, 4, 20, 110, 57, 22, CASE),58 slab("media_pod_outer_wall", 6, 24, 18, 126, 45, 21, CASE),59 slab("media_pod_inner_boss", 4, 18, 12, 94, 45, 18, CASE),60 ]61 62 # The wheel's shaft: three cylinders along +Y about (110, 45, 24), welded to the case.63 def along_y(name, d, h, yc):64 return s3d.at(s3d.cylinder(name, d, h), on=s3d.Frame((110, yc - h / 2, 24), normal=(0, 1, 0)))65 spindle = along_y("spindle", 5, 20, 45)66 shaft = [spindle, along_y("front_shoulder", 8.4, 2, 36), along_y("rear_clip", 9.6, 1.6, 54.2)]67 s3d.material(shaft, "steel", color=(0.60, 0.61, 0.63))68 case = s3d.group("case", deck, shell, shaft)69 70 keys = []71 for row, (y, z, shift, offset) in enumerate(ROWS):72 for col, x in enumerate(COLUMNS):73 key = s3d.at(keycap(f"key_r{row}_c{col}", 9.0 - row * 0.2, shift), x=x + offset, y=y, z=z)74 dark = row == 3 or col in (0, 9)75 s3d.material(key, "plastic", color=(0.36, 0.37, 0.39) if dark else (0.82, 0.82, 0.80))76 s3d.joint(f"case_to_key_r{row}_c{col}", key, top.move(x + offset, y, z - 12),77 kind="prismatic", axis="-Z", range=(0, 2.2))78 keys.append(key)79 80 mount = s3d.at(s3d.cylinder("trackpoint_mount", 9.2, 4), y=-9, z=12)81 s3d.material(mount, "plastic", color=(0.12, 0.12, 0.12))82 s3d.joint("case_to_trackpoint_mount", mount, top.move(0, -9), axis="+X",83 range=(-math.degrees(0.18), math.degrees(0.18)))84 85 stem = s3d.at(s3d.cylinder("nub_stem", 6.2, 8), y=-9, z=16)86 tip = s3d.at(s3d.sphere("nub_tip", 7.2), y=-9, z=16 + 10.5 - 3.6)87 s3d.material([stem, tip], "rubber", color=(0.74, 0.10, 0.10))88 nub = s3d.group("trackpoint_nub", stem, tip)89 s3d.joint("trackpoint_mount_to_nub", nub, mount.face("top").move(0, -9), axis="+Y",90 range=(-math.degrees(0.18), math.degrees(0.18)))91 92 # The wheel: four tori about +Y (Articraft's about Z, turned by rx = 90°), merged unfused.93 def ring(name, r, t, dy):94 return s3d.at(s3d.torus(name, 2 * r, 2 * t), on=s3d.Frame((110, 45 + dy - t, 24), normal=(0, 1, 0)))95 wheel = s3d.merge(ring("media_wheel", 7.2, 1.8, 0), ring("rim", 7.4, 1.9, 0),96 ring("front_band", 7.6, 1.7, -3.2), ring("rear_band", 7.6, 1.7, 3.2))97 s3d.material(wheel, "rubber", color=(0.15, 0.16, 0.17))98 s3d.joint("wheel_shaft_to_media_wheel", wheel, s3d.bbox(spindle, "+Y"), kind="continuous", axis="+Y")99 100 return s3d.assembly("compact_trackpoint_keyboard", case, keys, mount, nub, wheel)
100 lines · 2077 tokens (o200k_base)
The washing machine is sand3d's own. The other objects are sand3d rewrites of records of Articraft-10K (Zhou et al., arXiv 2605.15187), CC BY 4.0.
tools/quickstart from the code it shows