示例#1
0
def square(g, mat, dx, dy, fill: bool):
    with GContext(g):
        g.relative()

        if fill:
            num_lines = int(math.ceil(abs(dy) /
                                      (mat['tool_size'] * OVERLAP))) + 1

            line_step = 0
            if num_lines > 1:
                line_step = dy / (num_lines - 1)

            g.comment("Square fill={0}".format(fill))
            is_out = False
            for i in range(0, num_lines):
                if is_out:
                    g.move(x=-dx)
                else:
                    g.move(x=dx)
                is_out = not is_out
                if i < num_lines - 1:
                    g.move(y=line_step)

            if is_out:
                g.move(x=-dx)
            g.move(y=-dy)

        else:
            g.move(x=dx)
            g.move(y=dy)
            g.move(x=-dx)
            g.move(y=-dy)
示例#2
0
def hole_abs(g, mat, cut_depth, radius, x, y):
    with GContext(g):
        g.absolute()
        g.feed(mat['travel_feed'])
        g.move(z=CNC_TRAVEL_Z)
        g.move(x=x, y=y)
        hole(g, mat, cut_depth, r=radius)
        g.absolute()
示例#3
0
def board(g, mat, stock_height):
    with GContext(g):
        g.absolute()

        bolt(g, mat, stock_height, 0.5,  0.5)
        bolt(g, mat, stock_height, 0.5,  7.5)
        bolt(g, mat, stock_height, 7.5,  0.5)
        bolt(g, mat, stock_height, 7.5,  7.5)
        bolt(g, mat, stock_height, 4.75, 4.0)

        # get back to the origin, assuming the next step is a plane
        travel(g, mat, x=0, y=0)
        g.move(z=0)
示例#4
0
def drill_points(g, mat, cut_depth, points):
    with GContext(g):
        g.absolute()
        sort_shortest_path(points)

        for p in points:
            g.feed(mat['travel_feed'])
            g.move(z=CNC_TRAVEL_Z)
            g.move(x=p['x'], y=p['y'])
            g.move(z=0)
            drill(g, mat, cut_depth)

        # Leaves the head at CNC_TRAVEL_Z)
        g.move(z=CNC_TRAVEL_Z)
        g.move(x=0, y=0)
示例#5
0
def overCut(g, mat, cut_depth, _dx, _dy):
    g.feed(mat['travel_feed'])
    g.spindle('CW', mat['spindle_speed'])

    with GContext(g):
        g.relative()

        tool = mat['tool_size']
        half = tool / 2
        dx = _dx - tool
        dy = _dy - tool
        length = dx * 2 + dy * 2

        g.move(z=1)
        g.move(x=half, y=half)
        g.move(z=-1)

        def path(g, plunge, total_plunge):
            g.move(x=dx, z=plunge * dx / length)
            g.move(x=half)
            g.move(x=-half, y=-half)
            g.move(y=half)

            g.move(y=dy, z=plunge * dy / length)
            g.move(y=half)
            g.move(x=half, y=-half)
            g.move(x=-half)

            g.move(x=-dx, z=plunge * dx / length)
            g.move(x=-half)
            g.move(x=half, y=half)
            g.move(y=-half)

            g.move(y=-dy, z=plunge * dy / length)
            g.move(y=-half)
            g.move(x=-half, y=half)
            g.move(x=half)

        steps = calc_steps(cut_depth, -mat['pass_depth'])
        run_3_stages(path, g, steps)

        g.move(z=-cut_depth)
        g.move(z=1)
        g.move(x=-half, y=-half)
        g.move(z=-1)
示例#6
0
def plane(g, mat, depth, x0, y0, x1, y1):
    dx = x1 - x0
    dy = y1 - y0

    # print("plane", dx, dy)

    with GContext(g):
        g.comment("Plane depth = {} size = {}, {}".format(depth, dx, dy))
        g.relative()

        g.spindle('CW', mat['spindle_speed'])
        g.feed(mat['feed_rate'])
        g.move(x=x0, y=y0)

        z = 0
        while (z > depth):
            dz = -mat['pass_depth']
            if z + dz < depth:
                dz = depth - z
                z = depth
            else:
                z = z + dz

            # first line to distribute depth cut.
            g.move(x=dx, z=dz / 2)
            g.move(x=-dx, z=dz / 2)

            # nice edges
            g.move(x=dx)
            g.move(y=dy)
            g.move(x=-dx)
            g.move(y=-dy)

            # now the business of cutting.
            square(g, mat, dx, dy, True)

        g.move(z=-depth)
        g.move(x=-x0, y=-y0)
