CamBam

Resources => Scripts and Plugins => Topic started by: billt on October 03, 2013, 04:00:27 am



Title: Drag-Knife Script
Post by: billt on October 03, 2013, 04:00:27 am
Adding drag-knife functionality to CAMBAM!
This will be useful for all of us messing with cutting vinyl, wood veneer, cardboard...

This Python script takes selected polylines and generates new polylines used for the drag-knife tool path.
From the tool path polyline, an engrave MOP must be used to create the actual tool path and G-code.
Extract the file drag_knife.py from the attached ZIP file and save it into your "Scripts" directory.

Without compensation, sharp corners are rounded due to the drag-knife tip offset.
This script adds "corner features" which includes an overcut and swivel arc to the next cut segment.
Also added is a "retract" feature at the corners which retracts during the swivel motion for thick materials.
Note, the blade must be oriented toward the +X direction which allows the first point to be precisely located.
These features are well described at: www.DonekTools.com

Also featured is support for the knife tip to exactly follow arc paths.
The concept is based on bicycle front/rear wheel paths.
The "front wheel" is driven by the machine engrave path, and the knife tip is the "rear wheel".
The tool offset (distance from the tool centerline to knife tip) correlates to the bike wheelbase.
Formulas for bike wheel path are found at:  http://math.ucsd.edu/~ebender/87/bicycle.pdf

The script works in concept, however the polyline start/end points can create a problem with cut results.
I tested using a modified Cricut holder (with blade auto-spring!), 2mm blade has a very small .009" offset.
I guess my machine has poor resolution, and the tiny arc paths did not orient the blade exit correctly.
This resulted in some start/end corners that were not perfect and did not release free.
Picking the start/end points in the middle of a horizontal section would give better results.
Although CAMBAM does not make it easy to select the polyline start point...
I am now working on Rev 2 which will attempt to find a good start point, and make all cuts CCW.

Also of interest, I will be posting soon my DIY drag-knife tool designs.
Several options should get you going hopefully for under $20.
I have on order two other Roland blade holders for modifications: spring feature and hold in a 1/2" collet.
Also a potential X-Acto drag-knife design which should work well for thicker material like cardboard.

By the way, if anyone is willing to make this into a Plugin, that would be awesome!

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: billt on October 03, 2013, 04:08:29 am
If a plugin could be created, a helpful feature would be to slow the tool speed down for the corner features.
A related "Quality" setting on some vinyl cutters affects the acceleration speed in/out of corners.
This would help the quality of corner cuts.
Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Bubba on October 03, 2013, 22:47:22 pm
If a plugin could be created, a helpful feature would be to slow the tool speed down for the corner features.
A related "Quality" setting on some vinyl cutters affects the acceleration speed in/out of corners.
This would help the quality of corner cuts.
Cheers - BillT


Did you considered a 'Exact stop' settings. I believe it would help with corners..


Title: Re: Drag-Knife Script
Post by: billt on October 05, 2013, 03:10:08 am
Thanks for the tip.
I will try this out and let you know if it improves the corners.
 - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 20, 2014, 12:36:10 pm
Here's my take on making a holder which holds a Roland type knife holder :)
And it works to my surprise.
There are two problems, however. Both related to knife tip offset.
1. Corners - simplest check is a right corner - because the edge lags behind (0.25 mm for that knife) at the turning point it has still not cut the material to the corner. Therefore a small arc is cut in practice before the knife pivots itself on the perpendicular line.
2. Closed shapes not cut - again a classic G-code program stops at where the tool axis is but the knife is a bit behind and there is a tiny distance of uncut material left which hampers the consequent removal of waste material.

The factory cutting plotters have this value settable and their software accounts for it.

Otherwise the spring force is adjusted by Z-height and DOC by the adjusting cap leaving just enough of the blade protruding.
But the Chinese Roland type holder clone I got is manufactured with quite loose tolerances so that the adjustment cap is shaking on its thread.


Title: Re: Drag-Knife Script
Post by: billt on April 21, 2014, 02:27:35 am
Dragonfly -
I was also able to modify a Roland-style cutter, and it provides spring force adjustment screw.
See the topic http://www.cambam.co.uk/forum/index.php?topic=3667.0

Your post is not clear - did you use the drag knife script from my earlier post to modify your cut path?
I believe that this would fix your corner and end point issues.
It is not a plugin, but can be loaded to you Scripts directory, select the paths, then run the script.
New paths with corner over-cut features are created to compensate for the drag knife offset.
You will need to update your knife offset value in the script itself before running.

BTW I recently bought a Silhouette Portrait for a little over $100.
It is a small machine that cuts up to 8 inches wide, and works really well for small vinyl projects.
The software is free and really good for artistic 2D stuff, but does not do 2.5D or export g-code.
I found that you can fake an export by printing to PDF then converting to dxf.
So... I have not made any improvements to the script since the initial release.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 21, 2014, 12:21:57 pm
I haven't tested your script yet, just downloaded it. First I wanted to see whether I got right the concept of how a cutting plotter knife works. I tried on a piece of some domestic adhesive foil whose backing is quite thin and it still worked. Tomorrow I'll get a piece of real vinyl foil for testing.

As I mentioned the quality of the Chinese knife holder is poor (at least to me) and it appears there is only one bearing to support the knife. So, with a friend of mine who has a small precise lathe, we decided to make a holder of our own and with all metric threads.

The picture you posted in the other thread is not very clear but it seems there are differences in construction although external body shape is the same. Wen I remove the hollow screw at the back nothing comes out. It seems the spring and magnet are inserted from the front and then the bearing is press fitted into the body. My main problem is that the knife protrudes too far over the cap even with the set screw removed and this requires unscrewing the adjusting cap too much so it starts to shake loosely.


Title: Re: Drag-Knife Script
Post by: lloydsp on April 21, 2014, 13:41:39 pm
Bill,
For scheduling, I cannot attend to it now, but that looks to be an easy script to make into a plugin.

If someone doesn't get to it before I do, I'll do that as soon as I get this current (pressing) project out.

LLoyd


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 21, 2014, 14:25:47 pm
I just tried the script on a shape I used to test the cutting.
It creates a new poly so it's better to have a new empty active layer ready.
The new path looks like what I've seen in a Roland plotter user manual I downloaded and read. Haven't tried to go into the code  but I am impressed.
With red circles I've marked the small corrections along the long irregular curves.
In the yellow circle and zoomed is what I consider an intentionally created start point with the original closed shape broken at the same spot. Am I right in my conclusion?


Title: Re: Drag-Knife Script
Post by: billt on April 22, 2014, 15:16:34 pm
Dragonfly -
You are correct, the feature that you circled and zoomed is the first point of your polyline path.
The script expects that the knife tip is manually oriented toward the +X direction.
Your start segment is not horizontal, so the first tool point is offset to the +X by the knife offset value, and then swivels toward the direction of the first path segment.
Note also at the end of the path, the tool will swivel back to +X to prepare for the next polyline.

LLoyd - Thanks for offering to pluginize my creation!
I will watch for updates and will look forward to testing it out.

This start point could be improved or automated for better results, but I have not gotten around to it yet.
 - The script could search for a horizontal segment in the polyline to set the start point in the middle of the segment.  Then a swivel at the beginning and end of the path would not be necessary.  It should give a cleaner cut.  It might also help to do a slight overcut of the end point to make sure that the material is fully cut through.
 - Or, I notice as I watch my Silhouette machine that it does a quick slice in the top corner of the material in a "waste" area to orient the knife prior to cutting the first path.  This would be easy to program, just determine the direction of the first cut segment.  In this case the knife would not need to be manually oriented.  Maybe as a plugin a checkbox could select whether the user wants to manually orient in +X, or do an automated slice in a waste zone.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 22, 2014, 19:48:27 pm
Bill,
I am looking at the script code but understand too little of it. Especially because I have no idea about CB API functions and objects.
Is there a way to make it adjust and compensate only real corners and not to make the tiny dents along the curved shapes. I don't need that accuracy for what I intend to do and they disrupt the constant velocity mode.
Also I think it would be useful if it is possible to make the cut overlap between start and end a bit larger. Still there are tiny uncut spikes.
Maybe because the actual knife offset is too small - 0.25 mm.


Title: Re: Drag-Knife Script
Post by: billt on April 22, 2014, 21:36:13 pm
The script function does follow curves exactly.
The location of the "tiny dents" that you have circled in red are at points where polyline segments meet at an angle larger than the value specified by the variable "SwivelAngle" that you can set at the beginning of the script.
The default value is set to 40 (degrees).
If you have a low precision part a better value to try might be 89 (degrees) - you will find that your "tiny dents" on the curved segments will no longer be created.

You are correct, there is currently no overcut at the start/end point.
As I mentioned previously, this would be a good feature to add in a future revision.
You might be able to fake it by using a smaller than actual value for the Offset, although this might affect your precision at the corners.

