def clamp_base(): base_shape = [CLAMP_BASE_WIDTH, CLAMP_LENGTH, CLAMP_BASE_HEIGHT] base = grounded_cube(base_shape) runner_base_shape = [CLAMP_TROUGH_WIDTH + 2 * CLAMP_RUNNER_WIDTH, CLAMP_LENGTH, CLAMP_TROUGH_HEIGHT] runner_base = grounded_cube(runner_base_shape) return base + runner_base - pole_hole()
def box(): floor = down(BIG)(grounded_cube([BIG, BIG, BIG])) side = forward(HALF_LENGTH)(grounded_cube([THICKNESS, LENGTH, HEIGHT])) left_side = left(SIDE_OFFSET)(side) right_side = right(SIDE_OFFSET)(side) rear = forward(THICKNESS / 2)(grounded_cube([WIDTH, THICKNESS, HEIGHT])) door = bottom() + left_side + right_side + rear return tilt_back(door) - floor
def keystone_box(): return grounded_cube([ KEYSTONE_WIDTH + 2 * KEYSTONE_THICKNESS, KEYSTONE_LENGTH + 2 * KEYSTONE_THICKNESS, KEYSTONE_DEPTH + 2 * KEYSTONE_THICKNESS ]) - down(KEYSTONE_THICKNESS)(grounded_cube([ KEYSTONE_WIDTH, KEYSTONE_LENGTH, KEYSTONE_DEPTH + 4 * KEYSTONE_THICKNESS ]))
def mount_panel(): width = 3.0 * inches length = 2.0 * inches + 2.0 * PANEL_THICKNESS height = 3.0 * inches punches = mount_hole_punch(width, length, height) bottom_punches = rotate([-90, 0, 0])(punches) back_piece = grounded_cube([width, PANEL_THICKNESS, height]) - punches bottom = grounded_cube([width, length, PANEL_THICKNESS]) return forward(length / 2)(back((length - PANEL_THICKNESS) / 2) (back_piece) + bottom) - bottom_punches
def bard_brick(): double_thickness = 2 * THICKNESS base = basic_brick(WIDTH, LENGTH, HEIGHT) interior = down(THICKNESS)(basic_brick(WIDTH - double_thickness, LENGTH - double_thickness, HEIGHT)) handle = up(HEIGHT - HANDLE_HEIGHT)( forward((LENGTH + HANDLE_LENGTH) / 2 - THICKNESS)(grounded_cube( [HANDLE_WIDTH, THICKNESS + HANDLE_LENGTH, HANDLE_HEIGHT]))) chop = back(LENGTH / 2)(cube([CHOP_WIDTH, CHOP_LENGTH, 2 * CHOP_HEIGHT], center=True)) side_ridge = grounded_cube([SIDE_RIDGE_THICKNESS, LENGTH, HEIGHT]) side_ridges = union()([right(x)(side_ridge) for x in RIDGE_X]) end_ridge = forward(END_RIDGE_Y)(grounded_cube( [END_RIDGE_W + THICKNESS, END_RIDGE_DEPTH, HEIGHT])) brick = base - interior + handle - chop + side_ridges + end_ridge return mirror([0, 0, 1])(down(HEIGHT)(brick))
def switch_hole(): base_shape = [SWITCH_HOLE_WIDTH, SWITCH_HOLE_LENGTH, SWITCH_HOLE_HEIGHT * 2] base_elevation = SWITCH_HOLE_ELEVATION base = forward(SWITCH_HOLE_Y_OFFSET)(up(base_elevation)( grounded_cube(base_shape)) ) return base
def keystone_bottom_shelf(): return back( (KEYSTONE_LENGTH - KEYSTONE_BOTTOM_SHELF_LENGTH) / 2)(grounded_cube([ KEYSTONE_WIDTH + 2 * KEYSTONE_THICKNESS, KEYSTONE_BOTTOM_SHELF_LENGTH + KEYSTONE_THICKNESS, KEYSTONE_THICKNESS ]))
def mounting_slots(): slot = grounded_cube([MOUNT_SLOT_WIDTH, MOUNT_SLOT_THICKNESS, HOLE_HEIGHT]) return union()([ right(x)(forward(y)(slot)) for x in [-MOUNT_SLOT_X_OFFSET, MOUNT_SLOT_X_OFFSET] for y in [-MOUNT_SLOT_Y_OFFSET, 0, MOUNT_SLOT_Y_OFFSET] ])
def keystone_clasps(): clasp = up(KEYSTONE_THICKNESS + KEYSTONE_REACH + KEYSTONE_THICKNESS)( grounded_cube([ KEYSTONE_WIDTH + 2 * KEYSTONE_THICKNESS, KEYSTONE_CLASP_LENGTH + KEYSTONE_THICKNESS, KEYSTONE_CLASP_DEPTH ])) offset = (KEYSTONE_LENGTH - KEYSTONE_CLASP_LENGTH) / 2 return back(offset)(clasp) + forward(offset)(clasp)
def long_plank(self, width, plank_count): board = grounded_cube([width, self.table_length, self.plank_size]) groove = up(self.plank_size - self.plank_groove)( rotate([0, -45, 0])( right(self.plank_size / 2)( grounded_cube([self.plank_size, 2 * self.table_length, self.plank_size]) ) ) ) groove_offsets = [ width / (plank_count) * (index - (plank_count - 2) / 2) for index in range(plank_count - 1) ] grooves = union()([ right(groove_offset)(groove) for groove_offset in groove_offsets ]) return board - grooves
def single_groove_cut(self, ratio): angle = -math.degrees(TAB_ANGLE) * ratio side = TAB_DIAMETER + 2 * self.inflation offset = TAB_DIAMETER - ratio * GROOVE_THICKNESS vertical_offset = TOP_PLATE_THICKNESS single = grounded_cube( [side, side, GROOVE_THICKNESS + 2 * self.inflation]) grooves = left(offset)(single) + right(offset)(single) + forward( offset)(single) + back(offset)(single) return up(vertical_offset)(rotate(angle, v=[0, 0, 1])(grooves))
def support(self): thickness = self.plank_size / 2 base_pad = down(thickness)( grounded_cube([self.seat_width, self.table_length, thickness]) ) center_bench_pad = up(self.seat_height - self.beam_size)( grounded_cube([thickness , self.table_length, self.beam_size]) ) center_offset = (self.bench_beam_width - self.beam_size)/2 bench_pad = up(self.seat_height - self.beam_size)( grounded_cube([thickness , self.table_length, self.beam_size]) ) return ( left(self.seat_offset_x)(base_pad) + right(self.seat_offset_x)(base_pad) + left(self.bench_beam_width/2)(center_bench_pad) + right(center_offset)(center_bench_pad) + bench_pad + up(self.beam_size) )
def roof_sides(self): ridge = self.crown() ridge_offset = self.roof_side_width / 6 single_side = grounded_cube( [self.roof_length, self.roof_side_width, self.roof_thickness]) single_side += forward(ridge_offset)(ridge) single_side += back(ridge_offset)(ridge) offset = 0.5 * self.roof_side_width back_side = rotate(45, [1, 0, 0])(back(offset)(single_side)) front_side = rotate(180, [0, 0, 1])(back_side) return back_side + front_side
def single_leg(self, angle, offset_x, offset_y): chopper = grounded_cube([self.table_beam_width, self.beam_size, self.table_height]) beam = cube([self.beam_size, self.beam_size, 4 * self.table_height], center=True) angled_beam = up(self.table_height)( rotate([0, angle, 0])(beam) ) return right(offset_x)( forward(offset_y)( angled_beam * chopper ) )
def grabbers(): gripper_shape = [CLAMP_GRIP_WIDTH, CLAMP_LENGTH, CLAMP_GRIP_HEIGHT] gripper = grounded_cube(gripper_shape) gripper_offset = (CLAMP_BASE_WIDTH - CLAMP_GRIP_WIDTH) / 2 grippers = left_right_symmetric(gripper_offset, gripper) bumper_shape = [CLAMP_BUMPER_WIDTH, CLAMP_LENGTH, CLAMP_BUMPER_THICKNESS] bumper_elevation = CLAMP_GRIP_HEIGHT - CLAMP_BUMPER_THICKNESS bumper_offset = (CLAMP_BASE_WIDTH - CLAMP_BUMPER_WIDTH) / 2 round_bumper_radius = CLAMP_BUMPER_WIDTH / 2 shrinkage = CLAMP_BUMPER_THICKNESS / round_bumper_radius round_bumper = right(0)( rotate([90, 0, 0])( scale([1.0, shrinkage, 1.0])( cylinder(r=round_bumper_radius, h=CLAMP_LENGTH, segments=4, center=True)))) bumper = up(bumper_elevation)(round_bumper) # grounded_cube(bumper_shape) + ) bumpers = left_right_symmetric(bumper_offset, bumper) clipper_shape = [CLAMP_BASE_WIDTH, CLAMP_LENGTH, CLAMP_TOP_CLIP] clipper = grounded_cube(clipper_shape) return (grippers + bumpers) * clipper
def front_wall(self): door_opening = left(self.door_opening_offset)(up( self.door_opening_threshold)(grounded_cube([ self.door_opening_width, 2 * self.wall_thickness, self.door_opening_height ]))) single_door = self.door() reverse_door = mirror([1, 0, 0])(single_door) single_offset = (self.door_width + self.door_crack) / 2 right_door = left(self.door_opening_offset - single_offset)(single_door) left_door = left(self.door_opening_offset + single_offset)(reverse_door) return forward(self.wall_y_offset)(self.main_wall() - door_opening + right_door + left_door)
def door(self): forward_offset = self.door_thickness / 2 - 0.5 * nscale_inches # slight merge into frame main_panel = grounded_cube( [self.door_width, self.door_thickness, self.door_height]) horizontal_beam = grounded_cube( [self.door_width, self.door_beam_thickness, self.door_beam_width]) vertical_beam = grounded_cube( [self.door_beam_width, self.door_beam_thickness, self.door_height]) horizontal_offset = (self.door_width - self.door_beam_thickness) / 2 vertical_offset = self.door_height - self.door_beam_thickness / 2 diagonal_offset = (self.door_width - self.door_beam_width) / 2 diagonal_skew = 2 * diagonal_offset / self.door_height diagonal_beam = multmatrix([ [1, 0, diagonal_skew, -diagonal_offset], [0, 1, 0, 0], [0, 0, 1, 0], ])(vertical_beam) beams = horizontal_beam + up(vertical_offset)(horizontal_beam) beams += left(horizontal_offset)(vertical_beam) beams += right(horizontal_offset)(vertical_beam) beams += diagonal_beam return up(self.door_opening_threshold - 0.5 * self.door_oversize)( forward(forward_offset)(main_panel + forward( (self.door_beam_thickness - self.door_thickness) / 2)(beams)))
def keystone_top_shelf(): return forward( (KEYSTONE_LENGTH - KEYSTONE_TOP_SHELF_LENGTH) / 2)(grounded_cube([ KEYSTONE_WIDTH + 2 * KEYSTONE_THICKNESS, KEYSTONE_TOP_SHELF_LENGTH + KEYSTONE_THICKNESS, KEYSTONE_THICKNESS ]))
def keystone_hole(): depth = KEYSTONE_DEPTH + 3 * KEYSTONE_THICKNESS return down(KEYSTONE_THICKNESS / 2)(grounded_cube([ KEYSTONE_WIDTH + KEYSTONE_THICKNESS, KEYSTONE_LENGTH + KEYSTONE_THICKNESS, depth ]))
def switch_holder(): holder_shape = [SWITCH_HOLDER_WIDTH, SWITCH_HOLDER_LENGTH, SWITCH_HOLDER_HEIGHT] return forward(SWITCH_HOLDER_Y_OFFSET)( grounded_cube(holder_shape) )
def short_clipper(): return grounded_cube([2 * PLATTER_WIDTH, MOUNT_Y_CLEARANCE - 0.01, HOLE_HEIGHT])
def side_clipper(): return left(SHIFTINESS)(grounded_cube([PLATTER_WIDTH, 2 * PLATTER_LENGTH, HOLE_HEIGHT]))
def pole_hole(): return grounded_cube([POLE_HOLE_WIDTH, POLE_HOLE_LENGTH, HOLE_HEIGHT])
def runners(): runner_shape = [CLAMP_RUNNER_WIDTH, CLAMP_LENGTH, CLAMP_RUNNER_HEIGHT] runner = grounded_cube(runner_shape) runner_offset = (CLAMP_TROUGH_WIDTH + CLAMP_RUNNER_WIDTH) / 2 return left_right_symmetric(runner_offset, runner)
def narrow_clipper(): return grounded_cube([MOUNT_X_CLEARANCE - 0.01, 2 * PLATTER_LENGTH, HOLE_HEIGHT])
def turnout_housing(): housing_shape = [HOUSING_WIDTH, HOUSING_THICKNESS, HOUSING_HEIGHT] housing = up(HOUSING_ELEVATION)(grounded_cube(housing_shape)) return replicate_along_y_axis(HOUSING_LOCATIONS, housing)
def ur_corner_clipper_clipper(): return right(SHIFTINESS)( back(SHIFTINESS)( grounded_cube([PLATTER_WIDTH, PLATTER_LENGTH, HOLE_HEIGHT])))
def socket_hole(): socket_hole_shape = [SOCKET_HOLE_WIDTH, SOCKET_HOLE_LENGTH, 2 * SOCKET_HOLE_HEIGHT] return down(SOCKET_HOLE_HEIGHT)(forward(SOCKET_HOLE_Y_OFFSET)( grounded_cube(socket_hole_shape) ))
def top_clipper(): return back(SHIFTINESS)(grounded_cube([2 * PLATTER_WIDTH, PLATTER_LENGTH, HOLE_HEIGHT]))
def lead_hole(): lead_hole_shape = [LEAD_HOLE_WIDTH, LEAD_HOLE_LENGTH, LEAD_HOLE_HEIGHT] return down(0.1)(forward(LEAD_HOLE_Y_OFFSET)( grounded_cube(lead_hole_shape) ))