示例#7
0
def drill(g, mat, cut_depth):
    if cut_depth >= 0:
        raise RuntimeError('Cut depth must be less than zero.')

    with GContext(g):
        g.relative()

        num_plunge = 1 + int(-cut_depth / (0.05 * mat['plunge_rate']))
        dz = cut_depth / num_plunge

        g.comment("Drill depth={} num_taps={}".format(cut_depth, num_plunge))
        g.spindle('CW', mat['spindle_speed'])
        g.feed(mat['plunge_rate'])

        if num_plunge > 1:
            # move up and down in stages.
            for i in range(0, num_plunge):
                g.move(z=dz)
                g.move(z=-dz)
                g.move(z=dz)
        else:
            g.move(z=cut_depth)

        g.move(z=-cut_depth)
示例#8
0
def hill(g, mat, diameter, dx, dy):
    r_hill = diameter / 2
    ht = mat['tool_size'] * 0.5
    hy = dy / 2
    doc = mat['pass_depth']
    step = 0.5

    def rough_arc(bias):
        y = 0
        end = hy + ht
        last_plane = 0
        last_y = 0
        step = ht / 4

        g.move(x=dx)
        g.move(x=-dx / 2)

        while y < end:
            do_plane = False

            y += step
            if y >= end:
                do_plane = True
                y = end
            if last_plane - height_func(y + step, ht, r_hill) >= doc:
                do_plane = True

            if do_plane:
                # move to the beginning of the plane
                g.move(y=bias * (y - last_y))

                # cut the plane
                z = height_func(y, ht, r_hill)
                dz = z - last_plane
                g.comment("Cutting plane. y={} z={} dx={} dy={} dz={}".format(
                    y, z, dx, end - y, dz))
                rectangleTool(g, mat, dz, dx, end - y, 0.0,
                              "bottom" if bias > 0 else "top", "center", True)

                # move to the bottom of the plane we just cut
                g.move(z=dz)
                g.comment("Cutting plane done.")

                last_y = y
                last_plane += dz

        g.move(-dx / 2)
        g.abs_move(z=origin_z)
        g.move(y=-end * bias)

    def arc(bias, step):
        y = 0
        low_x = True
        end = hy + ht

        while y < end:
            if y + step > end:
                g.move(y=(end - y) * bias)
                y = end
            else:
                y += step
                g.move(y=step * bias)

            dz = height_func(y, ht, r_hill)
            g.feed(mat['plunge_rate'])
            g.abs_move(z=origin_z + dz)
            g.feed(mat['feed_rate'])

            if low_x is True:
                g.move(x=dx)
                low_x = False
            else:
                g.move(x=-dx)
                low_x = True

        if low_x is False:
            g.move(x=-dx)
        g.abs_move(z=origin_z)
        g.move(y=-end * bias)

    with GContext(g):
        g.comment('hill')
        g.relative()
        mult = 0.2

        # rough pass
        origin_z = g.current_position['z']

        g.spindle()
        g.dwell(0.5)
        g.spindle('CW', mat['spindle_speed'])
        rough_arc(1)

        g.spindle()
        g.dwell(0.5)
        g.spindle('CCW', mat['spindle_speed'])
        rough_arc(-1)

        # smooth pass
        g.spindle()

        g.spindle()
        g.dwell(0.5)
        g.spindle('CW', mat['spindle_speed'])

        arc(1, mult * ht)

        g.spindle()
        g.dwell(0.5)
        g.spindle('CCW', mat['spindle_speed'])

        arc(-1, mult * ht)

        g.spindle()