By the way, you need to use half the width of the knife for the Offset value since this is the distance from the centerline of the knife to the knife tip.  So if measuring the knife with calipers gives 0.25mm use 0.125mm for the Offset value.  Maybe this will correct your uncut end points?

Let me know how you make out with these suggestions.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 23, 2014, 09:47:04 am
Thanks for your assistance. It appears I have misunderstood the usage of the '"Swivel Angle" variable :)


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 23, 2014, 18:31:02 pm
Interesting. This simple shape I drew from a rectangle and a circle just for testing causes "division by zero" error at line 83 -> V2.X = 0.
But that's all I can tell at the moment.


Title: Re: Drag-Knife Script
Post by: lloydsp on April 23, 2014, 20:25:52 pm
Those are easy to fix.  I'll let Bill modify it until everyone is happy, before I tackle plugin-izing it. :)

Lloyd


Title: Re: Drag-Knife Script
Post by: billt on April 24, 2014, 17:42:03 pm
I checked out your file and it fails at an intermediate point on the curve - the point is also the last point on the polyline.
I deleted the point and changed the curve bulge to 1 and the cut path worked properly.
Maybe the rounding errors of the curve bulge value causes the end point not to exactly match the start point resulting in the error.
By the way, I did not get any error displayed, even with the diagnostic level set to 4 - where did your "division by zero" error show up?
Cheers - BillT


Title: Re: Drag-Knife Script
Post by: lloydsp on April 24, 2014, 18:26:15 pm
Bill,
I don't know this is the case, but if that supposed cause of the error is true, you may have to restrict the precision of your arithmetic in the script.

I've already worked with someone else's plugin where it was necessary to round everything to (eh, roughly) 1/100,000th inch or 1/1000th mm.

CB calculates everything out to extreme precision, so 1E-18 <> 0   <G>

LLoyd


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 24, 2014, 22:57:04 pm
Bill, the message I got in the message window. On the attached picture your knife offset is far too large than mine.
I should mention also that I am tinkering with your code on a "hit & miss" principle :)
With the Roland type tiny knife I thunk there's no need for lifting, so I set lift and DOC = 0. And tried to make the code do an overlap cut at start/end with some success (on a different shape). At least on screen the geometry looks like what I want it to be. But the division by zero on the shape I posted disappeared. I suspect the code never runs through that part because most probably I've messed up with the funky Python syntax which I stumble on for the first time :)


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 29, 2014, 18:41:18 pm
That Python is a real constrictor :D
I've never had any experience with it and in the last days am fighting with the code to not much positive result. :(
1.
Since vinyl foil is less than 1/10 mm thick there is no need for complex swivel knife maneuvering when turning. So I am trying to change the code to my liking but hit a rock here:
Code:
   C3Sweep = Math.Acos(Vector2F.DotProduct(V3,VN1)/(V3.Length*VN1.Length))
There are cases when
Code:
Vector2F.DotProduct(V3,VLast)
equals zero and consequently
Code:
C3Sweep = Math.Acos(0)
but instead of 90 the calculation returns NaN (not a number). I split the expression to simple ones that result in separate variables and although the latter are displayed with the expected values in the log still the NaN makes a mess of the new polylines.
This happens even in the original code in a special case when there is a 90 degree arc (1/4 circle).

2.
Before the actual calculations begin I am trying to make all selected shapes (polylines only) have a CCW direction of rotation. I do this successfully with a VB script but under Python, acting in a similar way does not change the direction. I suspect I am acting on a copy of the real poly but can't figure where I make a mistake and how to make the changes.

Any help will be appreciated.

P.S.
Quote
xpoly = XPolyline(ent)
seg = xpoly.FirstSegment

What is 'XPolyline'? Couldn't find info in the 'doc/api' section.


Title: Re: Drag-Knife Script
Post by: billt on April 29, 2014, 19:43:45 pm
Dragonfly -
Thanks for finding these bugs.

The first V3.X divide-by-zero issue I can easily add an "if V3.X==0" condition and a couple of lines to handle the zero value.

Acos(0) should return 90, but if it is giving you NaN there might be a solution.
A wikipedia search on "Inverse trigonometric functions" suggest that functions atan or atan2 might be able to better handle zero (or close to zero) values.
I will modify and check a couple of cases to see if it makes an improvement.

Regarding your CCW rotation, I had the same issue as you - I was acting on a copy of the polyline.
Andy responded with a correction to my code - see the thread below.
http://www.cambam.co.uk/forum/index.php?topic=3652.0

Third regarding XPolyline() - it is a 2-D Polyline entity, and has helpful functions related to 2-D.
Of course this stuff is not in the doc/api, but I have found you can explore the available functions by running a simple script such as:
for m in dir(XPolyline()): print m
print help(XPolyline)
See the topic at: http://www.cambam.co.uk/forum/index.php?topic=3057.0


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 29, 2014, 20:39:08 pm
Thanks Bill,
I've missed the thread from the first link and will try the modification.
The second one I read but I presume I have to install stand alone Python on my PC in order to explore the functions. Or maybe first I should see where 'print' outputs to under CB.
Apart from being a stranger to Python I've forgotten a lot of things in maths and my brain has gotten very rusty :)
Also, I intend to try and see what effect, if any, rounding the point coordinate values have on the drag knife script output. There's a VB script for that by dh42.


Title: Re: Drag-Knife Script
Post by: billt on April 29, 2014, 21:59:24 pm
Python is actually baked into CB - I believe it is the Iron Python distribution.
The Math Library is now pre-compiled, so you do not need to import it.
Other external libraries can be imported, but you would need to set the import path.
See the following thread:
http://www.cambam.co.uk/forum/index.php?topic=3062.msg19215#msg19215

And the print results will show up in the message window - you can scroll or copy/paste to notepad for easier viewing.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on April 30, 2014, 21:41:46 pm
Hi Bill,
I continue to dig but hit a rock :)
I am thinking of an approach to finding the points where tool center should return on a following segment after overshooting the end of the previous. For test purpose I put up script that will walk the segments in sequence and draw a circle (Circle2F needed) using the first point2F (P1) as a center. The radius is set 2 mm for better visual inspection. Then I try to find a point where an Arc intersects with the circle or the circle intersects with a Line. Both methods are said to return a Line2F object. The code runs OK. But I can't access the values of the points. I get a message that Line2F has no property P1 (or P2). Tried X1/Y1, x1/y1, a/b with the same error appearing.
Only ToString method works and in the description it will return a string: (X1,Y1)-(X2,Y2). But because there is only one valid intersection point in the message window there are strange combinations (the attached picture).
At firs I though those are negative signs but it seems they are the dashes from the truncated output. They appear either in front and there are two -- when the result is expected to be negative, or at the end. I presume this is due to which Point2F is valid and which is undefined.
But the main problem is I can't access those values from the script. Otherwise it seems the coordinates are valid.
I wanted to make the CamBam.CAD do the maths internally instead of applying complex calculations within the script. And it seems for now the idea is applicable.
Here's the code: Note, I work with Metric units.
Code:
#PropTest.py

####### MAIN LOOP #########################################

CamBamUI.MainUI.UndoBuffer.AddUndoPoint("Undo Here")
CamBamUI.MainUI.UndoBuffer.Add(doc.ActiveLayer.Entities)

for entity in view.Selection:
  if entity.GetType().Name == "Polyline":
    xpoly = XPolyline(entity)
    app.log("************************Polyline**************************")
    app.log("Polyline:    "+entity.ID.ToString())
    app.log("Segments:    "+entity.NumSegments.ToString())
    seg = xpoly.FirstSegment
    poly = Polyline()
    SegNum = 1
    VFirst = Vector2F(1,0)
    VLast = Vector2F(1,0)

# ####### Loop for each segment within the Polyline #########
    while seg is not None:

      V1 = seg.VNormal1.Normal().Normal().Normal()
      V2 = seg.VNormal2.Normal().Normal().Normal()
      SName = seg.GetType().Name
      app.log("Segment        ="+SegNum.ToString())
      app.log("Name           ="+SName.ToString())
      if SName == "XPolySegLine":
         cir = Circle2F(seg.P1,2)
         cir1 = Circle(seg.P1,2) 
         MyLine = Line2F(seg.P1, seg.P2)
         XSect = cir.LineIntersect(MyLine)
         app.log("P1    = "+seg.P1.ToString())
         app.log("iSect = "+XSect.ToString())

      if SName == "XPolySegArc":
         Blg = Math.Tan(seg.Sweep / 4)
         MyArc = Arc2F(seg.Center, seg.P1, seg.P2, seg.Direction)
         cir = Circle2F(seg.P1,2)
         cir1 = Circle(seg.P1,2)   
         XSect = MyArc.CircleIntersect(cir)
         app.log("P1    = "+seg.P1.ToString())
         app.log("iSect = "+XSect.ToString())
      SegNum += 1
      seg = seg.NextSegment
      doc.Add(cir1)
 


