Exemple #1
0
def temple_hinge_pockets(temples):
    # We're operating in a 90 degree rotated fixture
    #l_hinge = poly.rotate_90(temples["left_hinge_contour"])
    #r_hinge = poly.rotate_90(temples["right_hinge_contour"])

    l_hinge = temples["left_hinge_contour"]
    r_hinge = temples["right_hinge_contour"]
    if not poly.is_ccw(l_hinge):
        l_hinge = poly.reverse(l_hinge)
    if not poly.is_ccw(r_hinge):
        r_hinge = poly.reverse(r_hinge)

    left_hinge_pocket_contours = []
    while len(l_hinge) > 0:
        l_hinge = poly.erode(1.5875 / 2, l_hinge)
        if len(l_hinge) > 0:
            l_hinge = l_hinge[0]
            left_hinge_pocket_contours.append(l_hinge)

    right_hinge_pocket_contours = []
    while len(r_hinge) > 0:
        r_hinge = poly.erode(1.5875 / 2, r_hinge)
        if len(r_hinge) > 0:
            r_hinge = r_hinge[0]
            right_hinge_pocket_contours.append(r_hinge)
    r = [
        cam.comment("Hinge Pockets"),
        cam.feedrate(750),
        cam.change_tool("1/16in endmill"),
        cam.start_spindle(15000),
        cam.dwell(3),
        cam.comment("Right Hinge Pocket"),
        cam.pocket(right_hinge_pocket_contours,
                   -abs(temples['pocket_depth']),
                   retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Left Hinge Pocket"),
        cam.pocket(left_hinge_pocket_contours,
                   -abs(temples['pocket_depth']),
                   retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Hinge Holes"),
        cam.change_tool("1mm drill"),
        cam.start_spindle(4500),
        cam.dwell(2),
        [
            cam.rmp(p + [-8.0], retract=10.0)
            for p in temples['right_hinge_holes']
        ],
        [
            cam.rmp(p + [-8.0], retract=10.0)
            for p in temples['left_hinge_holes']
        ],
        cam.rapid([None, None, 20.0]),
        cam.move([None, None, 0]),
        cam.contour(poly.rotate_90(temples['left_temple_contour']), True),
        cam.contour(poly.rotate_90(temples['right_temple_contour']), True),
    ]
    return r
def face_hinge_pockets(hinge_num, xposition, yposition):
    left_hinge = hinges.get_hinge(hinge_num)
    right_hinge = hinges.get_hinge(hinge_num, False)
    left_translate = [xposition, -yposition]
    #left_translate = [xposition, 0]
    right_translate = [xposition, yposition]
    #right_translate = [xposition, 0]
    # Adjust by pocket depth of hinge
    pocket_depth = left_hinge['pocket_depth']

    left_contour = poly.translate(left_hinge["face_contour"], left_translate[0], left_translate[1])
    right_contour = poly.translate(right_hinge["face_contour"], right_translate[0], right_translate[1])
    left_holes = poly.translate(left_hinge["face_holes"], left_translate[0], left_translate[1])
    right_holes = poly.translate(right_hinge["face_holes"], right_translate[0], right_translate[1])

    if not poly.is_ccw(left_contour):
        left_contour = poly.reverse(left_contour)
    if not poly.is_ccw(right_contour):
        right_contour = poly.reverse(right_contour)

    left_hinge_pocket_contours = [];
    while len(left_contour) > 0:
        left_contour = poly.erode(1.5875/2, left_contour)
        if len(left_contour) > 0:
            left_contour = left_contour[0]
            left_hinge_pocket_contours.append(left_contour)

    right_hinge_pocket_contours = [];
    while len(right_contour) > 0:
            right_contour = poly.erode(1.5875/2, right_contour)
            if len(right_contour) > 0:
                right_contour = right_contour[0]
                right_hinge_pocket_contours.append(right_contour)
    r = [
        cam.comment("Hinge Pockets"),
        cam.feedrate(750),
        cam.change_tool("1/16in endmill"),
        cam.start_spindle(15000),
        cam.dwell(3),
        cam.comment("Right Hinge Pocket"),
        cam.pocket(right_hinge_pocket_contours, -abs(right_hinge['pocket_depth']), retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Left Hinge Pocket"),
        cam.pocket(left_hinge_pocket_contours, -abs(left_hinge['pocket_depth']), retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Hinge Holes"),
        cam.change_tool("1mm drill"),
        cam.start_spindle(4500),
        cam.dwell(2),
        [cam.rmp(p + [-8.0], retract=10.0) for p in right_holes],
        [cam.rmp(p + [-8.0], retract=10.0) for p in left_holes],
        cam.rapid([None, None, 20.0]),
    ]
    return r
Exemple #3
0
def mill_temples(outdir, temples, order):
#TODO: Replace with information in materials database
    print 'Creating milling program for temples'
    top_thickness = 4 # Assume 4mm temple
    top_raw = 4
    if order.get("temple_material"):
        top_raw = order["temple_material"].get("top_raw_thickness") or order["temple_material"].get("top_thickness") or top_thickness

    print 'top raw', top_raw

    # Automatically determine some surfacing.  The bottom thickness
    # is a lamination and should be thin.  It should be thinned to 1mm.
    # The top should be thinned to bring total finished thickness to 6mm or less.
    thin_back = 0
    if top_raw > top_thickness:
        thin_back = top_raw - top_thickness

    l_temple = temples['left_temple_contour']
    r_temple = temples['right_temple_contour']
    offset = frame_offset(l_temple)

# Calculate entry points for bevelling operation
    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.rapid([0,0]),
        cam.activate_pin("stock_clamp"),
        surface_back(thin_back),
        index_holes(top_raw),


#        cam.rapid(l_temple[0]+[0]),
#        cam.contour(l_temple, True),
#        cam.move(l_temple[0]),
#        cam.rapid(r_temple[0]),
#        cam.contour(r_temple, True),

        rough_temple_bevel(l_temple, thin_back),
        rough_temple_bevel(r_temple, thin_back),
        cam.change_tool("1/16in endmill"),
        cam.rapid([0,0]),
        temple_hinge_pockets(temples, thin_back),
        cam.change_tool("dovetail"),
        bevel_temple(l_temple, thin_back),
        bevel_temple(r_temple, thin_back),
        temple_hinge_clearance(l_temple, thin_back),
        temple_hinge_clearance(r_temple, thin_back),
        cam.retract_spindle(),
        cam.deactivate_pin("stock_clamp"),
        cam.change_tool("1/8in endmill"),
        cam.end_program()
    ]
    open(outdir + "/temples_milling.ngc", "w").write(to_string(program))
def temple_hinge_pockets(temples):
    # We're operating in a 90 degree rotated fixture
    #l_hinge = poly.rotate_90(temples["left_hinge_contour"])
    #r_hinge = poly.rotate_90(temples["right_hinge_contour"])

    l_hinge = temples["left_hinge_contour"]
    r_hinge = temples["right_hinge_contour"]
    if not poly.is_ccw(l_hinge):
        l_hinge = poly.reverse(l_hinge)
    if not poly.is_ccw(r_hinge):
        r_hinge = poly.reverse(r_hinge)

    left_hinge_pocket_contours = [];
    while len(l_hinge) > 0:
        l_hinge = poly.erode(1.5875/2, l_hinge)
        if len(l_hinge) > 0:
            l_hinge = l_hinge[0]
            left_hinge_pocket_contours.append(l_hinge)

    right_hinge_pocket_contours = [];
    while len(r_hinge) > 0:
            r_hinge = poly.erode(1.5875/2, r_hinge)
            if len(r_hinge) > 0:
                r_hinge = r_hinge[0]
                right_hinge_pocket_contours.append(r_hinge)
    r = [
        cam.comment("Hinge Pockets"),
        cam.feedrate(750),
        cam.change_tool("1/16in endmill"),
        cam.start_spindle(15000),
        cam.dwell(3),
        cam.comment("Right Hinge Pocket"),
        cam.pocket(right_hinge_pocket_contours, -abs(temples['pocket_depth']), retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Left Hinge Pocket"),
        cam.pocket(left_hinge_pocket_contours, -abs(temples['pocket_depth']), retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Hinge Holes"),
        cam.change_tool("1mm drill"),
        cam.start_spindle(4500),
        cam.dwell(2),
        [cam.rmp(p + [-8.0], retract=10.0) for p in temples['right_hinge_holes']],
        [cam.rmp(p + [-8.0], retract=10.0) for p in temples['left_hinge_holes']],
        cam.rapid([None, None, 20.0]),

        cam.move([None, None, 0]),
        cam.contour(poly.rotate_90(temples['left_temple_contour']), True),
        cam.contour(poly.rotate_90(temples['right_temple_contour']), True),
    ]
    return r
Exemple #5
0
def index_holes(contours, thickness):
    # We put the index holes 1/2 between top and bottom, 160mm apart
    #    log(str(poly.right(face_c)))
    #    log(str(poly.left(face_c)))
    #    log(str(poly.right(face_c) - poly.left(face_c)))
    #    log(str((poly.right(face_c) - poly.left(face_c))/2))
    #    log(str(poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2))

    rightmost = -1000000
    leftmost = 1000000
    for contour in contours:
        right = poly.right(contour)
        left = poly.left(contour)
        rightmost = max(right, rightmost)
        leftmost = min(left, leftmost)


#    x_offset = poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2
    x_offset = rightmost - (rightmost - leftmost) / 2

    hole_radius = 4.85 / 2  # Measured from dowel pin
    tool_radius = 3.175 / 2
    helix_radius = hole_radius - tool_radius
    r_hole = [x_offset, 90]
    l_hole = [x_offset, -90]
    r = [
        cam.comment("Index Holes for secondary operations"),
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(15000),
        cam.feedrate(1000),
        cam.dwell(3),
        cam.rmh(r_hole + [-thickness - 1.0], helix_radius, 0.5, 1),
        cam.rmh(l_hole + [-thickness - 1.0], helix_radius, 0.5, 1),
    ]
    return r
Exemple #6
0
def nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness):
    """Creates the nose contour feature toolpath.  Angular arguments are in degrees."""

    nr = nose_rad
    h = nose_h
    sa = math.radians(nose_sa)
    ra = math.radians(nose_ra)
    xfloor = poly.left(face_con) - 3.175  # bottom most point minus tool radius
    xfloor = max(xfloor, -27.0)  # miminum safe distance without hitting clamp
    nose_tool_radius = 3.175

    nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, 0.0)

    r = [
        "(Nose Contour)",
        cam.change_tool("1/4in ballmill"),
        cam.start_spindle(20000),
        cam.feedrate(2000),
        cam.rmp(nextpoly[0] + [2.0])  # Start near our first contour
    ]

    direction = 1
    for i in range(-20, (thickness + 2) * 10):
        z = -i / 10.0
        #        r += cam.move(nextpoly[0])
        if (direction < 0):
            nextpoly.reverse()
        direction = direction * -1
        r += cam.contour(nextpoly, False)
        r += cam.move([None, None, z])
        nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, z)

    return r
def mill_temples(outdir, temples, temple_length):
#TODO: Replace with information in materials database
    front_surface_thickness = 0
    back_surface_thickness = 4
    final_front_thickness = 0
    final_back_thickness = 4
    thickness = final_front_thickness + final_back_thickness

    front_surface_removal = final_front_thickness - front_surface_thickness
    back_surface_removal = final_back_thickness - back_surface_thickness

    r_temple = poly.rotate_90(temples['right_temple_contour'])
    l_temple = poly.rotate_90(temples['left_temple_contour'])

    offset = frame_offset(l_temple)
    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.activate_pin("stock_clamp"),
        surface_front(front_surface_removal),
        surface_back(back_surface_removal),
        cam.change_tool("1/16in endmill"),
        cam.rapid([0,0]),
        cam.temporary_offset(offset),
        temple_hinge_pockets(temples),
        index_holes([l_temple, r_temple], thickness),
        #thin_temples([l_temple, r_temple], temple_length),
    ]
    open(outdir + "/temples_milling.ngc", "w").write(to_string(program))
Exemple #8
0
def rough_temple_bevel(temple,  thinning):
    p1 = extendLine(temple[-1], temple[-2], 3.175/2 - 0.5)
    p2 = extendLine(temple[0], temple[1], 3.175/2 - 0.5)
    p3 = extendLine(temple[0], temple[1], 15)
    p4 = extendLine(temple[-1], temple[-2], 15) # room for dovetail
# p1 and p2 are just extensions of the temple - move them to the side a bit to
# clearance for when the dovetail cutter comes through
    p1 = extendLine(p1, p2, 3)
    p2 = extendLine(p2, p1, 3)
    p3 = extendLine(p3, p4, 3)
    p4 = extendLine(p4, p3, 3)


# Move to the dovetail cutter entry point, helix through stock.
# Cut a circle big enough to admit the dovetail cutter.
# Rough cut the end of the temple
# Clear a return path for the dovetail cutter.
    return [
        cam.change_tool("1/8in endmill"),
        cam.feedrate(1000),
        cam.rmh(p4 + [-5-thinning], 1, pitch=1),
        cam.move(p1),
        cam.move(p2),
        cam.move(p3),
        cam.move(p4),
        cam.rapid(p4 + [10])
        ]
def index_holes(contours, thickness):
# We put the index holes 1/2 between top and bottom, 160mm apart
#    log(str(poly.right(face_c)))
#    log(str(poly.left(face_c)))
#    log(str(poly.right(face_c) - poly.left(face_c)))
#    log(str((poly.right(face_c) - poly.left(face_c))/2))
#    log(str(poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2))

    rightmost = -1000000
    leftmost = 1000000
    for contour in contours:
        right = poly.right(contour)
        left = poly.left(contour)
        rightmost = max(right, rightmost)
        leftmost = min(left, leftmost)

#    x_offset = poly.right(face_c) - (poly.right(face_c) - poly.left(face_c))/2
    x_offset = rightmost - (rightmost - leftmost)/2

    hole_radius = 4.85/2 # Measured from dowel pin
    tool_radius = 3.175/2
    helix_radius = hole_radius - tool_radius
    r_hole = [x_offset, 90]
    l_hole = [x_offset, -90]
    r = [
        cam.comment("Index Holes for secondary operations"),
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(15000),
        cam.feedrate(1000),
        cam.dwell(3),
        cam.rmh(r_hole + [-thickness - 1.0], helix_radius, 0.5, 1),
        cam.rmh(l_hole + [-thickness - 1.0], helix_radius, 0.5, 1),
    ]
    return r
Exemple #10
0
def generic_nose_contour(face_con, thickness, thin_back, centering_shift):
    """ Use the tapered endmill to create a nose relief along the curve of the
    glasses frame.
    First construct a path that is a simple, average shape for a nose: 8 mm nose radius, 34 degree
    splay.  Compare the curve to the spline of the glasses, if the spline crosses our naive curve, follow
    the glasses curve until it crosses the naive curve again, then keep following the naive curve.
    """
    curve_offset = 0 # Set so tapered endmill cuts about 1mm from front face of frame
    nose_sa = math.radians(34) # Experiment with this
    nose_rad = 9
    xfloor = -26 # set to avoid hitting clamp
    nose_height = 8 # again, experiment
    naive_poly = nose.nose_poly(nose_rad, nose_height, nose_sa, nose_sa, xfloor, curve_offset, 0)
    # close it
    #naive_poly = naive_poly + [naive_poly[0]]


    intersect = poly.difference(naive_poly, face_con)
    intersect = intersect[1:] + [intersect[0]]
    eroded = poly.erode(2, intersect)[0]
    finish = poly.erode(1.5, intersect)[0]

    hole_radius = 4.85/2 # Measured from dowel pin
    tool_radius = 3.175/2
    helix_radius = hole_radius - tool_radius


    return [
        cam.change_tool("tapered"),
        cam.start_spindle(20000),
        cam.feedrate(1000),
        cam.rmh(eroded[0] + [-thickness - 1.0], helix_radius, 0.5, 1),
        cam.contour(eroded, False),
        cam.contour(finish[::-1], False),
        ]
Exemple #11
0
def mill_temples(outdir, temples, temple_length):
    #TODO: Replace with information in materials database
    front_surface_thickness = 0
    back_surface_thickness = 4
    final_front_thickness = 0
    final_back_thickness = 4
    thickness = final_front_thickness + final_back_thickness

    front_surface_removal = final_front_thickness - front_surface_thickness
    back_surface_removal = final_back_thickness - back_surface_thickness

    r_temple = poly.rotate_90(temples['right_temple_contour'])
    l_temple = poly.rotate_90(temples['left_temple_contour'])

    offset = frame_offset(l_temple)
    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.activate_pin("stock_clamp"),
        surface_front(front_surface_removal),
        surface_back(back_surface_removal),
        cam.change_tool("1/16in endmill"),
        cam.rapid([0, 0]),
        cam.temporary_offset(offset),
        temple_hinge_pockets(temples),
        index_holes([l_temple, r_temple], thickness),
        #thin_temples([l_temple, r_temple], temple_length),
    ]
    open(outdir + "/temples_milling.ngc", "w").write(to_string(program))