示例#9
0
def hole(g, mat, cut_depth, **kwargs):
    radius = 0
    offset = "inside"
    fill = True
    di = None

    if 'r' in kwargs:
        radius = kwargs['r']
    if 'd' in kwargs:
        radius = kwargs['d'] / 2
    if 'offset' in kwargs:
        offset = kwargs['offset']
    if 'fill' in kwargs:
        fill = kwargs['fill']
    if 'di' in kwargs:
        di = kwargs['di']

    tool_size = mat['tool_size']
    half_tool = tool_size / 2

    if offset == 'inside':
        radius_inner = radius - half_tool
    elif offset == 'outside':
        radius_inner = radius + half_tool
    elif offset == 'middle':
        radius_inner = radius
    else:
        raise RuntimeError("offset not correctly specified")

    if radius_inner < 0.2:
        raise RuntimeError("Radius too small. Consider a drill.")
    if cut_depth >= 0:
        raise RuntimeError('Cut depth must be less than zero.')
    if mat["tool_size"] < 0:
        raise RuntimeError('Tool size must be zero or greater.')

    was_relative = g.is_relative

    with GContext(g):
        g.relative()

        g.comment("hole")
        g.comment("depth=" + str(cut_depth))
        g.comment("tool size=" + str(mat['tool_size']))
        g.comment("radius=" + str(radius))
        g.comment("pass depth=" + str(mat['pass_depth']))
        g.comment("feed rate=" + str(mat['feed_rate']))
        g.comment("plunge rate=" + str(mat['plunge_rate']))

        # The trick is to neither exceed the plunge or the depth-of-cut/pass_depth.
        # Approaches below.

        feed_rate = mat['feed_rate']
        path_len_mm = 2.0 * math.pi * radius_inner
        path_time_min = path_len_mm / feed_rate
        plunge_from_path = mat['pass_depth'] / path_time_min
        depth_of_cut = mat['pass_depth']

        # Both 1) fast little holes and 2) too fast plunge are bad.
        # Therefore, apply corrections to both. (If for some reason
        # alternate approaches need to be reviewed, they are in
        # source control.)
        if plunge_from_path > mat['plunge_rate']:
            factor = mat['plunge_rate'] / plunge_from_path
            if factor < 0.3:
                factor = 0.3  # slowing down to less than 10% (factor * factor) seems excessive
            depth_of_cut = mat['pass_depth'] * factor
            feed_rate = mat['feed_rate'] * factor
            g.comment('adjusted pass depth=' + str(depth_of_cut))
            g.comment('adjusted feed rate =' + str(feed_rate))

        g.spindle('CW', mat['spindle_speed'])
        g.feed(mat['travel_plunge'])

        g.move(x=radius_inner)
        if 'z' in kwargs:
            if was_relative:
                g.move(z=kwargs['z'])
            else:
                g.abs_move(z=kwargs['z'])

        g.feed(feed_rate)

        def path(g, plunge, total_plunge):
            g.arc2(x=-radius_inner,
                   y=radius_inner,
                   i=-radius_inner,
                   j=0,
                   direction='CCW',
                   helix_dim='z',
                   helix_len=plunge / 4)
            g.arc2(x=-radius_inner,
                   y=-radius_inner,
                   i=0,
                   j=-radius_inner,
                   direction='CCW',
                   helix_dim='z',
                   helix_len=plunge / 4)
            g.arc2(x=radius_inner,
                   y=-radius_inner,
                   i=radius_inner,
                   j=0,
                   direction='CCW',
                   helix_dim='z',
                   helix_len=plunge / 4)
            g.arc2(x=radius_inner,
                   y=radius_inner,
                   i=0,
                   j=radius_inner,
                   direction='CCW',
                   helix_dim='z',
                   helix_len=plunge / 4)

            if fill and radius_inner > half_tool:
                r = radius_inner
                dr = 0
                step = tool_size * 0.8
                min_rad = half_tool * 0.8
                if di:
                    min_rad = di / 2

                while r > min_rad:
                    if r - step < min_rad:
                        step = r - min_rad
                    r -= step

                    #print("r={} step={}".format(r, step))

                    dr += step
                    g.move(x=-step)
                    g.arc2(x=-r, y=r, i=-r, j=0, direction='CCW')
                    g.arc2(x=-r, y=-r, i=0, j=-r, direction='CCW')
                    g.arc2(x=r, y=-r, i=r, j=0, direction='CCW')
                    g.arc2(x=r, y=r, i=0, j=r, direction='CCW')
                g.move(x=dr)

        steps = calc_steps(cut_depth, -depth_of_cut)
        run_3_stages(path, g, steps)

        g.move(z=-cut_depth)  # up to the starting point
        g.feed(mat['travel_plunge'])  # go fast again...else. wow. boring.

        g.move(z=1.0)

        return_center = True
        if 'return_center' in kwargs:
            return_center = kwargs['return_center']

        if return_center:
            g.move(x=-radius_inner)  # back to center of the circle