Title: Re: Drag-Knife Script
Post by: billt on May 01, 2014, 02:25:07 am
Dragonfly -

The Line2F object does have point properties, but they are p1,p2 and not P1,P2.
It is a pain to figure these out since they are case sensitive and are not standardized.
These can be found by compiling a script of: print help(Line2F)

I added two lines to both of your loops.
         app.log("iSect.p1 = "+XSect.ToString())
         app.log("iSect.p2 = "+XSect.ToString())

I made a similar polyline and ran the script.
The resulting message window results in something similar to:



Title: Re: Drag-Knife Script
Post by: billt on May 01, 2014, 02:43:23 am
continued...

iSect = 2,0-
iSect.p1 = 2,0-
iSect.p2 = 2,0-

This result of p1=p2 can be explained by the fact that your "MyLine" used for the intercept always starts at the center of the circle, so there is only one intercept point.  I cannot fully explain the "-" that shows up after the "0" but it is probably related to the fact that the line has a zero length - maybe because the direction cannot be determined?

Your approach of finding the intercept of a circle with the next segment will work if the next segment is always a line, however if the next segment is an arc the intercept should be instead with the tangent line at P1 of the next segment.  My script does use this correct tangent method for arcs.  I am working on the defects that you found and should have the solution posted within a couple of days.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: billt on May 01, 2014, 03:50:27 am
Dragonfly -
You will find part of the API documented at:
http://www.cambam.info/doc/api/ (http://www.cambam.info/doc/api/)

I just posted a text file which lists the doc() of the primary namespaces CamBamUI, Geom, CAD, and CAM.
This file identifies all objects including those that are missing from the online api documentation.
For example XPolyline.
See the post: http://www.cambam.co.uk/forum/index.php?topic=3057.0 (http://www.cambam.co.uk/forum/index.php?topic=3057.0)

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on May 01, 2014, 11:34:59 am
Bill,
I am using already both sources thanks to your cooperation.
My main difficulty is proper comprehension of what I read there because, as I already pointed, I haven't been hands on programming for a very very long time. Some knowledge is slowly surfacing from deep in my memory, other things I have to learn again or are totally new for me. But this is a kind of challenge and I'll do some more digging today. :)
Thanks again for the help.

Ivan

BTW, has anyone found a way to get the contents of the message window to a text file?


Title: Re: Drag-Knife Script
Post by: Dragonfly on May 03, 2014, 22:17:06 pm
Does anyone know how to terminate Python script execution from within the script?

exit() does it by causing an error  ;D

I have a definite advance with my version of the script but want to put some means of stopping it under conditions with geometry which is too fine for the actual knife offset.

Best check for NaN results I found so far:
Code:
def IsNaN(num):
    return str(num).lower().find('nan')>=0


Title: Re: Drag-Knife Script
Post by: lloydsp on May 03, 2014, 23:08:56 pm
exit() can only properly exit main.   Invocation in inner loops sends an exception up-hill that may not be handled well.


According to all the usual suspects,

import sys
.
.
.
sys.exit(none) or sys.exit(0) should exit gracefully, raising an exception with a "normal termination" value set, and letting all the various 'trys' and other loops to clean up.

Lloyd


Title: Re: Drag-Knife Script
Post by: billt on May 05, 2014, 04:23:50 am
New corrected script is uploaded.
The divide by zero error is fixed - it was a mistake on my part.
I traced the NaN error back to a floating point precision issue.
Turns out that Acos() returns a NaN error if calculating anything larger than exactly 1.
To correct it, I rounded the input value to 10 decimal places.

Added a new SwivelAngle variable and logic to prevent small angles generating a swivel move (requested by Dragonfly).
The old SwivelAngle variable is now re-named RetractAngle to be more clear on it's function.
Added a RetractEnable toggle value to make it easier when it comes time for pluginizing.
I also made some updates for readability and improved the logic.

Cheers - BillT

Variable Descriptions as listed in the script:
###########################################################################
#  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.
#
###########################################################################


Title: Re: Drag-Knife Script
Post by: Dragonfly on May 05, 2014, 18:56:31 pm
Bill,
I tried the new script on geometry I use to test my version of it (it passes all successfully ATM). On the first letter 'F' of the 'Flight Service' text your script enter and endless loop so I had to terminate CB.
BTW, Is there a way to terminate a script running from the keyboard. I tried Ctrl-C, (Ctrl)-Break, Esc with no result.

Here's what I set the parameters to:
Code:
KnifeTipOffset = .25
CutDepth = .05
SwivelAngle = 10
RetractEnable = 0
RetractAngle = 40
RetractDepth = .05
I am working in millimeters. And I need an output for vinyl cutting only so 0.050 mm is still too deep but left this value for the test.
Attached is the .cb file in millimeters.
Note, the letters are quite small and there are other thin elements because I want to see what happens with tiny cuts, large will cut OK even if with some inaccuracy.
P.S. I am attaching also my current work script, but it is not tidied up, nor commented. I have to do this soon.


Title: Re: Drag-Knife Script
Post by: billt on May 06, 2014, 10:43:50 am
Dragonfly -
I do not understand how your system ended in an endless loop, mine ran with your parameters.
I did find an error in the logic for the first segment with the RetractEnable set to 0.
The point was set to be placed at C1 instead of CFirst so the first swivel path was not placed.
The logic has been fixed and script updated.

I ran your file with your parameters and the result is attached.
The generated cut lines are on Layer 1.
Please try the updated script and let me know if you get the same result.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: bendelange on June 03, 2014, 18:16:14 pm
Can anyone tell me how to use this script in CamBam. I never used scripts in CamBam and can't find how to do this.


Title: Re: Drag-Knife Script
Post by: lloydsp on June 03, 2014, 18:23:33 pm
Click on "script" in the top toolbar, then 'open'.  Select this script from the list.

It will open up in a text window.

Then, in that window, click "tools", and "compile", or just press F5.

In order for that all to work, the script itself must be copied to the Cambam system/scripts folder.

In XP, this appears at: C:\Documents and Settings\All Users\Application Data\CamBam plus 0.9.8\scripts

Elsewhere on other OS's.

You can find AND open that folder for copying things into it most easily by using (from an open CamBam session) Tools/Browse system folder, then opening the scripts folder.


Lloyd



Title: Re: Drag-Knife Script
Post by: dh42 on June 03, 2014, 19:28:27 pm
Can anyone tell me how to use this script in CamBam. I never used scripts in CamBam and can't find how to do this.

Hello,

You can find a little video here
http://www.usinages.com/cambam/pilotage-couteau-rotatif-t65995-15.html#p734970

++
David


Title: Re: Drag-Knife Script
Post by: bendelange on June 03, 2014, 20:57:23 pm
I found the scripts directory (it was a hidden folder on Windows 7) copied the file and changed the extension to py.
I drew a rectangle in CamBam (CamBam plus [0.9] Rel 8P (beta-2)) selected it and run the script (drag_knife_6-May-2014.txt),
I got an error unexpected newline on line 236. In the editor it seemed that the right parenthesis was missing on the last line. I added a parenthesis and it seemed to run it gave some lines output on the bottom screen but nothing changed in my rectangle.
Then I modified the rectangle as shown in the movie by adding some circles to the rectangle selecting them all and do a union on it. Selected all and ran the script. After this I got a lot of output in the lower screen and it ran forever.
Any suggestions?


Title: Re: Drag-Knife Script
Post by: dh42 on June 03, 2014, 21:03:09 pm
Hello,

