Author Topic: Perl for CNC  (Read 23683 times)

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Perl for CNC
« on: May 11, 2013, 18:29:25 pm »
Hi There,

Several different people suggested that I write up how I use Perl in generating input for CamBam and my CNC machine, so I thought I would have a go at it.

Over the years I have written many programs to generate patterns of various sorts, in the first place to control a graph plotter; later to do computer graphics and now to output on the CNC router.  They all basically come down to algorithms that generate a bunch of lines, followed by a conversion of the lines to the requisite commands to control some output device.  It is this second part that might be useful to someone here, although I will also say something below about generating Bezier curves and Voronoi polyhedra.

Lines can be of three types: simple point-to-point connections, described as (x1, y1, x2, y); open polylines, described as (x1, y1, x2, y2, x3, y3, ... xn, yn) and closed polylines, where the last point is the same as the first one (at least to some tolerance).  An example might be:

10, 160, 10, 100
10, 130, 50, 130
50, 160, 50, 100
110, 160, 70, 160, 70, 100, 110, 100
70, 130, 100, 130
130, 160, 130, 100, 170, 100
190, 160, 190, 100, 230, 100
260, 160, 250, 150, 250, 110, 260, 100, 280, 100, 290, 110, 290, 150, 280, 160, 260, 160
10, 70, 10, 10, 30, 40, 50, 10, 50, 70
80, 70, 70, 60, 70, 20, 80, 10, 100, 10, 110, 20, 110, 60, 100, 70, 80, 70
130, 10, 130, 70, 160, 70, 170, 60, 170, 50, 160, 40, 130, 40
150, 40, 170, 10
190, 70, 190, 10, 230, 10
250, 70, 250, 10, 280, 10, 290, 20, 290, 60, 280, 70, 250, 70

which consists of a dozen or so lines spelling out "Hello World".

Assume that a program has produced this as output.  I have three approaches to getting this converted to GCode.

1) Convert the lines into a '.cb' file directly, which can then be used by CamBam for further manipulation and GCode generation.

2) Convert the lines into an '.stl' file, which allows for 3D profiling of the surface.  This can then be imported into CamBam and then carved as a surface.

3) Generate GCode directly.  This is good for simply engraving the lines at a single depth using a V-Cutter.

A fourth thing I do is to convert the lines to a 'png' file, which is handy during debugging to see what the line-drawing algorithm has generated.  CamBam cannot import these.  It can import '.gif's, but this is not a great approach to getting lines into CamBam.


A different approach altogether is to use a mathematical function that calculates a 'z' coordinate given 'x' and 'y' and to apply this across a grid of coordinates to generate an '.stl' file directly.



I will spread this writeup across several messages, so that I can upload files with each.  The Perl code has been given a '.txt' extension to get it through the forum's file filter.  You will need to remove these.  I am assuming a UNIX system here.  I know nothing about Windows!  Presumably Perl on Windows makes provision for reading from STDIN and writing to STDOUT and for executing from a command line.  I work in mm, but inches should be fine.  You might need to adjust the precision of some print statements.

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Converting lines directly to CamBam
« Reply #1 on: May 11, 2013, 18:30:55 pm »

I attach a program called 'lines_to_cb' (and a support library) which reads a set of lines from its input and puts them into a template '.cb' file to give a '.cb' file that should open correctly in CamBam.

You need to make the template file by opening CamBam and simply hitting SaveAs, without adding any objects to the project.

The saved template will have an empty <objects /> tag in the middle.  My code simply replaces this with all the XML for a bunch of polylines corresponding to those read.  A polyline will be closed if the last point is approximately the same as the first.  Otherwise it will be open.  By using your own template file, all the defaults should be whatever you are used to.

You might run this by saying:

cat hello_world.txt | lines_to_cb template.cb > hello_world.cb

The name of the template file defaults to 'template.cb'.

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Converting lines to STL
« Reply #2 on: May 11, 2013, 18:34:31 pm »
I attach a program called 'lines_to_stl' (and a support library) which reads a set of lines from its input and generates a surface in stl format.  The lines stand proud of the surface.

