예제 #1
0
def panelmountmini():
    """panelmount

    panel mount for panel Mount cable -B to Mini-B cable
    http://adafru.it/936
    """
    base = cube([40, 20, THICK_WALL], center=True)
    # screw hole
    screw_hole = cylinder(r=1.75, h=THICK_WALL * 2, center=True, segments=30)
    # create two holes + hole usb cube
    base -= hole()(left(14)(screw_hole) + right(14)(screw_hole) +
                   cube([17.5, 12, THICK_WALL * 2], center=True))
    # change orientation
    base = right(0.5 * THICK_WALL)(rotate([0, 90, 0])(rotate([0, 0,
                                                              90])(base)))
    return base
예제 #2
0
def ref_arrow_3d(arr_length, origin, label, ref_rotation=(0, 0, 0)):
    """
    Create 3-axis ref frame, with color for x, y, z
    :param arr_length: length of arrow
    :param origin: set origin of arrows. (x, y, z)
    :param ref_rotation: tuple for rotation
    :param label: dictionary of labels for the three axis. {'x': label_x, 'y': label_y, 'z': label_z}
    :return:
    """
    ref_frame = union()
    ref_frame.add(
        color([1, 0, 0])(arrow(heigth=arr_length,
                               tail=origin,
                               rotation=(0, 90, 0),
                               label=label['x'])))  # x_axis
    ref_frame.add(
        color([0, 1, 0])(arrow(heigth=arr_length,
                               tail=origin,
                               rotation=(-90, 0, 0),
                               label=label['y'])))  # y_axis
    ref_frame.add(
        color([0, 0, 1])(arrow(heigth=arr_length,
                               tail=origin,
                               rotation=(0, 0, 0),
                               label=label['z'])))  # z_axis
    ref_frame = rotate(list(ref_rotation))(ref_frame)
    return ref_frame
예제 #3
0
def rot_arrow(radius, angle_init, angle_end, label, text_flip=False):
    """
    Create curved arrow as 1 degree-step cylinders with a cone at the end ==> arrow
    Add also a label in the middle of the arrox as a text.
    :param radius: radius is in cm
    :param angle_init: in degrees
    :param angle_end: in degrees
    :param label: label to be given to the arrow
    :param text_flip: rotate text by 180 degrees
    :return: arrow

    example:

    arr_curved = color([1, 0, 0])(rot_arrow(8000, az.to('deg').value,0, label='AZ'))
    array.add(arr_curved)

    """
    curved_arrow = union()
    point = cylinder(r1=radius / 15, r2=0, h=radius / 8)
    point = rotate([0, -90, -90])(point)

    if angle_end > angle_init:
        angles = np.deg2rad(np.arange(angle_init, angle_end, 1))[1:-5]
        x = radius * np.cos(angles)
        y = radius * np.sin(angles)
        point = rotate([0, 0, np.rad2deg(angles[-2])])(point)
    elif angle_end < angle_init:
        angles = np.deg2rad(np.arange(angle_init, angle_end, -1))[:-5]
        x = radius * np.cos(angles)
        y = radius * np.sin(angles)
        point = rotate([0, 0, np.rad2deg(angles[-2]) + 180])(point)

    curved_body = arco(x, y, radius / 30)
    point = translate([x[-2], y[-2], 0])(point)
    curved_arrow.add(point)
    curved_arrow.add(curved_body)
    testo = linear_extrude(radius / 30)(text(label, size=radius / 5))
    index = x.size // 3 * 2
    testo = rotate([0, 0, np.rad2deg(angles[index])])(testo)
    if text_flip:
        testo = rotate([0, 0, 180])(testo)
        testo = translate(
            [0.15 * len(label) * x[index], 0.15 * len(label) * y[index],
             0])(testo)
    testo = translate([1.1 * x[index], 1.1 * y[index], 0])(testo)
    curved_arrow.add(testo)
    return curved_arrow
예제 #4
0
def side_pegs(single_peg, shape, margin):
    peg_set = up(shape[2] / 2)(rotate([90, 0, 0])(grid_pegs(
        single_peg,
        centered_grid(width=shape[0], length=shape[2], margin=margin))))
    half_length = shape[1] / 2
    left_pegs = back(half_length)(peg_set)
    right_pegs = forward(half_length)(peg_set)
    return left_pegs + right_pegs