Yes, same for me, but I'm not familiar with python and I don't search for the error.  :-[

The one on the vidéo is on the first message of this page (reply #30 from dragonfly)

++
David


Title: Re: Drag-Knife Script
Post by: billt on June 11, 2014, 03:25:07 am
bendelange -
Note, the script is designed to only work with polylines.
If you tested a polyrectangle, convert it to a polyline before running the script.
I have not gotten a newline error on line 236 - seems OK for me.
If you still get the same error, please upload your file so I can test it.
Cheers - BillT


Title: Re: Drag-Knife Script
Post by: bendelange on June 11, 2014, 13:37:03 pm
I downloaded "drag_knife_6-May-2014.txt" again and checked it but there is still a parenthesis missing at the last line.
Adding the parenthesis and running the script on a simple polyline that I drew in CamBam results in an endless loop.
Same polyline with the script from October 2013 "drag_knife.txt" runs nicely.


Title: Re: Drag-Knife Script
Post by: billt on June 11, 2014, 17:47:39 pm
It appears that there were several lines cut from the end of the script when I uploaded it.
This explains the missing parenthesis and the endless loop.
Attached is the file again which has been working for me.
I will check this time to make sure that it has uploaded fully.
Cheers - BillT


Title: Re: Drag-Knife Script
Post by: billt on June 11, 2014, 17:54:04 pm
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

Code:
# 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)


Title: Re: Drag-Knife Script
Post by: BR52 on June 11, 2014, 17:56:06 pm
Hello bendelange,

You need to put examples having problems.
The BillT said:
               please upload your file so I can test it.  ::)

   Armando


Title: Re: Drag-Knife Script
Post by: bendelange on June 11, 2014, 18:31:24 pm
Copy/pasted last file and that works!


Title: Re: Drag-Knife Script
Post by: billt on June 11, 2014, 19:28:50 pm
Great!  If you have any problems or suggestions for additional features let me know.
Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on July 12, 2014, 12:51:42 pm
Hi Bill,
I had to move with all my junk to a new place and didn't have time to play with foil cutting and your last script.
Now that all the lines of code are present it ran on a ragged example curve where my version fails  :(
I have a question though. As you can see on the attached picture the script inserts moves which at least for my needs are not required. How can I and is it possible to avoid them by defining the initial control values?
Here are the values I use:
Offset = .25
CutDepth = 0
RetractDepth = 0
SwivelAngle = 90
I do not want the polyline points to go below zero level but rather set the DOC in the MOP, so CutDepth is set to 0. In fact I want a flat polyline with no points above zero too.
I am attaching also a DXF file with the test shape.

Cheers,
Ivan


Title: Re: Drag-Knife Script
Post by: billt on July 14, 2014, 02:32:27 am
Ivan:
If you zoom in closely you will see that your path has little zigs in it which cause the extra swivel paths.
These must be manually fixed in your path to make it smooth.
To manually remove them, you can select them in the points collection window and press "DEL".
The short, straight "zig" line segments will be the points with a zero bulge value.

I suppose I could add a feature to the script to ignore the next point if the distance is less than a certain value.
However I am not sure if this is the right thing to do or if it would give the desired result.
Maybe another option could be a script to identify these "almost" duplicate points and remove them from the path.
There is already a plugin that removes duplicate points, but it does not have an adjustable tolerance.

As far as setting the depth of cut using the MOP - yes you can do this, but then you will lose the ability to use the retract/swivel feature of the script for thicker materials.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: Dragonfly on July 14, 2014, 09:21:21 am
What you describe is what I am trying to achieve in my version of the script - ignore 'dents' which are smaller than the offset and simplify the path. Those are hardly achievable in practice even on a dedicated cutting plotter, therefore can be ignored. Either this or a preset accuracy threshold to control the behavior will bring more flexibility IMHO.
I know I can manually edit the curve, in CorelDraw (which it is exported from) and has more tools and ease of work than in CB but still it's PITA if there are number of curves. I am using this one as it causes errors in my script and is useful for debugging :)  "Arc fit" in CB also is able to simplify a polyline.

Also I am a bit confused about the angle threshold in your script. Which angle is it? Is it the deviation (difference relative to previous direction) or the actual angle between two segments. I suspect I can't fully understand it in the code.
 


Title: Re: Drag-Knife Script
Post by: billt on July 29, 2014, 00:01:13 am
Latest revision adds a variable DentLength to ignore "Dents" created by converting bitmaps to paths.

Ivan -
Your file in addition to dents has a few overlap segments.
Before running the script, I cleaned it using Edit>Polyline>Remove Overlaps with a tolerance of .02.
This reduced the segments from 256 to 249.
I also set the new variable DentLength to .02 which removed all of the dents.
If you set the value too large, it is more likely to ignore correct swivel paths.
I have also asked the forum for help with adding an automatic Remove Overlaps to the script.

Cheers - BillT

Code:
# DRAG_KNIFE.PY
# Rev: 26-July-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
# Rev: 27-Jul-2014 Bill Trondsen
#      - Added DentLength variable and compensation, requested by Dragonfly
#
###########################################################################
#  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 20 degrees.
#
#    DentLength: swivel paths are not placed if the segment is shorter than DentLength value
#        This feature will help to compensate for small jagged "Dents" on some scanned paths for instance
#        Requested by forum member Dragonfly
#        Similar in effect to builtin polyline function "Remove Overlaps"
#        Warning - could remove correct swivels if path contains short segments
#        Suggested default is 0
#
#    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 = 0
SwivelAngle = 20
DentLength = .02
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 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)

      if seg.Length > DentLength: # Ignore placement of short "Dent" segments
          poly.Add(C1.X, C1.Y, CutDepth, C1B)

      if C2Angle >= SwivelAngle:  # then do a swivel move
        if seg.Length > DentLength: # Ignore swivel segment for "Dents"
          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)

      else: # otherwise 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)


Title: Re: Drag-Knife Script
Post by: Bubba on December 24, 2014, 15:37:28 pm
OK, I'm green as cabbage if comes to using a script. Tried today with samples provided in this topic. The only think I was able to see after clicking compile(F5) that script was running but no gcode. What I did wrong (besides trying it)?  :D ;D ;D


Title: Re: Drag-Knife Script
Post by: lloydsp on December 24, 2014, 19:26:31 pm
Bubba,
Most scripts create only objects that describe the toolpath.

Once the objects are created, you need to select them, and create the MOp yourself.

That's not to say a script CAN'T produce a full MOp and g-code -- but most don't, only the objects.

Look up in your drawing tree after running the script, and you'll probably see that some new polylines have been created to describe where the knife should run.

Lloyd


Title: Re: Drag-Knife Script
Post by: Bubba on December 24, 2014, 21:28:30 pm
Lloyd. Thanks I try that.

All,
Have Wonderful Christmas.


Title: Re: Drag-Knife Script
Post by: Dragonfly on December 24, 2014, 23:31:38 pm
This particular script requires that at least one polyline (works only on polylines, so we need a conversion before running) is selected. For better observation results make a new empty layer and chack it is the active one. New modified polylines will appear there.
Because the knife offsets are typically small (mine is 0.25 mm) you need to zoom in to see the added knife compensation parts.
Cheers!


Title: Re: Drag-Knife Script
Post by: GraphicMan on December 31, 2014, 10:55:28 am
This thread is like a treasure in a desert
Bill you should be awarded for this
really great job you have done!

I was searching all over the internet for an answer to some issues I found in all the available drag knife gadgets/software

one of these wonders is why the toolpath ignores a corner action to a segment if it is shorter than the blade offset! (see the attached pic), I never got this, it is just not understandable for me, my head kept spinning but this thread proved for me that it is from the software weakness not anything else (correct me).

I also thought about that a blade with any offset can never follow the actual path exactly, unless compensated and this does not only give us the ability to cut smaller components than the blade offset but to use any blade with any offset, and this raises a question here, wish would be better a blade with a smaller or bigger offset?

before I decided to post here I made sure to read the whole thread and to test the code as well
please allow me to mention my points, comments and question as follows:

Basically I found the code great and really does what it has to do, hands down, but here we go:

1. Is there is a way to use the VB script instead of the Python?, the reason is that I found out that CB does not run the code on winxp and it seems that it needs the dotnet 3.5 which I realized that it need to install about 850mb to the system!!! the thing that I am avoiding for many reasons, one of the reasons CB is a great software is because it is too light. so something to thing about for people using mach3 with winxp. CB run VB scripts without dotnet 3.5 and hence the convert to VB (if possible).

2. I know the code need to work with polylines only, I have imported a logo of mine and even after converting it to polyline it did not want to work, after some playing around I needed to breakup the logo and join it, I am not sure what would be a proper solution here but this is a totally unneeded additional steps in the whole long process of a vinyl cutting as an example.

3. I am still new with CB and I was wondering how to convert a circle to a polyline, I was basically wondering according to the bicycle theory Bill referred to (which is amazing and the core of the code) will cutting a perfect circle require a modified path or not?, I noticed that if you have a perfectly lined blade (still with offset) meaning that when you rotate the blade 180 deg the blade direction stays on exactly same line, the circle should not come out perfect, smaller offset will help but if you get a perfect circle (talking here about the start/end meeting point) it means that your tip is not properly centered, please correct me on this. So I wanted to see how the code will deal with the circle but I could not make one already.

4. Is it possible to let the code automatically generate the new shapes in a separate layer? in an attempt to reduce whole operation steps.

5. No offend to mr. dragonfly but I am really not happy and confused with the added angle features, I am still not getting the differences between the 2 angles, I think drawing bitmap issues should not be resolved with the code ever, It should be sorted out with the illustration software and when satisfied work with code. If Bill insists on adding these features then I suggest re-explaining them because I could not really understand them myself.

6. Even before I read this threat I have been thinking about a way to get better corner cuts, the fact the tip swivel on corners ruin them in a way, I was happy when I read a part here where there was a suggestion to swivel the starting point in a waste area, if that is the case then why not do that in every swivel?, yes to every swivel, this feature can be extremely beneficial specially in small very detailed cuts, at the same time it will not be time consuming because the machine will not travel so far away from the cut work area as it is small already, I suggest to input a starting location for swivel actions to be made were it changes slightly with 0.3mm in X+ direction for every new swivel action just to avoid tip plunge misalignment due to the mark of the previous swivel, just an idea to start with.

