Esempio n. 1
0
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
Esempio n. 2
0
def projection():
    d = motor.body_diameter + 10.
    outer = sp.hull()(
        sp.square((plate_width, d), center=True),
        spu.back(lower_extent - 5.)(sp.square((plate_width, 10.),
                                              center=True)),
    )

    mounting_holes = spu.back(mount_holes_offset)(place_at_centres(
        (mount_holes_distance, 0.), mounting_slot()))

    return outer - motor.mountable_face() - mounting_holes
Esempio n. 3
0
    def __init__(self, retainer_diameter, height, depth, threads_per_inch, cap_diameter, hole_diameter, cap_thickness,**kwargs):
        r_r = to_mm(retainer_diameter/2.)
        height = to_mm(height)
        h_r = to_mm(hole_diameter/2.)
        c_r = to_mm(cap_diameter/2.)
        c_t = to_mm(cap_thickness)
        threads_per_inch = threads_per_inch
        o_d = kwargs.get('outer_diameter')
        i_d = kwargs.get('inner_diameter')

        if 'bodytube' in kwargs:
            o_d = kwargs['bodytube'].outer_diameter
            i_d = kwargs['bodytube'].inner_diameter

        print i_d
        i_r = to_mm(i_d/2.)
        o_r = to_mm(o_d/2.)

        print retainer_diameter
        flange_d = to_mm(kwargs.get('flange_diameter'), safe=True)
        flange_t = to_mm(kwargs.get('flange_thickness'), safe=True)
        
        spine_diameter = to_mm(kwargs.get('spine_diameter'), safe=True)

        round_radius = to_mm(kwargs.get('round_radius',0))

        if flange_d and flange_t:
            flange = cylinder(h=flange_t, r=flange_d/2.)
        else:
            flange = cylinder(h=height, r=o_r/2.)  # HACK because this will be removed

        self.retainer = difference() (self.threaded_male_column(height, to_mm(retainer_diameter), threads_per_inch) + flange,
                                      cylinder(h=height, r=o_r),
                                      up(height-depth), cylinder(h=depth, r=i_r))
        
        self.cap = difference()(cylinder(h=height,r=c_r),
                                self.threaded_female_column(height-c_t, to_mm(retainer_diameter), threads_per_inch),
                                cylinder(h=height, r=h_r))

        if spine_diameter:
            no_spines = kwargs.get('spines',0)
            spines = []
            for idx in xrange(0, no_spines):
                spines.append(rotate([0,0,360/no_spines*idx])(right(c_r)(cylinder(h=height-c_t-spine_diameter/2, r=spine_diameter/2)+
                                  up(height-c_t-spine_diameter/2)(sphere(r=spine_diameter/2.)))))
            self.cap+=union()(*spines)

        self.round = rotate_extrude()(right(c_r-round_radius)(square([round_radius,round_radius])*circle(round_radius)))
        self.cap -= up(height-round_radius)(rotate_extrude()(right(c_r-round_radius)(square([round_radius,round_radius]))))
        self.cap += up(height-round_radius)(self.round)
Esempio n. 4
0
def slice_mesh(fn='LOGOROBOT.stl', t_m=3.0):
    """ Return list of slices from stl modifed with through holes for alignment.

    Args:
      filename (str): STL file with 3D solid to turn into slices
      t_m (float): material thickness

    Returns:
      list of PolyLines that are the 2D profiles of the slices

    """
    poly = PolyMesh(filename=fn)
    #custom rotation for LOGOROBOT
    rot = sl.rotate(-90, [1, 0, 0])(poly.get_generator())
    poly = PolyMesh(generator=rot)
    slices = []
    plane = sl.square(1000, True)
    axis = np.array([0, 0, 1])  # slice in Z direction
    (alpha_min, alpha_max) = mesh_extremum(poly, axis)
    for alpha in frange(alpha_min, alpha_max, t_m):
        norm = list(axis * alpha)
        slice_polyline = PolyLine(generator=plane)
        slice_args = (slice_polyline, norm)
        slice = planar_slice(poly, slice_args, t_m)
        slices.append(slice)
    return slices