예제 #5
0
def topbox(down, logo):
    """topbox

    constructs the top part of the box
    :param down: if true downward ray box created
    :param logo: if true logo is generated, logo slows rendering
    """
    top = cube([LENGTH_TOP, WIDTH_TOP, THICK_WALL])
    # 4 screws used, 2 was insufficient
    screw_fixout = 3.5  # mm (radius)
    screw_fixin = 2  # TODO: connect to holesize threaded inserti
    screw_toph = 5
    cyl = screw(screw_fixout, screw_toph, screw_fixin, HEIGHT_TOP)
    top += translate([SCREW_FIXOFFST, SCREW_FIXOFFST, 0])(cyl)
    top += translate([LENGTH_TOP - SCREW_FIXOFFST, SCREW_FIXOFFST, 0])(cyl)
    top += translate(
        [LENGTH_TOP - SCREW_FIXOFFST, WIDTH_TOP - SCREW_FIXOFFST, 0])(cyl)
    top += translate([SCREW_FIXOFFST, WIDTH_TOP - SCREW_FIXOFFST, 0])(cyl)

    # sliding should be prevented with 4 protrusion,
    # 1 is logo and 3 other are knobs
    x_knob = cube([THICK_WALL, THICK_WALL * 3, HEIGHT_TOP - THICK_WALL])
    x_knobs = translate(
        [THICK_WALL, WIDTH_TOP / 2 - 1, THICK_WALL])(x_knob) + translate([
            LENGTH_TOP - 2 * THICK_WALL, WIDTH_TOP / 2 - 1, THICK_WALL
        ])(x_knob)
    y_knob = cube([THICK_WALL * 3, THICK_WALL, HEIGHT_TOP - THICK_WALL])
    y_knobs = translate([LENGTH_TOP * 0.25, 0, THICK_WALL
                         ])(forward(THICK_WALL)(y_knob) +
                            forward(WIDTH_TOP - 2 * THICK_WALL)(y_knob))
    top += y_knobs + x_knobs
    # LOGO slows down render, should be turned off when developing
    if logo:
        top += translate([
            0.5 * (LENGTH_TOP - (120 + THICK_WALL * 2)),
            WIDTH_TOP - THICK_WALL - (13 + THICK_WALL * 2), 0
        ])(createlogo())
    if not down:
        laser_y = 24 + 2 * THICK_WALL
        top -= translate(
            [75 + 10 + 48 + THICK_WALL + 10, laser_y - 0.5 * 8,
             0])(cube([20, 8, THICK_WALL]))
    # FIX FOR BOX orientation
    top = rotate([0, 0, 180])(mirror([0, 1, 0])(rotate([0, 180, 0])(top)))

    return top
예제 #6
0
def boxmount():
    base = cube([30, 50, 2])
    circ = cylinder(h=10, r=1.6, segments=30)
    circs = right(5)(circ) + right(25)(circ)
    base -= forward(5)(circs)
    base -= forward(25)(circs)
    base -= forward(45)(circs)
    base = rotate([90, 0, 90])(base)
    return base
예제 #7
0
def mount_panel():
    width = 3.0 * inches
    length = 2.0 * inches + 2.0 * PANEL_THICKNESS
    height = 3.0 * inches
    punches = mount_hole_punch(width, length, height)
    bottom_punches = rotate([-90, 0, 0])(punches)
    back_piece = grounded_cube([width, PANEL_THICKNESS, height]) - punches
    bottom = grounded_cube([width, length, PANEL_THICKNESS])
    return forward(length / 2)(back((length - PANEL_THICKNESS) / 2)
                               (back_piece) + bottom) - bottom_punches
예제 #8
0
def threadedinsert(flip_x, thick, holesize, length):
    """insert
    heatpress insert

    Heatpress can be inserted from the top. The screw should also be inserted
    from the top. The screw is centered at the origin.
    The wall thickness are specified by;
    http://uk.farnell.com/tr-fastenings-brass-inserts-for-plastics
    The length and hole size should be obtained from the sheet.
    this threaded is supported by a triangle and can be mirrored in the
    x-direction
    :param flip_x: flip insert in, origin shifted back
    :param length: length of the insert
    :param holesize: diameter of the hole
    """
    # NOTE: other options
    # -sliding ; this results in a cable collision
    # -press insert; more recommended for photopolymer parts, less permanent
    # -bolt printed inside; requires print pause, not useful in production
    # -magnet; magnets are dangerous for electronics
    x_extent = holesize + 2 * thick
    y_extent = holesize / 2 + thick + SCREW_FIXOFFST
    base = cube([x_extent, y_extent, length])
    triangle = polygon([[0, 0], [y_extent, y_extent], [0, y_extent]])
    prism = linear_extrude(x_extent)(triangle)
    support = translate([x_extent, y_extent, 0])(rotate([90, 0, -90])(prism))
    base = support + up(y_extent)(base)
    base -= translate([holesize / 2 + thick, holesize / 2 + thick,
                       0])(cylinder(h=length + y_extent,
                                    r=holesize / 2,
                                    segments=30))
    # changed orientation to simplify placement
    base = down(y_extent + length)(base)
    # center origin at Z-axis
    base = translate(
        [-x_extent / 2, -SCREW_FIXOFFST + thick + holesize / 2, 0])(base)
    if flip_x:
        base = rotate([0, 0, 180])(base)
    return base
예제 #9
0
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
예제 #10
0
def arrow(heigth, tail, label, rotation=(0, 0, 0)):
    """
    Create arrow with rotation. Default is VERTICAL, along Z-axis
    :param heigth: (float) height
    :param tail:    (tuple) position of tail.
    :param rotation: (tuple) rotation along x, y and z axis
    :param label: something converted to string to put as label on axis
    :return: arrow with label
    TODO: add rotation from rotation function and not with the *rotate* in *solid*
    """
    arrow_inst = union()
    arrow_inst.add(cylinder(r=heigth / 20, h=heigth))
    arrow_inst.add(
        translate([0, 0, heigth])(cylinder(r1=heigth / 10, r2=0,
                                           h=heigth / 8)))
    arrow_inst.add(
        translate([0, 0, heigth * 1.2])(rotate([90, -90, 0])(linear_extrude(
            heigth / 40)(text(text=label,
                              size=heigth / 5,
                              font="Cantarell:style=Bold")))))
    arrow_inst = rotate(list(rotation))(arrow_inst)
    arrow_inst = translate(list(tail))(arrow_inst)
    return arrow_inst
