def box(width, height, depth, half=False, topbox=False): obj = sp.part() left = sp.cube([thickness, depth, height]) right = left.copy() right = spu.right(width - thickness)(right) obj += left + right top = sp.cube([width - 2 * thickness, depth, thickness]) top = spu.right(thickness)(top) if (half): ha = spu.up(height / 2 - thickness / 2)(top) obj += ha h = sp.cylinder(holes / 2, thickness + 10) top -= sp.translate([50, 50, 0])(h) top -= sp.translate([width - 50, 50, 0])(h) top -= sp.translate([width - 50, depth - 50, 0])(h) top -= sp.translate([50, depth - 50, 0])(h) bottom = top top = spu.up(height - thickness)(top) obj += top + bottom if (not topbox): sta = sp.cube([width * 3 / 4, thickness, 100]) sta = sp.rotate([0, -45, 0])(sta) cutout = sp.cube([width, depth, height]) cutout = spu.down(height / 4)(spu.left(width / 4)(cutout)) cutout -= spu.back(5)(sp.cube( [width / 2 - thickness, depth + 10, height / 2 - thickness])) sta -= spu.back(depth / 2)(cutout) sta = spu.right(thickness)(sta) sta += spu.right(width)(sp.mirror([1, 0, 0])(sta)) sta += sp.mirror([0, 0, 1])(sta) sta = spu.forward(depth - thickness)(sta) obj += (spu.up(height / 2)(sta) - ha) if (half and topbox): window = sp.cube( [width - 2 * thickness, thickness, height / 2 - 1.5 * thickness]) window = sp.translate([thickness, 0, thickness])(window) obj += spu.up(height / 2 - thickness / 2)(window) return obj
def getOblongArm(self): '''Return a SolidPython object modeling an oblong arm (per specs in ArmParams object) bounded by four arcs of circles. ''' eps = 0.01 p, q, s, t, u, w = self.p, self.q, self.s, self.t, self.u, self.w r1, r2 = p - s, q - t domis, chi, dhi = 2 * max(r1, r2), 1.1, -0.05 arc1 = back(r1 + s)(cylinder(r=r1, h=1)) arc2 = back(q - r2)(cylinder(r=r2, h=1)) rl, vl, p1, p2 = self.solveArcArc(p, q, s, t, u) rr, vr, p3, p4 = self.solveArcArc(p, q, s, t, w) rightcircle = color(Green)(translate([u, -vl, dhi])(cylinder(r=rl, h=chi))) leftcircle = color(Red)(translate([w, -vr, dhi])(cylinder(r=rr, h=chi))) yrhi, yrlo, ylhi, yllo = p1[1], p2[1], p3[1], p4[1] xr, xl = min(p1[0], p2[0]), max(p3[0], p4[0]) dominol = translate([xl - domis, -yllo, dhi])(cube([domis, yllo - ylhi, chi])) dominor = translate([xr, -yrlo, dhi])(cube([domis, yrlo - yrhi, chi])) return (arc1 * arc2 - dominol - dominor) + rightcircle + leftcircle
def key_lettering(): messages = ["LeRoy", "Dental"] layout = union()([ forward((index - 0.5) * -LETTER_HEIGHT)(text(message, halign='center', valign='center')) for index, message in enumerate(messages) ]) lettering = up(THICKNESS / 2 - LETTERING_RISE)( linear_extrude(height=2 * LETTERING_RISE)(scale([0.8, 0.8, 1])(layout))) return back(HANDLE_DIAMETER / 2)(lettering)
def makeBridges(rail, span): BridgeN = rail.Bridges BridgeOffset = rail.BridgeOffset BridgeWide = rail.BridgeWide BridgeStep = (rail.CapLen-2*rail.BridgeOffset)/max(1,BridgeN-1) CapWide = rail.CapWide asm = None proto = cube([BridgeWide, span, rail.CapThik]) proto = back(span-CapWide)(proto) for k in range(BridgeN): b = right(BridgeOffset+k*BridgeStep-BridgeWide/2)(proto) asm = b + asm if asm else b return color(Cyan)(asm) if asm else None
def ueyeholder(): """ueyeholder creates a holder for an ueye camera A holder for an uEye camera to view upward. The uEye camera cannot look upward due its connector on the back. This design solves this problem via a cubical enclosure. """ #### UEYE cubical dimension margin = 0.3 size_x = 34 # mm size_y = 32 # mm size_z = 34.6 # mm ### UEYE screw screw_d = 3 # mm screw_z = 30.4 # sep z-direction screw_z -= screw_d screw_ytop = 19.8 # mm screw_ytop -= screw_d screw_ybottom = 21.8 screw_ybottom -= screw_d screw_zoff = 1.3 + screw_d / 2 connector_z = 18 # mm connector_x = 16.2 # mm #### # box # camera is pushed in from bottom holder = cube([ size_x + 2 * THCKW + margin, size_y + 2 * THCKW + margin, size_z + THCKW + connector_z + margin ]) holder -= translate([THCKW, THCKW, THCKW])(cube([ size_x + margin, size_y + margin, size_z + THCKW + connector_z + margin ])) # 4 screw holes socket = cylinder(h=size_x + 2 * THCKW, r=screw_d / 2, segments=SGM) socket = rotate([0, 90, 0])(socket) sockets = socket + forward(screw_ybottom)(socket) temp = (screw_ytop - screw_ybottom) * 0.5 sockets += up(screw_z)(back(temp)(socket) + forward(screw_ytop - temp)(socket)) # substraction prep sockets holder -= translate([ 0, (size_y - screw_ybottom) * 0.5 + THCKW + 0.5 * margin, screw_zoff + THCKW + connector_z + 0.5 * margin ])(sockets) # space connector holder -= translate([THCKW + 0.5 * (size_x - connector_x), 0, THCKW])(cube( [connector_x, THCKW, size_z + THCKW + connector_z])) return holder
def laserbase(laserheight): """laserabase creates the basis for the laser with ventilation wall The laserbase is in the XY plane at quadrant 1. One corner is at the origin. The width is parallel to the x-axis. The laser was provided by Odic Force, productid OFL510-1. The padheight is laser height- 16.5 The laserbundle travels in the +x direction and departs from the center, that is 15 mm. param: laserheight: the desired height of the laser """ # The laser tube is at 8 mm from bottom. # The laser tube has a diameter of 17 mm # The laser is at 8 + 17 * 0.5 - 1 = 16.5 mm (shim of 1 mm needed) # The laser base is 30x60 mm, which was made # 30x75 mm to make room for the ventilator # PARAMETERS height = laserheight - 15.5 # [mm], xdisp = 48.5 # [mm], x-displacement screws ydisp = 16 # [mm], y-displacement screws r_shaft = 2 # [mm], shaft radius screws h_head = 5 # [mm], height shaft head r_head = 3.5 # [mm], top radius screws tspile = 4 # [mm], y-thickness ventilation spile hspile = 25 # [mm], height ventilation spile length = 75 # [mm], x-direction length laser width = 30 # [mm], y-direction width laser screw_offst = 7 # [mm], screw offset +x-edge # MINIMAL MATERIAL BASE screws = screw(r_head, h_head, r_shaft, height) + right(xdisp)(screw( r_head, h_head, r_shaft, height)) spiegel = forward(ydisp / 2)(mirror([0, 1, 0])(back(ydisp / 2)(screws))) screws += spiegel base = translate([length - xdisp - screw_offst, (width - ydisp) / 2, 0])(screws) # ventilation wall # spile spile = up(height)(cube([THICK_WALL, tspile, hspile])) nofspiles = ceil((width) / (tspile * 2)) # shift base base = right(THICK_WALL)(base) # add wall base += cube([THICK_WALL, width, HEIGHT_WALL]) # create pockets for i in range(0, nofspiles): base -= hole()(forward(i * 2 * tspile + THICK_WALL)(spile)) return base
def mounting_posts(self, distance_from_surface): positioning_post_height = distance_from_surface + self.board_thickness + 3 positioning_post = forward(1)( up(positioning_post_height / 2)( cube((4, 4, positioning_post_height), center=True) ) ) return ( back(self.board_length + m2_shaft_radius + FUDGE)( mount_post_m2(distance_from_surface) ) + left(7)(positioning_post) + right(7)(positioning_post) )
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 projection(): from . import arm_mount magic_1 = (arm_mount.face_diameter / 2.) bar = sp.translate( (0., -magic_1, 0.))(plate.projection(size=(width, length + magic_1))) mounting_holes = place_mounting_holes( drilled_hole.projection(mounting_hole_diameter)) tie_rod_holes = spu.back(tie_rod_hole_offset)(place_at_centres( (tie_rod_hole_centres, 0.), drilled_hole.projection(tie_rod_hole_diameter))) return bar - mounting_holes - tie_rod_holes
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 assembly(): x_bars = sp.rotate([0, 90, 0])( [ spu.back(d)( box_section.volume( length=outer * 2. + box_section.default_size[0], center=True ) ) for d in split_centers(seat_depth) ] ) y_bars = sp.rotate([90, 0, 0])( [ spu.left(d)( box_section.volume( length=seat_depth - box_section.default_size[0], center=True ) ) for d in [-outer, outer] ] ) _mount_bar_centres = (mount_bar_centres - box_section.default_size[0]) / 2. mount_bars = spu.up(box_section.default_size[0])( sp.rotate([90, 0, 0])( [ spu.left(d)( box_section.volume( length=seat_depth + box_section.default_size[0], center=True ) ) for d in [-_mount_bar_centres, _mount_bar_centres] ] ) ) frame = sp.union()( sp.color('red')(x_bars), sp.color('green')(y_bars), sp.color('blue')(mount_bars), ) return frame
def assembly(): magic_1 = inner_length - 100. return sp.union()( sp.color('red')(lower_frame.assembly()), sp.color('green')(sp.translate((0, 180, 160))(seat_mount.assembly())), sp.color('blue')( sp.translate( ( 0, rear_axle_position, -(box_section.default_size[0] / 2.) - rear_axle_bearing.shaft_height ) )(rear_axle.assembly()) ), sp.color('magenta')( sp.translate((inner + (box_section.default_size[0] / 2.), 300, 0))( sp.rotate((90, 0, -90))(motor.assembly()) ) ), sp.color('pink')( spu.forward(inner_length + box_section.default_size[0])( sp.rotate((90, 0, 180))(bumpers.front.assembly()) ), spu.back(box_section.default_size[1])( sp.rotate((90, 0, 0))(bumpers.rear.assembly()) ), ), sp.color('lime')( sp.translate( (-inner + (box_section.default_size[0] / 2.) + 1., magic_1, 0) )(brake_pedal.assembly()) ), sp.color('orange')( sp.translate((0, 1100., 0))( sp.rotate((50., 0, 0))(steering.assembly()) ) ), sp.color('brown')( sp.translate((0, 75, box_section.default_size[0] / 2.))( electronics_tray.assembly() ) ), )
def ur_corner_clipper_clipper(): return right(SHIFTINESS)( back(SHIFTINESS)( grounded_cube([PLATTER_WIDTH, PLATTER_LENGTH, HOLE_HEIGHT])))
def x_side_slots(): slot = rounded_platter([TOP_SLOT_LENGTH, SIDE_SLOT_WIDTH, HOLE_HEIGHT], SIDE_SLOT_RADIUS) return forward(CORNER_HOLE_Y_OFFSET)(slot) + back(CORNER_HOLE_Y_OFFSET)(slot)
def make_hole(self): body = square([self.width, self.height]) layer_width = (phone_width + 2 * radius) moved_right = right(layer_width / 2 - self.width / 2)(body) moved_down = back(self.height / 2 + self.y_adjust)(moved_right) return moved_down
def holes(): return sp.rotate((0., 0., 180.))(sp.union()( light.holes(), spu.back((light.diameter / 2.) + 9.)(mount.holes()), ))
def horizontal_beams(self, width, elevation): cross_beam = up(elevation - self.beam_size)( grounded_cube([width, self.beam_size, self.beam_size]) ) return forward(self.horizontal_beam_offset_y)(cross_beam) + back(self.horizontal_beam_offset_y)(cross_beam)
def cleat_opening(): return down(DEFAULT_CONNECTOR_BLOCK_THICKNESS)(back( SWITCH_CLEAT_LENGTH / 2)(right(SWITCH_CLEAT_OFFSET)(cube([ SWITCH_CLEAT_WIDTH, SWITCH_CLEAT_LENGTH, 3 * DEFAULT_CONNECTOR_BLOCK_THICKNESS ]))))
def renderparts(): """ renderparts renders all the subcomponents of the box placed in separate function to prevent collision """ print_screw = screw(3, 2, 2, 10) # create a printable screw scad_render_to_file(print_screw, 'print_screw.scad') print_lasershim = lasershim(1) scad_render_to_file(print_lasershim, 'shim.scad') print_laserbase = laserbase(LASER_HEIGHT) scad_render_to_file(print_laserbase, 'laserbase.scad') fasten = cable_fasten(TIE_HEIGHT, TIE_WIDTH, THICK_WALL, True) scad_render_to_file(fasten, 'cable_fasten.scad') print_insert = threadedinsert(True, THICK_WALL, 4.0, 5.8) scad_render_to_file(print_insert, 'print_insert.scad') print_polygonshim = polygonshim(1) scad_render_to_file(print_polygonshim, 'polygonshim.scad') print_polygonbase = polygonbase(LASER_HEIGHT) scad_render_to_file(print_polygonbase, 'polygonbase.scad') print_boxmount = boxmount() scad_render_to_file(print_boxmount, 'boxmount.scad') mirror_mount_down = mirrormount(True, LASER_HEIGHT) mirror_mount_down += back(20)(cube([30, 50, 2])) scad_render_to_file(mirror_mount_down, 'mirror_mount_down.scad') topdownr = topbox(True, False) scad_render_to_file(topdownr, 'topboxdown.scad') topupr = topbox(False, False) scad_render_to_file(topupr, 'topboxup.scad') top_height = 4 # top height screw in mm top_r = 3.5 # top r screw in mm for screw head shaft_r = 2 # screw radius offset = 5 screw_length = THICK_WALL + offset print_hscrew = hscrew(top_r, top_height, shaft_r, 5 + THICK_WALL) scad_render_to_file(print_hscrew, 'hscrew.scad') print_xulabase = xulaconnector() scad_render_to_file(print_xulabase, "xulabase.scad") # logo = createlogo() # scad_render_to_file(logo, 'logo.scad') panelmountr = panelmountmini() scad_render_to_file(panelmountr, 'panelmountmini.scad') onderkantdown = onderkantbox(True) scad_render_to_file(onderkantdown, 'onderkantdown.scad') onderkantup = onderkantbox(False) scad_render_to_file(onderkantup, 'onderkantup.scad')
def holes(): return spu.back(40.)(drilled_hole.projection(10.)),
def top_clipper(): return back(SHIFTINESS)(grounded_cube([2 * PLATTER_WIDTH, PLATTER_LENGTH, HOLE_HEIGHT]))
def function_row(width_units, wall_height=default_wall_height, margin_length=0, margin_width=0): x_grid_size = mount_width + switch_spacing y_grid_size = mount_length + switch_spacing case = key_grid_tester( 1, width_units, wall_height=wall_height, margin_length=margin_length, margin_width=margin_width, ) wall_length, wall_width = key_grid_tester_wall_dimensions( 1, width_units, wall_height, margin_length, margin_width) board_left = wall_width / 2 - 70 board_up = 10 board_forward = wall_length / 2 - wall_thickness def position_board(part): if 1 == 1: return left(board_left)(down(1)(rotate((0, 0, 90))(part))) return left(board_left)(up(board_up)(forward(board_forward)(rotate( (0, -90, 90))(part)))) control_box_case, control_box_cutout = control_box(wall_length, wall_width, wall_height) split_offset = x_grid_size / 2 if width_units % 2 else 0 def position_mounting_points(part): x_offset = wall_width / 2 - wall_thickness y_offset = wall_length / 2 - wall_thickness return (left(x_offset)(forward(y_offset)(part)) + right(x_offset)(forward(y_offset)(part)) + left(x_offset)(back(y_offset)(part)) + right(x_offset)(back(y_offset)(part)) + right(split_offset - wall_thickness)(forward(y_offset)(part)) + right(split_offset + wall_thickness)(forward(y_offset)(part)) + right(split_offset - wall_thickness)(back(y_offset)(part)) + right(split_offset + wall_thickness)(back(y_offset)(part))) full_case = ( case - control_box_cutout + control_box_case - left(wall_width / 2 - 20)(cube( (15, 1 * y_grid_size * 2, 23 * 2), center=True)) #- position_board(pro_micro.board_profile(3)) + position_mounting_points( cylinder(wall_thickness * 2 / 3, wall_height, segments=16)) - position_mounting_points(down(2)(cylinder_outer(m2_shaft_radius, 10)))) big_block = cube((200, 200, 200), center=True) alignment_tab = cube( (wall_thickness, wall_thickness / 2, wall_height - wall_thickness), center=True) alignment_tabs = right(split_offset)(up( (wall_height - wall_thickness) / 2)(forward(wall_length / 2 - wall_thickness)(alignment_tab) + back(wall_length / 2 - wall_thickness)(alignment_tab))) return ( (full_case - right(100 + split_offset)(big_block) + alignment_tabs), (full_case - left(100 - split_offset)(big_block) - alignment_tabs), )
def assembly(): return sp.rotate((0., 0., 180.))(sp.union()( sp.color("red")(spu.up(15.)(light.volume())), sp.color("green")(spu.back((light.diameter / 2.) + 9.)( mount.volume())), ))
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))) screw_hole_1 = u.right(screw_offset)(screw_hole) screw_hole_2 = u.right(screw_offset_2)(screw_hole) wire_run = u.up(20)(s.cube(size=[spacer_depth, 4, 9])) final = body - slot - slot_round - screw_hole_1 - screw_hole_2 - wire_run s.scad_render_to_file(final, __file__.replace('.py', '.scad'), variables=v)
def posts(self): post = cylinder(r=self.crown_radius, h=self.post_height, segments=16) post_pair = forward(self.wall_y_offset)(post) + back( self.wall_y_offset)(post) return left(self.wall_x_offset)(post_pair) + right( self.wall_x_offset)(post_pair)
def back_wall(self): return back(self.wall_y_offset)(self.main_wall())
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) ) ) screw_hole_1 = u.right(screw_offset)(screw_hole) screw_hole_2 = u.right(screw_offset_2)(screw_hole) wire_run = u.up(20)(s.cube(size=[spacer_depth, 4, 9]))
def back(self, d: float) -> "SolidBuilder": self._center_y -= d self._origin_y -= d self._oso = back(d)(self._oso) return self
def toothpaste_key(): non_lettering = back(1 * mm)(key_shaft()) + key_handle() if DO_SMUDGE: non_lettering = smudge(SMUDGE, non_lettering) key = up(THICKNESS / 2)(non_lettering + key_lettering()) return rotate(-90, [0, 0, 1])(key)
def projection(): return spu.back(y_offset)(plate.projection(size)) - common.bearing_holes()