7. If memory serves me well , I remember that I was working in a sign shop back in 2002 (12 years back) they had a large vinyl cutter plotter and I remember the very small detailed work they were asked to cut, and if I remember correctly I dont remember any issues of the cuts, not to mention how fast it was, So I appreciate anyone to tell me how these machines/their software works? perhaps we can get better ideas from a very old technology already!, do you think their software were using the path modification technique as well? may be not, otherwise why the need of the very small blade offsets?, however I still like to know from you guys when using our code here with the path modification tech, what would be the pros and cons of using a small or larger blade offsets?, something to think about now when making a new drag knife.

Sorry for the long post, but thought to share my thoughts all sorted at once.

Cheers and happy new year for all.


Title: Re: Drag-Knife Script
Post by: lloydsp on December 31, 2014, 12:32:47 pm
Graphicman,

Converting python to Visual Basic is more-or-less a manual process.  I have not (yet) found a 'translator' that will do a yeoman job of it. 

As far as XP and python... the core .dlls and libraries for .Net 3.5 aren't all that big.  It's the whole development package that's 850MB.  The reference assemblies needed for runtime are at C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5, and occupy only about 15.8MB.

I'm not a drag knife user, but do a bit of trigonometry and geometry (and stayed at a Holiday Inn last night! <G>).  The toolpath for any 'trailing segment' with one point leading and one point following a circle would be another larger circle, with the actual 'cutting' point being always tangent to the circle to be cut and the leading point being dragged around the larger encompassing circle.  The size of the larger circle could be described simply by placing the segment tangent to the cutting line (with it's point at the tangency), then describing a new radius from the center of the 'cut' circle to the other point of the segment.  One or two right triangles would describe it adequately to do the math.

In fact, the snippet I posted yesterday explaining the math behind calculating a new cutting depth for a ball nose bit also can be used to describe the drag-knife circle path.

Lloyd

LLoyd



Title: Re: Drag-Knife Script
Post by: GraphicMan on December 31, 2014, 12:47:01 pm
Interesting,

And yes I tried to cut a circle using the code and amazingly it proved what i was thinking of. the code fixed the star/end connection by compensating it, so this question is answered now.

Do you know were i can download the needed files for the CB to work with python?

*please mention the number of the point when discussing them to better understand

thank you


Title: Re: Drag-Knife Script
Post by: lloydsp on December 31, 2014, 13:23:52 pm
Graphicman,

I think this is all you need: http://www.microsoft.com/en-us/download/details.aspx?id=22

It's probably just the 'downloader' component for the update, because it's not large enough (even compressed) to hold the entire 20MB update.

I didn't include cites to your questions, because your questions should have been visible on the screen while reading my responses...

LLoyd


Title: Re: Drag-Knife Script
Post by: GraphicMan on January 05, 2015, 03:30:13 am
Graphicman,

I think this is all you need: http://www.microsoft.com/en-us/download/details.aspx?id=22

It's probably just the 'downloader' component for the update, because it's not large enough (even compressed) to hold the entire 20MB update.

I didn't include cites to your questions, because your questions should have been visible on the screen while reading my responses...

LLoyd


This installer asks to download 53mb, however I have clearly noticed the so many restarting times the downloader did after every few megabytes, I check the temp and found so many folders with so many files specially under a folder that it created related to dotnet 2!!, I have the dot net 2 already installed, but it seems that it will download these files no matter what, anyways that package is still too large in download and installation! it is a complete mess and it result of so many problems in m cad & cam programs I have that I never experienced before (as expected).

Can you please convert this code to VB? Please:)



Title: Re: Drag-Knife Script
Post by: Bubba on January 05, 2015, 13:01:19 pm
 So I appreciate anyone to tell me how these machines/their software works?
++++++++++++++++++++++
I used to own a sign shop in the mid nineties, and owned the Huston Instruments plotter/vinyl cutter. We were able to cut text as small as .125" out of 3 mil vinyl. The CAD program that drove the cutter was simple windows 3.1 based system, and it followed vectors just like CamBam engrave MOP does. The vinyl cutter employed a tangential cutter head and because of it we were able to cut text/graphics that small although it was royal pain to "weed it". ;)


Title: Re: Drag-Knife Script
Post by: GraphicMan on January 05, 2015, 13:20:09 pm
So I appreciate anyone to tell me how these machines/their software works?
++++++++++++++++++++++
I used to own a sign shop in the mid nineties, and owned the Huston Instruments plotter/vinyl cutter. We were able to cut text as small as .125" out of 3 mil vinyl. The CAD program that drove the cutter was simple windows 3.1 based system, and it followed vectors just like CamBam engrave MOP does. The vinyl cutter employed a tangential cutter head and because of it we were able to cut text/graphics that small although it was royal pain to "weed it". ;)

Thanks for your input
can you tell me what did u mean by a tangential cutter head? does not have an offset? how the blade look like?, this is interesting because I know so many vinyl cutter plotters that have the normal blades (45 or 60 deg) with offset , it has a very small offset yes but you must enter it for the machine, meaning that if you input incorrect offset to the used blade it will result in inaccurate corners, about these machine I am not sure if they use a compensated path regarding to the used offset or not (like our script here) , but if not and even if the offset is super small a rounded rectangle for example will never look perfect, and I doubt that these expensive machines work that way, at the same time I cant imagine they use a compensated cutting path too! what do you think?


Title: Re: Drag-Knife Script
Post by: dzarek on January 16, 2015, 09:21:41 am
Welcome
Looking for another script , I found this, and I have a question
It is possible to rework the script as a script do the loops on the corners ? as in the picture below


Title: Re: Drag-Knife Script
Post by: GraphicMan on January 16, 2015, 10:38:05 am
that is very beautiful idea. it might not be the best in all situations, but I believe I have seen it somewhere, may be sheetcam, it have a drag knife gadget, but you have to buy the software i believe.

this method should provide the fastest and sharpest possible corners, but it also has its cons.



Title: Re: Drag-Knife Script
Post by: Bubba on January 16, 2015, 13:48:00 pm
can you tell me what did u mean by a tangential cutter head?
**************************

Tangential cutter head has little stepper motor inside and it rotates the blade in the direction of a cut. I think the  cutting edge was on center. As I was researching machines before purchasing one there were cheaper options with a 'drag knife' heads and thats what we are working with here, where offset is necessary  for it to follow the line correctly.


Title: Re: Drag-Knife Script
Post by: GraphicMan on January 16, 2015, 14:58:28 pm
can you tell me what did u mean by a tangential cutter head?
**************************

Tangential cutter head has little stepper motor inside and it rotates the blade in the direction of a cut. I think the  cutting edge was on center. As I was researching machines before purchasing one there were cheaper options with a 'drag knife' heads and thats what we are working with here, where offset is necessary  for it to follow the line correctly.

ok the one that i recalled i am sure it did not have that A axiz motor, same as many other vinyl that have a tiny drag knife, but still the question, how these machine can achieve that tiny details? even if they have very small offset .25mm it is impossible to get that fine details without compensated path like this script does. I am really wondering about that! perhaps you know better since you were looking for many options,


Title: Re: Drag-Knife Script
Post by: Dragonfly on January 16, 2015, 16:49:20 pm
Dedicated cutting plotters with free pivoting knife have this algorithm built into their firmware and thus appear "transparent" to the user because they do the path corrections in real time while processing the job.


Title: Re: Drag-Knife Script
Post by: Bubba on January 16, 2015, 16:55:53 pm
 I am really wondering about that! perhaps you know better since you were looking for many options,
******************************
Truthfully, I don't know. I remember the one thing that turned me of the drag knife type machines(even though it cost much less), was the minimum size letters and graphic detail cut reliably. The tangential head made all the difference. At that time my main point of interest was to get the machine to communicate with PC running Win 3.1, thru 25 pin serial port and designing and making signs,banners vehicle lettering, etc... All I remember,because I was amused how the machine including the head after booting it up,aligned itself perfectly every time. It used the similar file format (DWG) to DXF and often used the DXF file format because the sing software used both. As I stated in my earlier post it cut fine text fine the weeding was the pain..


Title: Re: Drag-Knife Script
Post by: GraphicMan on January 16, 2015, 17:08:45 pm
Dedicated cutting plotters with free pivoting knife have this algorithm built into their firmware and thus appear "transparent" to the user because they do the path corrections in real time while processing the job.

So this algorithm is ancient and have been used without notice since the 90's?!, I have not seen any cam software using it at all, Just very few of them hardly the drag knife gadget featured very recently!!

Thanks for your respond Dragonfly