예제 #11
0
def ref_arrow_2d(length, origin, label, ref_rotation=(0, 0), inverted=False):
    """
    Create 3-axis ref frame, with color for x,y
    :param length: length of arrow
    :param label. dictionary of labels for the 2 axis: {'x': label_x, 'y': label_y}
    :param origin: set origin of arrows. (x, y)
    :param ref_rotation: tuple for rotation
    :return: arrow with right text rotation.
    """
    ref_frame = union()
    if inverted:
        ref_frame.add(
            color([1, 0, 0])(arrow(heigth=length,
                                   tail=origin,
                                   label=label['x'],
                                   rotation=(-90, 180, 0))))  # x_axis
        ref_frame.add(
            color([0, 1, 0])(multmatrix(m=rotation(90, 'x'))(arrow(
                heigth=length,
                tail=origin,
                label=label['y'],
                rotation=(0, 90, 0)))))  # y_axis
        ref_frame = rotate(list(ref_rotation))(ref_frame)
    else:
        ref_frame.add(
            color([1, 0, 0])(multmatrix(m=rotation(-90, 'x'))(arrow(
                heigth=length,
                tail=origin,
                label=label['x'],
                rotation=(0, 90, 0)))))  # x_axis
        ref_frame.add(
            color([0, 1, 0])(arrow(heigth=length,
                                   tail=origin,
                                   label=label['y'],
                                   rotation=(-90, 0, 0))))  # y_axis
        ref_frame = rotate(list(ref_rotation))(ref_frame)
    return ref_frame
예제 #12
0
def polygonshim(height):
    """polygonshim

    The polygon shim is located in first quadrant of the XY plane.
    A corner is at the origin. The width is parallel to the y-axis.
    The shim can be used to align the polygon.
    The shim was designed for polygon mirror Motor aficio 1018 G029-196.

    :param height: height shim
    """
    # BASE:
    length = 68  # mm [y-direction]
    width = 48  # mm [x-direction]
    r_shaft = 2  # mm shaft radius
    slot_width = 2  # width slot
    base = cube([width / 2, length, height])

    def slot(radius, height, width):
        """slot

        openscad styled vertically oriented printable slot
        origin formed by the center of the left circle

        :param radius: the radius of the top of the screw
        :param height: the height of the slot
        :param width: the width of the slot, i.e. distance between radii
        """
        cyl = cylinder(h=height, r=radius)
        outer = hull()(cyl, right(width)(cyl))
        return outer

    # create 2 screw slots
    simple_slot = slot(r_shaft, height, slot_width)
    base -= translate([3.1, length - 4, 0])(simple_slot)
    base -= translate([3.2, 4 + 1.29, 0])(rotate([0, 0, -50])(simple_slot))
    # create hole for polygon rotation axis
    base -= translate([24, 24, 0])(cylinder(h=height, r=10))
    # create hole for polygon lock
    base -= translate([24 - 7.5, 0, 0])(cube([15, 10, height]))
    #  mirror and add to original
    spiegelold = right(width)(mirror([1, 0, 0])(base))
    base += spiegelold
    return base
예제 #13
0
def panel_set():

    front = back(NARROW_WIDTH)(rotate(180, [0, 0, 1])(rotate(90, [1, 0, 0])(
        forward(PANEL_HEIGHT / 2 + PANEL_THICKNESS)(front_panel()))))
    back_piece = forward(NARROW_WIDTH)(rotate(0, [0, 0, 1])(rotate(
        90,
        [1, 0, 0])(forward(PANEL_HEIGHT / 2 + PANEL_THICKNESS)(back_panel()))))
    side = up(1.5 * PANEL_THICKNESS)(left(WIDE_WIDTH / 2)(rotate(
        90, [0, 0, 1])(rotate(90, [1, 0, 0])(forward(PANEL_HEIGHT / 2)(
            side_panel())))))
    mount = down(PANEL_THICKNESS)(right(1.5 * inches + PANEL_THICKNESS)(rotate(
        [90, 0, -90])(mount_panel())))
    # return mount
    return front + \
           back_piece + \
           mount + \
           forward((NARROW_WIDTH - PANEL_THICKNESS) / 2)(side) + \
           back((NARROW_WIDTH - PANEL_THICKNESS) / 2)(side)
예제 #14
0
def polygonbase(laserheight):
    """polygonbase

    defines the base of a polygon

    The polygon base is located in the first quadrant of the XY plane.
    A corner is at the origin. The width is parallel the y-axis.
    The laser bundle is at 24 mm in the y-direction and the laser bundle
    should be between [10.65, 13.65] mm in the z-direction.
    The height of the base is laserheight - 12.15 mm.
    The height of the base should be at least 7.2 mm. The polygon motor result
    in a protrusion.
    The laser is directed in the +x-direction. The length is oriented along
    y-axis, 21000 RPM polygon
    base could be rotated if laserbase is made smaller. New polygon base at
    24000 RPM seems to be harder to rotate.
    The polygon rotates clockwise.

    :param laserheight: the desired height of the laser, [mm]
    """
    # TODO: the polygon is larger than its, it has a negative x- and y-extent
    # BASE:
    length = 68  # [mm], y-direction
    width = 48  # [mm], x-direction
    height = laserheight - 12.5  # [mm]
    r_shaft = 2  # [mm], shaft radius
    r_head = 3.5  # [mm], head radius
    h_head = 5  # [mm], head insert
    slot_width = 2  # [mm], width slot

    def slot(r_head, h_head, r_shaft, width, height):
        """slot

        openscad styled vertically oriented printable slot
        origin formed by the center of left circle

        :param r_head: the radius of the top of the screw, [mm]
        :param h_head: the height of the top of the screw, [mm]
        :param r_shaft: the radius of the shaft of the  screw, [mm]
        :param width: the width of the slot, [mm]
        :param height: the height of the slot, [mm]
         """
        h_shaft = height - h_head - (r_head - r_shaft)
        head = cylinder(h=h_head, r=r_head, segments=30)
        # 45 degrees cone for printability
        cone = up(h_head)(cylinder(h=r_head - r_shaft,
                                   r1=r_head,
                                   r2=r_shaft,
                                   segments=30))
        shaft = up(h_head + (r_head - r_shaft))(cylinder(h=h_shaft,
                                                         r=r_shaft,
                                                         segments=30))
        cyl = head + cone + shaft
        inner = hull()(cyl, right(width)(cyl))
        cyl = cylinder(h=height, r=r_head + THICK_WALL)
        outer = hull()(cyl, right(width)(cyl))
        slot = outer - hole()(inner)
        return slot

    wall_slot = slot(r_head, h_head, r_shaft, slot_width, height)
    base = translate([3.1, length - 4, 0])(wall_slot)
    base += translate([3.2, 4 + 1.29, 0])(rotate([0, 0, -50])(wall_slot))
    spiegel = right(width)(mirror([1, 0, 0])(base))
    base += spiegel
    return base