Esempio n. 5
0
def slice_mesh(fn="LOGOROBOT.stl", t_m=3.0):
    """ Return list of slices from stl modifed with through holes for alignment.

    Args:
      filename (str): STL file with 3D solid to turn into slices
      t_m (float): material thickness

    Returns:
      list of PolyLines that are the 2D profiles of the slices

    """
    poly = PolyMesh(filename=fn)
    # custom rotation for LOGOROBOT
    rot = sl.rotate(-90, [1, 0, 0])(poly.get_generator())
    poly = PolyMesh(generator=rot)
    slices = []
    plane = sl.square(1000, True)
    axis = np.array([0, 0, 1])  # slice in Z direction
    (alpha_min, alpha_max) = mesh_extremum(poly, axis)
    for alpha in frange(alpha_min, alpha_max, t_m):
        norm = list(axis * alpha)
        slice_polyline = PolyLine(generator=plane)
        slice_args = (slice_polyline, norm)
        slice = planar_slice(poly, slice_args, t_m)
        slices.append(slice)
    return slices
Esempio n. 6
0
def flat():
    body = square(size=[length, height])
    holes = []
    num_cutouts = int(ceil(length / step))
    for i in xrange(num_cutouts + 1):
        holes.append(right((i + 1) * step)(slit()))
    body -= union()(holes)
    return body
Esempio n. 7
0
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
Esempio n. 8
0
def square_key(size, top_delta, progress):
    """
    square key
    """

    if isinstance(size, list):
        dims = [size[i] - top_delta[i] * progress for i in [0, 1]]
    else:
        dims = size - (top_delta * progress)

    return s.square(dims, center=True)
Esempio n. 9
0
def create_left_buttom_circle():
    p0 = switches.get_cap_corner((0, 1), Point2(0.5, -0.5))
    p1 = switches.get_cap_corner((1, 1), Point2(0.5, -0.5))
    p2 = switches.get_cap_corner((3, 1), Point2(0, -0.62))
    circle = utils.three_point_cicle(p0,
                                     p1,
                                     p2,
                                     radius_adjustment=1.5 * mm,
                                     segments=1000)
    right_edge = switches.get_cap_corner(Point2(0, 0), Point2(-0.5, 0.5)).x
    return circle * sc.square(right_edge * 2, center=True)
Esempio n. 10
0
def joints_bb_coord(mechanism):
    joints_coord = []
    bb_coord = []
    origin = numpy.array([0, 0, 0])

    ternary_body = filter_three_joints(mechanism)
    ternary_joints = ternary_body.joints
    for i in range(len(ternary_joints)):
        joints_coord.append(ternary_joints[i].pose[0])

    BBox = ternary_body.bounding_box()
    BBox_points = BBox.points
    BBox_point0 = numpy.append(BBox_points[0],
                               [0])  #numpy append to add a z coord

    width = numpy.linalg.norm(pts_to_vec(BBox_points[0], BBox_points[2]))
    height = numpy.linalg.norm(pts_to_vec(BBox_points[0], BBox_points[1]))

    if width == height:
        bb_square = BBox
    elif width > height:
        bb_square = PolyLine(generator=solid.square(width)).simplified()
        tr_vec = translation_matrix(pts_to_vec(origin, BBox_point0))
        bb_square *= tr_vec
    else:
        bb_square = PolyLine(generator=solid.square(height)).simplified()
        tr_vec = translation_matrix(pts_to_vec(origin, BBox_point0))
        bb_square *= tr_vec

    bb_square_points = [
        numpy.append(bb_square.points[0], [0]),
        numpy.append(bb_square.points[2], [0])
    ]  #numpy append to add a z coord - consistency

    # For the sake of clarity transforming the arrays of bb_square_points to tuplles #
    # In this way the output of the function would be always lists of tupples #

    bb_pts_tpl = map(tuple, bb_square_points)

    return joints_coord, bb_pts_tpl
