def __init__(self, cone, shoulder=None, thickness=None, threads_per_inch=6, offset=None): super(ThreadedBaseOutset, self).__init__(cone, shoulder, thickness) shoulder = to_mm(self.shoulder) thickness = to_mm(thickness, self.thickness) radius = to_mm(cone.inner_diameter / 2.) offset = to_mm(offset, to_inch(thickness)) tooth = to_mm(1. / threads_per_inch * sqrt(3) / 2.) self.cone = union()( (cone.cone - cylinder(h=offset, r=3 * radius)), down(shoulder)( self.threaded_male_column(length=shoulder + offset, diameter=radius * 2 - thickness * 2, threads_per_inch=threads_per_inch)), self.slice(cone.cone, thickness, offset=offset)) - down(shoulder - thickness)(cylinder( h=shoulder + offset, r=radius - thickness - tooth)) self.mate = down(shoulder)(cylinder(h=shoulder, r=radius)) + self.slice(cone.cone, offset) \ - down(shoulder)( self.threaded_female_column(length=shoulder + offset, diameter=radius * 2 - thickness * 2, threads_per_inch=threads_per_inch))
def __init__(self, cone, shoulder=None, thickness=None, threads_per_inch=6): super(ThreadedBaseFlat, self).__init__(cone, shoulder, thickness) shoulder = to_mm(self.shoulder) thickness = to_mm(self.thickness) radius = to_mm(cone.inner_diameter / 2.) tooth = to_mm(1. / threads_per_inch * sqrt(3) / 2.) self.cone = cone.cone + self.slice(cone.cone, thickness) + down(shoulder)( self.threaded_male_column(length=shoulder, diameter=radius * 2 - thickness * 2, threads_per_inch=threads_per_inch)) \ - down(shoulder - thickness)(cylinder(h=shoulder + thickness, r=radius - thickness - tooth)) self.mate = down(shoulder)(cylinder(h=shoulder, r=radius)) \ - down(shoulder)( self.threaded_female_column(length=shoulder + thickness, diameter=radius * 2 - thickness * 2, threads_per_inch=threads_per_inch)) sectioner = down(shoulder + self.epsilon)(cylinder( h=shoulder + self.epsilon, r=radius)) + cylinder( h=thickness / 2, r=radius - thickness - thickness / 2. - tooth) + cylinder( h=thickness, r=radius - thickness - thickness - tooth) self.cone_section1 = self.cone - sectioner self.cone_section2 = self.cone * sectioner
def __init__(self, cone, shoulder=None, thickness=None, cutout_width=None, cutout_length=None): super(HollowBaseCutout, self).__init__(cone, shoulder, thickness) cutout_width = to_mm(cutout_width, cone.inner_diameter * 0.3) cutout_length = to_mm(cutout_length, self.shoulder / 2.0) self.cutout_width = to_inch(cutout_width) self.cutout_length = to_inch(cutout_length) radius = to_mm(cone.inner_diameter / 2.) shoulder = to_mm(self.shoulder) thickness = to_mm(self.thickness) chord = sqrt(radius * radius - (radius - cutout_width**2)) self.cone = difference()(union()(self.cone, difference()( down(shoulder - cutout_length)(cylinder(h=thickness, r=radius)), translate([-radius, -radius, -shoulder + cutout_length])(cube([ radius * 2 - cutout_width - thickness, 2 * radius, cutout_length ]))), intersection()(translate( [radius - cutout_width - thickness, -chord, -shoulder])(cube([thickness, chord * 2, cutout_length])), down(shoulder)(cylinder(h=shoulder, r=radius)))), translate([ radius - cutout_width, -radius, -shoulder - 1 ])(cube([ cutout_width, 2 * radius, cutout_length + 1 ])))
def __init__(self, cone, shoulder=None, thickness=None, threads_per_inch=6, thread_height=None, thread_diameter=None, screw_length=None, screw_diameter=None, screw_size=None): super(ScrewInBaseWithScrewHole, self).__init__(cone, shoulder, thickness, threads_per_inch, thread_height, thread_diameter) radius = to_mm(cone.inner_diameter / 2) shoulder = to_mm(self.shoulder) thickness = to_mm(self.thickness) screw_length = to_mm(screw_length) screw_radius = to_mm(screw_diameter / 2) if not screw_radius: "get_screw_size" self.mate = difference()( union()(self.mate, down(shoulder)(cylinder(h=screw_length, r=screw_radius + thickness / 2.)), up(min(screw_length - shoulder - thickness, -thickness))(cylinder(h=thickness, r=radius))), down(shoulder)(cylinder(h=screw_length, r=screw_radius)))
def __init__(self, cone, shoulder=None, thickness=None, threads_per_inch=6, thread_height=None, thread_diameter=None): super(ScrewInBase, self).__init__(cone, shoulder, thickness) shoulder = to_mm(self.shoulder) thickness = to_mm(thickness, self.thickness) radius = to_mm(cone.inner_diameter / 2.) thread_height = to_mm(thread_height, self.length / 3) thread_diameter = to_mm(thread_diameter, cone.inner_diameter / 2.) tooth = to_mm(1. / threads_per_inch * sqrt(3) / 2.) self.cone = (cone.cone + self.slice( cone.cone, thread_height)) - self.threaded_female_column( length=thread_height, diameter=thread_diameter, threads_per_inch=threads_per_inch) self.mate = union()( down(shoulder)(cylinder(h=shoulder, r=radius)) - down(shoulder - thickness) (cylinder(h=shoulder - thickness * 2, r=radius - thickness)), self.threaded_male_column( length=thread_height, diameter=thread_diameter, threads_per_inch=threads_per_inch)) - down(thickness)(cylinder( h=thread_height + thickness, r=thread_diameter / 2 - thickness - tooth))
def __init__(self, cone, shoulder=None, thickness=None, screw_length=None, screw_diameter=None, screw_size=None): super(HollowBaseWithScrewHole, self).__init__(cone, shoulder, thickness) radius = cone.inner_diameter * MM2IN / 2 shoulder = self.shoulder * MM2IN thickness = MM2IN * self.thickness screw_length = screw_length * MM2IN screw_radius = screw_diameter * MM2IN / 2 if not screw_radius: "get_screw_size" self.cone = difference()( union()(self.cone, down(shoulder)(cylinder(h=screw_length, r=screw_radius + thickness / 2.)), up(min(screw_length - shoulder - thickness, -thickness))(cylinder(h=thickness, r=radius))), down(shoulder)(cylinder(h=screw_length, r=screw_radius)))
def final(): return down(1)(block()) \ - left(y / 2)( \ right(21)(down(5.5)(usbconn())) \ + right(4)(down(2)(button())) \ + right(14)(arduino()) \ )
def __init__(self, cone, shoulder=None, thickness=None, upper_tpi=6, lower_tpi=4, offset=None, thread_height=None, thread_diameter=None): super(ThreadedBaseOutsetScrewInBase, self).__init__(cone, shoulder, thickness) shoulder = to_mm(self.shoulder) thickness = to_mm(thickness, self.thickness) radius = to_mm(cone.inner_diameter / 2.) offset = to_mm(offset, to_inch(thickness)) upper_tooth = to_mm(1. / upper_tpi * sqrt(3) / 2.) lower_tooth = to_mm(1. / lower_tpi * sqrt(3) / 2.) thread_height = to_mm(thread_height, self.length / 3) thread_diameter = to_mm(thread_diameter, cone.inner_diameter / 2.) self.cone = difference()( union()((cone.cone - cylinder(h=offset, r=3 * radius)), color("red")(self.slice(cone.cone, thread_height, offset))), up(offset - self.epsilon)(self.threaded_female_column( length=thread_height + 2 * self.epsilon, diameter=thread_diameter, threads_per_inch=upper_tpi)), cylinder(h=to_mm(0.25), r=radius - thickness)) core_radius = min(thread_diameter / 2 - thickness - upper_tooth, radius - thickness - lower_tooth) lower_thread = down(shoulder)(self.threaded_male_column( length=shoulder + offset, diameter=radius * 2 - thickness * 2., threads_per_inch=lower_tpi)) upper_thread = up(offset)(self.threaded_male_column( length=thread_height, diameter=thread_diameter, threads_per_inch=upper_tpi)) self.center_mate = upper_thread + lower_thread + cylinder( h=thickness, r=radius - thickness) - down(shoulder - thickness)( cylinder(h=shoulder + offset + thread_height, r=core_radius)) self.mate = difference()( down(shoulder)(cylinder(h=shoulder, r=radius)) + self.slice(cone.cone, offset), down(shoulder)(self.threaded_female_column( length=shoulder + offset, diameter=radius * 2 - thickness * 2, threads_per_inch=lower_tpi)), cylinder(h=thickness, r=radius - thickness))
def __init__(self, cone, shoulder=None, thickness=None): super(HollowBase, self).__init__(cone, shoulder, thickness) if not self.shoulder: raise ValueError("Shoulder must be specified") if not self.thickness: raise ValueError("Thickness must be specified") radius = cone.inner_diameter * MM2IN / 2 thickness = MM2IN * self.thickness shoulder = self.shoulder * MM2IN self.cone = cone.cone + down(shoulder)(cylinder( h=shoulder, r=radius)) - down(shoulder - thickness)(cylinder( h=shoulder - thickness, r=radius - thickness))
def volume(): base = spu.up(base_height / 2.)( sp.cube([width, base_length, base_height], center=True) ) mounting_holes = spu.down(1)( place_at_centres( [0, mounting_hole_centres], sp.cylinder(d=mounting_hole_diameter, h=base_height + 2) ) ) base -= mounting_holes bearing = spu.up(shaft_height)( sp.rotate([0, 90, 0])( sp.cylinder(d=60, h=width, center=True) - sp.cylinder(d=shaft_diameter, h=width + 1, center=True) ) ) return sp.union()( base, bearing, )
def index_card_holder( width, length=DEFAULT_CARD_HOLDER_LENGTH, height=DEFAULT_CARD_HOLDER_HEIGHT, thickness=DEFAULT_CARD_HOLDER_THICKNESS, cut_out_elevation=DEFAULT_CUT_OUT_ELEVATION, front_cut_length=DEFAULT_FRONT_CUT_LENGTH, back_cut_length=DEFAULT_BACK_CUT_LENGTH, margin=DEFAULT_MARGIN, ): shape = [width, length, height] box = open_top_box(shape, thickness) cutouts = box_cut_out( shape, thickness, elevation=cut_out_elevation, front_length=front_cut_length, back_length=back_cut_length, ) single_peg = down(DEFAULT_PEG_HOLE_DIAMETER)( solid_peg(diameter=DEFAULT_PEG_HOLE_DIAMETER)) holes = bottom_pegs(single_peg, shape, margin) \ + back_pegs(single_peg, shape, margin) \ + side_pegs(single_peg, shape, margin) result = box - holes if cutouts: result -= cutouts return result
def assembly(): axle = sp.color('red')( round_bar.volume( diameter=axle_diameter, length=axle_length, center=True ) ) sprocket_assy = spu.up(sprocket_pos)( sp.color('green')(sp.rotate((180, 0, 0))(drive_sprocket.assembly())) ) brake_disc_assy = spu.down(brake_disc_pos)( sp.color('blue')(brake_disc.assembly()) ) wheels = [ sp.rotate([0, a, 0])( spu.left(wheel_centre_distance / 2.)( sp.color('cyan')(wheel.assembly()) ) ) for a in [0, 180] ] return sp.union()( sp.rotate([0, 90, 0])(sp.union()( axle, sprocket_assy, brake_disc_assy, )), wheels, )
def assembly(): column = tube.volume(diameter=column_diameter, wall_thickness=2., length=column_length) return sp.union()( spu.up(column_length)( spu.up(wheel.plate_thickness / 2.)( sp.color('red')(wheel.volume()), spu.up(wheel.plate_thickness / 2.)( sp.color('green')(instrument_panel.assembly()) ), sp.translate((150, 80))( sp.rotate((0., 60., 0.))( sp.color('blue')(throttle.assembly()) ) ), ), sp.rotate((0, 180, 0))(sp.color('cyan')(wheel_mount.volume())), ), sp.color('magenta')(column), spu.up(440.)(sp.color('purple')(column_mount.upper.assembly())), spu.up(60.)(sp.color('grey')(column_mount.lower.assembly())), sp.rotate((0, 0, 0))( sp.color('orange')(arm_mount.volume()), sp.color('pink')(spu.down(arm.thickness)(arm.volume())), ), )
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 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 extrude_example_transforms() -> OpenSCADObject: path_rad = PATH_RAD height = 2 * SHAPE_RAD num_steps = 120 shape = circle_points(rad=path_rad, num_points=120) path = [Point3(0, 0, i) for i in frange(0, height, num_steps=num_steps)] max_rotation = radians(15) max_z_displacement = height / 10 up = Vector3(0, 0, 1) # The transforms argument is powerful. # Each point in the entire extrusion will call this function with unique arguments: # -- `path_norm` in [0, 1] specifying how far along in the extrusion a point's loop is # -- `loop_norm` in [0, 1] specifying where in its loop a point is. def point_trans(point: Point3, path_norm: float, loop_norm: float) -> Point3: # scale the point from 1x to 2x in the course of the # extrusion, scale = 1 + path_norm * path_norm / 2 p = scale * point # Rotate the points sinusoidally up to max_rotation p = p.rotate_around(up, max_rotation * sin(tau * path_norm)) # Oscillate z values sinusoidally, growing from # 0 magnitude to max_z_displacement max_z = lerp(path_norm, 0, 1, 0, max_z_displacement) angle = lerp(loop_norm, 0, 1, 0, 10 * tau) p.z += max_z * sin(angle) return p no_trans = make_label('No Transform') no_trans += down(height / 2)(extrude_along_path(shape, path, cap_ends=False)) # We can pass transforms a single function that will be called on all points, # or pass a list with a transform function for each point along path arb_trans = make_label('Arbitrary Transform') arb_trans += down(height / 2)(extrude_along_path(shape, path, transforms=[point_trans], cap_ends=False)) return no_trans + right(3 * path_rad)(arb_trans)
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 makestack(dia): stack = union()(cylinder(d=dia + WALL * 2, h=TRAY_H - FLOOR) - up(FLOOR)(cylinder(d=dia, h=TRAY_H))) hole_pcg = 0.7 stack -= hole()(down(1)(cylinder(d=dia * hole_pcg, h=TRAY_H))) stack -= hole()(translate([-dia / 2 - WALL, -dia / 2 * hole_pcg, -1])(cube( [dia / 2 + WALL, dia * hole_pcg, TRAY_H * 3]))) return stack
def volume(): lip = spu.down(lip_width)(sp.cylinder(d=lip_diameter, h=lip_width)) face_plate = sp.cylinder(d=face_diameter, h=face_width) # Drill and tap holes for axle key screws as appropriate axle_clamp = sp.cylinder(d=clamp_diameter, h=face_width + clamp_width) axle = spu.down(lip_width + 1)( sp.cylinder( d=axle_diameter, h=lip_width + face_width + clamp_width + 2 ) ) # Drill and tap holes for brake disc mounting as appropriate mounting_holes = sprocket.place_mounting_holes(drilled_hole.volume(6)) return sp.union()(lip, face_plate, axle_clamp) - axle - mounting_holes
def make_lamp_scad(filename, bright_stars, stick_figures, radius, thickness): """Use bright stars and input arguements to create the scad lamp.""" # Create a main shell to be inscribed on shell = solid.difference()(solid.sphere(r=radius), solid.sphere(r=radius - thickness / 2), sutil.down(radius)(solid.cube(2 * radius, center=True))) # Add stick figures i_shell = make_stick_figures(shell, stick_figures, radius, 0.5) # i_shell = shell # Add another layer of shell (without inscription) c_shell = solid.difference()(solid.sphere(r=radius - thickness / 2), solid.sphere(r=radius - thickness), sutil.down(radius)(solid.cube(2 * radius, center=True))) # Add stars to both the i_shell and c_shell i_stars = solid.difference() i_stars.add(i_shell) for _, az, alt, _, rad in bright_stars: i_stars.add( solid.rotate(a=[0, -1 * (90 - alt), az])(solid.cylinder(rad, h=radius))) c_stars = solid.difference() c_stars.add(c_shell) for _, az, alt, _, rad in bright_stars: c_stars.add( solid.rotate(a=[0, -1 * (90 - alt), az])(solid.cylinder(rad, h=radius))) complete = solid.union()(i_stars, c_stars) # Render to file solid.scad_render_to_file(i_stars, filename + '-inscription' + '.scad', file_header='$fn = %s;' % SEGMENTS) solid.scad_render_to_file(c_stars, filename + '-stars' + '.scad', file_header='$fn = %s;' % SEGMENTS) solid.scad_render_to_file(complete, filename + '-complete' + '.scad', file_header='$fn = %s;' % SEGMENTS)
def makeTube(idi, odi, hi, transl, half, eps): '''Make a tube or half-tube. idi, odi = inner and outer diameters; hi= height; transl = [x,y,z] translation vector; half = whole or half indicator: -1=right half, 0=whole, +1=left half. ''' loss = cylinder(d=idi, h=hi+2*eps) tube = cylinder(d=odi, h=hi) - hole()(down(eps)(loss)) if half: block = cube([odi/2, odi+2*eps, hi+2*eps]) dx = -(odi+eps)/2 if half < 0 else 0 tube -= translate([dx, -(eps+odi)/2,0])(block) return translate(transl)(tube)
def volume(): face_plate = sp.cylinder(d=face_diameter, h=face_width) # Drill and tap holes for column key screws as appropriate column_clamp = sp.cylinder(d=clamp_diameter, h=length) column = spu.down(1)(sp.cylinder(d=column_diameter, h=length + 2)) mounting_holes = arm.place_mounting_holes( drilled_hole.volume(arm.mounting_hole_diameter)) return sp.union()(face_plate, column_clamp) - column - mounting_holes
def assembly(): main_bar = sp.rotate((0, 90, 0))( box_section.volume(length=bar_length, center=True) ) return sp.union()( sp.color('red')(main_bar), spu.down(0.5 * d)( mount(), sp.rotate((0, 0, 180))(mount()), ), )
def volume(): extrusion = sp.rotate((0, 0, 0))(sp.union()( spu.down(length)(sp.linear_extrude(length)(projection_main())), spu.down(10.)(sp.linear_extrude(10.)(projection_fan())), )) rotated_extrusion = sp.rotate( (90, 0, 0))(spu.forward(fan.size[1] / 2.)(extrusion)) tray_mounting_holes = sp.linear_extrude(10.)(mounting_holes(6)) def cable_cutout(position, diameter): return sp.translate(position)(sp.rotate( (0, 90, 0))(sp.cylinder(d=diameter, h=outer_wall_thickness + 1., center=True))) cable_cutouts = sp.union()( cable_cutout((-33, 20, 15), 15.), cable_cutout((-33, 60, 10), 12.), ) return rotated_extrusion - tray_mounting_holes - cable_cutouts
def hole_set(): diameter_list = [1, 2, 3, 4, 5, 6, 7, 8] @ mm offset = -0.5 * PLATTER_LENGTH hole_list = [] for diameter in diameter_list: radius = 0.5 * diameter offset += radius + HOLE_SPACING hole_list.append( down(HOLE_EXTENSION)(forward(offset)(cylinder(r=radius, h=HOLE_HEIGHT, segments=16)))) offset += radius print(offset) return union()(hole_list)
def __init__(self, cone, shoulder=None, thickness=None, threads_per_inch=6): super(ThreadedBaseInset, self).__init__(cone, shoulder, thickness) shoulder = to_mm(self.shoulder) thickness = to_mm(self.thickness) radius = to_mm(cone.inner_diameter / 2.) tooth = to_mm(1. / threads_per_inch * sqrt(3) / 2.) self.cone = difference()( union()(cone.cone, down(thickness)(cylinder(h=thickness, r=radius)), down(shoulder)(self.threaded_male_column( length=shoulder, diameter=radius * 2 - thickness * 2, threads_per_inch=threads_per_inch))), down(shoulder - thickness)(cylinder(h=shoulder, r=radius - thickness - tooth))) self.mate = down(shoulder)(cylinder(h=shoulder - thickness, r=radius)) \ - down(shoulder)(self.threaded_female_column(length=shoulder, diameter=radius * 2 - thickness * 2, threads_per_inch=threads_per_inch))
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 corner_holes(): hole = down(0.1 * mm)(cylinder(r=CORNER_HOLE_RADIUS, h=HOLE_HEIGHT, segments=16)) return union()([ right(dx * CORNER_HOLE_X_OFFSET)(forward( dy * CORNER_HOLE_Y_OFFSET)(hole)) for dx, dy in [ (-1, -1), (-1, 1), (-1, 0), (1, 0), (1, -1), (1, 1), ] ])
def process(outline_file, solderpaste_file, stencil_thickness=0.2, include_ledge=True, ledge_height=1.2, ledge_gap=0.0, increase_hole_size_by=0.0): outline_shape = create_outline_shape(outline_file) cutout_polygon = create_cutouts( solderpaste_file, increase_hole_size_by=increase_hole_size_by) if ledge_gap: # Add a gap between the ledge and the stencil outline_shape = offset_shape(outline_shape, ledge_gap) outline_polygon = polygon(outline_shape) stencil = linear_extrude(height=stencil_thickness)(outline_polygon - cutout_polygon) if include_ledge: ledge_shape = offset_shape(outline_shape, 1.2) ledge_polygon = polygon(ledge_shape) - outline_polygon # Cut the ledge in half by taking the bounding box of the outline, cutting it in half # and removing the resulting shape from the ledge shape # We always leave the longer side of the ledge intact so we don't end up with a tiny ledge. cutter = bounding_box(ledge_shape) height = abs(cutter[1][1] - cutter[0][1]) width = abs(cutter[0][0] - cutter[3][0]) if width > height: cutter[1][1] -= height / 2 cutter[2][1] -= height / 2 else: cutter[2][0] -= width / 2 cutter[3][0] -= width / 2 ledge_polygon = ledge_polygon - polygon(cutter) ledge = utils.down(ledge_height - stencil_thickness)( linear_extrude(height=ledge_height)(ledge_polygon)) stencil = ledge + stencil # Rotate the stencil to make it printable stencil = rotate(a=180, v=[1, 0, 0])(stencil) return scad_render(stencil)
def process(outline_file, solderpaste_file, stencil_thickness=0.2, include_ledge=True, ledge_height=1.2, ledge_gap=0.0, increase_hole_size_by=0.0): outline_shape = create_outline_shape(outline_file) cutout_polygon = create_cutouts(solderpaste_file, increase_hole_size_by=increase_hole_size_by) if ledge_gap: # Add a gap between the ledge and the stencil outline_shape = offset_shape(outline_shape, ledge_gap) outline_polygon = polygon(outline_shape) stencil = linear_extrude(height=stencil_thickness)(outline_polygon - cutout_polygon) if include_ledge: ledge_shape = offset_shape(outline_shape, 1.2) ledge_polygon = polygon(ledge_shape) - outline_polygon # Cut the ledge in half by taking the bounding box of the outline, cutting it in half # and removing the resulting shape from the ledge shape # We always leave the longer side of the ledge intact so we don't end up with a tiny ledge. cutter = bounding_box(ledge_shape) height = abs(cutter[1][1] - cutter[0][1]) width = abs(cutter[0][0] - cutter[3][0]) if width > height: cutter[1][1] -= height/2 cutter[2][1] -= height/2 else: cutter[2][0] -= width/2 cutter[3][0] -= width/2 ledge_polygon = ledge_polygon - polygon(cutter) ledge = utils.down( ledge_height - stencil_thickness )( linear_extrude(height=ledge_height)(ledge_polygon) ) stencil = ledge + stencil # Rotate the stencil to make it printable stencil = rotate(a=180, v=[1, 0, 0])(stencil) return scad_render(stencil)