예제 #15
0
def onderkantbox(down):
    """onderkantbox

    constructs the bottom part of the box
    :param down: if true ray will be directed downward
    """
    # construct a base
    # height wall ; earlier experiments ; 40 (bottom) + 25 (top)
    height = 65
    base = cube([LENGTH_TOP, WIDTH_TOP, THICK_WALL + height])
    base -= translate([THICK_WALL, THICK_WALL, THICK_WALL])(cube(
        [LENGTH_TOP - 2 * THICK_WALL, WIDTH_TOP - 2 * THICK_WALL, height]))
    # NOTE the order in which objects are placed is important
    #     there can be coflicts between the stickit/panel mount and the
    #     mirror mount
    #     most likely this is due to the inner workings of the hole function

    # the polygon is the lowest part, for certainty its offset is set at
    # THICK_WALL laser_y = 24 (polygon) + 2 * THICK_WALL
    # as a result y-offset laserbase is  laser_y - 0.5 * 30 (width laserbase)
    # the y-offset mirror base=laser_y-0.5*light_hole-THICK_WALL-INSERT_MIRROR
    # the x-offset of the laserbase is 0,
    # it comes with an integrated ventilation
    # the x-offset of the polygon is  75 (length_base) + 10 (laserlens)
    # the x-offset mirror is 75 + 10 + 48 (width polygon) + THICK WALL (safety
    # margin) TODO: for an unknown reason the stickit nead to be added first
    #       other wise the photodiode mount will be effected
    # add stick
    base += translate([THICK_WALL + 90, WIDTH_TOP, 0])(xulaconnector())
    # add laser base
    laser_y = 24 + 2 * THICK_WALL
    base += translate([0, laser_y - 0.5 * 30, 0])(laserbase(LASER_HEIGHT))
    # add polygon 4 is space for square
    base += translate([75 + 10 + 4, 2 * THICK_WALL,
                       0])(polygonbase(LASER_HEIGHT))
    # add mirror; y position is corrected for mirror_insert,
    # thick wall +8 (square) and light hole
    base += translate([75 + 10 + 48 + THICK_WALL + 8, laser_y,
                       0])(mirrormount(down, LASER_HEIGHT))

    # add exits DC barrels
    r_barrel = 6.6
    dcbarrel = rotate([90, 0, 0])(cylinder(r=r_barrel,
                                           h=2 * THICK_WALL,
                                           segments=30))
    # NOTE: offset between DC barrels should
    #       be larger than radius due to extent
    base -= translate([
        THICK_WALL + r_barrel + 10, WIDTH_TOP, THICK_WALL + r_barrel * 2
    ])(dcbarrel + up(2 * r_barrel + 4 + THICK_WALL)(dcbarrel))
    # add exit for microusb (also has width of DC barrel)
    base -= translate(
        [LENGTH_TOP - THICK_WALL, WIDTH_TOP - 23.2,
         THICK_WALL + 11 + 23])(rotate([0, 0, 90])(dcbarrel))
    # add mount belt
    mount_box = cube([10, 30, 50])
    base -= translate(
        [LENGTH_TOP - THICK_WALL, WIDTH_TOP - 60, THICK_WALL + 15])(mount_box)
    base += translate(
        [LENGTH_TOP - THICK_WALL, WIDTH_TOP - 60, THICK_WALL + 15])(boxmount())
    # you need to create room mirror
    if down:
        # TODO: remove manual fixed parameters
        #        manual fix parameters; x 10 shift and y extent 20
        base -= translate(
            [75 + 10 + 48 + THICK_WALL + 10, laser_y - 0.5 * light_hole,
             0])(cube([20, light_hole, THICK_WALL]))

    # add two cable ties;
    #   corner
    # base += translate([LENGTH_TOP - 18, WIDTH_TOP - 10, THICK_WALL])
    #   (cable_fasten(TIE_HEIGHT, TIE_WIDTH, THICK_WALL, True))
    #   laserbase
    base += translate([75 - 10, WIDTH_TOP - 20,
                       THICK_WALL])(cable_fasten(TIE_HEIGHT, TIE_WIDTH,
                                                 THICK_WALL, False))
    # add fasteners at corners
    #  bottom left and upper right corner
    upshift = THICK_WALL + height - HEIGHT_TOP + THICK_WALL
    base += translate([SCREW_FIXOFFST, SCREW_FIXOFFST,
                       upshift])(threadedinsert(True, THICK_WALL, 4.0, 5.8))
    base += translate(
        [LENGTH_TOP - SCREW_FIXOFFST, WIDTH_TOP - SCREW_FIXOFFST,
         upshift])(threadedinsert(False, THICK_WALL, 4.0, 5.8))
    base += translate([LENGTH_TOP - SCREW_FIXOFFST, SCREW_FIXOFFST,
                       upshift])(threadedinsert(True, THICK_WALL, 4.0, 5.8))
    base += translate([SCREW_FIXOFFST, WIDTH_TOP - SCREW_FIXOFFST,
                       upshift])(threadedinsert(False, THICK_WALL, 4.0, 5.8))
    base = mirror([0, 1, 0])(base)
    return base