Esempio n. 11
0
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))
Esempio n. 12
0
def joints_bb_coord (mechanism):
	joints_coord=[]
	bb_coord=[]
	origin = numpy.array([0,0,0])
	
	ternary_body = filter_three_joints(mechanism)
	ternary_joints = ternary_body.joints
	for i in range(len(ternary_joints)):
		joints_coord.append(ternary_joints[i].pose[0])
	
	BBox = ternary_body.bounding_box()
	BBox_points= BBox.points
	BBox_point0 = numpy.append(BBox_points[0], [0]) #numpy append to add a z coord

	width = numpy.linalg.norm(pts_to_vec(BBox_points[0],BBox_points[2]))
	height = numpy.linalg.norm(pts_to_vec(BBox_points[0],BBox_points[1]))
	
	if width == height:
		bb_square = BBox
	elif width > height:
		bb_square = PolyLine(generator = solid.square(width)).simplified()
		tr_vec = translation_matrix(pts_to_vec(origin, BBox_point0))
		bb_square *= tr_vec
	else:
		bb_square = PolyLine(generator = solid.square(height)).simplified()
		tr_vec = translation_matrix(pts_to_vec(origin, BBox_point0))
		bb_square *= tr_vec

	bb_square_points = [numpy.append(bb_square.points[0], [0]), numpy.append(bb_square.points[2], [0])] #numpy append to add a z coord - consistency

	# For the sake of clarity transforming the arrays of bb_square_points to tuplles #
	# In this way the output of the function would be always lists of tupples #

	bb_pts_tpl = map (tuple, bb_square_points)

	return joints_coord, bb_pts_tpl
Esempio n. 13
0
def main(params: Params):
    profile = utils.profile_with_screws(params)

    cutout = None
    if params.cutout_depth > 0:
        cutout = s.linear_extrude(params.cutout_depth)(
            s.square([params.interface_width, params.height])
        )

    if cutout is not None:
        cutout_x = params.screw_spacing * 2 + params.screw_head_radius * 2
        cutout_z = params.depth - params.cutout_depth
        profile = s.difference()(profile, s.translate([cutout_x, 0, cutout_z])(cutout))

    return profile
Esempio n. 14
0
def generalized_pot(extrude_func,
                    prof_n1,
                    prof_p1,
                    pot_l,
                    pot_w,
                    holes=True,
                    base_th=3,
                    emboss_text=""):
    base_prof = S.difference()(
        # main profile
        S.difference()(
            prof_p1(),
            prof_n1(),
        ),

        # cut off everything above the base height
        S.translate([-pot_l * 5, base_th])(S.square(pot_l * 10), ),
    )
    base = S.hull()(extrude_func(base_prof))

    # bottom holes
    if holes:
        base = S.difference()(
            base,
            S.translate([0, 0,
                         -INC])(S.linear_extrude(base_th * 2)(hole_pattern(
                             pot_l, pot_w)), ),
        )

    # embossed text
    emboss_depth = 0.4
    font_size = 6
    if len(emboss_text):
        base = S.difference()(
            base,

            # text
            S.translate([0, 10, base_th - emboss_depth])(S.linear_extrude(
                emboss_depth * 2)(S.text(
                    EMBOSS_TEXT,
                    halign="center",
                    valign="center",
                    size=font_size)), ))

    return S.difference()(
        S.union()(extrude_func(prof_p1), base),
        extrude_func(prof_n1),
    )
Esempio n. 15
0
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
Esempio n. 16
0
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)
Esempio n. 17
0
def plane_from_normal(norm):
    plane = sl.square(1000, True)
    plane_poly = PolyLine(generator=plane)
    plane_axis = np.array([0, 0, 1])
    if norm == plane_axis:
        return plane
    rot_axis = np.cross(norm, plane_axis)
    cos_theta = np.dot(norm, plane_axis)
    theta = math.acos(cos_theta)
    quaternion = quaternion_about_axis(theta, rot_axis)

    z = np.array([0, 0, 1])
    x = np.array([1, 0, 0])
    rot_axis = np.cross(x, z)
    cos_theta = np.dot(z, x)
    theta = math.acos(cos_theta)
    quat = quaternion_about_axis(theta, rot_axis)
    quat_mat = quaternion_matrix(quat)
    x * quat
    I = identity_matrix()
    plane_poly.points
    plane_poly * e
    e = euler_from_quaternion(quat)
    np.dot(quat, np.array(z))
