def nut(screw_type: str = 'm3') -> OpenSCADObject: dims = screw_dimensions[screw_type.lower()] outer_rad = dims['nut_outer_diam'] inner_rad = dims['screw_outer_diam'] ret = difference()(circle(outer_rad, segments=6), circle(inner_rad)) return ret
def draw_profile(): obj = prof_p1 + S.color("black")(prof_n1) # draw intersection points if True: obj += S.color("red")(S.linear_extrude(10)(S.union()( S.translate(bottom_meet_pt)(S.circle(0.2)), S.translate(upper_meet_pt)(S.circle(0.2)), ))) return obj
def projection(): """ This is an approximation of the body. It matches the maximum outer dimensions but does not accurately reflect the profile. """ body = sp.union()( sp.circle(d=45., segments=32), sp.hull()( sp.circle(d=30., segments=32), place_mounting_holes(sp.circle(d=15., segments=32)), ), ) return body - sp.circle(d=bore, segments=32) - mounting_holes()
def mountable_face(): outer = sp.circle(d=body_diameter) shaft_cutout = sp.circle(d=shaft_surround_diam) mounting_holes = place_at_centres([mounting_hole_centres, 0], sp.circle(d=mounting_hole_diameter)) vent_holes = place_n_at_x_around(8, vent_holes_centres / 2., sp.circle(d=vent_holes_diameter)) return sp.union()( shaft_cutout, mounting_holes, vent_holes, )
def hole_pattern(pot_l, pot_w): obj = S.union() r1 = 4 pot_lw_ratio = pot_l / pot_w big_hole_dx = pot_w / 5 big_hole_dy = big_hole_dx * pot_lw_ratio obj += S.circle(r1) for i in [-1, 1]: for j in [-1, 1]: obj += S.translate([big_hole_dx * i, big_hole_dy * j, 0])(S.circle(r1)) return obj
def arc(rad:float, start_degrees:float, end_degrees:float, segments:int=None) -> OpenSCADObject: # Note: the circle that this arc is drawn from gets segments, # not the arc itself. That means a quarter-circle arc will # have segments/4 segments. bottom_half_square = back(rad)(square([3 * rad, 2 * rad], center=True)) top_half_square = forward(rad)(square([3 * rad, 2 * rad], center=True)) start_shape = circle(rad, segments=segments) if abs((end_degrees - start_degrees) % 360) <= 180: end_angle = end_degrees - 180 ret = difference()( start_shape, rotate(a=start_degrees)(bottom_half_square.copy()), rotate(a=end_angle)(bottom_half_square.copy()) ) else: ret = intersection()( start_shape, union()( rotate(a=start_degrees)(top_half_square.copy()), rotate(a=end_degrees)(bottom_half_square.copy()) ) ) return ret
def __init__(self): # stretched oval body = hull()(circle(radius) + right(phone_width)(circle(radius))) # used to hold the layers together body = body - self.screw_holes() # set self self.body = body # proper X-axis alignment self.body = right(radius)(body) # cut possible hole if self.hole: self.body -= self.hole.make_hole()
def create_screws(screw_position=Screw_Position.In_case_wall, diameter=2.1 * mm): holes = [ sc.translate((*pos, 0))(sc.circle(d=diameter, segments=30)) for pos in get_scew_positions(screw_position) ] return sc.union()(holes)
def screw_hole( radius: float, length: float, head_radius: t.Optional[float] = None, cap_depth: t.Optional[float] = None, angle=None, ): solids = [s.linear_extrude(length)(s.circle(r=radius))] if angle is not None: counter = s.translate([0, 0, length])(cone(head_radius, angle, False)) solids.append(counter) if cap_depth is not None: cut = s.translate([0, 0, length - cap_depth])( s.linear_extrude(cap_depth)(s.circle(r=head_radius)) ) solids.append(cut) return s.union()(*solids)
def arc_inverted(rad: float, start_degrees: float, end_degrees: float, segments: int = None) -> OpenSCADObject: # Return the segment of an arc *outside* the circle of radius rad, # bounded by two tangents to the circle. This is the shape # needed for fillets. # Note: the circle that this arc is drawn from gets segments, # not the arc itself. That means a quarter-circle arc will # have segments/4 segments. # Leave the portion of a circumscribed square of sides # 2*rad that is NOT in the arc behind. This is most useful for 90-degree # segments, since it's what you'll add to create fillets and take away # to create rounds. # NOTE: an inverted arc is only valid for end_degrees-start_degrees <= 180. # If this isn't true, end_degrees and start_degrees will be swapped so # that an acute angle can be found. end_degrees-start_degrees == 180 # will yield a long rectangle of width 2*radius, since the tangent lines # will be parallel and never meet. # Fix start/end degrees as needed; find a way to make an acute angle if end_degrees < start_degrees: end_degrees += 360 if end_degrees - start_degrees >= 180: start_degrees, end_degrees = end_degrees, start_degrees # We want the area bounded by: # -- the circle from start_degrees to end_degrees # -- line tangent to the circle at start_degrees # -- line tangent to the circle at end_degrees # Note that this shape is only valid if end_degrees - start_degrees < 180, # since if the two angles differ by more than 180 degrees, # the tangent lines don't converge if end_degrees - start_degrees == 180: raise ValueError("Unable to draw inverted arc over 180 or more " "degrees. start_degrees: %s end_degrees: %s" % (start_degrees, end_degrees)) wide = 1000 high = 1000 top_half_square = translate((-(wide - rad), 0, 0))(square([wide, high], center=False)) bottom_half_square = translate( (-(wide - rad), -high, 0))(square([wide, high], center=False)) a = rotate(start_degrees)(top_half_square) b = rotate(end_degrees)(bottom_half_square) ret = (a * b) - circle(rad, segments=segments) return ret
def three_point_cicle(p0: Point2, p1: Point2, p2: Point2, radius_adjustment=0, segments=100): center = _circle_center_by_three_points(p0, p1, p2) radius = ((center[0] - p0[0])**2 + (center[1] - p0[1])**2)**0.5 return solid.translate( (center[0], center[1], 0))(solid.circle(radius + radius_adjustment, segments=segments))
def projection(): p = outer_projection(3.1) horn_button = sp.translate((-18, 15))(sp.square(cherry_mx_cutout, center=True)) headlight_button = sp.translate((-18, -15))(sp.square(cherry_mx_cutout, center=True)) light_switch = sp.translate((0, -15))(sp.circle(d=switch_diameter, segments=32)) gear_select_switch = sp.translate((18, 15))(sp.circle(d=switch_diameter, segments=32)) display_button = sp.translate((18, -15))(sp.square(cherry_mx_cutout, center=True)) return p - horn_button - headlight_button - light_switch - gear_select_switch - display_button
def leg(dims: typing.List[float], flare: bool = True) -> s.OpenSCADObject: """ """ x, y, z = dims leg = s.cube(dims, center=True) if flare: flare = s.linear_extrude(x)(s.circle(r=y, segments=3)) flare = s.rotate([0, -90, 0])(flare) flare = s.translate([x / 2, 0, -y * 1.1])(flare) leg = s.union()(leg, flare) return leg
def fret1(innerdia, outerdia, circcount, height): """ generates 2d cutout pattern where all the cuts lie between the given inner and outer dia This pattern is just a number of circles between 3 and 5 """ cdia = (outerdia - innerdia) / 2 rangle = 360 / circcount offset = (innerdia + (outerdia - innerdia) / 2) / 2 cuts = solid.union()([ solid.rotate(a=rangle * i, v=(0, 0, 1))(solid.translate( (offset, 0))(solid.circle(d=cdia, segments=20))) for i in range(circcount) ]) return solid.linear_extrude(height=height, convexity=circcount + 1)(cuts)
def projection(): pq = (-15., 25.) pa = (0., 0.) pb = (30., 3.) pc = (38., 6.) pd = (44., 12.) dq = 6. da = 15. db = 8. dc = 8. dd = 8. return sp.difference()( sp.union()( hull_part(pa, pq, da, dq), hull_part(pa, pb, da, db), hull_part(pb, pc, db, dc), hull_part(pc, pd, dc, dd), ), sp.translate(pa)(sp.circle(d=pot_shaft_diameter, segments=16)), sp.translate(pq)(sp.circle(d=3., segments=16)), )
def projection(): panel = sp.square(tray_dimensions, center=True) frame_mounting_holes = place_at_centres( mounting_hole_centres, sp.circle(d=mounting_hole_diameter, segments=32)) return panel - frame_mounting_holes - placements.vesc( vesc.holes()) - placements.lighting_control_board( lighting_control_board.holes()) - placements.relay_board( relay_board.holes()) - placements.bec_module( bec_module.holes()) - placements.logic_board( logic_board.holes()) - placements.vesc_fan( shroud.mounting_holes(32))
def inset_screw_hole( radius: float, length: float, head_radius: t.Optional[float] = None, inset_depth: t.Optional[float] = None, angle=None, ): screw_height = length - inset_depth return s.union()( screw_hole(radius, length, head_radius, angle=angle), s.translate([0, 0, screw_height])( s.linear_extrude(inset_depth)(s.circle(r=head_radius)) ), )
def sector(radius=20, angles=(45, 135), segments=24): r = radius / math.cos(180 * degree_to_radians / segments) step = int(-360 / segments) points = [[0, 0]] for a in range(int(angles[0]), int(angles[1] - 360), step): points.append([ r * math.cos(a * degree_to_radians), r * math.sin(a * degree_to_radians) ]) for a in range(int(angles[0]), int(angles[1] - 360), step): points.append([ r * math.cos(angles[1] * degree_to_radians), r * math.sin(angles[1] * degree_to_radians), ]) return solid.difference()( solid.circle(radius, segments=segments), solid.polygon(points), )
def control_points(points: Sequence[Point23], extrude_height: float = 0, center: bool = True) -> OpenSCADObject: """ Return a list of red cylinders/circles (depending on `extrude_height`) at a supplied set of 2D points. Useful for visualizing and tweaking a curve's control points """ # Figure out how big the circles/cylinders should be based on the spread of points min_bb, max_bb = bounding_box(points) outline_w = max_bb[0] - min_bb[0] outline_h = max_bb[1] - min_bb[1] r = min(outline_w, outline_h) / 20 # if extrude_height == 0: c = circle(r=r) else: h = extrude_height * 1.1 c = cylinder(r=r, h=h, center=center) controls = color(Red)([translate([p.x, p.y])(c) for p in points]) return controls
def projection(): cu = 30. cd = -30. def arm(a, b): return sp.hull()( sp.translate(a)(sp.circle(d=20., segments=32)), sp.translate(b)(sp.circle(d=25., segments=32)), ) # Drill these holes in the existing steering wheel box_mounting_holes = instrument_panel.place_mounting_holes( drilled_hole.projection(diameter=4.)) return sp.union()( sp.square((75., 75.), center=True), arm((-xu, yu), (0, cu)), arm((xu, yu), (0, cu)), arm((-xd, yd), (0, cd)), arm((xd, yd), (0, cd)), ) - place_mounting_holes( sp.circle(d=mounting_hole_diameter)) - box_mounting_holes
def example(): """Run lab_0 example. Creates all_shapes.scad and all_shapes.dxf files. Returns: open, squarcle, and star PolyLines """ # Make an open PolyLine defined with points open_pl = PolyLine([[0,0],[0,60],[100,0],[200,0]]) # Make an OpenSCAD generator squarcle_gen = ( solid.square(50) + solid.translate([50,25])(solid.circle(25)) - solid.translate([20,15])(solid.text('S',size=20)) ) # Use the OpenSCAD generator to make a PolyLine squarcle_pl = PolyLine(generator=squarcle_gen).simplified() # Create star.dxf by saving a PolyLine star().save('star.dxf') # Load PolyLine from DXF file star_pl = PolyLine(filename='star.dxf').simplified() # Scale, translate and rotate PolyLines small_open_pl = 0.5 * open_pl trans_squarcle_pl = (0,50,0) * squarcle_pl trans_rot_star_pl = (50,175,numpy.pi/2) * star_pl # Combine the geometries and save them all_shapes = small_open_pl + trans_squarcle_pl + trans_rot_star_pl all_shapes.save('all_shapes.scad') all_shapes.save('all_shapes.dxf') return (open_pl, squarcle_pl, star_pl)
grip_r = gripper_r_arm.children[0] grip_l = gripper_l_arm.children[2] # GET A SUPPORT FOR THE GRIPPER # # Just a square # # Calculating translation vectors Pt0 = numpy.asarray(grip_r[0].joints[1].pose[0]) Pt1 = numpy.asarray(grip_r[0].joints[0].pose[0]) Pt0_inv = numpy.array([Pt0[0] * (-1), Pt0[1], 0]) tr_matrix = translation_matrix(pts_to_vec(Pt0, Pt1)) tr_matrix_inv = translation_matrix(pts_to_vec(Pt0_inv, Pt1)) # The holes # a_circle = PolyLine(generator = solid.circle(r = 7/2.0)) right_circle = a_circle.clone() left_circle = a_circle.clone() right_circle *= translation_matrix([40,0,0]) left_circle *= translation_matrix([-40,0,0]) right_down_circ = right_circle.clone() right_down_circ *= tr_matrix left_down_circle = left_circle.clone() left_down_circle *= tr_matrix_inv circles = right_circle + right_down_circ + left_circle + left_down_circle rec = PolyLine(generator = solid.square(size = [175,175], center = True))
# GENERATING THE GRID AND THE NODES # grid = grid_cart(cell_n,1) grid = grid_cart_pts(cell_n, cell_y, 1, 1) # to be consistent we assume that each cell has 1 unit topo_nodes = [closest_points(x,grid) for x in nodes_pts] if __name__ == '__main__': p = PolyLine(filename='ternary_link_030.png') p_bBox = p.bounding_box() p_bBox_origin = numpy.append(p_bBox.points[0],[0]) tr_mtx = translation_matrix(pts_to_vec(p_bBox_origin, origin)) p *= tr_mtx # Lets create big circles and position them # a_circle= PolyLine(generator= solid.circle(5.5)).simplified() a_circle_lst=[] for i in range(len(joints_pose_tr)): b = a_circle.clone() trl_mtx = translation_matrix(joints_pose_tr[i]) b *= trl_mtx a_circle_lst.append(b) # Lets create circles/holes for the joints and position them # c_circle= PolyLine(generator= solid.circle(3.5)).simplified() c_circle_lst=[] for i in range(len(joints_pose_tr)): d = c_circle.clone() trl_mtx = translation_matrix(joints_pose_tr[i])
def projection(diameter): return sp.circle(d=diameter, segments=32)
#!/usr/bin/env python3 import solid as sd import solid.utils as su inch = 25.4 # mm length = 8 * inch width = 1.25 * inch height = 1.5 * inch wall = .25 * inch lip = .5 * inch punch = 3 / 8 * inch v_punch_shift = ((width + wall) + (width + 2 * wall + 2 * lip)) / 4 gap = .4 # mm inner_circle = sd.circle(d=width) inner_oval = sd.square([length, width], center=True) inner_oval += sd.translate([-length / 2, 0])(inner_circle) inner_oval += sd.translate([length / 2, 0])(inner_circle) punch_circle = sd.circle(d=punch) lip_circle = sd.circle(d=width + 2 * wall + 2 * lip) lip_oval = sd.square([length, width + 2 * wall + 2 * lip], center=True) lip_oval += sd.translate([-length / 2, 0])(lip_circle) lip_oval += sd.translate([length / 2, 0])(lip_circle) hole_oval = lip_oval lip_oval = sd.translate([0, 0, -wall])(sd.linear_extrude(wall)(lip_oval)) outer_circle = sd.circle(d=width + 2 * wall) outer_oval = sd.square([length, width + 2 * wall], center=True) outer_oval += sd.translate([-length / 2, 0])(outer_circle)
def mounting_holes(s): return spu.forward(length / 2.)(place_at_centres( (fan.size[0] + 6., length - 10.), sp.circle(d=3.1, segments=s)))
def slit(): return rotate(a=back_bend_degrees)( forward(y_offset)( union()(hull()( circle(r=radius) + forward(height)(circle(r=radius))))))
def holes(): return place_at_centres( mounting_hole_centres, sp.circle(d=mounting_hole_diameter, segments=16) )
def arm(a, b): return sp.hull()( sp.translate(a)(sp.circle(d=20., segments=32)), sp.translate(b)(sp.circle(d=25., segments=32)), )
import solid as sc import typing import math from euclid3 import Point2 import utils import z3 circle_center = Point2(15, 15) circle_radius = 10 circle = sc.translate((*circle_center, 0))(sc.circle(circle_radius, segments=100)) square = sc.square(20, center=True) def dist_square(a, b): return (a[0] - b[0])**2 + (a[1] - b[1])**2 PRECISION = 6 def assert_tangent_to_circle(fillet_center, fillet_radius: float, circle_radius: Point2, circle_center: Point2): dist_squared = (circle_center.x - fillet_center[0])**2 + ( circle_center.y - fillet_center[1])**2 return dist_squared == (circle_radius + fillet_radius)**2 def assert_tangent_to_line(
def mounting_holes(): return place_at_centres((51., 51.), sp.circle(d=4.))
def main_vent(): return sp.intersection()( sp.square([d - 2. for d in size], center=True), sp.circle(d=64.), )
def projection(diameter): return sp.circle(d=diameter)
def screw_holes(self): return [ left(screw_hole_shift)(circle(screw_hole_radius)), right(screw_hole_shift + phone_width)(circle(screw_hole_radius)) ]