예제 #16
0
def mirrormount(down, laserheight):
    """mirrormount

    A 25 mm x 25 mm square and 2 mm thick first sided mirror is used to refract
    the ray downward or upward. The thickness is in the +x-direction.
    This mirror is tilted at a 45 degrees and is positioned by a holder.
    The holder is put in place via two pillars.
    A photodiode mount is placed into these pillars to detect the laser motion.
    It is important that the photodiode is at the correct height
    The photodiode_height is LASER_HEIGHT-2.5, to ensure the laser hits the
    photodiode at its center.
    :param down: if true downward refraction, if false upward refraction
    :param laserheight: height laser bundle, [mm]
    """
    width_mirror = 25  # [mm]
    # thickness y+ pillar, y- pillar is insert+THICK_wall
    tpillar_left = 14  # [mm]
    insert_mirror = 5  # [mm]
    thick_mirror = 2  # [mm]
    # height_mirror < photodiode_height
    height_mirror = laserheight - 6  # [mm]
    # 4.5 determined via felix printed box
    photodiode_height = laserheight - 4.5  # [mm]
    cable_guide = 2  # [mm]
    # sensor width with cables is 5.6 (measurement @diode)
    sensor_width = 2  # [mm]
    # sensor height is 4 (measurement @ photodiode)
    sensor_height = 4.5  # [mm]
    sensor_insert = 2  # [mm] diode thickness i 2 @ measured
    # margin is needed for FFF printer
    margin = 0.5  # [mm]
    # defines the thickness of the holder
    thick = 1.3  # [mm]
    # offset constraint set by upward proj. due to cable collision possibility
    offset = 19  # [mm] offset sensor pole
    x_width = 0.5 * sqrt(2) * (thick_mirror + margin + 2 * thick)
    # TODO: xbound seems to be an y_bound
    x_bound = 0.5 * sqrt(2) * (2 * thick + width_mirror + margin) + x_width
    y_bound = offset + THICK_WALL + sensor_insert

    holder = cube([
        thick_mirror + margin + 2 * thick,
        light_hole + THICK_WALL + insert_mirror + tpillar_left,
        width_mirror + margin + 2 * thick
    ])

    holder_inner = translate([thick, 0, thick])(cube([
        thick_mirror + margin, light_hole + tpillar_left + insert_mirror,
        width_mirror + margin
    ]))
    # the holder can contain left over of filament.
    # To remove these left over a cleaning hole is needed.
    holder_inner += translate([thick, 0, thick + width_mirror + margin])(cube(
        [thick_mirror + margin, tpillar_left - THICK_WALL, thick]))

    holder -= hole()(holder_inner)
    # up mirror
    holder = up(height_mirror)(rotate([0, 45, 0])(holder))
    # pillars
    # light exit has a width of light_hole
    # pillars are next to this exit point and have a width of tpillar_left,
    # and THICK_WALL + insert_mirror
    mount_mirror = cube([
        x_width, light_hole + tpillar_left + THICK_WALL + insert_mirror,
        height_mirror
    ])
    mount_mirror += holder
    # create pocket for light 2x is for certainty
    mount_mirror -= forward(tpillar_left)(cube(
        [2 * width_mirror, light_hole, 2 * width_mirror]))
    if not down:
        mount_mirror = right(x_bound)(mirror([1, 0, 0])(mount_mirror))

    # add mount photodiode
    # the photodiode is at height photodiode_height mm
    # the cable guides are cable_guide mm thick, the pins of the photodiode
    # are sensor width displaced, the photodiode is sensor height tall
    # the photodiode sensor insert is sensor_insert, the wall between light
    # exit and sensor is fixed at 1 mm, kept small to get maximum out of light
    # path. The top has a three time thickness, to create a connection between
    # mirror and pole
    enclosure = cube([
        THICK_WALL + sensor_insert,
        cable_guide * 2 + sensor_width + THICK_WALL + 1,
        sensor_height + photodiode_height + 2 * THICK_WALL
    ])
    photodiode = cube([
        sensor_insert + THICK_WALL, cable_guide * 2 + sensor_width,
        sensor_height
    ])
    # substract central pillar
    photodiode -= translate([0, cable_guide, 0
                             ])(cube([THICK_WALL, sensor_width,
                                      sensor_height]))
    # combine pole with photodiode housing
    pole = enclosure - hole()(translate([0, 1, photodiode_height])(photodiode))

    combined = mount_mirror + translate([offset, tpillar_left + light_hole, 0
                                         ])(pole)
    # a trafo is executed to simplify positioning;
    # light should be centered at y=0
    combined = translate([y_bound, tpillar_left + 0.5 * light_hole,
                          0])(mirror([1, 0, 0])(mirror([0, 1, 0])(combined)))
    # add tie-wrap
    # TODO: remove custom parameters
    fasten = translate([9, tpillar_left + 9,
                        0])(cable_fasten(TIE_HEIGHT, TIE_WIDTH, THICK_WALL,
                                         True))
    combined += fasten

    return combined