The code works by using a function to calculate the 'dropoff' profile of a point depending on its distance from the nearest line.  The actual function provided results in a line 2mm wide with an edge profile that follows a sin function down until it is 10mm wide, after which the surface is flat.  You can easily change this function to give a completely different width and profile.  CamBam actually supports edge profiles, although these are always circles.  Mine are similar, but on both sides of the line.

I use an amazingly inefficient algorithm for calculating the distance of each point from the nearest line, namely that I calculate the distance of each point from all lines and take the minimum!  There must be a better way, but this at least works and computer time is cheap.  If you have more than a thousand lines it will get tedious...

The program needs to know the size of the surface being generated and the depth of the dropoff, so you might run it as:

cat hello_world.txt | lines_to_stl 0 300 0 180 5 > hello_world.stl

giving a 300x180 surface with lines raised by 5mm.

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Converting lines directly to GCode
« Reply #3 on: May 11, 2013, 18:35:38 pm »

I attach a program called 'lines_to_gcode', which reads a set of lines from its input and generates GCode directly.  The lines are carved into the surface.

This is pretty trivial stuff, simply moving along the clearance plane to the start of each line and then cutting to the end of it.

You will almost certainly want to fix the code to perform initialization appropriate to your setup.  Mine is pretty simple minded!  Please don't trust me here.  This code is mostly for illustration if what can be done.

The program allows you to specify the clearance plane, target depth and cutting speed.  You might run it by saying:

cat hello_world.txt | lines_to_gcode clearance 5 target_depth -1 speed 2000 > hello_world.nc

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Converting lines to PNG
« Reply #4 on: May 11, 2013, 18:37:21 pm »
I attach a program called 'lines_to_png' which reads a set of lines and generates a '.png' file.  This makes use of the Image::Magick library.  Image Magick is open source code that you can get from http://www.imagemagick.org/.  The installation process is not as smooth as it might be, but the library is well written and the Perl interface to it is OK.  There is a lot more that could be said about using this library.

My program needs to know the dimensions of the graphic, so you might run it as:

cat hello_world.txt | lines_to_png 300 180 > hello_world.png

If you edit the code you can change the stroke width, colour, etc.  Image::Magick also supports polygons, but I am not using them here, even for polylines.

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Generating STL from a function
« Reply #5 on: May 11, 2013, 18:39:10 pm »
I attach a library, 'function_to_stl.pm' and an example call to it 'test_function_to_stl.txt'.  This generates an '.stl' surface mapping the surface over a given area.  The example maps the sum of three sin waves.  I like sin waves because they are bounded between +1 and -1.  The sum of three of them cannot be more than +3 or less than -3.

The library simply evaluates the function at every point in the range and generates a corresponding mesh surface.  CamBam does not care about correct surface normals, which are only used to differentiate 'in' and 'out'.  I use clockwise triangles, which it interprets correctly.  I generate the ascii version of the .stl format.  Binary would be nicer, but I had problems moving the file between different machines due to 'big-endian' issues.

You run it by saying:

test_function_to_stl > function.stl

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Generating Bezier curves
« Reply #6 on: May 11, 2013, 18:41:03 pm »
There is quite a simple CPAN library for generating curves: Math::Bezier, which you can get from http://search.cpan.org/~abw/Math-Bezier-0.01/Bezier.pm.  I attach it here, since it is small and stand-alone, but getting it from CPAN would be better.

A Bezier curve is defined by its end points and a number of control points (normally two is enough) in the middle, i.e. (x1, y1, xc1, yc1, xc2, yc2, x2, y2).  If you want to butt two lines together smoothly, the control points at the joined ends of the lines need to be symmetrically opposite one another.  The library simply returns a number of points along the line.  Assuming your curves are not too long, 20 points along it is reasonable.

I used this approach for making a jigsaw puzzle, where the edges have randomly varying curves.

I attach an example program that draws a square with curved sides.  It puts out lines in my normal format which can then be converted to CamBam or whatever as above.  You run it by saying one of:

