def locked_offset(): global locked_count name = "locked_" + str(locked_count) locked_count += 1 j_name = "locked_joint_" + str(locked_count) thickness = 6 #span 2 layers peg_height = 3.2 clearance = 3.2 base = solid.cylinder(r=1.9, h=thickness, segments=100) conn1 = solid.cube([4 / math.sqrt(2), 4 / math.sqrt(2), 3], center=True) conn2 = solid.cube([4 / math.sqrt(2), 4 / math.sqrt(2), 3], center=True) #wtf??? can't get z axis on Joint to work, no matter what I put it just #defaults to 0, so I'm going to orient everything at the origin. b_placed = solid.translate([0, 0, 3])(base) unit = b_placed + solid.translate([0, 0, 1.5])(conn1) + solid.translate( [0, 0, 10.5])(conn2) pm = PolyMesh(generator=unit) pm.save("lock.stl") j1 = Joint( ((0, 0, 12), NZ_JOINT_POSE[1]), #9 name=j_name) OT = (0, 0, 0) OQ = (0, 0, 1, 0) OP = (OT, OQ) layers = Layer(pm, name="lol", color='blue') b = Body(pose=OP, elts=[layers], joints=[j1], name=name) return b, name, j_name
def slat_end(matress_width, overhang): length = matress_width + overhang * 2 half_cross = hole()(cube((3 / 2, 11 / 2, 1 / 4)) + translate((0, 2, 0))(cube((3 / 2, 3 / 2, 3 / 4)))) return part()(OneBySix(length) - translate((length - 3 / 2 - overhang, 0, 0))(half_cross) - translate((overhang, 0, 0))(half_cross))
def nameplate(id): #create the plate bottom = cube([xlen, ylen, 0.01], center=True) top = cube([xlen-zlen-zlen, ylen-zlen, 0.1], center=True) top = translate([0, zlen/2, zlen-0.1])(top) plate = hull()([bottom, top]) # define the text id_str = name_str.replace('$ID',f'{id:03d}') msg = text(id_str, size=text_size, font=text_font, spacing = text_spacing, halign='center', valign='center') msg = linear_extrude(zlen+1)(msg) msg = resize([text_width,text_height,0])(msg) msg = translate([0, zlen/2, -0.5])(msg) #add text to the plate plate = plate - msg #generate output files scad_file = Path.cwd() / 'scad_files' / f'plate_{id:03d}.scad' if scad_file.parent.exists() is False: scad_file.parent.mkdir() scad_render_to_file(plate, str(scad_file)) stl_file = Path.cwd() / 'stl_files' / f'plate_{id:03d}.stl' if stl_file.parent.exists() is False: stl_file.parent.mkdir() subprocess.run(['openscad', '-o', str(stl_file), str(scad_file)])
def single_plate(cylinder_segments=100): top_wall = sl.cube([keyswitch_width + 3, 1.5, plate_thickness], center=True) top_wall = sl.translate( (0, (1.5 / 2) + (keyswitch_height / 2), plate_thickness / 2))(top_wall) left_wall = sl.cube([1.5, keyswitch_height + 3, plate_thickness], center=True) left_wall = sl.translate( ((1.5 / 2) + (keyswitch_width / 2), 0, plate_thickness / 2))(left_wall) side_nub = sl.cylinder(1, 2.75, segments=cylinder_segments, center=True) side_nub = sl.rotate(rad2deg(pi / 2), [1, 0, 0])(side_nub) side_nub = sl.translate((keyswitch_width / 2, 0, 1))(side_nub) nub_cube = sl.cube([1.5, 2.75, plate_thickness], center=True) nub_cube = sl.translate( ((1.5 / 2) + (keyswitch_width / 2), 0, plate_thickness / 2))(nub_cube) side_nub = sl.hull()(side_nub, nub_cube) plate_half1 = top_wall + left_wall + side_nub plate_half2 = plate_half1 plate_half2 = sl.mirror([0, 1, 0])(plate_half2) plate_half2 = sl.mirror([1, 0, 0])(plate_half2) plate = plate_half1 + plate_half2 if plate_file is not None: socket = sl.import_(plate_file) socket = sl.translate([0, 0, plate_offset])(socket) plate = sl.union()(plate, socket) return plate
def cage_stabilizer(assemble=False): """stabilizer with 3 clamps for HolMOS-cage""" cage_base = 30 stabilizer_base = base.rods30_dist_third_rod stabilizer_height = 10 angle = -atan(cage_base / 2 / stabilizer_base) / math.pi * 180 stabilizer = translate((0, stabilizer_base / 2, 0))(cube( (cage_base + 4, stabilizer_base - 10, stabilizer_height), center=True)) stabilizer -= translate((-cage_base, stabilizer_base / 2, 0))(rotate( (0, 0, angle))(cube( (cage_base, stabilizer_base, 2 * stabilizer_height), center=True))) stabilizer -= translate((cage_base, stabilizer_base / 2, 0))(rotate( (0, 0, -angle))(cube( (cage_base, stabilizer_base, 2 * stabilizer_height), center=True))) stabilizer = translate((0, -25, 0))(stabilizer) for (dd, y) in ((25, 0), (10, 21)): stabilizer -= translate((0, y, 0))(cylinder(d=dd, h=20, center=True)) stabilizer += cage_3_clips() return stabilizer
def cage_circumference(d_outer=80.5, wall_thick=2, h=10, assemble=None): """Circle to fit cage ends, e.g. to transport cage inside a cylindrical tube""" d_inner = base.rods30_dist_third_rod + 7 # absolute diameter: contact to clips. clamp = translate((0, 0, 5))(cage_3_clips(inside=True)) # bottom at z=0 circ_x_at_clamp = ((d_outer / 2)**2 - 30**2)**.5 back_face = cube((2 * circ_x_at_clamp, wall_thick, h), center=True) back_face = translate((0, -30 + wall_thick / 2, h / 2))(back_face) circle = cylinder(d=d_outer, h=h) circle -= translate( (0, 0, wall_thick))(cylinder(d=d_outer - 2 * wall_thick, h=2 * h)) # relative diameter: wall thickness circle -= translate((0, 0, -2))(cylinder(d=d_inner, h=2 * h)) # clear space past -y of clamps, so that cage can rest against wall when used with hook. helper_block_y = 30 circle -= translate((0, -20 - 10 - helper_block_y / 2, 0))(cube( (100, helper_block_y, 100), center=True)) # add some holes to screw cage onto something for angle_deg in (-30, 30, 150, 210): hole_position = lambda obj: rotate(angle_deg)(translate( (d_inner / 2, 0, 0))(obj)) circle += hole_position(cylinder(d=8, h=wall_thick)) circle -= hole_position(cylinder(d=3.2, h=2 * h, center=True)) return clamp + circle + back_face
def teensy_holder(): s1 = sl.cube([3, teensy_holder_length, 6 + teensy_width], center=True) s1 = sl.translate([1.5, teensy_holder_offset, 0])(s1) s2 = sl.cube([teensy_pcb_thickness, teensy_holder_length, 3], center=True) s2 = sl.translate([ (teensy_pcb_thickness / 2) + 3, teensy_holder_offset, -1.5 - (teensy_width / 2), ])(s2) s3 = sl.cube([teensy_pcb_thickness, teensy_holder_top_length, 3], center=True) s3 = sl.translate([ (teensy_pcb_thickness / 2) + 3, teensy_holder_top_offset, 1.5 + (teensy_width / 2), ])(s3) s4 = sl.cube([4, teensy_holder_top_length, 4], center=True) s4 = sl.translate([ teensy_pcb_thickness + 5, teensy_holder_top_offset, 1 + (teensy_width / 2) ])(s4) shape = sl.union()(s1, s2, s3, s4) shape = sl.translate([-teensy_holder_width, 0, 0])(shape) shape = sl.translate([-1.4, 0, 0])(shape) shape = sl.translate( [teensy_top_xy[0], teensy_top_xy[1] - 1, (6 + teensy_width) / 2])(shape) return shape
def locked_offset(): global locked_count name = "locked_" + str(locked_count) locked_count +=1 j_name = "locked_joint_" + str(locked_count) thickness = 6 #span 2 layers peg_height = 3.2 clearance = 3.2 base = solid.cylinder(r=1.9, h=thickness, segments = 100) conn1 = solid.cube([4/math.sqrt(2),4/math.sqrt(2),3],center=True) conn2 = solid.cube([4/math.sqrt(2),4/math.sqrt(2),3],center=True) #wtf??? can't get z axis on Joint to work, no matter what I put it just #defaults to 0, so I'm going to orient everything at the origin. b_placed = solid.translate([0,0,3])(base) unit = b_placed + solid.translate([0,0,1.5])(conn1) + solid.translate([0,0,10.5])(conn2) pm = PolyMesh(generator = unit) pm.save("lock.stl") j1 = Joint( ((0, 0, 12),NZ_JOINT_POSE[1]), #9 name=j_name ) OT = (0, 0, 0) OQ = (0, 0, 1, 0) OP = (OT, OQ) layers=Layer( pm, name="lol", color='blue' ) b = Body(pose=OP, elts=[layers], joints=[j1], name=name) return b, name, j_name
def create_servo_mount(): """ right now designed to fit Jacobs institute model """ width = 6.5 length = 20.0 depth = 2.3 voffset = -18.5 - 9 left_bar = solid.cube([width,length,depth], center = True) hole = solid.cylinder(r=2,h=10, center =True,segments = 100) hole1 = solid.translate([0,4,0])(hole) hole2 = solid.translate([0,-4,0])(hole) left_bar = solid.difference()(left_bar, hole1) left_bar = solid.difference()(left_bar, hole2) right_bar = solid.cube([width,length,depth],center = True) right_bar = solid.difference()(right_bar, hole1) right_bar = solid.difference()(right_bar, hole2) left_spread = -30.0 right_spread = 17.0 left_bar = solid.translate([left_spread, 0,-(depth/2 + voffset)])(left_bar) right_bar = solid.translate([right_spread, 0 , -(depth/2+voffset)])(right_bar) connector = solid.cube([(right_spread - left_spread) + width,width,depth],center=True) placed_connector = solid.translate([(left_spread+right_spread)/2,-(length/2 +width/2), -(depth/2+voffset)])(connector) total_mount = left_bar + placed_connector + right_bar pl = PolyMesh(generator= total_mount) attach_point1 = PolyMesh(generator =solid.translate([width, 0,0])(right_bar)) attach_point2 = PolyMesh(generator =solid.translate([-width, 0,0])(left_bar)) return pl, attach_point1, attach_point2
def board_hook(clip_z=30, hook_opening=18, assemble=False): """ Hook for topmost end of cage - can be used to hang setup from a door, whiteboard, poster board, cabinet... 2019-05-13 - printed, works well. But: real-life poster board is one inch thick. """ assert base.__rods30, "this only makes sense for rod-mount" rod_clips = base.base_rods30(z_length=clip_z) rod_clips = translate((0, 0, clip_z / 2))(rod_clips) # start at z=0 hook_thick = 4 hook_width = 30 hook_z = 35 strut_height = 10 hook = translate((0, hook_opening - 20 + hook_thick / 2))(cube( (hook_width, hook_thick, hook_z), True)) hook = translate((0, 0, hook_z / 2))(hook) strut = cube((hook_thick, hook_opening + .1, strut_height), True) strut = translate((hook_width / 2 - hook_thick, (hook_opening - 40) / 2, strut_height / 2))(strut) strut += mirror((1, 0, 0))(strut) assembly = rod_clips + hook + strut if assemble: return translate((0, -50, 0))(rotate((0, 180, 180))(assembly)) else: return assembly
def __post_init__(self): if self.base is None: self.base = [18.16, 18.16] if self.top_delta is None: self.top_delta = [6, 4] if self.size is None: self.size = [1, 1] if self.skew is None: self.skew = [0, 0] if self.tilt is None: self.tilt = [0, 0] self.dims = [self.base[i] * self.size[i] for i in [0, 1]] self.top_dims = [self.dims[i] - self.top_delta[i] for i in [0, 1]] dish_kwargs = { 'dish_type': self.dish_type, 'top_dims': self.top_dims, 'key_z': self.z } if self.dish_kwargs is not None: dish_kwargs.update(self.dish_kwargs) self.dish = Dish(**dish_kwargs) # masks used to exclude anything not inside/outside the key self.inside = s.difference()(s.translate([0, 0, 50])(s.cube([100, 100, 100], center=True)), self._shape(self.thickness, self.depth)) self.outside = s.difference()(s.cube([1000, 1000, 1000], center=True), self.hull(self.thickness, self.depth, mod=2))
def control_box(wall_length, wall_width, wall_height): max_board_thickness = max(pro_micro.board_thickness, distribution_board.board_thickness) board_surface_pos = max(20 + wall_thickness - wall_length, 5) case_length = (board_surface_pos + max_board_thickness + 3 + wall_thickness) case_width = (pro_micro.board_length + distribution_board.board_length + 3 * wall_thickness) board_offset_forward = (board_surface_pos + max_board_thickness - case_length / 2) def position_control_box(part): """Position the control box on the final model.""" #return left(case_width / 2)( return left(wall_width / 4 - case_width / 2)(forward( (wall_length + case_length) / 2)(up(wall_height / 2)(part))) def position_controller(part): """Position the controller board within the control box.""" return forward(board_offset_forward)( left(case_width / 2 - wall_thickness + wall_thickness / 4)(rotate( (90, -90, 0))(part))) def position_distribution_board(part): """Position the distribution board within the control box.""" return forward(board_offset_forward)( right(case_width / 2 - wall_thickness + wall_thickness / 4)(rotate( (90, 90, 0))(part))) center_post_length = max_board_thickness + 3 center_post_offset_right = (case_width / 2 - wall_thickness * 1.5 - distribution_board.board_length) inner = (down(wall_thickness / 2 + 1)(back(wall_thickness + 1)(cube( ( case_width - 2 * wall_thickness, case_length + 2, wall_height - wall_thickness + 1, ), center=True, ))) + rotate( (90, 0, 0))(right(center_post_offset_right)(cylinder_outer(4.5, 100)))) case = position_control_box( cube((case_width, case_length, wall_height), center=True) - inner # Center post (between the two boards): + forward(board_surface_pos - case_length / 2 + center_post_length / 2) (right(center_post_offset_right) (cube((wall_thickness * 2, center_post_length, wall_height), center=True) - rotate((90, 0, 0)) (cylinder_outer(m2_shaft_radius, center_post_length)))) - position_controller(pro_micro.board_profile(0)) - position_distribution_board(distribution_board.board_profile(0))) cutout = position_control_box(inner) return (case, cutout)
def end(width): body = translate((-2, -2, 2.75))(cube((width + 4, 5.5, 0.75))) bridle = platformbed.joints.base_side_bridle_joint() tenon = cube((1.5, 1.5, 0.75)) return (body - bridle - translate( (width - 1.5, 0, 0))(platformbed.joints.base_side_bridle_joint()) - translate((width / 3 - 0.75, 0, 2.75))(tenon) - translate( (2 * width / 3 - 0.75, 0, 2.75))(tenon))
def rj9_holder(): shape = sl.union()( sl.translate([0, 2, 0])(sl.cube([10.78, 9, 18.38], center=True)), sl.translate([0, 0, 5])(sl.cube([10.78, 13, 5], center=True)), ) shape = sl.difference()(rj9_cube(), shape) shape = sl.translate(rj9_position)(shape) return shape
def key_shaft(): trunk_length = SHAFT_LENGTH - 0.5 * THICKNESS trunk = back(trunk_length / 2)(cube([THICKNESS, trunk_length, KEY_HEIGHT], center=True)) slot = back(SLOT_LENGTH / 2)(cube( [SLOT_WIDTH, SLOT_LENGTH, 2 * KEY_HEIGHT], center=True)) tip = cylinder(r=THICKNESS / 2, h=KEY_HEIGHT, center=True, segments=16) return forward(trunk_length)(trunk + tip - slot)
def cross(h=4, slop=_SLOP): out = s.union()( s.cube([4 + 2 * slop, 1.3 + 2 * slop, h], center=True), s.cube([1.1 + 2 * slop, 4 + 2 * slop, h], center=True), ) return out
def hJoint (right, out, name): female = out # Create the outer cylinder j = solid.rotate(a = [-90, 0, 0])\ (solid.cylinder(r=outerD/2, h=width, segments = 20)) j = solid.translate(v = [0, 0, outerD/2])(j) # Create the clamp j = j + solid.cube([outerD,width,border]) j = j + solid.translate([0, 0, border+thick])\ (solid.cube([outerD,width,border])) j = j - solid.translate(v = [0, 0, border])(solid.cube([outerD,width,thick+2*t])) # Create the center hole c = solid.rotate(a = [90, 0, 0])\ (solid.cylinder(r=innerD/2,center=True, h=2*width, segments=20)) if female: if (right and out) or (not right and not out): off = -(width-6) else: off = width-6 c = solid.translate(v = [0, width/2+off, outerD/2])(c) else: c = solid.translate(v = [0, width/2, outerD/2])(c) j = solid.difference()(j, c) if not female: if (right and out) or (not right and not out): off = -border else: off = border c = solid.rotate(a = [90, 0, 0])\ (solid.cylinder(r=(outerD)/2-border,center=True, h=width, segments = 20)) c = solid.translate(v = [0, width/2+off, outerD/2])(c) cube = solid.cube([outerD, width, 2*border+thick]) c = solid.difference()(c, \ solid.translate(v = [-outerD/2.0, 0, 0])(cube)) j = solid.difference()(j, c) # Create bolt holes j = solid.difference()(j, solid.translate(v=[.65*outerD, width/2, 0]) (solid.cylinder(r=bolt/2, h = outerD, segments = 20))) j = solid.difference()(j, solid.translate(v=[.85*outerD, width/2, 0]) (solid.cylinder(r=bolt/2, h = outerD, segments = 20))) # Support bar # j = j + solid.translate(v = [-thick,0,border])(solid.cube([thick, width, thick+2*t])) # Move and rotate j = solid.translate(v=[0, 0, -border])(j) if right: j = solid.translate(v=[width, 0, 0])(solid.rotate(a=[0, 0, 90])(j)) j = PolyMesh(generator=j) j.save("heliodon/joint" + name + ".stl") return j
def rcube(size, rnd=0, center=True): ''' primitive for a cube with rounded edges on 4 sides ''' if rnd == 0: return solid.cube(size, center=center) round_ratio = (1 - rnd) * 1.1 + 0.5 #TODO fix rounded cube for detent use-case c = solid.cube(size, center=center) * solid.resize( (size[0] * round_ratio, 0, 0))(solid.cylinder( h=size[2], d=size[1] * round_ratio, center=center)) return c
def make_base(): base = solid.cube(BASE_DIMENSIONS, center=True) pole_hole = solid.cube( [POLE_DIMENSIONS[0] * 2, POLE_DIMENSIONS[1], BASE_DIMENSIONS[2] + 1], center=True) pole_hole = solid.utils.left(BASE_DIMENSIONS[0] / 2)(pole_hole) bottom_hole = solid.cube(BOTTOM_HOLE_DIMENSIONS, center=True) bottom_hole = solid.utils.down(BASE_DIMENSIONS[2] / 2 + 1)(bottom_hole) return (base - pole_hole) - bottom_hole
def q(x, y=None, z=None, center=True): """A quick cube""" if isinstance(x, (tuple, list)): return solid.cube(x, center=center) else: if y is None: y = x if z is None: z = x return solid.cube([x, y, z], center=center)
def rasp_pi(): base = solid.color([0,.7,.1])(solid.cube([8.5,5.5,.1])) metal = t55_to_1([209,209,209]) yellow = t55_to_1([255, 188, 60]) ether = solid.translate([-0.1,3.9,0])(solid.cube([2.1,1.6,1.4])) ether = solid.color(metal)(ether) usb = solid.cube([1.7,1.3,1.5]) usb = solid.translate([-.7,1.9,0])(solid.color(metal)(usb)) audio = solid.cube([1.2, 1.5, 1.2]) audio = solid.translate([1.5,-.5,0])(solid.color([0,0,0])(audio)) tv = solid.cube([1,1.9,1.5]) tv = solid.translate([3.4,-.8,0])(solid.color(yellow)(tv)) hdmi = solid.cube([1.5,1.1,.9]) hdmi = solid.translate([3.4,4.6,0])(solid.color(metal)(hdmi)) gpio = solid.cube([3.2,.4,1.2]) gpio = solid.translate([5.3,.1,0])(solid.color([0,0,0])(gpio)) sdcard = solid.cube([1.8,2.9,.4]) sdcard = solid.translate([6.7, 1.6, -.4])(solid.color([0,0,0])(sdcard)) musb = solid.cube([.5,.7,.3]) musb = solid.translate([7.9, 4.5, 0])(solid.color([0,0,0])(musb)) out = [base, ether, usb, audio, tv, hdmi, gpio, sdcard, musb] return join_list(out)
def end(width): body = cube((width, 1.5, 2.75)) tenon = cube((1.5, 1.5, 0.75)) return ( body + translate((width/3-0.75, 0, 2.75))(tenon) + translate((2*width/3-0.75, 0, 2.75))(tenon) - platformbed.joints.base_side_dovetail_joint() - translate((width, 0, 0))(mirror((1, 0, 0))(platformbed.joints.base_side_dovetail_joint())) - translate((width/2-0.75, 0, 1.375))(cube((1.5, 1.5, 1.375))) )
def rampBar(leng, wide, high, transl): '''Return a bar of specified length, width, height, except with ends ramping up at 45 degrees at one end, -45 at other, in a plane rotated about y axis. Parameters: leng, wide, high give x,y,z sizes. transl = 3-vector with x,y,z distances to translate the origin-corner of the bar. ''' s2 = sqrt(2) cu = cube([leng, wide, high]) box = rotate(a=[0,-45,0])(back(wide)((cube([s2*high, 3*wide, s2*high])))) return translate(transl)(cu-box-right(leng)(box))
def thing(d=27.9, h=10, width=16, width_hole=10.2, z=0, X=45): center = solid.cube(size=(width, width, h), center=True) - solid.hole()( solid.cube(size=(width_hole, width_hole, h * 2), center=True)) axis_base = solid.cube(size=(d, width_hole / 2, h), center=True) axis_1 = solid.rotate(a=X)(axis_base) axis_2 = solid.rotate(a=-X)(axis_base) outer_cylinder = solid.cylinder(d=d, h=h, center=True, segments=256) ret = (center + axis_1 + axis_2) * outer_cylinder return solid.translate(v=(0, 0, z + h / 2))(ret)
def makeRail(self): length = self.RailLen cap = cube([length, self.CapWide, self.CapThik]) leg = up(self.CapThik)(cube( [length, self.LegThik, self.ChanHi + self.eps])) asm = cap + forward( self.ChanHang1)(leg) + forward(self.CapWide - self.ChanHang2 - self.LegThik)(leg) px = self.Pillar1 while px < length: asm += self.makePillar(px) px += self.PillarSep return asm
def scaffold(length, color=[0, 0, 1, 1]): h = solid.translate([diameter / 2.0, 0, length / 2.0])( solid.scale([diameter, diameter, length])( solid.cube(center=True) ) ) + solid.translate([0, 0, length / 2.0])( solid.scale([center_notch + tool_radius * 2, center_notch, length])( solid.cube(center=True) ) ) # scale & move in Z to ensure overlap h = solid.translate([0, 0, -(length * .1)/2.0])(solid.scale([1, 1, 1.1])(h)) return solid.color(color)(h)
def arduino(): usbhole = up(2.5)(cube([2.5, 7.5, 9], True)) board = up(3.75)(cube([2, x, 7.5], True)) smds = up(1.25)(cube([1.5, 5, 2.5], True)) dupont = up(2.5)(cube([2.5, 2.5, 5], True)) pinhole = cube([39, 1, 1], True) return (usbhole) \ + up(1)(left(3.75)(smds)) \ + up(1)(left(2)(board)) \ + left(4.25)(up(3.5)(forward((x/2)-1.25)(dupont))) \ + left(4.25)(up(3.5)(back((x/2)-1.25)(dupont))) \ + left(5)(up(2.25)(forward((x/2)-1.25)(pinhole))) \ + left(5)(up(2.25)(back((x/2)-1.25)(pinhole)))
def make_solid(arr): HEIGHT = 1 SCALE = 2 # output defaults to 1 mm per unit; this lets us increase the size of objects proportionally. cubes = [ translate([i * SCALE, j * SCALE, 0])(color('black')(cube(size=[SCALE, SCALE, HEIGHT]))) for i, row in enumerate(arr) for j, col in enumerate(row) if arr[i, j] == 1 ] base_plate = color('white')(cube(size=(arr.shape[0] * SCALE, arr.shape[1] * SCALE, HEIGHT / 2))) qrobj = union()(*cubes, base_plate) return qrobj
def groove_cylinder(cube_size, round_groove=False): if round_groove: target = cylinder(r=GROOVE_DIAMETER / 2, h=cube_size * 2.1, center=True, segments=16) else: target = cube([GROOVE_DIAMETER, GROOVE_DIAMETER, cube_size * 2.1], center=True) groove = rotate(90, [0, 1, 0])(target) groove += cube( [TAB_LENGTH, TAB_WIDTH, 3 * DEFAULT_CONNECTOR_BLOCK_THICKNESS], center=True) return groove
def rounded_plate(xyz, r): '''centered plate with rounded (xy) corners''' x, y, z = xyz cube_x = cube([x - 2 * r, y, z], center=True) cube_y = cube([x, y - 2 * r, z], center=True) plate = cube_x + cube_y dx, dy = x / 2 - r, y / 2 - r for x, y in [[dx, dy], [-dx, dy], [-dx, -dy], [dx, -dy]]: plate += translate([x, y, 0])(cylinder(r=r, h=z, center=True)) return plate
def rounded_cube(shape, radius, segments=24): diameter = 2 * radius long_shape = [shape[0] - diameter, shape[1], shape[2]] wide_shape = [shape[0], shape[1] - diameter, shape[2]] half_width = shape[0] / 2 - radius half_length = shape[1] / 2 - radius half_height = shape[2] / 2 corner = cylinder(r=radius, h=shape[2], center=True, segments=segments) corners = replicate_along_xy_axes([-half_width, half_width], [-half_length, half_length], corner) return up(half_height)( cube(long_shape, center=True) \ + cube(wide_shape, center=True) \ + corners )
def switch_plate(): top_wall = forward((1.5 + keyswitch_length) / 2)( up(plate_thickness / 2)( cube((keyswitch_width + 3, 1.5, plate_thickness), center=True) - down(notch_plate_thickness)( # Notch for switch clips back(0.75)(cube((notch_width, notch_depth * 2, plate_thickness), center=True))))) left_wall = left((1.5 + keyswitch_width) / 2)(up(plate_thickness / 2)(cube( (1.5, keyswitch_length + 3, plate_thickness), center=True))) plate_half = top_wall + left_wall return plate_half + mirror((0, 1, 0))(mirror((1, 0, 0))(plate_half))
def init_keyhole(self): top_wall = sl.cube([self.width + 3, 1.5, self.thickness], center=True) top_wall = sl.translate( (0, (1.5 / 2) + (self.height / 2), self.thickness / 2) )(top_wall) left_wall = sl.cube([1.5, self.height + 3, self.thickness], center=True) left_wall = sl.translate( ((1.5 / 2) + (self.width / 2), 0, self.thickness / 2) )(left_wall) side_nub = sl.cylinder(1, 2.75, segments=self.cylinder_segments, center=True) side_nub = sl.rotate(rad2deg(pi / 2), [1, 0, 0])(side_nub) side_nub = sl.translate((self.width / 2, 0, 1))(side_nub) nub_cube = sl.cube([1.5, 2.75, self.thickness], center=True) nub_cube = sl.translate( ((1.5 / 2) + (self.width / 2), 0, self.thickness / 2) )(nub_cube) side_nub = sl.hull()(side_nub, nub_cube) plate_half1 = top_wall + left_wall + side_nub plate_half2 = plate_half1 plate_half2 = sl.mirror([0, 1, 0])(plate_half2) plate_half2 = sl.mirror([1, 0, 0])(plate_half2) plate = plate_half1 + plate_half2 if self.hotswap_socket is not None: self.hotswap_socket = sl.translate([0, 0, self.thickness])( self.hotswap_socket) plate = sl.union()(plate, self.hotswap_socket) if self.cap_height is not None: cap = sl.cube([self.width, self.width, self.cap_height], center=True) self.cap = sl.translate([0, 0, ( self.thickness + self.switch_height + self.thickness)])( cap) if self.side == "left": plate = sl.mirror([-1, 0, 0])(plate) return plate
def strunk(): c1 = solid.cylinder(r= 15, h = 70) c2 = solid.translate([9,0,0])(solid.cylinder(r=15, h= 70)) m1 = solid.translate([0,-15,0])(solid.cube([9,30,70])) total = join_list([c1,c2,m1]) total = solid.translate([0,0,84])(total) return total
def test_body_without_color(self) -> None: self.assertTrue( utils.compare_flattened_openscad_children( MockEmbodiedComponent(size=2.0, color=None).body, solid.cube(size=2.0)), msg="Colorless components' bodies should not have colors applied", )
def viz(self,position): """ Generates a OpenScad model to visualize the sun position """ ## Generating the hemisphere ## starting_sphere = solid.sphere(self.r, segments= 64) box_sub = solid.utils.down(((self.r * 2 + 10)/2))(solid.cube((self.r * 2 + 10), center= True)) hemisphere = starting_sphere - box_sub hemisphere = PolyMesh(generator= hemisphere).simplified() #hemisphere = (solid.utils.color([0.75,0.75,0.75,0.1]))(hemisphere.get_generator()) #this sucks...need to do this way in order do render #hemisphere = PolyMesh(generator= hemisphere) ## Generate the sphere for the sun ## sun_sphere = solid.sphere(5, segments= 64) vector = position sun_sphere = (solid.translate(vector))(sun_sphere) sun_sphere = PolyMesh(generator= sun_sphere).simplified() L1 = Layer(hemisphere, name= "hem", color=[200,200,200,1000]) L2 = Layer(sun_sphere, name="sun", color='yellow') B1 = Block([L1, L2]) return B1.show(is_2d= False)
def create_crank_shaft(save = False): """ Oriented relative to the shaft that will be driven at the origin in the +Z direction. """ global shaft_count name = "shaft_" + str(shaft_count) j_name = "shaft_joint_" + str(shaft_count) mount_plate = solid.cylinder(r = 10, h= 3) shaft = solid.cube([4/math.sqrt(2),4/math.sqrt(2),6], center = True) shifted_shaft = solid.translate([0,0,3])(shaft) total = mount_plate+shaft pl = PolyMesh(generator=total) if save: pl.save("crank.stl") j1 = Joint( ((0, 0, 0),Z_JOINT_POSE[1]), name=j_name ) OT = (0, 0, 0) OQ = (0, 0, 1, 0) OP = (OT, OQ) layers=Layer( pl, name="lol", color='blue' ) b = Body(pose=OP, elts=[layers], joints=[j1], name=name) return b, name, j_name
def add_servo_mount(poly): """ add shaft mounting hole """ hole = solid.cube([4,4,50], center = True) pm = PolyMesh(generator = hole) return poly - pm
def conic_section(theta): line = solid.polygon(points = [[0,0],[50,50],[49.9,50],[0,.1]]) cone = solid.rotate_extrude( convexity = 20)(line) plane = solid.translate([0,0,5])(solid.cube([50,50,.1],center = True)) plane = solid.rotate([0,theta,0])(plane) section = solid.rotate([0,-1*theta, 0])(solid.intersection()(cone, plane)) return section
def ssupport(): arch1 ,thet1, rad1= circle_arch(30.0, 5.0, 3) arch1 = solid.translate([14,-28/2,0])(solid.rotate([0,0, -thet1/2])(arch1)) arch2 = solid.translate([0,0,1])(arch1) arch3 = solid.translate([0,0,-1])(arch1) arch1 = join_list([arch1, arch2, arch3]) pillar1 = solid.rotate([0,90,0])(solid.cylinder(r=2, h=35) ) pillar1 = pillar1 - solid.translate([-1,0,-3])(solid.cube([37,4, 8])) pillar2 = solid.rotate([180,0,0])(solid.translate([0,28])(pillar1)) return join_list([arch1, pillar1, pillar2])
def rect2scad(rect, height, z_start = 0.0, mirrored = False): """ Convert a Rectangle into an openscad cube by giving it a height and Z start """ scad_cube = sc.translate([rect.left(), rect.bot(), z_start])( sc.cube([rect.width, rect.height, height]) ) if mirrored: return sc.scale([1,1,-1])(scad_cube) else: return scad_cube
def plot_space(dict, tl): path_labels = sorted(dict.keys()) path_count = len(path_labels) out =[] for i in range(path_count): color = t55_to_1( colorout2(i,path_count) ) for j in range(len(dict[path_labels[i]])): x = dict[path_labels[i]][j][0]*tl y = dict[path_labels[i]][j][1]*tl z = j*tl out += [solid.color(color)(solid.translate([x,y,z])(solid.cube([tl,tl,1])))] return out
def create_shaft_connector(): """ Oriented relative to the shaft that will be driven at the origin in the +Z direction. TODO: Consider refactoring into mechanism with joint at O. """ mount_plate = solid.cylinder(r = 10, h= 3) shaft = solid.translate([-2,-2,0])(solid.cube([4,4,20])) shifted_shaft = solid.translate([0,0,3])(shaft) total = mount_plate+shaft pl = PolyMesh(generator=total) return pl
def arc(radius): a = solid.difference()( solid.cylinder(r=radius, h=thick, segments=48), solid.cylinder(r=radius-width, h=thick, segments=48)) a = solid.intersection()(a, solid.cube([radius, radius, thick])) a = solid.difference()(a, solid.translate(v=[.75*outerD, radius-width/2, 0]) (solid.cylinder(r=bolt/2, h=2*thick, segments=20, center=True))) a = solid.difference()(a, solid.translate(v=[radius-width/2, .75*outerD, width/2.0]) (solid.cylinder(r=bolt/2, h=2*thick, segments=20, center=True))) c = solid.translate(v=[radius-width/2, 0, 0])\ (solid.cylinder(r=bolt/2, h=2*thick, segments=20, center=True)) # Add bolt holes for fastening the two sheets of acryllic together for step in range(1,3): a = solid.difference()(a, solid.rotate(a = [0,0, step * 30])(c)) PolyLine(generator = solid.projection()(a)).save("heliodon/a" + str(radius) + ".dxf") return PolyMesh(generator=a)
heights 0-1, base 1-4, lighting 5-6 floor/pane 7-top, chamber ''' out_file = make_output() orange = t55_to_1([255,127,0]) battery = solid.color([1,0,0])(solid.cylinder(r=1,h=3)) battery += solid.color([0,0,0])(solid.translate([0,0,3])(solid.cylinder(r=1,h=3))) battery = solid.translate([11,2,2])(solid.rotate([0,90,0])(battery)) led = solid.cylinder(r=1,h=1, segments = 20) led += solid.translate([0,0,1])(solid.sphere(r=1, segments= 20)) wire = solid.cube([.2,.2,1]) led += solid.translate([-.1,.8,-1])(wire)+ solid.translate([-.1,-1,-1])(wire) led = solid.color(orange)(led) led2 = solid.translate([5,3,1.5])(led) led = solid.translate([9,3,1.5])(led) vessel = solid.cube([20,7,15])- solid.translate([1,1,1])(solid.cube([18,5,15])) vessel -= solid.translate([1,-1,6])(solid.cube([18,3,10])) vessel -= solid.translate([.5,.25,5.5])(solid.cube([19,.5,10])) vessel -= solid.translate([1,1,1])(solid.cube([20,5,3])) vessel -= solid.translate([.5,.5, 5.25])(solid.cube([20,6,.5])) vessel = solid.color([0,.5,9])(vessel) pane1 = solid.translate([.5,.25,5.5])(solid.cube([19,.5,9.5])) pane2 = solid.translate([.5,.5, 5.25])(solid.cube([19.5,6,.5]))
out_file = make_output() clearance = 15 width = 70 length = 120 thick = 20 depth = 40 leg1 = solid.translate([8,8,0])(solid.cylinder(r=4, h=clearance)) leg2 = solid.translate([8,width-8,0])(solid.cylinder(r=4, h=clearance)) leg3 = solid.translate([length-8,8,0])(solid.cylinder(r=4, h=clearance)) leg4 = solid.translate([length-8,width-8,0])(solid.cylinder(r=4, h=clearance)) legs = join_list([leg1, leg2, leg3, leg4]) legs = solid.color([0,0,0])(legs) table = solid.cube([length,width,thick]) table -= solid.translate([depth+3,-1,3])(solid.cube([length+1-depth ,width+2,thick-6])) table -= solid.translate([-1,3,3])(solid.cube([depth,width-6,thick-6])) table = solid.translate([0,0,clearance])(table) table = solid.color(t55_to_1([140,80,33]))(table) mid = solid.translate([length-20,width/2,clearance])(solid.color([0,0,0])(solid.cylinder(r=5,h=thick-1))) glass = solid.translate([0,0,clearance+thick])(solid.color([1,1,1,.3])(solid.cube([length,width,3]))) drawer = solid.cube([depth,width-6, thick-7 ]) drawer -= solid.translate([1,1,1])(solid.cube([depth-2, width-8, thick-5])) drawer += solid.cube([2,width-6, thick-6]) handle, theth, rh = circle_arch(30, 7, 2) handle = solid.translate([13,width/2-3, thick/2-3])(solid.rotate([0,0,90+45])(handle))
def square_neg(poly,joint): transform = matrix_pose(joint.pose) w, l, h = 4/math.sqrt(2),4/math.sqrt(2),20 h_hole = PolyMesh(generator=solid.cube([w,l,h],center =True)) tf_snap_sub = transform * h_hole return poly - tf_snap_sub
half_guide_width = guide_width / 2.0 square_width = width - height # the width without the round edge bolt_z = height / 2.0 bolt1_y = bolt_from_edge - outer_rad bolt2_y = square_width + outer_rad - bolt_from_edge bolt_base1_y = (bolt_base_dia / 2.0) - outer_rad bolt_base2_y = square_width + outer_rad - (bolt_base_dia / 2.0) bolt_base_depth = depth * 0.66 # rotation of bolt base to merge into the side bolt_base_angle = math.degrees(math.atan2( bolt_base_depth, bolt_base_dia / 2.0)) hnt = nt / 2.0 # half nested tolerance # body centre body = s.cube(size=[depth, square_width, height]) # body round edge 1 body += u.up(outer_rad)(s.rotate(a=[0, 90, 0])( s.cylinder(r=outer_rad, h=depth, segments=segments) )) # body round edge 2 body += u.forward(square_width)(u.up(outer_rad)(s.rotate(a=[0, 90, 0])( s.cylinder(r=outer_rad, h=depth, segments=segments) ))) # inner to subtract from the body for the body inner = s.cube( size=[depth - wall_width, square_width, height - walls_width] ) inner += u.up(inner_rad)(s.rotate(a=[0, 90, 0])( s.cylinder(r=inner_rad, h=depth - wall_width, segments=segments)
wall_holes += [solid.rotate([0,0,i*30])(wallh)] wall_ho = join_list(wall_holes) bucket -= wall_ho bucket -= solid.translate([0,0,2])(solid.rotate([0,0,15])(wall_ho)) bucket = solid.color("SaddleBrown")(bucket) return bucket ### out_file = make_output() ''' light measurements 123 cm long 15 cm wide 5 cm tall 1:30 slope, or 6 degree slant. ''' light = solid.cube([5,15,123])- solid.translate([1,1,1])(solid.cube([5,13,121])) light = solid.color([.4,.4,.4])(light) tube1 = solid.color([1,1,1])(solid.translate([4,4,1])(solid.cylinder(r=2, h=121))) tube2 = solid.translate([0,6,0])(tube1) trough = solid.color([.4,.4,.4])(solid.translate([15,-2.5,0])(solid.cube([10,20,123]))) trough -= solid.translate([16,-1.5,-1])(solid.cube([8,18,125])) thole = solid.translate([14,7.5,10])(solid.rotate([0,90,0])(solid.cylinder(r=8, h = 5) )) tslots = [] for i in range(6): tslots += [solid.translate([0,0,i*18])(thole)] trough -= solid.translate([0,0,7])(join_list(tslots)) bucket = solid.translate([22.5,7.5,10])(solid.rotate([0,-90,0])(splanter())) bslots = []
### new subroutines ### out_file = make_output() rcling = 5 rbutt = 20 rail1 = solid.utils.arc( rad = rcling, start_degrees = 0, end_degrees = 180) rail1 -= solid.utils.arc( rad = rcling-1, start_degrees = 0, end_degrees = 180) rail2= solid.translate([0,0,6])(rail1) rail3 = solid.translate([0,0,6])(rail2) rails = solid.translate([0,0,4])(join_list([rail1,rail2, rail3])) rails += solid.translate([1,-.5,0])(solid.cube([4,1,20])) rails = solid.translate([30,20,-rcling+2])((solid.rotate([90,90,0])(rails))) rails = solid.color([0,0,0])(rails) buttress1 = solid.utils.arc( rad = rbutt, start_degrees = 0, end_degrees = 90) buttress1 -= solid.utils.arc( rad = rbutt-3, start_degrees = 0, end_degrees = 180) buttress1 += solid.translate([0,rbutt-2, -1.5])(solid.cube([rbutt, 2,3])) buttress2 = solid.translate([0,0,10])(buttress1) buttresses = buttress1 + buttress2 buttresses = solid.rotate([-90,-90,0])(solid.translate([0,0,5])(buttresses)) buttresses = solid.translate([30-rbutt-5,0,-rbutt+2])(buttresses) buttresses = solid.color([0,0,.8])(buttresses) board = solid.color([.4,.4,.4])(solid.cube([30,20,2])) object = [board, rails, buttresses]
v.spacer_height = s.var(45, comment='Height of the spacer, default is flush ' 'with the mounting surface.', end_comment='[45:90]') v.screw_head_radius = s.var(4, comment='Radius of hole to fix screw length.', end_comment='[2:4.5]') v.screw_radius = s.var(2, comment='Radius of screw thread.', end_comment='[1:4.5]') v.screw_length = s.var(10, comment='Length of thread to be inside spacer.', end_comment='[3:45]') v.head_hole_height = s.var('spacer_height - screw_length') body = s.cube(size=[spacer_depth, spacer_width, v.spacer_height]) slot = u.up(3)(s.cube(size=[spacer_depth, 10, 2])) slot_round = u.back(1)(u.up(2)( s.rotate(a=v.spacer_height, v=[1, 0, 0])( s.cube(size=[spacer_depth, 4, 4]) ) )) screw_hole = u.forward(5)( s.cylinder(r=v.screw_head_radius, h=v.head_hole_height, segments=32) + u.up(v.head_hole_height)( s.cylinder(r=v.screw_radius, h=v.screw_length, segments=32) ) )
pillar1 = solid.rotate([0,90,0])(solid.cylinder(r=2, h=35) ) pillar1 = pillar1 - solid.translate([-1,0,-3])(solid.cube([37,4, 8])) pillar2 = solid.rotate([180,0,0])(solid.translate([0,28])(pillar1)) return join_list([arch1, pillar1, pillar2]) ### ''' components and thoughts solid base to place books on solid back to prevent things falling behind it sides and roof are tiled in hexagons spaces to save on material 4 columns topped in a circular arch to bear most of the weight. ''' out_file = make_output() bord = 2 side = hexfield(4, bord, 4, 50, 50) side = solid.cube([40,30,2])-side frame = solid.cube([40,30,2])-solid.translate([2,2,-1])(solid.cube([36,26,4])) side = side + frame side2 =solid.rotate([0,-90,0])(side) side = solid.translate([30,0,0])(solid.rotate([0,-90,0])(side)) sides = solid.color([.1,.1,.9])(side+side2) base = solid.translate([-2,0,-2])(solid.cube([32,30,2])) top = solid.translate([0,0,40])(base) back = solid.translate([0,28,0])(solid.cube([28,2,38])) panels = solid.color([.25,.25,.15])(base+top+back) support1 = solid.rotate([0,-90,90])(ssupport()) support2 = solid.translate([0,7,0])(support1) support1 = solid.translate([0,21,0])(support1)
def shead(): head = solid.translate([-8,-13,181-27])(solid.cube([24,24,27])) return head