예제 #17
0
def slit():
    return rotate(a=back_bend_degrees)(
        forward(y_offset)(
            union()(hull()(
                circle(r=radius) + forward(height)(circle(r=radius))))))
예제 #18
0
def generate_skyline_stl(username, year, running_matrix):
    """
    Some code of this function is from https://github.com/felixgomez/gitlab-skyline
    """
    max_run_distance = max(running_matrix)
    total_run_distance = sum(running_matrix)
    base_top_width = 23
    base_width = 30
    base_length = 150
    base_height = 10
    max_length_run_distance = 40
    bar_base_dimension = 2.5

    base_top_offset = (base_width - base_top_width) / 2
    face_angle = math.degrees(math.atan(base_height / base_top_offset))

    base_points = [
        [0, 0, 0],
        [base_length, 0, 0],
        [base_length, base_width, 0],
        [0, base_width, 0],
        [base_top_offset, base_top_offset, base_height],
        [base_length - base_top_offset, base_top_offset, base_height],
        [base_length - base_top_offset, base_width - base_top_offset, base_height],
        [base_top_offset, base_width - base_top_offset, base_height],
    ]

    base_faces = [
        [0, 1, 2, 3],  # bottom
        [4, 5, 1, 0],  # front
        [7, 6, 5, 4],  # top
        [5, 6, 2, 1],  # right
        [6, 7, 3, 2],  # back
        [7, 4, 0, 3],  # left
    ]

    base_scad = polyhedron(points=base_points, faces=base_faces)

    year_scad = rotate([face_angle, 0, 0])(
        translate(
            [
                base_length - base_length / 5,
                base_height / 2 - base_top_offset / 2 - 1,
                -1.5,
            ]
        )(linear_extrude(height=2)(text(str(year), 6)))
    )

    user_scad = rotate([face_angle, 0, 0])(
        translate([base_length / 4, base_height / 2 - base_top_offset / 2, -1.5])(
            linear_extrude(height=2)(text("@" + username, 5))
        )
    )

    total_scad = rotate([face_angle, 0, 0])(
        translate(
            [
                base_length - base_length / 3 - 17,
                base_height / 2 - base_top_offset / 2,
                -1.5,
            ]
        )(linear_extrude(height=2)(text(str(round(total_run_distance, 1)) + " km", 5)))
    )

    running_scad = rotate([face_angle, 0, 0])(
        translate([base_length / 12, base_height / 2 - base_top_offset / 2, -1])(
            linear_extrude(height=2)(text("Running", 5))
        )
    )

    bars = None

    week_number = 1
    for i in range(len(running_matrix)):

        day_number = i % 7
        if day_number == 0:
            week_number += 1

        if running_matrix[i] == 0:
            continue

        bar = translate(
            [
                base_top_offset + 2.5 + (week_number - 1) * bar_base_dimension,
                base_top_offset + 2.5 + day_number * bar_base_dimension,
                base_height,
            ]
        )(
            cube(
                [
                    bar_base_dimension,
                    bar_base_dimension,
                    running_matrix[i] * max_length_run_distance / max_run_distance,
                ]
            )
        )

        if bars is None:
            bars = bar
        else:
            bars += bar

    scad_running_filename = "running_" + username + "_" + str(year)
    scad_skyline_object = base_scad - running_scad + user_scad + total_scad + year_scad

    if bars is not None:
        scad_skyline_object += bars

    scad_render_to_file(scad_skyline_object, scad_running_filename + ".scad")

    subprocess.run(
        [
            "openscad",
            "-o",
            scad_running_filename + ".stl",
            scad_running_filename + ".scad",
        ]
    )

    print("Generated STL file " + scad_running_filename + ".stl")
예제 #19
0
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)
예제 #20
0
파일: 3Dground.py 프로젝트: thomasgas/CREED
def tilted_grid(event, tel_pos=False, zen_az_arrows=False):
    """
    Return the telescopes positions in the TiltedGroundFrame and plot them according to azimuth and zenith of simulation
    :param event: event selected from simtel
    :param tel_pos: (bool) If True, plot the telescopes as spheres
    :param zen_az_arrows: plot curved arrows for ZEN and AZ in titled ref frame
    :return:
    """
    alt = event.mcheader.run_array_direction[1]
    az = event.mcheader.run_array_direction[0]

    array_pointing = HorizonFrame(alt=alt, az=az)
    ground_coordinates = GroundFrame(
        x=event.inst.subarray.tel_coords.x,
        y=event.inst.subarray.tel_coords.y,
        z=event.inst.subarray.tel_coords.z,  # *0+15.0*u.m,
        pointing_direction=array_pointing)

    tilted_system = TiltedGroundFrame(pointing_direction=array_pointing)

    tilted = ground_coordinates.transform_to(tilted_system)

    grid_unit = 20000  # in centimeters
    tilted_system = union()

    # ADD TELESCOPES AS SPHERES
    if tel_pos:
        # for i in range(tilted.x.size):
        for i in range(50):
            coords = [100 * tilted.x[i].value, 100 * tilted.y[i].value]
            position = translate(coords)(color([1, 0, 0])(sphere(r=800)))
            tilted_system.add(position)

    # add GRID
    grid_tilted = grid_plane(
        grid_unit=grid_unit,
        count=2 *
        int(100 * np.max(np.abs(ground_coordinates.x.value)) / grid_unit),
        line_weight=200,
        plane='xy')

    grid_tilted = color([1, 0, 0, 0.5])(grid_tilted)
    grid_tilted = grid_tilted + ref_arrow_2d(
        8000, label={
            'x': "x_tilted",
            'y': "y_tilted"
        }, origin=(0, 0))

    tilted_system = rotate([0, 90 - alt.to('deg').value,
                            az.to('deg').value])(tilted_system)
    tilted_system.add(grid_tilted)

    arr_curved_az = color([1, 1, 0])(rot_arrow(8000,
                                               az.to('deg').value,
                                               0,
                                               label='AZ'))
    tilted_system.add(arr_curved_az)
    arr_curved_alt = color([1, 0, 1])(rot_arrow(8000,
                                                0,
                                                90 - alt.to('deg').value,
                                                label='ZEN'))
    arr_curved_alt = rotate([90, 0, 0])(arr_curved_alt)
    tilted_system.add(arr_curved_alt)

    return tilted_system