test_bezier_to_lines | lines_to_cb > bezier.cb
test_bezier_to_lines | lines_to_stl 0 100 0 100 4 > bezier.stl
test_bezier_to_lines | lines_to_gcode > bezier.nc
test_bezier_to_lines | lines_to_png 100 > bezier.png

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Generating Voronoi Polyhedra
« Reply #7 on: May 11, 2013, 18:43:03 pm »
Voronoi Polyhedra are simply a way of dividing up a surface into cells, where the edges of the cells are equidistant from a set of randomly generated points.  These have something of an organic feel to them and drilling out the centres of the cells is a good way to lighten a structure or just make it look cute.

CamBam has the ability to set the roughing clearance, which is good for cutting inside cells, or the 'fillet' mechanism can be used (which for some reason deletes the polygons it is filletting).

There is a CPAN library called Math::Geometry::Voronoi, which can be downloaded from http://search.cpan.org/~samtregar/Math-Geometry-Voronoi-1.3/lib/Math/Geometry/Voronoi.pm.  I am not attaching it here because my recollection was that it has dependent libraries that also need to be downloaded.

I do attach an example program that simply generates a bunch of random points (actually it randomly disturbs a set of grid points) and then generates the lines corresponding to the Voronoi Cells by using the Math library.

You can run it by saying:

voronoi_to_lines | lines_to_cb > voronoi.cb
voronoi_to_lines | lines_to_png 500 > voronoi.png

I attach the .cb output from this.  When you first open it, the file appears to be empty and you will need to zoom in to the centre to see the mesh.  The outer lines generated go off to infinity.  The first thing to do with the file is to clip the mesh to an outline that you want to fill.  Then filletting or whatever.

Offline BR52

  • Wookie
  • ****
  • Posts: 368
    • View Profile
Re: Generating Voronoi Polyhedra
« Reply #8 on: May 16, 2013, 02:52:09 am »
Hi Bob, and falling short interested.

How install and run on Windows 64bit or 32bit.
On my Windows 7 64Bit this installed Strawberry Pert.
http://www.perl.org/get.html

The "ActiveState Perl" is Spam

In Windows you have to use "*.pl" an extension to run commands.
In the files you change the header to #!C:\strawberry\perl\bin\perl.exe -w
the interpretation of the module is to call Math::Geometry::Voronoi
Is equivalent to ..lib\Math\Geometry\Voronoi.pm

Installing the module Magick.
See here: http://www.imagemagick.org/script/binary-releases.php#windows
I installed the ImageMagick-6.8.5-6-Q16-x64-dll.exe Win64 dynamic at 16 bits-per-pixel
It automatically installs the module.
See the video tutorial: http://www.youtube.com/watch?v=PNd00dRqckE&feature=player_detailpage

Installing voronoi module, please see the attached image.
Where do you find modules.
http://search.cpan.org/
https://metacpan.org

              Armando

Offline BR52

  • Wookie
  • ****
  • Posts: 368
    • View Profile
Re: Generating Voronoi Polyhedra
« Reply #9 on: May 16, 2013, 03:03:58 am »
Here's all files altered of Bob and Run-Perl.txt

        Armando

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Re: Perl for CNC
« Reply #10 on: May 16, 2013, 16:23:26 pm »
Hi Armando,

This is excellent - at least I think you are saying that you have all this working.  From the timestamps on your files it looks as though you have been able to create the .cb and .stl files by running the programs.  Great!

I hope that these prove to be useful to you!  Let me know if you find any issues or bugs or if there are useful enhancements that could be made (or that you make).


Bob



As an aside, I am sorry to see ".pl" used as a file extension.  This was supposed to indicate a Perl Library and not an executable.  But I suppose that is a Windows convention.  Sigh!

Offline BR52

  • Wookie
  • ****
  • Posts: 368
    • View Profile
Re: Perl for CNC
« Reply #11 on: May 17, 2013, 02:11:46 am »
Bob, The credit is all yours thanks for your files.

Yes, used as a file extension is a convention of Windows.
Inside the file there is a convention in the header and footer.
I use text editor Notepad++ and WordPad.

I changed the file lines_to_gcode.pl compare with your file.
I also changed the file lines_to_cb.pm see.

A long time I use Perl, currently I use on Openscad.
The largest Perl community in South America is of Brazil.
http://www.pm.org/groups

         Armando