Title: Re: Drag-Knife Script
Post by: billt on January 16, 2015, 19:09:03 pm
dzarek/GraphicMan -
You propose the tip of the tool should go beyond the cut corner, form a loop, then restart cutting on the path.  This would then cut a small oval/pie shaped piece in the "waste" area of material and theoretically cut a sharper corner.

However, consider several issues with this path shape:
 - What about interior corners? - The oval loop will actually cut into the good material instead of waste area.
 - What if the project is a negative image used as a stencil?  Then the exterior material is good, and interior is waste.
 - What happens when cut paths are closer together than the oval cut - this will damage adjacent cut paths.
 - For sharp exterior corners on thin material such as vinyl, there could be lifting of the material when the blade re-enters the path, causing bunching of material and a worse cut.

I understand the proposal, but I think it is more complicated and will probably produce worse results.

Consider how the Donek path (used in this script) counteracts the damaged material at the swivel location in thick materials by lifting a small amount at each swivel.  He actually uses this method to cut cardboard with a full size razor blade drag knife tool (it has a .16"/4mm offset to the knife tip), with the "good" side facing down and the swivel action on the back side of the material, leaving a perfectly cut corner on the good side.

I suggest that you guys do some actual cut tests of swivel vs. oval for several cut angles and materials and post the results.  The cut paths could be easily hand-programmed for testing purposes.  I think that you will find the results will be worse with the oval than using a swivel path.

Cheers - BillT


Title: Re: Drag-Knife Script
Post by: GraphicMan on January 19, 2015, 17:37:49 pm
The idea is still very good, but not necessarily to replace the original one,
still good in some circumstances like large shapes vinyl cutting or any other thin material that you dont want any small damages on the corners of the used surface, yet the cut shapes has to be larger enough than the looped corner.


Title: Re: Drag-Knife Script
Post by: billt on January 20, 2015, 00:40:10 am
The idea is still very good, but not necessarily to replace the original one,
still good in some circumstances like large shapes vinyl cutting or any other thin material that you dont want any small damages on the corners of the used surface, yet the cut shapes has to be larger enough than the looped corner.
Please provide evidence to support your claims.


Title: Re: Drag-Knife Script
Post by: airnocker on May 26, 2015, 20:40:59 pm
Just finished reading through this entire post.  Great post, very enlightening and useful.

BillT - Any updates on the script?

Lloydsp - Any prospects for timeline on a plug-in?



Title: Re: Drag-Knife Script
Post by: lloydsp on May 26, 2015, 22:24:38 pm
No, unfortunately.  I'm stuck in "limbo", waiting for a never-coming approval from the Army contractor on the machine I've installed, and further stuck "out of state" spending time in a motel and money I can't afford to do it.  I have now spent (off and on) over 100 days on the road for this thing.  The client has stymied my every effort to get done, from changing the specs 'on the fly' to physically damaging the machine three times.

When I get shuck of this contract, I'll let everyone know with a big Shout and a Cheer!

Lloyd


Title: Re: Drag-Knife Script
Post by: airnocker on May 26, 2015, 23:23:39 pm
What a bummer, Lloyd.

Hopefully knowing that you have a huge group of supporters here, is of some consolation.

My watch says, "it's time for things to get better".

Best,



Title: Re: Drag-Knife Script
Post by: lloydsp on May 27, 2015, 01:36:12 am
I'm on the road now, and this week has gone better.  The client still has done NOTHING of their responsibilities to get the workspace ready -- things they knew about six months ago.  But my end is doing pretty good.

I found a couple of firmware bugs, found a lousy little 20-thou 'burr' on a ramp that was causing feed problems we couldn't identify easily, and have run about 20 hours of reliability runs on the paper-tubes path elements.

Tomorrow, I do a small pilot production run-- about 1000 units.  If it gets through the run, and the product is in specifications, the client is getting a bill the very next day!

FWIW, the software is owned by ME, and it's got a date-based licensing scheme that will simply stop working if they don't pay me to get the new key!

THEN, I'll be looking for a good hardware maintenance company to take the ongoing maintenance of this thing off my hands, so I can get back to being creative.

Lloyd



Title: Re: Drag-Knife Script
Post by: EddyCurrent on May 27, 2015, 12:27:07 pm
In case anyone else is making a plugin of this, I've made a start so don't bother (unless you really want to of course)
And I'll be passing it to Billt first.


Title: Re: Drag-Knife Script
Post by: GraphicMan on May 27, 2015, 18:17:15 pm
In case anyone else is making a plugin of this, I've made a start so don't bother (unless you really want to of course)
And I'll be passing it to Billt first.

I would be more than happy to test it, Go ahead bro


Title: Re: Drag-Knife Script
Post by: Garyhlucas on May 27, 2015, 21:12:41 pm
Lloyd,
Hope it works for you. Customers can be tough.  I now insist on pictures of their work completed.  No pictures, no plane tickets.  Three years ago my then boss ignored my advice about this. I traveled 11 hours from my door to theirs.  Called my boss and said "I can't find the control panels"  He said "Did they locate them in another building?"  I said "No, I mean one is still in the crate sitting out in the field, the other they can't find, they didn't install the conduits underground yet, but they poured all the concrete roads over the path! I'm going home."  11 more hours for nuttin!


Title: Re: Drag-Knife Script
Post by: EddyCurrent on May 28, 2015, 12:20:33 pm
Link to a plugin conversion of this script; http://www.cambam.co.uk/forum/index.php?topic=4911.msg37464#msg37464


Title: Re: Drag-Knife Script
Post by: jlowe1124 on July 07, 2015, 04:09:54 am
For the swivel action is there anyway you can remove the ramp effect and have it go straight up and  straight down after the swivel? Im cutting foam board and when it tries to swivel while on the ramp it just destroys the foam and the blade. It would be perfect then.


Title: Re: Drag-Knife Script
Post by: billt on October 06, 2015, 01:26:41 am
Latest version of the script (from 15-July-2015) includes several bug fixes found during conversion to a plugin (by EddyCurrent).  Also several features added by GraphicMan.  Script text is below and I will also try to update the file in the original topic post.  At this point the script is obsoleted by EddyCurrent's excellent plugin, however still might be useful for understanding the geometry, logic, or Python scripting syntax.
Cheers - BillT

Code:
# DRAG_KNIFE.PY
# Rev: 15-July-2015
# 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
# Rev: 27-Jul-2014 Bill Trondsen
#      - Added DentLength variable and compensation, requested by Dragonfly
# Rev: 3-June-2015 by GraphicMan
#   - Fixed the ramped swivel action (now swivel is done completely on the retract depth)
#   - Log disabled for much faster calculations
#   - Converts all polylines direction to CW
# Rev: 15-Jul-2015 Bill Trondsen
#      - Corrected VARIABLE description of CutDepth and RetractDepth to require NEGATIVE values
#
###########################################################################
#  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
#        Use a NEGATIVE value for CutDepth as the Z distance below the top surface of material.
#        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 20 degrees.
#
#    DentLength: swivel paths are not placed if the segment is shorter than DentLength value
#        This feature will help to compensate for small jagged "Dents" on some scanned paths for instance
#        Requested by forum member Dragonfly
#        Similar in effect to builtin polyline function "Remove Overlaps"
#        Warning - could remove correct swivels if path contains short segments
#        Suggested default is 0
#
#    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
#        Use a NEGATIVE value for RetractDepth as the Z distance below the top surface of material.
#        As a suggestion, try 1/2 the value of the CutDepth.
#
###########################################################################


KnifeTipOffset = .25
CutDepth = -.100
SwivelAngle = 20
DentLength = .02
RetractEnable = 0
RetractAngle = 40
RetractDepth = -0.050

# Convert All To CW################################

for ent in view.Selection:
  if ent.GetType().Name == "Polyline":
    # poly = Polyline(ent)
    poly = ent
    if poly.Direction.ToString() == "CCW":
      poly.Reverse()

###################################################

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)
    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

  #### 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


########################################################
# Add points to path with depth logic###################
########################################################

      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)

      if seg.Length > DentLength: # Ignore placement of short "Dent" segments
          poly.Add(C1.X, C1.Y, CutDepth, C1B)

      if C2Angle >= SwivelAngle:  # then do a swivel move
        if seg.Length > DentLength: # Ignore swivel segment for "Dents"
          if RetractEnable == 1:
            poly.Add(C2.X, C2.Y, CutDepth, 0)
            poly.Add(C2.X, C2.Y, RetractDepth, C2B)
            poly.Add(P2X+KnifeTipOffset*VN1.X, P2Y+KnifeTipOffset*VN1.Y, RetractDepth, 0)
          elif RetractEnable == 0:
            poly.Add(C2.X, C2.Y, CutDepth, C2B)

      else: # otherwise 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)

#### End of Main Loop #####################################

      SegNum += 1
      seg = seg.NextSegment
    doc.Add(poly)


Title: Re: Drag-Knife Script
Post by: GraphicMan on October 06, 2015, 01:45:57 am
Well done
Apperciate the mention