예제 #21
0
def hscrew(head_r, head_height, shaft_r, length):
    """horizontal screw


    a horizontal screw consists out of three parts
    * a cylinder in the wall
    * possible a continuation of the head insert
    * shaft piece
    algorithm ensures it is printable
    param head_height: height head screw
    param head_r: radius head screw
    param shaft_r: radius shaft screw
    param lenght: lenght screw
    """
    # cylinder in the wall
    if head_height > THICK_WALL:
        shift = head_height - THICK_WALL
        cyl_wall = cylinder(h=THICK_WALL, r=head_r + THICK_WALL, segments=30)
        cyl_mid = up(THICK_WALL)(cylinder(h=shift,
                                          r1=head_r + shift + THICK_WALL,
                                          r2=head_r + THICK_WALL,
                                          segments=30))
        hscrew = cyl_mid + cyl_wall
    else:
        hscrew = cylinder(h=head_height, r=head_r + THICK_WALL, segments=30)

    # two cases:
    if length - head_height > head_height:
        shift = length - THICK_WALL
        cyl_shaft = up(head_height)(cylinder(h=shift,
                                             r1=shaft_r + shift + THICK_WALL,
                                             r2=shaft_r + THICK_WALL,
                                             segments=30))
    else:
        cyl_shaft = up(head_height)(cylinder(h=length - head_height,
                                             r1=head_r + THICK_WALL,
                                             r2=shaft_r + THICK_WALL,
                                             segments=30))

    hscrew += cyl_shaft
    hscrew = rotate([90, 0, 0])(hscrew)
    # gravity only one direction --> minimize in this direction
    # shaft
    field = cube([
        2 * (shaft_r + THICK_WALL), length - head_height,
        length + 2 * shaft_r + THICK_WALL
    ])
    field = translate([-shaft_r - THICK_WALL, -length,
                       -(length + shaft_r)])(field)
    sscrew = hscrew * field
    # top
    if head_height > THICK_WALL:
        field = cube([
            2 * (head_r + THICK_WALL), head_height,
            length + 2 * head_r + THICK_WALL
        ])
        field = translate(
            [-head_r - THICK_WALL, -head_height, -(length + head_r)])
        (field)
        tscrew = hscrew * field
    else:
        tscrew = rotate([90, 0, 0])(cylinder(h=head_height,
                                             r=head_r + THICK_WALL,
                                             segments=30))

    hscrew = tscrew + sscrew
    cyl_top = down(0.1)(cylinder(h=head_height + 0.1, r=head_r, segments=30))
    cyl_shaft = up(head_height - 0.1)(cylinder(h=length - head_height + 0.1,
                                               r=shaft_r,
                                               segments=30))
    interior = rotate([90, 0, 0])(cyl_shaft + cyl_top)
    omg = hscrew - hole()(interior)
    # OMG HOLE is buggy; hscrew-=hole()(interior) does not always work
    return omg
예제 #22
0
def coffee_cover(diameter):
    height = 19 * mm
    thickness = 2 * mm
    notch = forward(diameter / 2 - 5 * mm)(
        (up(height)(rotate([-90, 0, 0])(cylinder(r=12 * mm, h=10 * mm)))))
    return cup(diameter, height, thickness, segments=96) - notch
예제 #23
0
def v_channel(length):
    return rotate([0, 0, 45.0])(cube([CUBE_WIDTH, CUBE_WIDTH, length],
                                     center=True))
예제 #24
0
def back_pegs(single_peg, shape, margin):
    return up(shape[2] / 2)(left(shape[0] / 2)(rotate([0, 90, 0])(grid_pegs(
        single_peg,
        centered_grid(width=shape[2], length=shape[1], margin=margin)))))
