; Print the kit flat, then fit wheels to the axles and push in split rivets. (define-component tractor-chassis ((number axle-radius 3.2mm) (number body-clearance 0.3mm)) (let* ((axle-height 5mm) (body (box 30mm 50mm 10mm)) (engine (translate 0 -11mm 10mm (box 22mm 23mm 10mm))) (chimney (translate 0 -15mm 20mm (cylinder 2.5mm 12mm))) (cabin (translate 0 14mm 10mm (difference (box 24mm 18mm 23mm) (translate 0 0 3mm (box 26mm 12mm 16mm))))) (axle-bores (repeat-compound i 2 (translate 0 (+ -15mm (* i 30mm)) axle-height (rotate 0 90deg 0 (cylinder (+ axle-radius body-clearance) 34mm :align '(center center center))))))) (difference (union body engine chimney cabin) axle-bores))) (define-component tractor-axle ((number axle-radius 3.2mm) (number axle-length 47.2mm) (number mouth-radius 1.8mm) (number cavity-radius 2.35mm) (number lip-depth 2.2mm) (number socket-depth 5.5mm)) (difference (cylinder axle-radius axle-length) (translate 0 0 -1mm (cylinder mouth-radius (+ axle-length 2mm))) (translate 0 0 lip-depth (cylinder cavity-radius (- socket-depth lip-depth))) (translate 0 0 (- axle-length socket-depth) (cylinder cavity-radius (- socket-depth lip-depth))))) (define-component tractor-wheel ((number radius 10mm) (number width 6mm) (number axle-radius 3.2mm) (number running-clearance 0.4mm)) (difference (cylinder radius width) (translate 0 0 -1mm (cylinder (+ axle-radius running-clearance) (+ width 2mm))))) (define-component tractor-rivet ((number mouth-radius 1.8mm) (number snap-interference 0.25mm) (number head-radius 4.8mm) (number head-thickness 1.6mm)) (let* ((stem-radius (- mouth-radius 0.2mm)) (barb-radius (+ mouth-radius snap-interference)) (barb-base 4.3mm) (slot-bottom (+ head-thickness 0.8mm))) (difference (union (cylinder head-radius head-thickness) (translate 0 0 (- head-thickness 0.2mm) (cylinder stem-radius 3.1mm)) (translate 0 0 barb-base (cone barb-radius 1mm 1.9mm))) (translate 0 0 slot-bottom (box 1.1mm 8mm 5mm))))) (model (meta :title "Snap-together tractor") (params (number wheel_radius 10mm :label "Wheel radius" :min 8 :max 12 :step 1) (number wheel_clearance 0.4mm :label "Wheel running clearance" :min 0.2 :max 0.6 :step 0.05) (number snap_interference 0.25mm :label "Rivet snap interference" :min 0.1 :max 0.35 :step 0.05) (toggle print_layout true :label "Print layout (changes export)")) (let* ((axle-radius 3.2mm) (body-half-width 15mm) (wheel-width 6mm) (wheel-side-gap 2mm) (wheel-end-play 0.6mm) (wheel-center (+ body-half-width wheel-side-gap (/ wheel-width 2))) (axle-half-length (+ body-half-width wheel-side-gap wheel-width wheel-end-play)) (axle-length (* 2 axle-half-length)) (rivet-head-thickness 1.6mm) (body-lift (- wheel_radius 5mm))) (part chassis (translate 0 0 (if print_layout 0mm body-lift) (tractor-chassis :axle-radius axle-radius))) (part axles (repeat-compound i 2 (let* ((axle (tractor-axle :axle-radius axle-radius :axle-length axle-length))) (if print_layout (translate (+ -28mm (* i 56mm)) 46mm 0 axle) (translate (- axle-half-length) (+ -15mm (* i 30mm)) wheel_radius (rotate 0 90deg 0 axle)))))) (part wheels (repeat-compound side 2 (repeat-compound i 2 (let* ((sign (- (* side 2) 1)) (wheel (tractor-wheel :radius wheel_radius :width wheel-width :axle-radius axle-radius :running-clearance wheel_clearance))) (if print_layout (translate (* sign 32mm) (+ -15mm (* i 30mm)) 0 wheel) (translate (* sign (- wheel-center (/ wheel-width 2))) (+ -15mm (* i 30mm)) wheel_radius (rotate 0 (* sign 90deg) 0 wheel))))))) (part rivets (repeat-compound side 2 (repeat-compound i 2 (let* ((sign (- (* side 2) 1)) (rivet (tractor-rivet :snap-interference snap_interference :head-thickness rivet-head-thickness))) (if print_layout (translate (+ -18mm (* side 24mm) (* i 12mm)) 46mm 0 rivet) (translate (* sign (+ axle-half-length rivet-head-thickness)) (+ -15mm (* i 30mm)) wheel_radius (rotate 0 (* sign -90deg) 0 rivet)))))))) (verify (tag eleven-printable-pieces) (metric pieces (stl connected-component-count)) (expect pieces (= 11))) (verify (tag closed-surfaces) (metric bad-edges (stl non-manifold-edge-count)) (expect bad-edges (= 0))))