Esempio n. 18
0
def plane_from_normal(norm):
    plane = sl.square(1000, True)
    plane_poly = PolyLine(generator=plane)
    plane_axis = np.array([0, 0, 1])
    if norm == plane_axis:
        return plane
    rot_axis = np.cross(norm, plane_axis)
    cos_theta = np.dot(norm, plane_axis)
    theta = math.acos(cos_theta)
    quaternion = quaternion_about_axis(theta, rot_axis)

    z = np.array([0, 0, 1])
    x = np.array([1, 0, 0])
    rot_axis = np.cross(x, z)
    cos_theta = np.dot(z, x)
    theta = math.acos(cos_theta)
    quat = quaternion_about_axis(theta, rot_axis)
    quat_mat = quaternion_matrix(quat)
    x * quat
    I = identity_matrix()
    plane_poly.points
    plane_poly * e
    e = euler_from_quaternion(quat)
    np.dot(quat, np.array(z))
Esempio n. 19
0
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(
Esempio n. 20
0
def projection():
    outer = sp.square(size, center=True)
    return outer - main_vent() - mounting_holes()
Esempio n. 21
0
def main_vent():
    return sp.intersection()(
        sp.square([d - 2. for d in size], center=True),
        sp.circle(d=64.),
    )
Esempio n. 22
0
 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
Esempio n. 23
0
def projection(size, radius=3., center=True):
    return sp.minkowski()(
        sp.square([a - 2. * radius for a in size], center=center),
        sp.circle(r=radius, segments=16),
    )
Esempio n. 24
0
def roundrect(vector: Vector2, radius: float):
    mod_vec = [v - radius * 2 for v in vector]
    return s.minkowski()(
        s.square(mod_vec), s.translate([radius, radius, 0])(s.circle(r=radius))
    )
Esempio n. 25
0
from solid import linear_extrude, scad_render_to_file
from solid.utils import color, down, left, Green
from math import sqrt, pi, sin, cos, atan2

#---------------------------------------------
if __name__ == '__main__':
    from solid import include, use, scad_render, rotate, square
    from sys import argv
    from re import sub
    arn = 0
    arn += 1
    gThik = float(argv[arn]) if len(argv) > arn else 6
    arn += 1
    circPitch = float(argv[arn]) if len(argv) > arn else 10
    use('GFgear.scad')
    tRateHold, toothHold, stickHold = 98765, 76543, 54321
    gearAsm = gear(toothHold, circPitch) + square([stickHold, 1])
    hs = linear_extrude(gThik, True)(rotate(tRateHold)(gearAsm))
    # Substitute variable names & formulae in place of various holders
    # Note, scad_render returns a string with a `use <...>` statement
    # and CSG .scad code for gear and square outline and its extrusion.
    hs = sub(str(toothHold), 'toothCount', scad_render(hs))
    hs = sub(str(tRateHold), '(0.5-abs($t-0.5))*tAngle*2', hs)
    hs = sub(str(stickHold), 'toothCount*{:0.4f}'.format(circPitch / 4), hs)
    hs = '/* [Params:] */\n// Number of Teeth\ntoothCount=11; // [3:300]\n// Total sweep angle; 1-360\ntAngle=90; // [1:360]\n$fn=20;\n{}'.format(
        hs)
    fo = open('tooth.scad', 'w+')
    fo.write(hs)
    fo.close()
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))

base = Block(Layer(geometries = circles + rec, color= 'red'), name = 'base_gripper')

# TO PRODUCE LAYOUT CUTS #

gen_laser_cuts(bot_leg, name = 'robot_leg')

grip_l_layout= gen_laser_cuts(grip_r, name = 'gripper_l_arm', plot_to_file = False) # Because it is just a mirror of grip_r 

gen_laser_cuts(grip_r, name = 'gripper_r_arm', sheet = (1200,600), plot_to_file = False).augmented(base).augmented(grip_l_layout).solved(margin = 3.0)[0].save('gripper.dxf')
 
# NOW CUT AND ASSEMBLE YOU LASY BASTARD #

"""
TEST FOR GRIPPER ARMS - this was a nightmare, I wish I was a more math guy
Esempio n. 27
0
def rcylinder(r, h, rnd=0, center=False):
    ''' primitive for a cylinder with rounded edges'''
    if rnd == 0: return solid.cylinder(r=r, h=h, center=center)
    mod_cyl = solid.translate((0, 0, -h/2 if center else 0))( \
        solid.rotate_extrude(convexity=1)(solid.offset(r=rnd)(solid.offset(delta=-rnd)(solid.square((r, h)) + solid.square((rnd, h))))))
    return mod_cyl