Exemple #12
0
def lens_groove(left_c, right_c, height):
    """Generates the toolpath for the lens holes (holes, groove and tabs)."""
    print 'Generating lens grooves'
    if not poly.is_ccw(left_c):
        left_c = poly.reverse(left_c)
    if not poly.is_ccw(right_c):
        right_c = poly.reverse(right_c)

    lgroove = poly.erode(1.8, left_c)[0]
    rgroove = poly.erode(1.8, right_c)[0]

    left_entry = poly.erode(7.0, left_c)[0][0];
    right_entry = poly.erode(7.0, right_c)[0][0];
    r = [
        "(Lens Grooves)",
        cam.change_tool("vgroove"),
        cam.start_spindle(20000),
        cam.dwell(5),
        cam.feedrate(2000),
        cam.rmp(right_entry + [height]),
        cam.contour(rgroove, True),
        cam.move(right_entry), # Get out from under the overhang
        cam.rmp(left_entry + [height]),
        cam.contour(lgroove, True),
        cam.move(left_entry), # Get out from under the overhang
    ]
    return r
def nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness):
    """Creates the nose contour feature toolpath.  Angular arguments are in degrees."""

    nr = nose_rad
    h = nose_h
    sa = math.radians(nose_sa)
    ra = math.radians(nose_ra)
    xfloor = poly.left(face_con) - 3.175  # bottom most point minus tool radius
    xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp
    nose_tool_radius = 3.175

    nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, 0.0)

    r = [
        "(Nose Contour)",
        cam.change_tool("1/4in ballmill"),
        cam.start_spindle(20000),
        cam.feedrate(2000),
        cam.rmp(nextpoly[0] + [2.0])  # Start near our first contour
    ]

    direction = 1
    for i in range(-20, (thickness+2)*10):
        z = -i/10.0