示例#10
0
def rectangleTool(g,
                  mat,
                  cut_depth,
                  dx,
                  dy,
                  fillet,
                  origin,
                  align,
                  fill=False,
                  adjust_trim=False):

    if cut_depth >= 0:
        raise RuntimeError('Cut depth must be less than zero.')

    with GContext(g):
        g.relative()

        g.feed(mat['travel_feed'])
        g.spindle('CW', mat['spindle_speed'])

        tool_size = mat['tool_size']
        half_tool = tool_size / 2
        x = 0
        y = 0
        x_sign = 0
        y_sign = 0
        rect_origin = origin

        if origin == "left":
            x_sign = 1
        elif origin == "bottom":
            y_sign = 1
        elif origin == "right":
            x_sign = -1
        elif origin == "top":
            y_sign = -1
        elif origin == "center":
            x_sign = 1
            rect_origin = "left"
        else:
            raise RuntimeError("unrecognized origin")

        if origin == "center":
            g.move(x=-dx / 2)

        if align == 'inner':
            x = half_tool * x_sign
            y = half_tool * y_sign
            dx -= tool_size
            dy -= tool_size
            if adjust_trim:
                fillet -= half_tool
                if fillet < 0:
                    fillet = 0
        elif align == 'outer':
            x = -half_tool * x_sign
            y = -half_tool * y_sign
            dx += tool_size
            dy += tool_size
            if adjust_trim:
                if fillet > 0:
                    fillet += half_tool
        elif align == "center":
            pass
        else:
            raise RuntimeError("unrecognized align")

        if dx == 0 and dy == 0:
            raise RuntimeError('dx and dy may not both be zero')
        if dx < 0 or dy < 0:
            raise RuntimeError('dx and dy must be positive')

        if abs(x) or abs(y):
            g.move(z=CNC_TRAVEL_Z)
            g.move(x=x, y=y)
            g.move(z=-CNC_TRAVEL_Z)

        if fill == False or dx == 0 or dy == 0:
            rectangle(g, mat, cut_depth, dx, dy, fillet, rect_origin)

        else:
            z_depth = 0
            z_step = mat['pass_depth']
            single_pass = True

            # the outer loop walks downward.
            while z_depth > cut_depth:
                this_cut = 0

                if z_depth - z_step <= cut_depth:
                    this_cut = cut_depth - z_depth
                    single_pass = False
                    z_depth = cut_depth
                else:
                    this_cut = -z_step
                    z_depth -= z_step

                dx0 = dx
                dy0 = dy
                fillet0 = fillet
                step = tool_size * 0.7

                first = True
                total_step = 0

                #print("dx={} dy={}".format(dx, dy))

                # the inner loop walks inward.
                # note that the cut hasn't happened at the top of the loop;
                # so only abort when they cross
                while dx0 > 0 and dy0 > 0:
                    #print("  dx={} dy={} step={}".format(dx0, dy0, step));
                    if first:
                        first = False
                        rectangle(g,
                                  mat,
                                  this_cut,
                                  dx0,
                                  dy0,
                                  fillet0,
                                  rect_origin,
                                  single_pass=single_pass,
                                  restore_z=False)

                    else:
                        g.move(x=step * x_sign, y=step * y_sign)
                        total_step += step
                        rectangle(g,
                                  mat,
                                  0.0,
                                  dx0,
                                  dy0,
                                  fillet0,
                                  rect_origin,
                                  single_pass=True)

                    # subtle the last cut doesn't overlap itself.
                    # probably a better algorithm for this
                    if dx0 - step * 2 < 0 or dy0 - step * 2 < 0:
                        dx0 -= step
                        dy0 -= step
                    else:
                        dx0 -= step * 2
                        dy0 -= step * 2

                    fillet0 -= step
                    if fillet0 < 0:
                        fillet0 = 0

                g.move(x=-total_step * x_sign, y=-total_step * y_sign)
                # don't need to move down; z is not restored g.move(z=this_cut)
            g.move(z=-cut_depth)

        if abs(x) or abs(y):
            g.move(z=CNC_TRAVEL_Z)
            g.move(x=-x, y=-y)
            if origin == "center":
                g.move(x=dx / 2)
            g.move(z=-CNC_TRAVEL_Z)