Title: Re: Drag-Knife Script
Post by: PUDDING on September 25, 2018, 12:14:50 pm
Fantastic plugin, thank you.

I have used an attachment from Amazon to make my drag knife, constructing the holder from oak to fit to in place of my Kress motor. Thank to your plugin it all works well to produce vinyl decals.

Many thanks,

Pudding


Title: Re: Drag-Knife Script
Post by: EddyCurrent on September 25, 2018, 16:59:39 pm
Pudding,

Any more details on the exact parts and build of your knife ?


Title: Re: Drag-Knife Script
Post by: PUDDING on September 25, 2018, 17:41:27 pm
It is based on a Yakamoz CB09 Graphtec Blade Holder obtained from Amazon. The main body is Oak with a 5mm birch ply closing plate. The internal spacer is lathe turned from aluminium. All the rest of the machining was done on my wood mill using Cambam.

Depth excluding the closing plate = 35mm
Top hat outer dia = 70mm
Top had inner dia = 43mm

I'm happy to give any further details if required


Title: Re: Drag-Knife Script
Post by: EddyCurrent on September 25, 2018, 22:41:29 pm
Excellent, can't complain about the price, I'll have to look into getting one of those blade kits, thanks for posting this.


Title: Re: Drag-Knife Script
Post by: dave benson on September 26, 2018, 01:01:08 am
Well that was timely.

I made a drag knife just after the plugin was made for doing 2 and 3 mm neoprene gaskets, but it's a little heavy for
light weight gasket paper.(too much resistance for turning).

I've just ordered one of those holders with various degree knives 60/45.
Like Eddy said, can't complain about the price.
Dave


Title: Re: Drag-Knife Script
Post by: Bubba on September 27, 2018, 20:21:07 pm
Well that was timely.

I made a drag knife just after the plugin was made for doing 2 and 3 mm neoprene gaskets, but it's a little heavy for
light weight gasket paper.(too much resistance for turning).

I've just ordered one of those holders with various degree knives 60/45.
Like Eddy said, can't complain about the price.
Dave


Excellent idea. Just like Dave, I have made drag knife to cut some heavy cardboard, it fine but not good enough to cut vinyl. So now, after ordering the Yakamoz CB09 Graphtec Blade Holder I'm designing holder for it to fit into .500 router collet.  


Title: Re: Drag-Knife Script
Post by: dave benson on June 12, 2019, 14:23:13 pm
I finally got around to testing the drag knife today, to cut some gaskets out of
0.3 mm gasket paper.
The roll of gasket paper I have is 2 meters wide by 10 meters long.
As I've had it for years, the outer wrap of the material had aged badly and was
a bit brittle, so I used this for the testing and setup of knife.
All I had was a piece of pine floor board which did vary some over it's surface (0.35 mm).

I had no luck with the plugin, it produced varing results on identical geometry.
The placement of the wheeling path was sometimes on the inside of the circles and sometimes
on the outside.

I went to some effort to make sure the geometry in the file was clean, but still no joy.
In the end I used a profile mop with a spiral leadin @ .5 mm depth and a feedrate of 200 mm\minute.
The results were over all quite good, the cuts were clean, and I ordered a self healing mat
too sort out the varying depth on the wood. I'll also make a  rectangular  hold down clamp out of 3 mm by  16 mm
flat bar. A4 size to suit the mat.


When the Drag Knife turned up, my first impression was that it was not going to be any good
for gaskets, but the  0.3 mm thick paper I used cut like a charm, and I will be using it for material
perhaps up to .5 mm thick.

Dave


Title: Re: Drag-Knife Script
Post by: EddyCurrent on June 12, 2019, 16:03:00 pm

I had no luck with the plugin, it produced varing results on identical geometry.
The placement of the wheeling path was sometimes on the inside of the circles and sometimes
on the outside.

Dave

Dave,

Something must have changed to give different results, any idea what that change was ?

Can you attach a file or files that show the problem ?

Did you try the script rather than the plugin ? operation should be identical but it would be good to check.


Title: Re: Drag-Knife Script
Post by: dave benson on June 13, 2019, 01:23:19 am
Hi Eddy
Here you go, I grouped the geometry closer together so you can see better, and added a CB file.
I haven't had a chance to seriously look in to it, I got this result on the very first run and thought that the geometry was dodgy and ran the file cleaner and then checked each polyline's parameters to make sure they were identical.
It seemed that the position of the geometry in the file effected the result.

I did try the script,(No Go Either) But did not look in to it any further as I had to press on and make the gaskets, I found out early on in the
Collision Detector that Python is not strongly typed and you can 'Willy Nilly' set something to something else and not worry about the Type Conversion, when I was a lot younger this would not have bothered me so much, now I find it a travesty and sacrilegious. ;D

Eddy I think it might be worthwhile to go back to the original source and have a look, I think the math is OK but how it's applied to the Geometry is not.

Dave


Title: Re: Drag-Knife Script
Post by: dave benson on June 13, 2019, 09:30:01 am
Eddy

I did a few more tests, and the duplicate points come from the wheeling path not being created
and then, when the non-existent path is  trying to be joined to the rest of the path polylines it happens.
Sometimes the segment at the wheeling path joining point is missing (I think pixelmaker or Dragonfly) mentioned
this but Bill miss-understood what he was saying.
Hope this helps.

Dave


Title: Re: Drag-Knife Script
Post by: EddyCurrent on June 13, 2019, 09:30:09 am
Dave,

billT wrote the original script, I just made it inot a plugin so I've never really looked at how it works.
It's about 6 months since Bill last logged into the forum, I'm in the middle of repairing a digital piano and so it might have to wait a while before I get to dig deeper.
Thanks for the files and explanation.


Title: Re: Drag-Knife Script
Post by: dave benson on June 13, 2019, 09:38:57 am
No Worries Eddy.
I found a Quite except-able way to do this with a profile mop that starts to spiral down from a small distance
above work surface (this automatically aligns the knife) and this works wonderfully for me, so I wont be needing the Drag Knife plugin to make any of my gaskets.
piano or synth?.
Dave


Title: Re: Drag-Knife Script
Post by: EddyCurrent on June 13, 2019, 13:48:06 pm
Dave,

So does the knife still rise up, but stay in the material at the corners to allow turning, and then drop down again full depth for cutting ?

It's quite an old but good quality Kawai digital piano, lots of faults thanks to previous owner and the age of the boards, but we are getting there now.


Title: Re: Drag-Knife Script
Post by: pixelmaker on June 13, 2019, 16:05:29 pm
Dave, you have to adjust the "Swivel Angle"
I never used this plugin because I have a large cutting plotter. But I've already successfully created code with it.

If you have a circle you have to add some points and reduce the Swivel Angle, in this case to 0.2.

The toolpath works as expected, starts and end at the swivel points

ralf


Title: Re: Drag-Knife Script
Post by: dave benson on June 14, 2019, 01:12:33 am
Thanks for the heads up Ralf.

I tried your file and even entered some new geometry everything went as expected, I then tried my file again and got a different result my previous result, (I think something is screwy with the file) so I'll try Later today  and see how I go.

Eddy here's a picture of one of the corners done with the profile mop, it looks good and so do the other cuts.
I think that for material this thin 0.3 mm the raising and lowering is not necessary, but could see that on thicker material
would be a great help.

I have a home made huge in comparison Drag Knife for cutting out neoprene gaskets (2 mm thick) and will do some more tests as soon as I machine down the shank to fit in my collet system, it has a large offset in comparison, and this is where I think the swivel action would be useful.

Eddy sadly the day they were handing out musical talent I was away, and one of my younger brothers got a double dose.
He makes acoustic guitars, using different wood varieties for various parts, which he keeps in a climate controlled box.
I offered to cut out some parts out for him, But he'll have none of it, as he uses mostly hand equipment collected over the years.
He has one of the smallest wood planes I've ever seen IIRC he called it a finger plane. It looks like a plane in miniature not a spoke shave.

Dave


Title: Re: Drag-Knife Script
Post by: pixelmaker on June 14, 2019, 10:23:28 am
Hello Dave
I get the error messages if Swivel Angle is wrong. You have to set the value partially for each object.
Please upload a file, then I'll set it for you.

The material looks like you couldn't cut it with a knife, but the magnification can be misleading..

ralf


Title: Re: Drag-Knife Script
Post by: dave benson on June 14, 2019, 15:48:38 pm
Thanks for the offer Ralf I really appreciate it, But I've had a look at the Python code and can see the problem.
In  line 129
CFirstSweep = Math.Acos(round(Vector2F.DotProduct(VFirst,V1)/(VFirst.Length*V1.Length),10))
The vector v1.length is NAN which gives a divide by zero error.
there is no error checking for this.
In line 152
        C2X = P2X+KnifeTipOffset/((1+(V2.Y/V2.X)**2)**.5)*Math.Sign(V2.X)