#        r += cam.move(nextpoly[0])
        if(direction < 0):
            nextpoly.reverse()
        direction = direction * -1
        r += cam.contour(nextpoly, False)
        r += cam.move([None, None, z])
        nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, nose_tool_radius, z)

    return r
Exemple #14
0
def surface_front(amount):
    if amount < 0.1:
        print 'Not surfacing front, returning'
        return None
    print "Surfacing front with amount", amount
    surface_amount = min(amount, 4)
    surface_heights = []
    while surface_amount <= amount:
        surface_heights.append(surface_amount)
        surface_amount = max(surface_amount+2, amount)
    print "surface amounts", surface_heights

    program =  [
        cam.comment("Surface front by %f mm" % amount),
        cam.flip_stock(),
        cam.change_tool("3/8in endmill"),
        cam.spindle_speed(20000),
        cam.feedrate(2000),
        cam.start_spindle(),]
    for height in surface_heights:
        program = program + cam.surface_along_y(-40, -110, 40, 110, 4.7625, -height)
    program = program + [
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.flip_stock(),
        ]
    return program
Exemple #15
0
def lens_holes(left_c, right_c, thickness):
    """Generates the toolpath for the lens holes (holes, groove and tabs)."""
    if not poly.is_ccw(left_c):
        left_c = poly.reverse(left_c)
    if not poly.is_ccw(right_c):
        right_c = poly.reverse(right_c)

    lhole = poly.erode(3.175 / 2.0, left_c)[0]
    rhole = poly.erode(3.175 / 2.0, right_c)[0]

    right_rough = poly.erode(0.1, rhole)[0]
    left_rough = poly.erode(0.1, lhole)[0]

    lgroove = poly.erode(0.8, left_c)[0]
    rgroove = poly.erode(0.8, right_c)[0]

    left_entry = poly.erode(2.0, lhole)[0][0]
    right_entry = poly.erode(2.0, rhole)[0][0]

    lhole = poly.reverse(lhole)
    rhole = poly.reverse(rhole)

    r = [
        "(Lens Holes)",
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(20000),
        cam.feedrate(2000),
        cam.rmh(right_entry + [-thickness - 1.0], 1.5, 0.5, 1.0),
        cam.contour(right_rough, True),
        cam.contour(rhole, True),
        cam.rmh(left_entry + [-thickness - 1.0], 1.5, 0.5, 1.0),
        cam.contour(left_rough, True),
        cam.contour(lhole, True),
    ]
    return r
def surface_back(amount):
    return [
        cam.change_tool("1/4in endmill"),
        cam.spindle_speed("20000"),
        cam.start_spindle(),
        cam.surface_along_y(-80, -100, -5, 100, 0.25/2, amount),
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.dactivate_pin("stock_clamp"),
        ] if amount > 0 else None
Exemple #17
0
def surface_back(amount):
    return [
        cam.change_tool("1/4in endmill"),
        cam.spindle_speed("20000"),
        cam.start_spindle(),
        cam.surface_along_y(-80, -100, -5, 100, 0.25 / 2, amount),
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.dactivate_pin("stock_clamp"),
    ] if amount > 0 else None
Exemple #18
0
def lens_holes(left_c, right_c, thickness):
    """Generates the toolpath for the lens holes (holes, groove and tabs)."""
    print 'Calculating the lens holes'
    tool_radius = 3.175
    if not poly.is_ccw(left_c):
        left_c = poly.reverse(left_c)
    if not poly.is_ccw(right_c):
        right_c = poly.reverse(right_c)

#    drawing = dxf.drawing('test.dxf')
#    drawing.add_layer('OUTLINE', color=1)
#    polyline = dxf.polyline(layer="OUTLINE")
#    polyline.add_vertices(left_c)
#    drawing.add(polyline)


    lhole = poly.erode(tool_radius/2.0, left_c)[0]
    rhole = poly.erode(tool_radius/2.001, right_c);
    rhole = rhole[0]
#    polyline = dxf.polyline(layer="OUTLINE")
#    polyline.add_vertices(lhole)
#    drawing.add(polyline)


    right_rough = poly.erode((tool_radius + 0.3)/2, right_c)[0]
    left_rough = poly.erode((tool_radius+0.3)/2, left_c)[0]
    #lgroove = poly.erode(0.8, left_c)[0]
    #rgroove = poly.erode(0.8, right_c)[0]

    left_entry = poly.erode(5.0, left_c)[0][0];
    right_entry = poly.erode(5.0, right_c)[0][0];

    lhole = poly.reverse(lhole)
    rhole = poly.reverse(rhole)

    r = [
        "(Lens Holes)",
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(22000),
        cam.feedrate(2000),
        cam.rmh(right_entry + [-thickness - 1.0], 1.5, 0.5, 1.0),
        cam.contour(right_rough, True),
        cam.feedrate(1000),
        cam.contour(rhole, True),
        cam.feedrate(2000),
        cam.rmh(left_entry + [-thickness - 1.0], 1.5, 0.5, 1.0),
        cam.contour(left_rough, True),
        cam.feedrate(1000),
        cam.contour(lhole, True),

    ]
    return r
Exemple #19
0
def surface_back(amount):
    if amount < 0.1:
        return None

    print 'surfacing back with', amount
    surface_amount = min(amount, 4)
    surface_heights = []
    while surface_amount <= amount:
        surface_heights.append(surface_amount);
        print surface_heights
        surface_amount = max(surface_amount+2, amount)
    print "surface amounts on back", surface_heights


    return [
        cam.comment("Surface back by %f mm" % amount),
        cam.change_tool("3/8in endmill"),
        cam.spindle_speed(15000),
        cam.feedrate(1500),
        cam.start_spindle(),
        cam.dwell(5),
        cam.surface_along_y(-40, -110, 40, 110, 4.7625, -amount),
        cam.rapid([None, None, 20]),
        ] if amount > 0 else None
    program =  [
        cam.comment("Surface back by %f mm" % amount),
        cam.change_tool("3/8in endmill"),
        cam.spindle_speed(20000),
        cam.feedrate(2000),
        cam.start_spindle(),
        cam.dwell(5),
        ]
    for height in surface_heights:
        program = program + cam.surface_along_y(-40, -110, 40, 110, 4.7625, -height),
    program = program + [
        cam.stop_spindle(),
        cam.retract_spindle(),
        ]
    return program
Exemple #20
0
def surface_front(amount):
    log("Surfacing front with amount %f" % amount)
    return [
        cam.flip_stock(),
        cam.change_tool("1/4in endmill"),
        cam.spindle_speed(20000),
        cam.feedrate(2000),
        cam.start_spindle(),
        cam.surface_along_y(-80, -100, -5, 100, 3.175, amount),
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.flip_stock(),
    ] if amount < 0 else None
Exemple #21
0
def bevel_entry_hole(temples, thickness):

    hole_radius = 8
    tool_radius = 3.175/2 # 1/2 inch
    helix_radius = hole_radius - tool_radius
    r = [
        cam.comment("Entry holes for temple bevelling operation"),
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(22000),
        cam.feedrate(800),
        cam.dwell(5),

    ]
def surface_front(amount):
    log("Surfacing front with amount %f" % amount)
    return [
        cam.flip_stock(),
        cam.change_tool("1/4in endmill"),
        cam.spindle_speed(20000),
        cam.feedrate(2000),
        cam.start_spindle(),
        cam.surface_along_y(-80, -100, -5, 100, 3.175, amount),
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.flip_stock(),
        ] if amount < 0 else None
Exemple #23
0
def temple_hinge_clearance(temple, thinning):
    # Endpoints for the top bevel
    entry = extendLine(temple[-1], temple[-2], 7.5)
    p1 = extendLine(temple[0], temple[-1], 1)
    p2 = extendLine(temple[-1], temple[0], 1)
    return [
       cam.change_tool("engraver"),
       cam.feedrate(750),
       cam.start_spindle(20000),
       cam.rmp(entry + [-2 - thinning]),
       cam.move(p1),
       cam.move(p2),
       cam.move(entry),
       cam.move(entry + [10]),
            ]
Exemple #24
0
def nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness, thin_back, centering_shift):
    """Creates the nose contour feature toolpath.  Angular arguments are in degrees."""#
    print 'Generating nose contour'
    nr = nose_rad
    nose_tool_radius = 3.175

    # We're cutting with a ball-end mill.  Where it actually cuts is dependent on the
    # ridge angle.  If you draw a line at the ridge angle and put it tangent to the ball mill,
    # that is the cutting line.  The angle between the center of the ball mill and the intersection
    # of the cutting line and the surface is 1/2 of the ridge angle.  From that and the radius
    # of the ball mill we can figure out the offset.
    cutter_offset = (nose_tool_radius)*math.tan(math.radians(nose_ra/2))

    sa = math.radians(nose_sa)
    ra = math.radians(nose_ra)
    h = nose_h + centering_shift
    print 'centering shift', centering_shift
#    h = nose_h

    xfloor = poly.left(face_con) - 3.175  # bottom most point minus tool radius
    xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp

    z_depth = -thin_back # Start a bit above the surface of the glasses
    nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, cutter_offset, z_depth)

    r = [
        "(Nose Contour)",
        cam.change_tool("1/4in ballmill"),
        cam.start_spindle(20000),
        cam.feedrate(4000),
        cam.rmp(nextpoly[0] + [2.0]),  # Start near our first contour
    ]

    direction = 1

    z_start = int((z_depth)*10) # We have to use integers for the range, also step in 1/10 mm steps

    for i in range(-z_start, int(((thickness)+3)*10)):
        z = -i/10.0
