The file got cut short again at the same spot - I am not sure what is the problem with the upload.
Attached below is the full script, you will need to copy/paste and save as a Drag-Knife.py file.
Cheers - BillT
# DRAG_KNIFE.PY
# Rev: 4-May-2014
# Bill Trondsen
# billtrondsen@yahoo.com
###########################################################################
# This CAMBAM script creates a polyline for Drag-Knife cutting
# Select all desired polylines and run the script
# Note: Material Surface set to Z=0
# Use an engraving path with depth of cut set to zero
# Drag-Knife Path Concept comes from: www.DonekTools.com
# Cut path is simulated by the path of a rear bicycle wheel
# Knowing the rear wheel path, calculate the front wheel (tool path)
# Formulas come from: http://math.ucsd.edu/~ebender/87/bicycle.pdf
#
# Release: 23-Sep-2013 Bill Trondsen
# Rev: 4-May-2014 Bill Trondsen
# - fix Acos precision errors by adding a round() function
# - add SwivelAngle for precision control
# - add RetractEnable toggle to prepare for pluginizing
# - resequence point logic to include RetractEnable and SwivelAngle
# Rev: 6-May-2014 Bill Trondsen
# - fix error in FirstSegment with RetractEnable=0
# - Point placed should be CFirst not C1
#
###########################################################################
# VARIABLES: Set these values for your tool and material
#
# KnifeTipOffset: knife tip distance from tool centerline
# (typically this is 1/2 the tool diameter)
#
# CutDepth: set to material thickness or slightly larger to assure cutting through the material
# A positive value for CutDepth will be set as a -Z value.
# This value would be equivalent to the Engrave Depth.
#
# SwivelAngle: this angle is used as a precision factor
# If the angle between segments is SMALLER than SwivelAngle, a Swivel move will NOT be produced.
# This will make the cut smoother, but less precise to the original path.
# Default value is 5 degrees.
#
# RetractEnable: this is a toggle to enable the Retract Feature
# Value of (1) enables Retract and (0) disables it
#
# RetractAngle: this angle is used for the Retract feature
# If the angle between segments is LARGER than RetractAngle, a Retract move will be produced.
# For thicker material like cardboard, this prevents gouging of material during the swivel move.
# Default value is 40 degrees
#
# RetractDepth: a smaller retract depth used during the swivel move
# A positive value for RetractDepth will be set as a -Z value.
# As a suggestion, try 1/2 the value of the CutDepth.
#
###########################################################################
KnifeTipOffset = .25
CutDepth = .05
SwivelAngle = 10
RetractEnable = 0
RetractAngle = 40
RetractDepth = 0.05
app.log("KnifeTipOffset "+KnifeTipOffset.ToString())
app.log("CutDepth "+CutDepth.ToString())
app.log("SwivelAngle "+SwivelAngle.ToString())
app.log("RetractEnable "+RetractEnable.ToString())
app.log("RetractAngle "+RetractAngle.ToString())
app.log("RetractDepth "+RetractDepth.ToString())
####### MAIN LOOP #########################################
CamBamUI.MainUI.UndoBuffer.AddUndoPoint("Undo Here")
CamBamUI.MainUI.UndoBuffer.Add(doc.ActiveLayer.Entities)
for ent in view.Selection:
if ent.GetType().Name == "Polyline":
xpoly = XPolyline(ent)
app.log("**********************************************************")
app.log("************************Polyline**************************")
app.log("**********************************************************")
app.log("Polyline: "+ent.ID.ToString())
seg = xpoly.FirstSegment
poly = Polyline()
SegNum = 1
######## Loop for each segment within the Polyline #########
while seg is not None:
P1X = seg.P1.X
P1Y = seg.P1.Y
P2X = seg.P2.X
P2Y = seg.P2.Y
V1 = seg.VNormal1.Normal().Normal().Normal()
V2 = seg.VNormal2.Normal().Normal().Normal()
VFirst = Vector2F(1,0)
VLast = Vector2F(1,0)
#### First Point is oriented to X-axis and calculate sweep/bulge to first segment
if seg == xpoly.FirstSegment:
CFirst = Point2F(P1X+KnifeTipOffset, P1Y)
CFirstXP = Vector3F.CrossProduct(Vector3F(1,0,0),Vector3F(V1.X,V1.Y,0))
CFirstDirection = Math.Sign(CFirstXP.Z)
if CFirstDirection == 0:
CFirstDirection = 1
CFirstSweep = Math.Acos(round(Vector2F.DotProduct(VFirst,V1)/(VFirst.Length*V1.Length),10))
CFirstB = Math.Tan(CFirstSweep/4)*CFirstDirection
app.log("CFirst "+CFirst.ToString())
app.log("CFirstSweep "+CFirstSweep.ToString())
app.log("CFirstXP "+CFirstXP.ToString())
app.log("CFirstDirection"+CFirstDirection.ToString())
app.log("CFirstB "+CFirstB.ToString())
#### Set the VN1 vector direction of the next segment
if seg == xpoly.LastSegment:
VN1 = VLast # vector VLast points toward +X after last segment
else:
VN1 = seg.NextSegment.VNormal1.Normal()
VN1.Invert()
#### Remaining Segments - Calculate Cut Points (C1,C2) and Cut Segment Bulge (C1B)
C1 = Point2F(P1X+V1.X*KnifeTipOffset,P1Y+V1.Y*KnifeTipOffset)
if seg.GetType().Name == "XPolySegLine":
C1B = 0
C2 = Point2F(P2X+V2.X*KnifeTipOffset, P2Y+V2.Y*KnifeTipOffset)
elif seg.GetType().Name == "XPolySegArc":
C1B = Math.Tan(seg.Sweep/4)
C2X = P2X+KnifeTipOffset/((1+(V2.Y/V2.X)**2)**.5)*Math.Sign(V2.X)
C2Y = P2Y+(KnifeTipOffset*V2.Y/V2.X)/((1+(V2.Y/V2.X)**2)**.5)*Math.Sign(V2.X)
C2 = Point2F(C2X,C2Y)
#### Calculate Bulge (C2B) for the Sweep Path between segments
VC2 = Vector2F(seg.P2,C2) # vector from P2 to C2 used for calculating sweep path bulge
C2XP = Vector3F.CrossProduct(Vector3F(VC2.X,VC2.Y,0),Vector3F(VN1.X,VN1.Y,0))
C2Direction = Math.Sign(C2XP.Z)
if C2Direction == 0:
C2Direction = 1
C2Sweep = Math.Acos(round(Vector2F.DotProduct(VC2,VN1)/(VC2.Length*VN1.Length),10))
C2B = Math.Tan((C2Sweep)/4)*C2Direction
C2Angle = C2Sweep*180/Math.PI
#### Calculate CLast to orient the tool in the +X direction to prepare for additional segments
CLast = Point2F(seg.P2.X+VLast.X*KnifeTipOffset, seg.P2.Y+VLast.Y*KnifeTipOffset)
###### End of Calculation Section
app.log("******************Segment*******************")
app.log("Segment "+SegNum.ToString())
app.log("P1 "+seg.P1.ToString())
app.log("P2 "+seg.P2.ToString())
app.log("V1 "+V1.ToString())
app.log("V2 "+V2.ToString())
app.log("V2X SIGN "+Math.Sign(V2.X).ToString())
app.log("V2Y SIGN "+Math.Sign(V2.Y).ToString())
app.log("C1 "+C1.ToString())
app.log("C2 "+C2.ToString())
app.log("C1B "+C1B.ToString())
app.log("VN1 "+VN1.ToString())
app.log("VN1.Length "+VN1.Length.ToString())
app.log("VC2 "+VC2.ToString())
app.log("VC2.Length "+VC2.Length.ToString())
app.log("C2Sweep "+C2Sweep.ToString())
app.log("C2B "+C2B.ToString())
########################################################
# Add points to path with depth logic###################
########################################################
#If First Segment
# If RetractEnable = 1
# Place CFirst, RetractDepth, CFirstB
# Place C1, RetractDepth, 0
# ElseIf RetractEnable = 0
# Place CFirst, CutDepth, CFirstB
#
#
#Place C1, CutDepth, C1B
#
#
#If C2Angle >= SwivelAngle then do a swivel move
# If RetractEnable = 1
# Place C2, CutDepth, 0
# Place C2, RetractDepth, C2B
# If RetractEnable = 0
# Place C2, CutDepth, C2B
#
#ElseIf C2Angle < SwivelAngle then do not do a swivel move
# Place P2+Offset*VN1, CutDepth, 0
#
#
#If Last Segment
# If RetractEnable = 1
# Place CLast, RetractDepth, 0
# If RetractEnable = 0
# Place CLast, CutDepth, 0
if seg == xpoly.FirstSegment:
if RetractEnable == 1:
poly.Add(CFirst.X, CFirst.Y, RetractDepth, CFirstB)
poly.Add(C1.X, C1.Y, RetractDepth, 0)
elif RetractEnable == 0:
poly.Add(CFirst.X, CFirst.Y, CutDepth, CFirstB)
poly.Add(C1.X, C1.Y, CutDepth, C1B)
if C2Angle >= SwivelAngle: # then do a swivel move
if RetractEnable == 1:
poly.Add(C2.X, C2.Y, CutDepth, 0)
poly.Add(C2.X, C2.Y, RetractDepth, C2B)
elif RetractEnable == 0:
poly.Add(C2.X, C2.Y, CutDepth, C2B)
elif C2Angle < SwivelAngle: # then do not do a swivel move
poly.Add(P2X+KnifeTipOffset*VN1.X, P2Y+KnifeTipOffset*VN1.Y, CutDepth, 0)
if seg == xpoly.LastSegment:
if RetractEnable == 1:
poly.Add(CLast.X, CLast.Y, RetractDepth, 0)
elif RetractEnable == 0:
poly.Add(CLast.X, CLast.Y, CutDepth, 0)
app.log("SwivelAngle "+SwivelAngle.ToString())
app.log("C2Angle "+C2Angle.ToString())
#### End of Main Loop #####################################
SegNum += 1
seg = seg.NextSegment
doc.Add(poly)