V2.X is NAN as well

As it is for this gasket making task the profile mop is far better for me as I can use holding tabs to keep the material from moving around.
So first I cut the circles (bolt holes) then cut the inside island using holding tabs to stop the material from moving around and getting stuck under the knife, then cutting the outside periphery last using holding tabs again.

The image in the last post was at X10 magnification and this pic below has a writing pen in it  to get some sense of the scale.
The second pic is of the edge of the gasket material to show just how brittle it is, I won't be actually using it in the turrets as it is no good for gaskets anymore.

I realise that the method I use would be no good for a vinyl cutter where the wheeling paths would be beneficial and perhaps working with the 2-3 mm neoprene gaskets I intend to make later on.

When the time comes and I need to use the wheeling paths then I'll write some new C# code from first principles using the website Bill pointed to.

Dave


Title: Re: Drag-Knife Script
Post by: dave benson on June 17, 2019, 12:17:50 pm
Ralf
I got minute today to add checking for the divide by zero error.
Could you have a look at this CB file and check the geometry (it looks OK to me).
If it looks good than I'll post the change I made so Eddy can add this to the plugin.
edit can't spell looks ::)
Dave


Title: Re: Drag-Knife Script
Post by: pixelmaker on June 18, 2019, 16:24:51 pm
The geometry is ok.
Most problems occur with circles.
Only there the error occurs with me so massively on that I must adapt the Swivel Angel.
Therefore test preferably with circles

ralf


Title: Re: Drag-Knife Script
Post by: dave benson on June 19, 2019, 00:40:24 am
Yes it's the tangent thing. Atan2 has some quirks but may be needed. Don't know yet just have to play around and see.
On the week end I'll see if something can be done, but don't hold your breath as
I'm flat out making parts in the shop, and am struggling to keep up.
Dave


Title: Re: Drag-Knife Script
Post by: dave benson on June 20, 2019, 01:46:54 am
Hi Ralf

I tinkered a bit more, and added a few lines to the script.
I can do circles without a problem, if I select those first and process them as a group, then select the other text geometry and do that separately.
The issue is that you have to remove the Arc's in the polyline.
Interestingly if you use that same geometry again the script fails.
and the items that you selected, for example 5 circles, they stay selected in the tree view, but in reality only the last circle in the selected group is selected, if you immediately do a rmb click and move the objects only the last polyline in the group moves, even though all the polylines are showing as selected in the tree view and in the drawing area?

So for now if you select the circles and convert them to polylines with CB, then remove the Arc's and run the original script on (no other geometry is allowed) them they'll be OK.
Then just run the original script on the rest of the geometry.

Dave


Title: Re: Drag-Knife Script
Post by: pixelmaker on June 20, 2019, 12:49:37 pm
Hallo Dave

after my tests it is enough to provide the circles and arcs with more nodes.
In CamBam a circle has 2 or 3 nodes if you convert it to a polyline. If you increase the number to more nodes there is no error. The distance of the nodes seems to be more important than the number. If the distance of the nodes in a circle is only 5-6mm there is no error.
But arcs remain arcs.

ralf


Title: Re: Drag-Knife Script
Post by: dave benson on June 20, 2019, 14:20:54 pm
HI Ralf

Interesting I hadn't tried that, I found out what was causing the script to fail on the second attempt (after the first try failed)
it hadn't failed completely the first time as the geometry was placed at Z-1 (the setting I had in the script).
When I put the geometry back at Z = 0 it worked again.
I also made this change to the script, but forgot to mention it in the previous post.
I had a look at an old textbook of vector math to swat up a bit as I've forgotten a lot of the details.
The divide by zero error I was sometimes getting was caused by the cross product calc.
what happens is the cross product is a magnitude and an angle between them and if the two vectors lay on top of each other
the angle = 0 , so I added these two lines to the script.

  #### 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)
        if V2.X == 0:
           Vector2F.X.SetValue(V2,1)

        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)

I also found this script at the DXF2Gode site, it's originally Bill's script from here, where they also had to modify the script
to get it to work for them.
So might provide some clues for us.

Code:
     def make_swivelknife_move(self):
         """
         Set these variables for your tool and material
         @param offset: knife tip distance from tool centerline. The radius of the
         tool is used for this.
         """



         offset =self.shape.LayerContent.tool_diameter/2
         dragAngle = self.shape.dragAngle

         startnorm = offset*Point(1,0,0)
         prvend, prvnorm = Point(0,0),Point(0,0)
         first = 1


         #start = self.startp

         #Use The same parent as for the shape
         self.parent=self.shape.parent

         for geo in self.shape.geos:
             if geo.type == 'LineGeo':
                 geo_b = deepcopy(geo)
                 if first:
                     first = 0
                     prvend = geo_b.Pa + startnorm
                     prvnorm = startnorm
                 norm = offset*geo_b.Pa.unit_vector(geo_b.Pe)
                 geo_b.Pa += norm
                 geo_b.Pe += norm
                 if not prvnorm == norm:
                     swivel = ArcGeo(Pa=prvend, Pe=geo_b.Pa, r=offset,direction=prvnorm.cross_product(norm).z)
                     swivel.drag = dragAngle < abs(swivel.ext)
                     self.geos.append(swivel)
                 self.geos.append(geo_b)

                 prvend = geo_b.Pe
                 prvnorm = norm
             elif geo.type == 'ArcGeo':
                 geo_b = deepcopy(geo)
                 if first:
                     first = 0
                     prvend = geo_b.Pa + startnorm
                     prvnorm = startnorm
                 if geo_b.ext > 0.0:
                     norma = offset*Point(cos(geo_b.s_ang+pi/2),sin(geo_b.s_ang+pi/2))
                     norme = Point(cos(geo_b.e_ang+pi/2), sin(geo_b.e_ang+pi/2))
                 else:
                     norma = offset*Point(cos(geo_b.s_ang-pi/2), sin(geo_b.s_ang-pi/2))
                     norme = Point(cos(geo_b.e_ang-pi/2), sin(geo_b.e_ang-pi/2))
                 geo_b.Pa += norma
                 if norme.x > 0:
                     geo_b.Pe = Point(geo_b.Pe.x+offset/(sqrt(1+(norme.y/norme.x)**2)),geo_b.Pe.y+(offset*norme.y/norme.x)/(sqrt(1+(norme.y/norme.x)**2)))
                 elif norme.x ==0:
                     geo_b.Pe = Point(geo_b.Pe.x,
                         geo_b.Pe.y)
                 else:
                     geo_b.Pe = Point(geo_b.Pe.x-offset/(sqrt(1+(norme.y/norme.x)**2)), geo_b.Pe.y-(offset*norme.y/norme.x)/(sqrt(1+(norme.y/norme.x)**2)))
                 if not prvnorm == norma:
                     swivel = ArcGeo(Pa=prvend, Pe=geo_b.Pa, r=offset, direction=prvnorm.cross_product(norma).z)
                     swivel.drag = dragAngle < abs(swivel.ext)
                     self.geos.append(swivel)
                 prvend = geo_b.Pe
                 prvnorm = offset*norme
                 if -pi<geo_b.ext<pi:
                     self.geos.append(ArcGeo(Pa=geo_b.Pa, Pe=geo_b.Pe, r=sqrt(geo_b.r**2+offset**2), direction=geo_b.ext))
                 else:
                     geo_b = ArcGeo(Pa=geo_b.Pa, Pe=geo_b.Pe, r=sqrt(geo_b.r**2+offset**2), direction=-geo_b.ext)
                     geo_b.ext = -geo_b.ext
                     self.geos.append(geo_b)

             else:
                 self.geos.append(copy(geo))
         if not prvnorm == startnorm:
             self.geos.append(ArcGeo(Pa=prvend, Pe=prvend-prvnorm+startnorm, r=offset, direction=prvnorm.cross_product(startnorm).z))

         self.geos.insert(0,self.geos[0].Pa)


Why I originally removed the Arc's was that the code as is was sometimes adding the geometry to the wrong end of the Arc.
I'm subed to 3Blue1brown where he has a series of Math videos, and I know he did Vectors, so on the weekend I'll look at a few jog my memory.

Dave


Title: Re: Drag-Knife Script
Post by: dave benson on June 30, 2019, 01:53:29 am
Ralf

I had a chance to have another quick look, Math is OK, and found the the code fails when the
circles are quite small, which meant that the segments were larger than the knifeTipoffset value.
I found that when I set the Arc tolerance to small the segment lengths were smaller than the knife tip offset value
and this caused many swivel movements (dent length set to zero) I could remove them if I set the
Angle value, so the parameter settings are  dependent on each other. I did trap for this but, to set the parameter bounds I need a typical file that you might use on a plotter.
So when you get some time, could you please post a test file with some real geometry, so that I can determine the
bounds for the variables.

Dave