« Last Edit: May 17, 2013, 02:30:32 am by BR52 »

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Converting SVG to lines
« Reply #12 on: June 16, 2013, 19:16:39 pm »
I find Inkscape rather complicated, but one of the tools I most like is the Bezier Curve drawing tool.  Inkscape allows you to import a jpg file and then to use it as a template to generate a bezier curve boundary.  Soothing!

Inkscape saves its data as an SVG file, which is basically an XML format.  Bezier curves are saved as 'paths', which have a 'd' attribute giving the coordinates and control points.  Inkscape also supports saving the file as a DXF file, which can be imported directly into CamBam.

However, what I wanted was a set of (x1, y1, x2, y2) lines as described above.  Luckily Inkscape has a 'Flatten Beziers' command (Extensions >> Modify Path >> Flatten Beziers...) which converts a bezier path to a series of straight lines.  Saving in SVG format then provides a 'd' path attribute that is just the set of coordinates along the path.  I then wrote a simple Perl script to convert these SVG paths to my lines format.

I attach an example SVG file with a bezier curve, the same file after flattening, my program to convert this to lines and the resulting lines file.  The program takes a very fast-and-loose approach to reading the SVG file, in that it does not parse the XML format, but just extracts the 'd' attributes.  The main complication is due to the fact that SVG has the origin at the top-left, while CamBam puts the origin at the bottom left.  All the 'y' coordinates have to be adjusted.  Sigh!  While I was at it, I added a 'padding' option to move the lines away from the origin.

You would run the program by saying something like:

svg_paths_to_lines 16 file.svg > file.lines

where the '16' is the amount of padding required.


As above, all the .txt extensions need to be removed.  Even .svg is not allowed!

Offline macbob

  • Storm Trooper
  • ***
  • Posts: 189
    • View Profile
    • Bob Mackay
Lines to STL again! Different profile
« Reply #13 on: June 16, 2013, 19:33:46 pm »
The second part of this project was to convert the object outline to an STL file, to give it a raised profile.  This was done in exactly the same way as described above in "Converting lines to STL", except that the profile I used gave each coordinate a height proportional to the square-root of its distance from the nearest line.  Square-roots get larger indefinitely, rather than reaching a plateau, so the result is a central ridge-line, which is what I wanted.  Using some form of sine function would have avoided this.

I attach my lines_to_stl program with this function, the eventual .cb file (zipped) with both the surface and the lines themselves (which are used as boundaries and for cutting out the object, and a photo of the resulting object.

To summarise, the full workflow for this project was:

Start with picture in .jpg format;
Import into Inkscape as background;
Trace boundaries with Bezier tool;
Save the file as an SVG file (for use if the curve needs later tweeking);
Flatten Beziers using Extensions >> Modify Path >> Flatten Beziers..., specifying a precision to get sufficiently smooth lines;
Save the file as an SVG file (not the same as the first one);
Extract the lines: svg_paths_to_lines 16 lines.svg > file.lines
Convert the lines file to an stl surface: cat file.lines | lines_to_stl 0 120 0 600 20 > file.stl
Also convert the lines to a CamBam file, for use as a clipping boundary: cat file.lines | lines_to_cb > file.cb
Open the file.cb in CamBam and pull in also the file.svg;
Rotate/scale/move as required;
In my case I cleaned up some lines that were not to be boundaries by drawing a cutting line; break at intersections; delete and finally join;
Add MOPs;

I hope that this approach is of interest.

Offline rymaeda

  • Ewok
  • *
  • Posts: 13
    • View Profile
Re: Perl for CNC
« Reply #14 on: February 17, 2015, 16:04:19 pm »
Dear MacBob,

This thread is higly inspiring, some ideas arised after I read it. Thanks by sharing your knowledge. The SVG parsing specially catched my attention and make me coding some stuff to parse it in C language.
To do this I used Expat XML parsing library with LCC-Win32 IDE, project code attached.
Sorry my bad english (I'm brazilian) and my poor code (I'm hobbyst and don't code for lasts 10 years).

Regards

Ricardo Maeda
« Last Edit: February 24, 2015, 04:09:24 am by rymaeda »