#        r += cam.move(nextpoly[0])
        if(direction < 0):
            nextpoly.reverse()
        direction = direction * -1
        r += cam.move([None, None, z-thin_back]) # Z adjusted for any surfacing that happened
        r += cam.contour(nextpoly, False)
        nextpoly = nose.nose_poly(nr, h, sa, ra, xfloor, cutter_offset, z)
    return r
Exemple #25
0
def index_holes(thickness):
# We put the index holes 1/2 between top and bottom, 160mm apart
    hole_radius = 4.85/2 # Measured from dowel pin
    tool_radius = 3.175/2
    helix_radius = hole_radius - tool_radius
    r = [
        cam.comment("Index holes for secondary operations"),
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(22000),
        cam.feedrate(1000),
        cam.dwell(5),
        # Index holes should be at 90, -90 but are shifted a bit to compensate
        # for inaccuracy on laser fixture
        cam.rmh([0, 85.00, -thickness - 1.0], helix_radius, 0.5, 1),
        cam.rmh([0, -85.00, -thickness - 1.0], helix_radius, 0.5, 1),
        ]
    return r
Exemple #26
0
def rough_nose_contour(nose_rad, nose_h, nose_sa, nose_ra, face_con, thickness, thin_back, centering_shift):
    sa = math.radians(nose_sa)
    ra = math.radians(nose_ra)
    h = nose_h + centering_shift
    h = nose_h
    xfloor = poly.left(face_con) - 3.175  # bottom most point minus tool radius
    xfloor = max(xfloor, -27.0) # miminum safe distance without hitting clamp
    cutter_offset = 1.5875 # radius of 1/8" cutter

    nosepoly = nose.nose_poly(nose_rad, h, sa, ra, xfloor, cutter_offset, thickness+thin_back)

    return [
        "(Rough nose contour)",
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(20000),
        cam.feedrate(2000),
        cam.rmp(nosepoly[0] + [1.0]),
        cam.rmh([0, 85.00, -thickness - 1.0], helix_radius, 0.5, 1),
            ]
Exemple #27
0
def bevel_temple(temple, thinning):
    # Assume a 20 degree dovetail cutter, cutting 5mm from bottom
    dovetail_offset = 9.52/2 - 1.82

    entry = extendLine(temple[-1], temple[-2], 7.5)
    # Endpoints for the undercut
    p1 = extendLine(temple[-1], temple[-2], dovetail_offset)
    p2 = extendLine(temple[0], temple[1], dovetail_offset)
    p2 = extendLine(p2, p1, 2)

    return [
        cam.change_tool("dovetail"),
        cam.feedrate(750),
        cam.start_spindle(20000),
        cam.rmp(entry + [-5-thinning]),
        cam.move(p1),
        cam.move(p2),
        cam.move(entry),
        cam.move(entry + [10]),
            ]
Exemple #28
0
def bevel_temple_ends(path1, path2, thinning):
    depth = -4 - thinning
# Assume a 14 degree dovetail cutter, cutting 5mm from bottom
    dovetail_offset = 12.35/2 - 1.25
    return [
            cam.comment("Bevel temple ends"),
            cam.change_tool("dovetail"),
            cam.start_spindle(20000),
            cam.feedrate(750),
            cam.rapid(path1[0]),
            cam.rapid([None, None, depth]),
            cam.move(path1[1]),
            cam.move(path1[2]),
            cam.move(path1[0]),
            cam.rapid([None, None, 10]),
            cam.rapid(path2[0]),
            cam.rapid([None, None, depth]),
            cam.move(path2[1]),
            cam.move(path2[2]),
            cam.move(path2[0]),
            cam.move([None, None, 20])
            ]
def lens_holes(left_c, right_c, thickness):
    """Generates the toolpath for the lens holes (holes, groove and tabs)."""
    if not poly.is_ccw(left_c):
        left_c = poly.reverse(left_c)
    if not poly.is_ccw(right_c):
        right_c = poly.reverse(right_c)

    lhole = poly.erode(3.175/2.0, left_c)[0]
    rhole = poly.erode(3.175/2.0, right_c)[0]

    right_rough = poly.erode(0.1, rhole)[0]
    left_rough = poly.erode(0.1, lhole)[0]

    lgroove = poly.erode(0.8, left_c)[0]
    rgroove = poly.erode(0.8, right_c)[0]

    left_entry = poly.erode(2.0, lhole)[0][0];
    right_entry = poly.erode(2.0, rhole)[0][0];

    lhole = poly.reverse(lhole)
    rhole = poly.reverse(rhole)

    r = [
        "(Lens Holes)",
        cam.change_tool("1/8in endmill"),
        cam.start_spindle(20000),
        cam.feedrate(2000),
        cam.rmh(right_entry + [-thickness - 1.0], 1.5, 0.5, 1.0),
        cam.contour(right_rough, True),
        cam.contour(rhole, True),
        cam.rmh(left_entry + [-thickness - 1.0], 1.5, 0.5, 1.0),
        cam.contour(left_rough, True),
        cam.contour(lhole, True),

    ]
    return r
Exemple #30
0
def mill_fronts(outdir, order):
    """Creates the g-code for the first milling operation.  The
    first milling operation is done on an unregistered plastic blank,
    so includes creating registration holes for subsequent operations."""

# Initial thickness of the forward-facing lamination.  0 if no lamination.
    top_thickness = 6
    bottom_thickness = 0
    top_raw = 6
    bottom_raw = 0
    if order.get("face_material"):
        top_thickness = order["face_material"].get("top_thickness")
        bottom_thickness = order["face_material"].get("bottom_thickness") or 0
        top_raw = order["face_material"].get("top_raw_thickness") or top_thickness
        bottom_raw = order["face_material"].get("bottom_raw_thickness") or bottom_thickness
    frame_thickness = top_thickness + bottom_thickness
    machining_z_offset = bottom_raw - bottom_thickness

#    top_thickness = 6
#    bottom_thickness = 0
#    total_thickness = 6
#    top_raw = 0


    # Automatically determine some surfacing.  The bottom thickness
    # is a lamination and should be thin.  It should be thinned to 1mm.
    # The top should be thinned to bring total finished thickness to 6mm or less.
    thin_back = 0
    if bottom_raw > bottom_thickness:
        thin_back = bottom_raw - bottom_thickness
    thin_front = 0
    if top_raw > top_thickness:
        thin_front = top_raw - top_thickness


# The machine has the stock clamp oriented 90 degrees to the way the
# software creates the contours.
    face_c = poly.rotate_90(order["face_con"])
    left_lens_c = poly.rotate_90(order["lhole_con"])
    right_lens_c = poly.mirror_y(left_lens_c, True)
    face_c = face_c + poly.reverse(poly.mirror_y(face_c, False))[1:]

    temple_height = abs(order["ltemple_con"][0][1] - order["ltemple_con"][-1][1])

    msg = check_frame_size(left_lens_c)
    if msg:
        print msg
        sys.exit(1)
#   Instead of offset, we'll make sure this thing is centered on the stock
    offset = frame_offset(face_c)
    top = poly.top(face_c)
    bottom = poly.bottom(face_c)
    left = poly.left(face_c)
    right = poly.right(face_c)

    print 'frame bounding box: ', top, bottom, left, right
    y_shift = (top + bottom)/2
    x_shift = (left + right)/2

    print 'x and y shift', x_shift, y_shift
    face_c = poly.translate(face_c, -x_shift, -y_shift)
    left_lens_c = poly.translate(left_lens_c, -x_shift, -y_shift)
    right_lens_c = poly.translate(right_lens_c, -x_shift, -y_shift)

# Groove for lenses is 2/3 of the distance from back to front.
# Here we're calculating the actual cutting depth so we need to add
# back the material that we surfaced away from the back.
    groove_depth = -(float(machining_z_offset) + (2.0/3)*float(frame_thickness))
    hinge_loc = order["ltemple_con"][0][1] - (order["ltemple_con"][0][1] - order["ltemple_con"][-1][1])/2

    size_info = order.get('size_info')
    if not size_info and order.get('usersizes'):
        # Legacy order
        size_info =  order.get('usersizes')
        size_info["noseradius"] = size_info["nose_radius"]
        size_info["noseheight"] = size_info["nose_height"]
        size_info["splayangle"] = size_info["nose_splayangle"]
        size_info["ridgeangle"] = size_info["nose_ridgeangle"]

    generic = not size_info or len(size_info) == 0

    generic = True # TESTING

    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.activate_pin("stock_clamp"),
        cam.rapid([0,0]),
        surface_front(thin_front),
        surface_back(thin_back),

        cam.change_tool("1/8in endmill"),
        cam.rapid([0, 0]),

        # Note that X and Y parameters in the order are switched from our system
        #TODO: replace the thickness offset with the thickness of the TEMPLE, not the fronts.
        index_holes(frame_thickness+machining_z_offset),
        lens_holes(left_lens_c, right_lens_c, frame_thickness + machining_z_offset),
        lens_groove(left_lens_c, right_lens_c, groove_depth),

#        rough_nose_contour(
#            float(size_info["noseradius"]),
#            float(size_info["noseheight"]),
#            float(size_info["splayangle"]),
#            float(size_info["ridgeangle"]),
#            face_c, frame_thickness, machining_z_offset, -x_shift ),


        face_hinge_pockets(order.get("lhinge") or 1, hinge_loc, order["ltemple_x"], (-x_shift, -y_shift), machining_z_offset),

        #nose_pads(order, thickness),
        nose_contour(
            float(size_info["noseradius"]),
            float(size_info["noseheight"]),
            float(size_info["splayangle"]),
            float(size_info["ridgeangle"]),
            face_c, frame_thickness, machining_z_offset, -x_shift ),

