def rectArea(area, bit_diameter):
    """ Required arguments: area (as (x=length, y=width), bit_diameter.
    Assumes that the bit is already in the origin corner at required depth of cut.
    """
    length, width = area
    if bit_diameter > length or bit_diameter > width:
        raise ValueError("Bit is too large to cut specified area")
    file_text = G.set_INCR_mode()
    # magic number 0.5 is the pass-to-pass overlap
    pass_width = bit_diameter - 0.5
    current_x = 0

    # first pass
    file_text += G.G1_Y(width - bit_diameter)

    # sentinel to track the pass direction; out is opposite to back, and the
    # bit is now ready to come back
    out = False
    while current_x < (length - bit_diameter):
        # prepare for the next pass
        # current_x = min(current_x + pass_width, length - bit_diameter)
        # file_text += G.G1_X(current_x)

        if current_x + pass_width <= length - bit_diameter:
            file_text += G.G1_X(pass_width)
            current_x = current_x + pass_width
        else:
            file_text += G.G1_X(length - bit_diameter - current_x)
            current_x = length - bit_diameter

        if out == True:
            file_text += G.G1_Y(width - bit_diameter)
        else:
            file_text += G.G1_Y(-(width - bit_diameter))

        out = not out

    # last move is a return to relative origin
    if out == True:
        # Moves straight back along original side wall
        # file_text += G.G1_XY(( -(length - bit_diameter), 0))
        # Change to: move across to other side, move straight back, then back to origin
        file_text += G.G1_Y((0, (width - bit_diameter)))
        file_text += G.G1_X((-(length - bit_diameter), 0))
        file_text += G.G0_Y((0, -(width - bit_diameter)))
    else:
        # Moves diagonally across the cut area
        # file_text += G.G1_XY(( -(length - bit_diameter), -(width - bit_diameter)))
        # Change to: move straight back, then back to origin
        file_text += G.G1_X((-(length - bit_diameter), 0))
        file_text += G.G0_Y((0, -(width - bit_diameter)))

    file_text += G.set_ABS_mode()
    return file_text
def _rectOutline(length, width, bit_diameter):
    """ Assumes it's in INCREMENTAL MODE.
    Since length and width arguments are not related to any position.
    The length and width define the outer boundaries of the cut.
    """
    # TODO: consider whether to climb-cut or not.
    # Cut the whole outline of the area, returning to the origin.
    file_text = G.G1_X(length - bit_diameter)
    file_text += G.G1_Y(width - bit_diameter)
    file_text += G.G1_X(-(length - bit_diameter))
    file_text += G.G1_Y(-(width - bit_diameter))
    return file_text
def roundedRectangle(length,
                     width,
                     corner_radius,
                     bit_diameter,
                     path_ref='outside'):
    """ Assumes it's in INCREMENTAL MODE.
    Since length and width arguments are not related to any position.
    With path_ref='outside', the length and width define the outer boundary of the cut.
    With path_ref='center', the length and width define the cut path (centerline of cut) boundary.
    With path_ref='inside', the length and width define the inner boundary of the cut.
    Assumes that the bit is already in a starting position, at least X of least Y edge;
    path_ref is not a consideration.
    """
    bit_radius = bit_diameter / 2.0
    corner_diameter = 2 * corner_radius
    if corner_radius <= 0:
        raise ValueError('corner_radius %d must be greater than 0.' %
                         corner_radius)
    if path_ref is 'outside':
        # TODO: check that corner_radius > bit_radius
        if corner_radius <= bit_radius:
            raise ValueError(
                'corner_radius %d must be greater than bit radius %d.' %
                (corner_radius, bit_radius))
        center_offset = corner_radius - bit_radius
        file_text = G.G1_X(length - corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((center_offset, center_offset),
                                         (0, center_offset))
        file_text += G.G1_Y(width - corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((-center_offset, center_offset),
                                         (-center_offset, 0))
        file_text += G.G1_X(-length + corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((-center_offset, -center_offset),
                                         (0, -center_offset))
        file_text += G.G1_Y(-width + corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((center_offset, -center_offset),
                                         (center_offset, 0))
    elif path_ref is 'center':
        file_text = G.G1_X(length - corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((corner_radius, corner_radius),
                                         (0, corner_radius))
        file_text += G.G1_Y(width - corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((-corner_radius, corner_radius),
                                         (-corner_radius, 0))
        file_text += G.G1_X(-length + corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((-corner_radius, -corner_radius),
                                         (0, -corner_radius))
        file_text += G.G1_Y(-width + corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((corner_radius, -corner_radius),
                                         (corner_radius, 0))
    elif path_ref is 'inside':
        center_offset = corner_radius + bit_radius
        file_text = G.G1_X(length - corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((center_offset, center_offset),
                                         (0, center_offset))
        file_text += G.G1_Y(width - corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((-center_offset, center_offset),
                                         (-center_offset, 0))
        file_text += G.G1_X(-length + corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((-center_offset, -center_offset),
                                         (0, -center_offset))
        file_text += G.G1_Y(-width + corner_diameter)
        file_text += G.G3XY_to_INCR_FULL((center_offset, -center_offset),
                                         (center_offset, 0))
    else:
        raise ValueError('Invalid path reference specified: %s.' % path_ref)
    return file_text