def rapid_to_next(myscreen, prv_tang, nxt_tang, c1, r1, c2, r2, prv, nxt): # rapid from prev, to nxt # while staying inside c1(r1) and c2(r) rad_default = 0.003 rad = min(rad_default, 0.9 * r1, 0.9 * r2) prv_tang.normalize() nxt_tang.normalize() prv_normal = -1 * prv_tang.xy_perp() nxt_normal = nxt_tang.xy_perp() cen1 = prv + rad * prv_normal # + rad1*prv_tang cen2 = nxt - rad * nxt_normal # rapid_tang # + rad1*prv_tang rapid_tang = cen2 - cen1 rapid_tang.normalize() trg1 = cen1 + rad * rapid_tang.xy_perp() # prv_tang src2 = cen2 + rad * rapid_tang.xy_perp() drawArc(myscreen, prv, trg1, rad, cen1, True, ovdvtk.blue) # lead-out arc ovdvtk.drawLine(myscreen, trg1, src2, ovdvtk.cyan) # rapid ngc_writer.xy_line_to(src2.x, src2.y) drawArc(myscreen, src2, nxt, rad, cen2, True, ovdvtk.lblue) # lead-in arc
def rapid_to_new_branch(myscreen, prv_tang, nxt_tang, c1, r1, c2, r2, prv, nxt): # rapid from prev, to nxt # while staying inside c1(r1) and c2(r) rad_default = 0.003 rad1 = min(rad_default, 0.9 * r1) # wrong? we get the new-branch r1 here, while we would want the old-branch r1 rad2 = min(rad_default, 0.9 * r2) prv_tang.normalize() nxt_tang.normalize() prv_normal = -1 * prv_tang.xy_perp() nxt_normal = nxt_tang.xy_perp() cen1 = prv + rad1 * prv_normal # + rad1*prv_tang cen2 = nxt - rad2 * nxt_normal # rapid_tang # + rad1*prv_tang rapid_tang = cen2 - cen1 rapid_tang.normalize() trg1 = cen1 + rad1 * prv_tang src2 = cen2 - rad2 * nxt_tang drawArc(myscreen, prv, trg1, rad1, cen1, True, ovdvtk.orange) # lead-out arc ngc_writer.pen_up() ovdvtk.drawLine(myscreen, trg1, src2, ovdvtk.magenta) # rapid ngc_writer.xy_line_to(src2.x, src2.y) ngc_writer.pen_down() drawArc(myscreen, src2, nxt, rad2, cen2, True, ovdvtk.mag2) # lead-in arc
def drawArc(myscreen, pt1, pt2, r, cen, cw, arcColor): # draw arc as many line-segments start = pt1 - cen end = pt2 - cen theta1 = math.atan2(start.x, start.y) theta2 = math.atan2(end.x, end.y) alfa = [] # the list of angles da = 0.1 CIRCLE_FUZZ = 1e-9 # idea from emc2 / cutsim g-code interp G2/G3 if (cw == False): while ((theta2 - theta1) > -CIRCLE_FUZZ): theta2 -= 2 * math.pi else: while ((theta2 - theta1) < CIRCLE_FUZZ): theta2 += 2 * math.pi dtheta = theta2 - theta1 arclength = r * dtheta dlength = min(0.01, arclength / 10) steps = int(float(arclength) / float(dlength)) rsteps = float(1) / float(steps) dc = math.cos(-dtheta * rsteps) # delta-cos ds = math.sin(-dtheta * rsteps) # delta-sin previous = pt1 tr = [start.x, start.y] for i in range(steps): tr = rotate(tr[0], tr[1], dc, ds) # ; // rotate center-start vector by a small amount x = cen.x + tr[0] y = cen.y + tr[1] current = ovd.Point(x, y) myscreen.addActor(ovdvtk.Line(p1=(previous.x, previous.y, 0), p2=(current.x, current.y, 0), color=arcColor)) ngc_writer.xy_line_to(current.x, current.y) previous = current
def printOffsets(ofs): nloop = 0 for lop in ofs: n = 0 N = len(lop) first_point=[] previous=[] for p in lop: # p[0] is the Point # p[1] is -1 for lines, and r for arcs if n==0: # don't draw anything on the first iteration previous=p[0] ngc_writer.pen_up() ngc_writer.xy_rapid_to( scale*previous.x, scale*previous.y) ngc_writer.pen_down() else: cw=p[3] # cw or ccw arc cen=p[2] # center of arc r=p[1] # radius of arc p=p[0] # target position if r==-1: # -1 means line ngc_writer.xy_line_to( scale*p.x, scale*p.y ) else: ngc_writer.xy_arc_to( scale*p.x, scale*p.y, scale*r, scale*cen.x, scale*cen.y, cw ) previous=p n=n+1 nloop = nloop+1
def rapid_to_new_branch(myscreen, prv_tang, nxt_tang, c1, r1, c2, r2, prv, nxt): # rapid from prev, to nxt # while staying inside c1(r1) and c2(r) rad_default = 0.003 rad1 = min( rad_default, 0.9 * r1 ) # wrong? we get the new-branch r1 here, while we would want the old-branch r1 rad2 = min(rad_default, 0.9 * r2) prv_tang.normalize() nxt_tang.normalize() prv_normal = -1 * prv_tang.xy_perp() nxt_normal = nxt_tang.xy_perp() cen1 = prv + rad1 * prv_normal # + rad1*prv_tang cen2 = nxt - rad2 * nxt_normal #rapid_tang # + rad1*prv_tang rapid_tang = cen2 - cen1 rapid_tang.normalize() trg1 = cen1 + rad1 * prv_tang src2 = cen2 - rad2 * nxt_tang drawArc(myscreen, prv, trg1, rad1, cen1, True, ovdvtk.orange) # lead-out arc ngc_writer.pen_up() ovdvtk.drawLine(myscreen, trg1, src2, ovdvtk.magenta) # rapid ngc_writer.xy_line_to(src2.x, src2.y) ngc_writer.pen_down() drawArc(myscreen, src2, nxt, rad2, cen2, True, ovdvtk.mag2) # lead-in arc
def rapid_to_next(myscreen, prv_tang, nxt_tang, c1, r1, c2, r2, prv, nxt): # rapid from prev, to nxt # while staying inside c1(r1) and c2(r) rad_default = 0.03 rad = min(rad_default, 0.9 * r1, 0.9 * r2) prv_tang.normalize() nxt_tang.normalize() prv_normal = -1 * prv_tang.xy_perp() nxt_normal = nxt_tang.xy_perp() cen1 = prv + rad * prv_normal # + rad1*prv_tang cen2 = nxt - rad * nxt_normal #rapid_tang # + rad1*prv_tang rapid_tang = cen2 - cen1 rapid_tang.normalize() trg1 = cen1 + rad * rapid_tang.xy_perp() #prv_tang src2 = cen2 + rad * rapid_tang.xy_perp() drawArc(myscreen, prv, trg1, rad, cen1, True, ovdvtk.blue) # lead-out arc ovdvtk.drawLine(myscreen, trg1, src2, ovdvtk.cyan) # rapid ngc_writer.xy_line_to(src2.x, src2.y) drawArc(myscreen, src2, nxt, rad, cen2, True, ovdvtk.lblue) # lead-in arc
def drawToolPath(myscreen, mic_list, cut_width): maxmic = mic_list[0] previous_center = maxmic[0] previous_radius = maxmic[1] nframe = 0 first = True previous_out1 = ovd.Point() out_tangent = ovd.Point() in_tangent = ovd.Point() for n in range(1, len(mic_list)): mic = mic_list[n] cen2 = mic[0] r2 = mic[1] previous_center = mic[6] previous_radius = mic[7] new_branch = mic[8] # true/false indicates if we are starting on new branch prev_branch_center = mic[9] prev_branch_radius = mic[10] # old branch MIC radius in1 = mic[3] in2 = mic[5] out2 = mic[4] out1 = mic[2] in_tangent = in2 - in1 # rapid traverse to in1 if not first: if new_branch: # new branch re-position move rapid_to_new_branch(myscreen, out_tangent, in_tangent, prev_branch_center, prev_branch_radius, cen2, r2, previous_out1, in1) else: # normal arc-rapid-arc to next MIC rapid_to_next(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) else: # spiral-clear the start-MIC. The spiral should end at in1 spiral_clear(myscreen, cut_width, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) # print "No rapid-move on first-iteration." first = False # in bi-tangent ovdvtk.drawLine(myscreen, in1, in2, ovdvtk.green) ngc_writer.xy_line_to(in2.x, in2.y) # cut-arc drawArc(myscreen, in2, out2, r2, cen2, True, ovdvtk.green) # out bi-tangent ovdvtk.drawLine(myscreen, out2, out1, ovdvtk.green) ngc_writer.xy_line_to(out1.x, out1.y) previous_out1 = out1 # this is used as the start-point for the rapid on the next iteration out_tangent = out1 - out2 if n == len(mic_list) - 1: # end of operation. do a final lead-out arc. final_lead_out(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) nframe = nframe + 1
def drawArc(myscreen, pt1, pt2, r, cen, cw, arcColor): # draw arc as many line-segments start = pt1 - cen end = pt2 - cen theta1 = math.atan2(start.x, start.y) theta2 = math.atan2(end.x, end.y) alfa = [] # the list of angles da = 0.1 CIRCLE_FUZZ = 1e-9 # idea from emc2 / cutsim g-code interp G2/G3 if (cw == False): while ((theta2 - theta1) > -CIRCLE_FUZZ): theta2 -= 2 * math.pi else: while ((theta2 - theta1) < CIRCLE_FUZZ): theta2 += 2 * math.pi dtheta = theta2 - theta1 arclength = r * dtheta dlength = max(0.001, arclength / 10) steps = int(float(arclength) / float(dlength)) if steps == 0: steps = 1 rsteps = float(1) / float(steps) dc = math.cos(-dtheta * rsteps) # delta-cos ds = math.sin(-dtheta * rsteps) # delta-sin previous = pt1 tr = [start.x, start.y] for i in range(steps): tr = rotate(tr[0], tr[1], dc, ds) # ; // rotate center-start vector by a small amount x = cen.x + tr[0] y = cen.y + tr[1] current = ovd.Point(x, y) myscreen.addActor( ovdvtk.Line(p1=(previous.x, previous.y, 0), p2=(current.x, current.y, 0), color=arcColor)) ngc_writer.xy_line_to(current.x, current.y) previous = current
def spiral_clear(myscreen, cutwidth, out_tangent, in_tangent, c1, r1, c2, r2, out1, in1): print "( spiral clear! )" ngc_writer.pen_up() # end spiral at in1 # archimedean spiral # r = a + b theta in1_dir = in1 - c1 in1_theta = math.atan2(in1_dir.y, in1_dir.x) # in1_theta = in1_theta # print "c1 =", c1 # print "in1 = ",in1 # print " end theta = ",in1_theta drawPoint(myscreen, c1, ovdvtk.red) # drawPoint( myscreen, in1, ovdvtk.blue, 0.006 ) # width = 2*pi*b # => b = width/(2*pi) b = cutwidth / (2 * math.pi) # r = a + b in1_theta = r_max # => # a = r_max-b*in1_theta a = r1 - b * in1_theta # figure out the start-angle theta_min = in1_theta theta_max = in1_theta dtheta = 0.1 min_r = 0.001 while True: r = a + b * theta_min if r < min_r: break else: theta_min = theta_min - dtheta # print "start_theta = ", theta_min Npts = (theta_max - theta_min) / dtheta Npts = int(Npts) # print "spiral has ",Npts," points" p = ovd.Point(c1) ngc_writer.xy_rapid_to(p.x, p.y) ngc_writer.pen_down() theta_end = 0 for n in range(Npts + 1): theta = theta_min + n * dtheta r = a + b * theta theta = theta - 2 * abs(in1_theta - math.pi / 2) trg = c1 + r * ovd.Point(-math.cos(theta), math.sin(theta)) ovdvtk.drawLine(myscreen, p, trg, ovdvtk.pink) ngc_writer.xy_line_to(trg.x, trg.y) p = trg theta_end = theta # add a complete circle after the spiral. print "( spiral-clear: final circle )" Npts = (2 * math.pi) / dtheta Npts = int(Npts) for n in range(Npts + 2): theta = theta_end + (n + 1) * dtheta # theta = theta_min + n*dtheta r = r1 # a + b*theta # theta = theta - 2* abs(in1_theta - math.pi/2 ) trg = c1 + r * ovd.Point(-math.cos(theta), math.sin(theta)) ovdvtk.drawLine(myscreen, p, trg, ovdvtk.pink) ngc_writer.xy_line_to(trg.x, trg.y) # if n != Npts+1: # drawPoint(myscreen, trg, ovdvtk.orange) # else: # drawPoint(myscreen, trg, ovdvtk.orange,0.004) p = trg
cen2, r2, previous_out1, in1) else: # normal arc-rapid-arc to next MIC rapid_to_next(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) else: # spiral-clear the start-MIC. The spiral should end at in1 spiral_clear(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) # print "No rapid-move on first-iteration." first = False # in bi-tangent ovdvtk.drawLine(myscreen, in1, in2, ovdvtk.green) ngc_writer.xy_line_to(in2.x, in2.y) # draw arc drawArc(myscreen, in2, out2, r2, cen2, True, ovdvtk.green) # out bi-tangent ovdvtk.drawLine(myscreen, out2, out1, ovdvtk.green) ngc_writer.xy_line_to(out1.x, out1.y) previous_out1 = out1 # this is used as the start-point for the rapid on the next iteration out_tangent = out1 - out2 if n == len(mic_list) - 1: # end of operation. do a final lead-out arc. final_lead_out(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) # print "Final lead-out arc"
def spiral_clear(myscreen, out_tangent, in_tangent, c1, r1, c2, r2, out1, in1): print "( spiral clear! )" ngc_writer.pen_up() # end spiral at in1 # archimedean spiral # r = a + b theta in1_dir = in1 - c1 in1_theta = math.atan2(in1_dir.y, in1_dir.x) # in1_theta = in1_theta # print "c1 =", c1 # print "in1 = ",in1 # print " end theta = ",in1_theta drawPoint(myscreen, c1, ovdvtk.red) # drawPoint( myscreen, in1, ovdvtk.blue, 0.006 ) # width = 2*pi*b # => b = width/(2*pi) b = 0.01 / (2 * math.pi) # r = a + b in1_theta = r_max # => # a = r_max-b*in1_theta a = r1 - b * in1_theta # figure out the start-angle theta_min = in1_theta theta_max = in1_theta dtheta = 0.1 min_r = 0.001 while True: r = a + b * theta_min if r < min_r: break else: theta_min = theta_min - dtheta # print "start_theta = ", theta_min Npts = (theta_max - theta_min) / dtheta Npts = int(Npts) # print "spiral has ",Npts," points" p = ovd.Point(c1) ngc_writer.xy_rapid_to(p.x, p.y) ngc_writer.pen_down() theta_end = 0 for n in range(Npts + 1): theta = theta_min + n * dtheta r = a + b * theta theta = theta - 2 * abs(in1_theta - math.pi / 2) trg = c1 + r * ovd.Point(-math.cos(theta), math.sin(theta)) ovdvtk.drawLine(myscreen, p, trg, ovdvtk.pink) ngc_writer.xy_line_to(trg.x, trg.y) p = trg theta_end = theta # add a complete circle after the spiral. print "( spiral-clear: final circle )" Npts = (2 * math.pi) / dtheta Npts = int(Npts) for n in range(Npts + 2): theta = theta_end + (n + 1) * dtheta # theta = theta_min + n*dtheta r = r1 # a + b*theta # theta = theta - 2* abs(in1_theta - math.pi/2 ) trg = c1 + r * ovd.Point(-math.cos(theta), math.sin(theta)) ovdvtk.drawLine(myscreen, p, trg, ovdvtk.pink) ngc_writer.xy_line_to(trg.x, trg.y) # if n != Npts+1: # drawPoint(myscreen, trg, ovdvtk.orange) # else: # drawPoint(myscreen, trg, ovdvtk.orange,0.004) p = trg
# new branch re-position move rapid_to_new_branch(myscreen, out_tangent, in_tangent, prev_branch_center, prev_branch_radius, cen2, r2, previous_out1, in1) else: # normal arc-rapid-arc to next MIC rapid_to_next(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) else: # spiral-clear the start-MIC. The spiral should end at in1 # spiral_clear(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) # print "No rapid-move on first-iteration." first = False # in bi-tangent ovdvtk.drawLine(myscreen, in1, in2, ovdvtk.green) ngc_writer.xy_line_to(in2.x, in2.y) # draw arc drawArc(myscreen, in2, out2, r2, cen2, True, ovdvtk.green) # out bi-tangent ovdvtk.drawLine(myscreen, out2, out1, ovdvtk.green) ngc_writer.xy_line_to(out1.x, out1.y) previous_out1 = out1 # this is used as the start-point for the rapid on the next iteration out_tangent = out1 - out2 if n == len(mic_list) - 1: # end of operation. do a final lead-out arc. final_lead_out(myscreen, out_tangent, in_tangent, previous_center, previous_radius, cen2, r2, previous_out1, in1) # print "Final lead-out arc"