#        nose_contour(
#            7.0, 8.0, 30.0, 32.0, face_c, frame_thickness, machining_z_offset, -x_shift),

        #generic_nose_contour(face_c, frame_thickness, machining_z_offset, -x_shift),


        cam.retract_spindle(),
        cam.deactivate_pin("stock_clamp"),
        cam.change_tool("1/8in endmill"),
    #    cam.rapid([face_c[0][0], face_c[0][1], -thin_back] ),
    #    cam.contour(face_c, True),
        cam.end_program(),
    ]
    print 'Writing face milling program to ', outdir + "/face_stange1.ngc"
    open(outdir + "/face_stage1.ngc", "w").write(to_string(program))
Exemple #31
0
def mill_fronts(outdir, order):
    """Creates the g-code for the first milling operation.  The
    first milling operation is done on an unregistered plastic blank,
    so includes creating registration holes for subsequent operations."""

    #TODO: Replace with information in materials database
    # Initial thickness of the forward-facing lamination.  0 if no lamination.
    front_surface_thickness = 0

    # The final desired thickness of the fronto facing lamination.  Must
    # be equal to or less than the front_surface_thickness.
    final_front_thickness = 0

    # Initial thickness of the face side lamination. Use this thickness only if
    # stock is solid
    back_surface_thickness = 4

    # The final thickness of the left and right extremes of the frame where the
    # hinge will go.  Must be equal to or less than back_surface_thickness.
    hinge_thickness = 4

    # The thickness of the highest point of the nosepad
    nosepad_thickness = 4

    # Final thickness of the main part of the frame.  Must be equal to or less than
    # the back_surface_thickness.
    final_back_thickness = 4

    thickness = final_front_thickness + final_back_thickness

    front_surface_removal = final_front_thickness - front_surface_thickness
    back_surface_removal = final_back_thickness - back_surface_thickness

    # The machine has the stock clamp oriented 90 degrees to the way the
    # software creates the contours.
    face_c = poly.rotate_90(order["face_con"])
    left_lens_c = poly.rotate_90(order["lhole_con"])
    right_lens_c = poly.rotate_90(order["rhole_con"])
    temple_height = abs(order["ltemple_con"][0][1] -
                        order["ltemple_con"][-1][1])

    msg = check_frame_size(face_c)
    if msg:
        print msg
        sys.exit(0)

    print 'milling front with hinge', order['lhinge'], order['rhinge']
    offset = frame_offset(face_c)

    groove_height = back_surface_removal + (thickness / 2)
    print 'groove', groove_height, back_surface_removal, (thickness / 2)
    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.activate_pin("stock_clamp"),
        surface_front(front_surface_removal),
        #        surface_back(back_surface_removal),
        cam.change_tool("1/8in endmill"),
        cam.rapid([0, 0]),
        cam.temporary_offset(offset),
        # Note that X and Y parameters in the order are switched from our system
        #TODO: replace the thickness offset with the thickness of the TEMPLE, not the fronts.
        index_holes([face_c], back_surface_thickness),
        lens_holes(left_lens_c, right_lens_c, back_surface_thickness),
        lens_groove(left_lens_c, right_lens_c,
                    back_surface_removal - (thickness / 2)),
        #        contour_face(
        #            back_surface_removal,
        #            back_surface_thickness - hinge_thickness,
        #            back_surface_thickness - nosepad_thickness,
        #            temple_height,
        #            face_c, left_lens_c, order['lhinge_y']),
        face_hinge_pockets(order["lhinge"], order["lhinge_y"],
                           order["ltemple_x"]),
        #        nose_pads(order, thickness),
        nose_contour(order["nose_rad"], order["nose_h"], order["nose_sa"],
                     order["nose_ra"], face_c, back_surface_thickness),
        cam.retract_spindle(),
        cam.deactivate_pin("stock_clamp"),
        cam.end_program(),
    ]
    open(outdir + "/face_stage1.ngc", "w").write(to_string(program))
def mill_fronts(outdir, order):
    """Creates the g-code for the first milling operation.  The
    first milling operation is done on an unregistered plastic blank,
    so includes creating registration holes for subsequent operations."""

#TODO: Replace with information in materials database
# Initial thickness of the forward-facing lamination.  0 if no lamination.
    front_surface_thickness = 0

# The final desired thickness of the fronto facing lamination.  Must
# be equal to or less than the front_surface_thickness.
    final_front_thickness = 0

# Initial thickness of the face side lamination. Use this thickness only if
# stock is solid
    back_surface_thickness = 4

# The final thickness of the left and right extremes of the frame where the
# hinge will go.  Must be equal to or less than back_surface_thickness.
    hinge_thickness = 4

# The thickness of the highest point of the nosepad
    nosepad_thickness = 4

# Final thickness of the main part of the frame.  Must be equal to or less than
# the back_surface_thickness.
    final_back_thickness =4

    thickness = final_front_thickness + final_back_thickness

    front_surface_removal = final_front_thickness - front_surface_thickness
    back_surface_removal = final_back_thickness - back_surface_thickness


# The machine has the stock clamp oriented 90 degrees to the way the
# software creates the contours.
    face_c = poly.rotate_90(order["face_con"])
    left_lens_c = poly.rotate_90(order["lhole_con"])
    right_lens_c = poly.rotate_90(order["rhole_con"])
    temple_height = abs(order["ltemple_con"][0][1] - order["ltemple_con"][-1][1])

    msg = check_frame_size(face_c)
    if msg:
        print msg
        sys.exit(0)

    print 'milling front with hinge', order['lhinge'], order['rhinge']
    offset = frame_offset(face_c)

    groove_height = back_surface_removal + (thickness/2)
    print 'groove', groove_height, back_surface_removal, (thickness/2)
    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.activate_pin("stock_clamp"),
        surface_front(front_surface_removal),
#        surface_back(back_surface_removal),

        cam.change_tool("1/8in endmill"),
        cam.rapid([0, 0]),
        cam.temporary_offset(offset),
# Note that X and Y parameters in the order are switched from our system
#TODO: replace the thickness offset with the thickness of the TEMPLE, not the fronts.
        index_holes([face_c], back_surface_thickness),
        lens_holes(left_lens_c, right_lens_c, back_surface_thickness),
        lens_groove(left_lens_c, right_lens_c, back_surface_removal - (thickness/2)),
#        contour_face(
#            back_surface_removal,
#            back_surface_thickness - hinge_thickness,
#            back_surface_thickness - nosepad_thickness,
#            temple_height,
#            face_c, left_lens_c, order['lhinge_y']),
        face_hinge_pockets(order["lhinge"], order["lhinge_y"], order["ltemple_x"]),
#        nose_pads(order, thickness),
        nose_contour(order["nose_rad"], order["nose_h"], order["nose_sa"], order["nose_ra"], face_c, back_surface_thickness),

        cam.retract_spindle(),
        cam.deactivate_pin("stock_clamp"),
        cam.end_program(),
    ]
    open(outdir + "/face_stage1.ngc", "w").write(to_string(program))
Exemple #33
0
def temple_hinge_pockets(temples, thinned):
    # We're operating in a 90 degree rotated fixture
    #l_hinge = poly.rotate_90(temples["left_hinge_contour"])
    #r_hinge = poly.rotate_90(temples["right_hinge_contour"])
    print 'Generating temple hinge pockets'

    l_hinge = temples["left_hinge_contour"]
    r_hinge = temples["right_hinge_contour"]
    if not poly.is_ccw(l_hinge):
        l_hinge = poly.reverse(l_hinge)
    if not poly.is_ccw(r_hinge):
        r_hinge = poly.reverse(r_hinge)

    #pocket_depth = temples['pocket_depth'] + thinned
    pocket_depth = 1 + thinned;

    def pocket_contours(contour):
        contours = []
        erode = poly.erode(1.5875/2, contour)
        making_progress = True
        while len(erode) > 0 and making_progress:
            making_progress = False
            for path in erode:
                if len(path) > 5:
                    making_progress = True
                    contours.append(path)
            erode = poly.erode(1.5875/2, contours[-1])
        return contours

    left_hinge_pocket_contours = pocket_contours(l_hinge)
    right_hinge_pocket_contours = pocket_contours(r_hinge)