예제 #25
0
def telescope(tel_description,
              camera_display_bool,
              pointing,
              origin,
              tel_num='0',
              ref_camera=True,
              ref_tel=False,
              sim_to_real=False):
    """
    Create telescope. Implemented only 'LST' by now. Everything is somehow in centimeters.
    :param tel_description: string for telescope type. 'LST', 'MST', ecc.
    :param camera_display_bool: input from camera_event.py loaded another event.
    :param pointing: dictionary for pointing directions in degrees above horizon, {'alt': val, 'az': val}
    :param origin: (x, y, z) position of the telescope
    :param tel_num: (int) Telescope ID to be plotted with the telescope
    :param ref_camera: (bool) create ref frame on camera
    :param ref_tel: (bool) create ref frame at the center of the telescope...TODO: needed?
    :param sim_to_real: (bool) WITHOUT THIS THE CAMERA IS IN CTAPIPE VISUALIZATION != REAL WORLD
    :return: geometry for the telescope.

    TODO: create real substructure for telescope?
    """

    DC_list = ['LSTCam', 'FlashCam', 'NectarCam', 'DigiCam']
    SC_list = ['SCTCam', 'ASTRICam', 'CHEC']

    # unpack camera_display values
    camera_display = camera_display_bool[0]
    bool_trig = camera_display_bool[1]

    if bool_trig:
        color_trig = [1, 0, 0]
    else:
        color_trig = [0, 1, 0]

    telescope_struct = union()

    tel_type = tel_description.split(':')[0]
    camera_name = tel_description.split(':')[1]

    if camera_name in DC_list:
        if tel_type == 'LST':
            # create mirror plane
            mirror_plane = mirror_plane_creator(tel_type=tel_type, radius=1150)

            # define arch
            arch = union()
            x_arco = np.linspace(-2200 / 2, 2200 / 2, 50)
            y_arco = 4 / 2300 * x_arco**2
            arch_struct = color([1, 0, 0])(arco(x_arco, y_arco, 30))
            arch_struct = multmatrix(m=rotation(-90, 'y'))(arch_struct)
            arch_struct = multmatrix(m=rotation(-90, 'x'))(arch_struct)
            arch.add(arch_struct)

            arch = translate([0, 0, np.max(y_arco) - 200])(arch)

            # append camera to arch
            camera_frame = cube([400, 400, 190], center=True)

            if sim_to_real:
                camera_display = multmatrix(
                    m=rotation(90, 'z'))(camera_display)
                camera_display = multmatrix(
                    m=rotation(180, 'x'))(camera_display)

            # check for arrows in reference frame
            camera_frame = camera_frame + camera_display

            if ref_camera:
                arrow_camera = ref_arrow_2d(500,
                                            label={
                                                'x': "x_cam",
                                                'y': "y_cam"
                                            },
                                            origin=(0, 0))
                arrow_camera = multmatrix(m=rotation(180, 'x'))(arrow_camera)
                camera_frame = camera_frame + arrow_camera

            # ADD camera_frame and camera display to arch structure
            arch.add(camera_frame)

            # put together arch and mirror plane
            telescope_struct.add(arch)
            telescope_struct.add(mirror_plane)
            # telescope_struct = translate([0, 0, 450])(telescope_struct)

        elif tel_type == 'MST':
            radius = 600
            height = 1800
            ratio_cam = 2
            mirror_plane = mirror_plane_creator(tel_type=tel_type,
                                                radius=radius)
            telescope_struct.add(mirror_plane)

            # add the long spiders to the structure
            structure = struct_spider(height, radius, radius / ratio_cam)

            # create camera structure with ref arrow and overplot the event
            side_cam = 2 * (radius / ratio_cam) / np.sqrt(2)
            camera_frame = cube([side_cam, side_cam, 100], center=True)
            if sim_to_real:
                camera_display = multmatrix(
                    m=rotation(90, 'z'))(camera_display)
                camera_display = multmatrix(
                    m=rotation(180, 'x'))(camera_display)
            camera_frame = camera_frame + camera_display

            # check for arrows in reference frame
            if ref_camera:
                arrow_camera = ref_arrow_2d(500,
                                            label={
                                                'x': "x_cam",
                                                'y': "y_cam"
                                            },
                                            origin=(0, 0))
                arrow_camera = multmatrix(m=rotation(180, 'x'))(arrow_camera)
                camera_frame = camera_frame + arrow_camera

            camera_frame = translate([0, 0, 110])(camera_frame)

            # raise to top of telescope, minus 30 cm in order to look nicer
            camera_frame = translate([0, 0, height - 30])(camera_frame)
            structure = structure + camera_frame

            # add structure, camera frame and camera on the telescope structure
            telescope_struct.add(structure)
            # telescope_struct = translate([0, 0, -150])(telescope_struct)

        elif tel_type == 'SST-1M':
            # TODO: CREATE MODEL FOR SST 1-M: re-use the MST
            print("sst")
            pass

    elif camera_name in SC_list:
        pass
        if tel_type == 'MST-SCT':
            print("MST-SCT")
        elif tel_type == 'SST:ASTRI':
            print("SST:ASTRI")
        elif tel_type == 'SST-GCT':
            print("SST-GCT")
    else:
        print("NO tel_name FOUND")
        sys.exit()

    telescope_struct = multmatrix(m=rotation(-90, 'z'))(telescope_struct)

    # rotate to pointing. First move in ALTITUDE and then in AZIMUTH
    zen = 90 - pointing['alt'].value
    az = pointing['az'].value
    telescope_struct = multmatrix(m=rotation(zen, 'y'))(telescope_struct)
    telescope_struct = multmatrix(m=rotation(-az, 'z'))(telescope_struct)

    # ADD TELESCOPE ID
    print(tel_num, tel_type)
    tel_number = color(color_trig)(linear_extrude(100)(text(text=str(tel_num),
                                                            size=10000,
                                                            spacing=0.1)))
    tel_number = rotate((0, 0, az + 90))(tel_number)
    tel_number = translate((origin[0] - 700, origin[1] - 700, 0))(tel_number)
    telescope_struct = translate(list(origin))(telescope_struct)
    telescope_struct = telescope_struct + tel_number

    return telescope_struct
예제 #26
0
def punch_hole(diameter, thickness):
    return rotate(90, [1, 0, 0])(cylinder(r=diameter / 2,
                                          h=thickness * 2,
                                          center=True,
                                          segments=16))