#    left_hinge_pocket_contours = [];
#    while len(l_hinge) > 0:
#        l_hinge = poly.erode(1.5875/2, l_hinge)
#        if len(l_hinge) > 0:
#            l_hinge = l_hinge[0]
#            left_hinge_pocket_contours.append(l_hinge)
#    right_hinge_pocket_contours = [];
#    while len(r_hinge) > 0:
#            r_hinge = poly.erode(1.5875/2, r_hinge)
#            if len(rhinge_) == 1:
#                right_hinge_pocket
#            if len(r_hinge) > 0:
#                r_hinge = r_hinge[0]
#                right_hinge_pocket_contours.append(r_hinge)
    r = [
        cam.comment("Hinge Pockets"),
        cam.feedrate(750),
        cam.change_tool("1/16in endmill"),
        cam.start_spindle(22000),
        cam.dwell(5),
        cam.comment("Right Hinge Pocket"),
        cam.pocket(right_hinge_pocket_contours, -abs(pocket_depth), retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Left Hinge Pocket"),
        cam.pocket(left_hinge_pocket_contours, -abs(pocket_depth), retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Hinge Holes"),
        cam.change_tool("1mm drill"),
        cam.start_spindle(5000),
        cam.dwell(2),
        [cam.rmp(p + [-8.0], retract=10.0) for p in temples['right_hinge_holes']],
        [cam.rmp(p + [-8.0], retract=10.0) for p in temples['left_hinge_holes']],
        cam.rapid([None, None, 20.0]),
    ]
    return r
Exemple #34
0
def contour_face(body_removal, hinge_removal, nosepad_removal, temple_height,
                 face_c, lens_c, x_pos):
    ''' Create the heightmap of the frame, surfacing the back and adding thickness for the
    hinge location and the nosepads.  '''
    if body_removal == hinge_removal == nosepad_removal == 0:
        return []  # Nothing to do

    cutter_radius = 6.35 / 2  # 3/4 inch cutter
    entry_point = [x_pos, 110, 0]

    facing_contour = poly.dilate(0.05, lens_c)

    # Reshape the facing contour so the first point is near the hinge
    center_y = poly.bottom(facing_contour) + (poly.top(facing_contour) -
                                              poly.bottom(facing_contour)) / 2
    center_x = poly.right(facing_contour) + (poly.left(facing_contour) -
                                             poly.right(facing_contour)) / 2
    split_idx = -1
    for idx, pt in enumerate(facing_contour):
        if pt[1] > center_y and (idx + 1) < len(facing_contour):
            if (pt[0] < x_pos and facing_contour[idx + 1][0] > x_pos) or (
                    pt[0] > x_pos and facing_contour[idx + 1][0] < x_pos):
                split_idx = idx
                break
    if split_idx < 0:
        print 'Error contouring back of frame: could not locate entry point for surfacing cut'
        return []
    facing_contour = poly.new_start(facing_contour, split_idx)
    # Ensure we're going clockwise, i.e. starting at the hinge and moving up over the frame
    if poly.is_ccw(facing_contour):
        facing_contour = poly.reverse(facing_contour)


# Calculate the Z values
# We'll need a few helper values.  nosepad_start is the inflection point of the nose bridge.
    nosepad_start = max([pt[0] for pt in face_c if pt[1] == 0]) + cutter_radius
    hinge_rampdown_start_x = x_pos + temple_height / 2 + cutter_radius
    hinge_rampdown_start_y = facing_contour[0][1] - cutter_radius
    hinge_rampup_start_x = x_pos - temple_height / 2 - cutter_radius
    hinge_rampup_start_y = facing_contour[0][1] - cutter_radius

    print nosepad_start, hinge_rampdown_start_x, hinge_rampdown_start_y, hinge_rampup_start_x, hinge_rampup_start_y
    '''
    Arbitrary heuristic, adjusted for aesthetics.
    1. If we're past the center point of the lens hole, we're either on the body
    of the frame or over the raised hinge point.
    2. If we're before the center point we're either on the body or over the nosepiece.

    1a. If we're above the cutter-radius-adjusted top of the temple, we're ramping down
    1b. If we're below the cutter-radius-adjusted bottom of the temple, we're ramping up
    1c. Otherwise we're at body thickness

    2a. If we're above the top of the nose cutout, we're at body thickness
    2b. When we reach nose cutout, we do a s-curve over 3 mm to nosepad height
    2c. Continue for length of cutter diameter to get rear of cutter over highest point
    2d. Continue for 10mm
    2e. S-curve down over 10mm
    '''
    print hinge_removal, body_removal

    def add_hinge_heights(contour):
        heightmap = []
        over_hinge = True  # Start over hinge

        items_to_skip = 0  # for fast-forwarding enumeration
        for idx, pt in enumerate(contour):
            if items_to_skip > 0:
                items_to_skip = items_to_skip - 1
                if items_to_skip == 0:
                    print 'first post ramp point', contour[idx + 1]
                continue

            if pt[1] < center_y:
                heightmap = heightmap + [pt]
            # Going up and around: start ramping down when we're clear of X or Y
            elif pt[0] > x_pos:
                if pt[0] > hinge_rampdown_start_x or pt[
                        1] < hinge_rampdown_start_y:
                    if (over_hinge):  # starting transition
                        transition_length = poly.polyline_length(
                            contour[:(idx + 1)], False)
                        ramp_segment = poly.segment(contour, transition_length,
                                                    transition_length + 5,
                                                    False)
                        ramp_segment = poly.ramp(ramp_segment, hinge_removal,
                                                 body_removal, False)
                        heightmap = heightmap + ramp_segment[:-1]
                        items_to_skip = len(ramp_segment)
                        print 'last ramp segment', ramp_segment[-1]
                        over_hinge = False
                    else:  # past transition but still on hinge side of lens hole
                        heightmap = heightmap + [pt + [body_removal]]
                else:  # We're on the top part but haven't reached the transition yet
                    heightmap = heightmap + [pt + [hinge_removal]]

            # Coming back up to the hinge: start ramping up if we encroach on both x and y
            elif pt[0] < x_pos and (pt[0] > hinge_rampup_start_x
                                    and pt[1] > hinge_rampdown_start_y):
                if (not over_hinge):  # starting transition
                    print pt, x_pos, hinge_rampup_start_x, hinge_rampdown_start_y, idx
                    transition_length = poly.polyline_length(
                        contour[:(idx + 1)], False)
                    ramp_segment = poly.segment(contour, transition_length,
                                                transition_length + 5, False)
                    ramp_segment = poly.ramp(ramp_segment, body_removal,
                                             hinge_removal, False)
                    heightmap = heightmap + ramp_segment
                    items_to_skip = len(ramp_segment)
                    over_hinge = True
                else:  # Over flat hinge area
                    heightmap = heightmap + [pt + [hinge_removal]]
            else:  # We're over the body area but back on the hinge side
                heightmap = heightmap + [pt + [body_removal]]
        return heightmap

    def add_nosepad_heights(contour):
        heightmap = []
        over_nosepad = False
        past_nosepad = False
        nosepad_flat_idx = -1

        items_to_skip = 0  # for fast-forwarding the enumeration
        for idx, pt in enumerate(contour):
            if items_to_skip > 0:
                items_to_skip = items_to_skip - 1
                continue
            if pt[1] >= center_y:
                heightmap = heightmap + [pt]
            elif not over_nosepad and not past_nosepad:
                if pt[0] < nosepad_start:  # Transition
                    transition_length = poly.polyline_length(
                        contour[:(idx + 1)], False)
                    ramp_segment = poly.segment(contour, transition_length,
                                                transition_length + 5, False)
                    ramp_segment = poly.ramp(ramp_segment, body_removal,
                                             nosepad_removal, False)
                    heightmap = heightmap + ramp_segment[:-1]
                    items_to_skip = len(ramp_segment)
                    nosepad_flat_idx = idx + items_to_skip  # we'll need this to go down
                    over_nosepad = True
                else:  # we're past the nosepad
                    heightmap = heightmap + [pt + [body_removal]]
            elif over_nosepad and not past_nosepad:
                if nosepad_flat_idx < 0:
                    print "ERROR! I think I'm on the nosepad but have not transitioned yet"
                    return []
                # We'll be cutting the far side with the back of the cutter, so need to move at
                # least the diameter to get any flat at all
                flat_length = poly.polyline_length(
                    contour[nosepad_flat_idx:(idx + 1)],
                    False) - (cutter_radius * 2)
                if flat_length < 5:
                    heightmap = heightmap + [pt + [nosepad_removal]]
                else:  # ramp down
                    transition_length = poly.polyline_length(
                        contour[:(idx + 1)], False)
                    ramp_segment = poly.segment(contour, transition_length,
                                                transition_length + 5, False)
                    ramp_segment = poly.ramp(ramp_segment, nosepad_removal,
                                             body_removal, False)
                    heightmap = heightmap + ramp_segment[:-1]
                    items_to_skip = len(ramp_segment)
                    nosepad_flat_idx = idx + items_to_skip  # we'll need this to go down
                    over_nosepad = False
                    past_nosepad = True
            else:
                heightmap = heightmap + [pt + [body_removal]]
        return heightmap

    facing_contour = add_hinge_heights(facing_contour)
    facing_contour = add_nosepad_heights(facing_contour)
    facing_contour = poly.reverse(facing_contour)
    right_facing = poly.mirror_y(facing_contour, True)

    passes = [1]
    heights = [p[2] for p in facing_contour]
    r = [
        cam.change_tool("1/4in ballmill"),
        cam.spindle_speed(22000),
        cam.feedrate(1000),
        cam.start_spindle(),
        cam.rmp(entry_point),
        cam.contour(facing_contour, True),
    ]

    for dilate in passes:
        dilated = poly.reverse(poly.dilate(dilate, facing_contour))
        #        dilated = add_hinge_heights(dilated)
        dilated = add_nosepad_heights(dilated)
        r = r + [
            cam.contour(dilated, True),
        ]
    return r
Exemple #35
0
def face_hinge_pockets(hinge_num, hinge_height, temple_position, centering_shift, thin_back):

    print 'Generating face hinge pockets', hinge_num
    xposition = hinge_height;
    yposition = temple_position+3.0; # 4mm for the temple, but less 1mm for temple hinge pocket
    print 'Position is ', xposition, yposition
    left_hinge = hinges.get_hinge(hinge_num)
    print 'Got left hinge'
    right_hinge = hinges.get_hinge(hinge_num, False)
    print 'Retrieved hinge contours'
    left_translate = [xposition, yposition]
    right_translate = [xposition, -yposition]
    print 'Calculated hinge translations'
    #right_translate = [xposition, 0]
    # Adjust by pocket depth of hinge
    #pocket_depth = left_hinge['pocket_depth']+thin_back

    pocket_depth = 1 + thin_back
    drill_depth = -thin_back - 2.0

    left_contour = poly.mirror_x(poly.rotate_90(left_hinge["face_contour"]), False)
    right_contour = poly.mirror_x(poly.rotate_90(right_hinge["face_contour"]), False)
    left_holes = poly.mirror_x(poly.rotate_90(left_hinge["face_holes"]), False)
    right_holes = poly.mirror_x(poly.rotate_90(right_hinge["face_holes"]), False)
    left_contour = poly.translate(left_contour, left_translate[0], -left_translate[1])
    right_contour = poly.translate(right_contour, right_translate[0], -right_translate[1])
    left_holes = poly.translate(left_holes, left_translate[0], -left_translate[1])
    right_holes = poly.translate(right_holes, right_translate[0], -right_translate[1])

    # Now center everything on the stock
    left_contour = poly.translate(left_contour, centering_shift[0], -centering_shift[1])
    right_contour = poly.translate(right_contour, centering_shift[0], -centering_shift[1])
    left_holes = poly.translate(left_holes, centering_shift[0], -centering_shift[1])
    right_holes = poly.translate(right_holes, centering_shift[0], -centering_shift[1])

    if not poly.is_ccw(left_contour):
        left_contour = poly.reverse(left_contour)
    if not poly.is_ccw(right_contour):
        right_contour = poly.reverse(right_contour)

    left_hinge_pocket_contours = [];
    while len(left_contour) > 0:
        left_contour = poly.erode(1.5875/2, left_contour)
        if len(left_contour) > 0:
            left_contour = left_contour[0]
            left_hinge_pocket_contours.append(left_contour)

    right_hinge_pocket_contours = [];
    while len(right_contour) > 0:
            right_contour = poly.erode(1.5875/2, right_contour)
            if len(right_contour) > 0:
                right_contour = right_contour[0]
                right_hinge_pocket_contours.append(right_contour)
    r = [
        cam.comment("Hinge Pockets"),
        cam.feedrate(750),
        cam.change_tool("1/16in endmill"),
        cam.start_spindle(20000),
        cam.dwell(3),
        cam.comment("Right Hinge Pocket"),
        cam.pocket(right_hinge_pocket_contours, -abs(pocket_depth), retract=-abs(pocket_depth)),
        cam.rapid([None, None, 20.0]),
        cam.comment("Left Hinge Pocket"),
        cam.pocket(left_hinge_pocket_contours, -abs(pocket_depth), retract=-abs(pocket_depth)),
        cam.rapid([None, None, 20.0]),
        cam.comment("Hinge Holes"),
        cam.change_tool("1mm drill"),
        cam.start_spindle(5000),
        cam.dwell(2),
        [cam.rmp(p + [drill_depth], retract=10.0) for p in right_holes],
        [cam.rmp(p + [drill_depth], retract=10.0) for p in left_holes],
        cam.rapid([None, None, 20.0]),
    ]
    return r
Exemple #36
0
def face_hinge_pockets(hinge_num, xposition, yposition):
    left_hinge = hinges.get_hinge(hinge_num)
    right_hinge = hinges.get_hinge(hinge_num, False)
    left_translate = [xposition, -yposition]
    #left_translate = [xposition, 0]
    right_translate = [xposition, yposition]
    #right_translate = [xposition, 0]
    # Adjust by pocket depth of hinge
    pocket_depth = left_hinge['pocket_depth']

    left_contour = poly.translate(left_hinge["face_contour"],
                                  left_translate[0], left_translate[1])
    right_contour = poly.translate(right_hinge["face_contour"],
                                   right_translate[0], right_translate[1])
    left_holes = poly.translate(left_hinge["face_holes"], left_translate[0],
                                left_translate[1])
    right_holes = poly.translate(right_hinge["face_holes"], right_translate[0],
                                 right_translate[1])

    if not poly.is_ccw(left_contour):
        left_contour = poly.reverse(left_contour)
    if not poly.is_ccw(right_contour):
        right_contour = poly.reverse(right_contour)

    left_hinge_pocket_contours = []
    while len(left_contour) > 0:
        left_contour = poly.erode(1.5875 / 2, left_contour)
        if len(left_contour) > 0:
            left_contour = left_contour[0]
            left_hinge_pocket_contours.append(left_contour)

    right_hinge_pocket_contours = []
    while len(right_contour) > 0:
        right_contour = poly.erode(1.5875 / 2, right_contour)
        if len(right_contour) > 0:
            right_contour = right_contour[0]
            right_hinge_pocket_contours.append(right_contour)
    r = [
        cam.comment("Hinge Pockets"),
        cam.feedrate(750),
        cam.change_tool("1/16in endmill"),
        cam.start_spindle(15000),
        cam.dwell(3),
        cam.comment("Right Hinge Pocket"),
        cam.pocket(right_hinge_pocket_contours,
                   -abs(right_hinge['pocket_depth']),
                   retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Left Hinge Pocket"),
        cam.pocket(left_hinge_pocket_contours,
                   -abs(left_hinge['pocket_depth']),
                   retract=0),
        cam.rapid([None, None, 20.0]),
        cam.comment("Hinge Holes"),
        cam.change_tool("1mm drill"),
        cam.start_spindle(4500),
        cam.dwell(2),
        [cam.rmp(p + [-8.0], retract=10.0) for p in right_holes],
        [cam.rmp(p + [-8.0], retract=10.0) for p in left_holes],
        cam.rapid([None, None, 20.0]),
    ]
    return r
Exemple #37
0
def mill_lenses(outdir, order):
    def to_polar(polyline):
        return [[-math.sqrt(p[0]**2 + p[1]**2), math.degrees(math.atan2(p[1],p[0])) + 180] for p in polyline]

    """ Creates g-code for milling the left and right lenses for the frames."""
    lens = g.Polygon(order['lhole_con'])
    x = lens.bounding_box()
    box = lens.bounding_box()
    center = g.Point((box.p2.x+box.p1.x)/2, (box.p2.y+box.p1.y)/2)
    shift_to_origin = g.Vector(-center.x, -center.y)
    lens = g.translate_polygon(lens, shift_to_origin)
    polar = g.polygon_to_uniform_polar(lens, 1500)

    # Inflate the polar form by 1/2 the diameter of the cutter, and convert
    # the angles to degrees
    tau = math.pi * 2
    conv = 360/tau
    roughing = [(pt.theta*conv, pt.r+4.77) for pt in polar]

    # Expand for the roughing cut
#    left_lens_rough = poly.dilate(4.77, left_lens)
    # Convert to polar coordinates
#    left_lens_roughing_polar = to_polar(left_lens_rough)
    # Start the cut from 0 degrees
#    angle_list = [p[1] for p in left_lens_roughing_polar]
#    zero_idx = angle_list.index(min(angle_list))
#    left_lens_roughing_polar = left_lens_roughing_polar[zero_idx:] + left_lens_roughing_polar[:zero_idx]
    # Cut it down to every 0.2 degrees
#    coarse = []
#    for idx, pt in enumerate(left_lens_roughing_polar):
#        if idx == 0 or (pt[1]-coarse[-1][1]) >= 0.2:
#            coarse.append(pt)

    # The polar distances aren't correct quite.  That's because the conversion assumed a flat
    # surface, but we'll actually be bending that contour around a sphere.  The lens is already
    # spherical.  So we need to adjust inwards a bit to account for the x distance actually being an arc
    # distance.

    # The radius of the sphere is 88mm (base 6 lens).  ArcLength = Radius * angle, and chord
    # length is sin(angle) * radius.
    roughing = [(p[0], math.sin(-p[1]/88) * 88) for p in roughing]
    roughing.sort(key=lambda pt: pt[0])
    closest = max([p[1] for p in roughing])
    if abs(closest) < 22.5:
        print "Error!  Cannot cut lens, it's too small.", closest

    roughing_reversed = [[-1*(math.degrees(-math.radians(p[1]))+360), p[1]] for p in roughing]

    program = [
        cam.setup(),
        cam.select_fixture("lens_clamp"),
        cam.retract_spindle(),
        cam.change_tool("1/4in endmill"),
        cam.start_spindle(20000),
        cam.rapid([-50, 0]),
        ["G1 Z0 F500"],
        cam.polar_contour(roughing),
        ["G1 X-50"],
        ["G1 A0"],
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.end_program(),
    ]
    open(outdir + "/left_lens.ngc", "w").write(to_string(program))
    program = [
        cam.setup(),
        cam.select_fixture("lens_clamp"),
        cam.retract_spindle(),
        cam.change_tool("1/4in endmill"),
        cam.start_spindle(20000),
        cam.rapid([-50, 0]),
        ["G1 Z0 F500"],
        cam.polar_contour(roughing_reversed),
        ["G1 X-50"],
        ["G1 A0"],
        cam.stop_spindle(),
        cam.retract_spindle(),
        cam.end_program(),
    ]
    open(outdir + "/right_lens.ngc", "w").write(to_string(program))
Exemple #38
0
def mill_hinges(outdir):
    """Creates the g-code for the first milling operation.  The
    first milling operation is done on an unregistered plastic blank,
    so includes creating registration holes for subsequent operations."""
    y_offsets = [y*15 for y in range(-5, 6)]
    x_offsets = [x*7 for x in range(-3, 4)]

    hinge = hinges.get_hinge(2);
    contour = hinge['face_contour']

    contours = []
    erode = poly.erode(1.5875/2, contour)
    while len(erode) > 0:
        if len(erode) >= 1:
            contours.append(erode[0])
        else:
            break
        erode = poly.erode(1.5875/2, contours[-1])



    program = [
        cam.setup(),
        cam.select_fixture("blank_clamp"),
        cam.retract_spindle(),
        cam.activate_pin("stock_clamp"),
        cam.change_tool("1/16in endmill"),
        cam.rapid([0,0]),
        cam.start_spindle(20000),
        cam.dwell(3),
#        cam.pocket(contours, -1, -1),
#        cam.rapid([None, None, 20.0]),
#        cam.change_tool("1mm drill"),
#        cam.start_spindle(4500),
#        [cam.rmp(p + [-2.5], retract=10.0) for p in hinge['face_holes']],
        ]



    for y_offset in y_offsets:
        for x_offset in x_offsets:
            program += [
                cam.rapid([x_offset, y_offset]),
                cam.temporary_offset((0,0)),
                cam.pocket(contours, -1.2, -1.2),
                cam.rapid([None, None, 20.0]),
                cam.remove_temporary_offset(),
                    ]
#    program += [
#            cam.change_tool("1mm drill"),
#            cam.start_spindle(4500),
#            ]
#    for y_offset in y_offsets:
#        for x_offset in x_offsets:
#            program += [
#                cam.rapid([x_offset, y_offset]),
#                cam.temporary_offset((0,0)),
#                [cam.rmp(p + [-2.5], retract=10.0) for p in hinge['face_holes']],
#                cam.rapid([None, None, 20.0]),
#                cam.remove_temporary_offset(),
#                    ]

    program += [
        cam.deactivate_pin("stock_clamp"),
        cam.end_program(),
    ]


    open(outdir + "/face_stage1.ngc", "w").write(to_string(program))
def contour_face(body_removal, hinge_removal, nosepad_removal, temple_height, face_c, lens_c, x_pos):
    ''' Create the heightmap of the frame, surfacing the back and adding thickness for the
    hinge location and the nosepads.  '''
    if body_removal == hinge_removal == nosepad_removal == 0:
        return [] # Nothing to do

    cutter_radius = 6.35/2 # 3/4 inch cutter
    entry_point = [x_pos, 110, 0]

    facing_contour = poly.dilate(0.05, lens_c)

# Reshape the facing contour so the first point is near the hinge
    center_y = poly.bottom(facing_contour) + (poly.top(facing_contour) - poly.bottom(facing_contour))/2
    center_x = poly.right(facing_contour) + (poly.left(facing_contour) - poly.right(facing_contour))/2
    split_idx = -1
    for idx, pt in enumerate(facing_contour):
        if pt[1] > center_y and (idx+1) < len(facing_contour):
            if (pt[0] < x_pos and facing_contour[idx+1][0] > x_pos) or (pt[0] > x_pos and facing_contour[idx+1][0] < x_pos):
                split_idx = idx
                break
    if split_idx < 0:
        print 'Error contouring back of frame: could not locate entry point for surfacing cut'
        return []
    facing_contour = poly.new_start(facing_contour, split_idx)
# Ensure we're going clockwise, i.e. starting at the hinge and moving up over the frame
    if poly.is_ccw(facing_contour):
        facing_contour = poly.reverse(facing_contour)

# Calculate the Z values
# We'll need a few helper values.  nosepad_start is the inflection point of the nose bridge.
    nosepad_start = max([pt[0] for pt in face_c if pt[1] == 0]) + cutter_radius
    hinge_rampdown_start_x = x_pos + temple_height/2 + cutter_radius
    hinge_rampdown_start_y = facing_contour[0][1] - cutter_radius
    hinge_rampup_start_x = x_pos - temple_height/2 - cutter_radius
    hinge_rampup_start_y = facing_contour[0][1] - cutter_radius

    print nosepad_start, hinge_rampdown_start_x, hinge_rampdown_start_y, hinge_rampup_start_x, hinge_rampup_start_y
    '''
    Arbitrary heuristic, adjusted for aesthetics.
    1. If we're past the center point of the lens hole, we're either on the body
    of the frame or over the raised hinge point.
    2. If we're before the center point we're either on the body or over the nosepiece.

    1a. If we're above the cutter-radius-adjusted top of the temple, we're ramping down
    1b. If we're below the cutter-radius-adjusted bottom of the temple, we're ramping up
    1c. Otherwise we're at body thickness

    2a. If we're above the top of the nose cutout, we're at body thickness
    2b. When we reach nose cutout, we do a s-curve over 3 mm to nosepad height
    2c. Continue for length of cutter diameter to get rear of cutter over highest point
    2d. Continue for 10mm
    2e. S-curve down over 10mm
    '''
    print hinge_removal, body_removal
    def add_hinge_heights(contour):
        heightmap = []
        over_hinge = True # Start over hinge

        items_to_skip = 0 # for fast-forwarding enumeration
        for idx, pt in enumerate(contour):
            if items_to_skip > 0:
                items_to_skip = items_to_skip - 1
                if items_to_skip == 0:
                    print 'first post ramp point', contour[idx+1]
                continue


            if pt[1] < center_y:
                heightmap = heightmap + [pt]
            # Going up and around: start ramping down when we're clear of X or Y
            elif pt[0] > x_pos:
                if pt[0] > hinge_rampdown_start_x or pt[1] < hinge_rampdown_start_y:
                    if(over_hinge): # starting transition
                        transition_length = poly.polyline_length(contour[:(idx+1)], False)
                        ramp_segment = poly.segment(contour, transition_length, transition_length+5, False)
                        ramp_segment = poly.ramp(ramp_segment, hinge_removal, body_removal, False)
                        heightmap = heightmap + ramp_segment[:-1]
                        items_to_skip = len(ramp_segment)
                        print 'last ramp segment', ramp_segment[-1]
                        over_hinge = False
                    else: # past transition but still on hinge side of lens hole
                        heightmap = heightmap + [pt + [body_removal]]
                else: # We're on the top part but haven't reached the transition yet
                    heightmap = heightmap + [pt + [hinge_removal]]

            # Coming back up to the hinge: start ramping up if we encroach on both x and y
            elif pt[0] < x_pos and (pt[0] > hinge_rampup_start_x and pt[1] > hinge_rampdown_start_y):
                if(not over_hinge): # starting transition
                    print pt, x_pos, hinge_rampup_start_x, hinge_rampdown_start_y, idx
                    transition_length = poly.polyline_length(contour[:(idx+1)], False)
                    ramp_segment = poly.segment(contour, transition_length, transition_length+5, False)
                    ramp_segment = poly.ramp(ramp_segment, body_removal, hinge_removal, False)
                    heightmap = heightmap + ramp_segment
                    items_to_skip = len(ramp_segment)
                    over_hinge = True
                else: # Over flat hinge area
                    heightmap = heightmap + [pt + [hinge_removal]]
            else: # We're over the body area but back on the hinge side
                heightmap = heightmap + [pt + [body_removal]]
        return heightmap

    def add_nosepad_heights(contour):
        heightmap = []
        over_nosepad = False
        past_nosepad = False
        nosepad_flat_idx = -1

        items_to_skip = 0 # for fast-forwarding the enumeration
        for idx, pt in enumerate(contour):
            if items_to_skip > 0:
                items_to_skip = items_to_skip-1
                continue
            if pt[1] >= center_y:
                heightmap = heightmap + [pt]
            elif not over_nosepad and not past_nosepad:
                if pt[0] < nosepad_start: # Transition
                    transition_length = poly.polyline_length(contour[:(idx+1)], False)
                    ramp_segment = poly.segment(contour, transition_length, transition_length+5, False)
                    ramp_segment = poly.ramp(ramp_segment, body_removal, nosepad_removal, False)
                    heightmap = heightmap + ramp_segment[:-1]
                    items_to_skip = len(ramp_segment)
                    nosepad_flat_idx = idx + items_to_skip # we'll need this to go down
                    over_nosepad = True
                else: # we're past the nosepad
                    heightmap = heightmap + [pt + [body_removal]]
            elif over_nosepad and not past_nosepad:
                if nosepad_flat_idx < 0:
                    print "ERROR! I think I'm on the nosepad but have not transitioned yet"
                    return []
                # We'll be cutting the far side with the back of the cutter, so need to move at
                # least the diameter to get any flat at all
                flat_length = poly.polyline_length(contour[nosepad_flat_idx:(idx+1)], False) - (cutter_radius*2)
                if flat_length < 5:
                    heightmap = heightmap + [pt + [nosepad_removal]]
                else: # ramp down
                    transition_length = poly.polyline_length(contour[:(idx+1)], False)
                    ramp_segment = poly.segment(contour, transition_length, transition_length+5, False)
                    ramp_segment = poly.ramp(ramp_segment, nosepad_removal, body_removal,  False)
                    heightmap = heightmap + ramp_segment[:-1]
                    items_to_skip = len(ramp_segment)
                    nosepad_flat_idx = idx + items_to_skip # we'll need this to go down
                    over_nosepad = False
                    past_nosepad = True
            else:
                heightmap = heightmap + [pt + [body_removal]]
        return heightmap


    facing_contour = add_hinge_heights(facing_contour)
    facing_contour = add_nosepad_heights(facing_contour)
    facing_contour = poly.reverse(facing_contour)
    right_facing = poly.mirror_y(facing_contour, True)

    passes = [1]
    heights = [p[2] for p in facing_contour]
    r = [
        cam.change_tool("1/4in ballmill"),
        cam.spindle_speed(22000),
        cam.feedrate(1000),
        cam.start_spindle(),
        cam.rmp(entry_point),
        cam.contour(facing_contour, True),
    ]

    for dilate in passes:
        dilated = poly.reverse(poly.dilate(dilate, facing_contour))
#        dilated = add_hinge_heights(dilated)
        dilated = add_nosepad_heights(dilated)
        r = r + [ cam.contour(dilated, True),]
    return r