1. ## Cutting Strategy Routine

Registered forum members do not see this ad.

I have no idea how difficult it would be, but I often wish I had a lisp
or a spread sheet program would caculate the most efficient way
to get a series of rectangles and squares out of a rectangle 48 units
wide by 96 units tall (48"x 96" is the dimention of a standard sheet of U.S. plywood).
The best scenario for me would be being able to input a list of dimentions from the command line(Acad 2000) such as 22.25,33.625-
12.375,55.5625-33.3125,44.875 etc. Autocad would then draw the required number of 48"x 96" rectangles and place the inputed rectangles
and squares within the 48"x96" rectangles in an arrangement that would give the best yield of square inches of parts with the least amount unused area (waste). An option of rotating the rectangles 90 degrees (or not) would be helpfull because some jobs require the x and y coordinates of the parts list to allign with the 48" x 96" rectangles x any y coordinates, and some do not require that.

The other scenario would be for me to hand draw the rectangles representing the parts and then Autocad(2000) would arrange them
within the borders of 48"x96" rectangles without overlapping and in an
arrangement that would give the best yield of square inches and
the least amount of wasted square inches

Because list programing is beyond my skill at this point, I do not know
if this is possible or how difficult it would be.

Frank

2. You could draw a rectangle and then use a offset distance to draw many smaller rectangles that fit within this rectangle.Youre also parts as if youre going to be using these parts numerous times why not create blocks?Have I understood you correctly?

3. Frank,

Nesting programs are very interesting to do and very very complicated to do correctly. You also need very steadfast rules. For example, is there a minimal distance between the objects, can the objects use the edge of the material, are there machine holding clamps that must be accounted for.

For a manual sheet metal shearing operation, then all clearances could be 0. For a laser or plasma cutting, then it's a maybe. For a millwork router, it's a must.

The alogritims are fairly simple, but can get very in depth in the tree department.

I'd post a couple that I have done, but they are covered by NDAs -David

4. Hyposmurf,
Thank you for the reply. The problem isnt that I cant draw the 48"x96'
rectangle and then manually figure out how to most efficently get
the smaller ones to fit within it, the problem is that it is time consuming
and time is money.

I will deal with the "loss of material" by adding the waste (in my case
usually .125" ) to the sizes I input ie: If i need a part size to net
24.25x 32.75 I will input it as 24.375x32.875 ( This will actually double
the actuall "kerf" for parts that do not come off the outside edge of
the sheet but if I had a program to even do it that accurately it
be close enough and save me a lot of time.
So then to answer your post, there would be a zero dimention between
parts and they can be right on the edge of the material.
The other rule of importance to my application would be an option
to rotate the parts 90 degrees(if necessary for more efficient yield) or not to rotate them to deal with the variable that some material has a "grain" direction and some material does not. The xand y coordinates of the parts list would allways be entered to be oriented correctly when
the option not to rotate has been selected.
I look forward to your postings
Frank

5. Frank,

The next part of the equation is whether or not the cutting process is totally free form or a shear / overrun cut.

Can the machine actually work this example:

This scenario is impossible with shearing operation. 2, 3, & 4 would have to be glued back together <g>

Also it would next to impossible with a circular sawing cut. Laser / Plasma could do it.

As to data input, I would use an ASCII text file

test.dat

Code:
```&#40;setq data '&#40;
&#40;"pn1" 24.375 30.375 0&#41;
&#40;"pn2" 12.375 24.375 1&#41;
&#40;"pn3" 10.625 22.875 0&#41;
&#41;&#41;```
With the sequence:

string_part_number x_axis y_axis boolean_rotate0=false/1=true
space delimited, Autolisp list format.

There would be a need to reserve at least 1 character in the part number for internal program use. I normally have it so that your part number cannot use "0" ( zero ) for the first letter.

That way I could do this:
Code:
```&#40;if &#40;= &#40;last &#40;"pn2" 12.375 24.375 1&#41;&#41; 1&#41;
&#40;setq data &#40;append data &#40;list &#40;"0pn2" 24.375 12.375 1&#41;&#41;&#41;&#41;```
-David

PS: If you do get a finished program up an running, it probably has some monetary value to someone, so I wouldn't post it in it's entirety. You never know, someone may offer you big bucks for it!!!

6. Wow David,
You nailed the last two items I ommited in an effort to simplify.
The need to label the parts with a number, and internal cuts.
I wanted to see if anything could be managed and I of course knew
if a computer figured out a strategy with the least waste it wouldnt
arrange the parts to be sawn with a circular saw
On occasion I will make a stopped cut and finish with a hand saw
or a jig saw to avoid a 40 mile trip to my hardwood ply. dealer to buy
an \$89.00 sheet for cutting one part.
For the most part, the sheets have to be sawn either all the way through
the y axis or the x axis and then further sawn.
As I feared, I will interpret the last part of your post as meaning
this type of routine would be a large undertaking that a person wouldnt
likely give away.
I do appreciate your time spent on this but I honestly couldnt write a
lisp that would draw a one inch line in positive x at this point.
As you know, a CNC router could also cut the scenario you posted
but I dont have one.
I saw a lot of custom lisp routines being posted to help people with
special applications and thought it wouldnt hurt to ask
I will put the info you you posted in my files for future days.
Frank

7. Frank,

The first one of these I did was on an old old sheet metal punch press. ( Wedomatic I think called ) It had 52 punches of various sizes and shapes. So basically we had the program pick the punch, calculate the offset so that the cut edge was in the proper position, and issue a down mode ( punch ). All virtual. We had a machine that could convert DXF formats into CNC ticker tape. Put the proper sheet of metal on the machine table bed, clamp it down The machine moved the sheet of metal around so that the punch was in the proper and wham wham wham, leaving a small piece at each corner that was then the last process before the blank was manually pull from the table. It was in the late '80s ( ACAD 2.62 ) and was a blast.

Seeing how yours is basically a free form style, programming it would be a lot easier. 1 gotcha is the 0.125" blade width.

Try this scenario:

48" material width

(1) piece 23.875, (1) piece 24.000 - all finished sizes. Technically they can be cut from 1 blank. By including the blade width in your data, it would pretty well preclude this type of cut. I would suggest letting the program calculate the blade stuff and use the actual finished piece size. Who knows, you may have to go to a 3\16" blade someday or someone makes a 1\16" diamond edged knife. That way the program could easily be modified to accept the new blade parameter.

-David

8. David,
I had anticipated that risk (missing an optimum yield by doubling the
tool path) but I figured on doing some of the thinking myself.
Better idea to let the computer do as much as possible
So then the rules at this point:

The sheet must be cut completely through the X or Y axis before
secondary cuttings can be made. This rule applies to secondary cuttings also.

There are no clamps or other obstacles for the routine to consider.

The routine will calculate a variable waste amount on the edges of the material and between each part.

A variable to select whether or not the parts X and Y axises can
be interchanged for greater yield to deal with materials that have
or do not have a "grain" direction.

The "parts" will be givin numbers as they are entered and the routine
will indicate what the numbers are in the finished product.

The only other thing that comes to mind right now is that it
would be of use to have a variable to have it layed out as though
it was going to be cut by laser because sometimes it is worth it timewise
to make a few "stopped" cuts on the saw when the material is costing
nearly \$100.00 dollars a sheet. However I would be thankfull for
a routine of any design that you can create.
Thanks for the help David and let me now if I forgot any other rules.

Frank

9. Frank,

For simplisty in development, it is better to focus on either free style or shear alone. I choose shear.

Cut and paste this to an new pure ASCII text file named test1.dat

Code:
```&#40;setq data '&#40;
&#40;"pn1" 24.375 30.375 0&#41;
&#40;"pn2" 12.375 24.375 1&#41;
&#40;"pn3" 10.625 22.875 0&#41;
&#41;&#41;```
Save this as new.lsp

Code:
```;=======================================================================
;    New.Lsp                                    Dec 22, 2004
;    Edit Name And SubRoutine Prefix nw_ To Ensure Unique Definitions
;================== Start Program ======================================
&#40;princ "\nCopyright &#40;C&#41; 2004, Fabricated Designs, Inc."&#41;
&#40;setq nw_ nil lsp_file "New"&#41;

;================== Macros =============================================
&#40;defun PDot &#40;&#41;&#40;princ "."&#41;&#41;

&#40;PDot&#41;;++++++++++++ Set Modes & Error ++++++++++++++++++++++++++++++++++
&#40;defun nw_smd &#40;&#41;
&#40;SetUndo&#41;
&#40;setq oldlay &#40;getvar "CLAYER"&#41;
olderr *error*
*error* &#40;lambda &#40;e&#41;
&#40;while &#40;> &#40;getvar "CMDACTIVE"&#41; 0&#41;
&#40;command&#41;&#41;
&#40;and &#40;/= e "quit / exit abort"&#41;
&#40;princ &#40;strcat "\nError&#58; *** " e " *** "&#41;&#41;&#41;
&#40;and &#40;= &#40;logand &#40;getvar "UNDOCTL"&#41; 8&#41; 8&#41;
&#40;command "_.UNDO" "_END" "_.U"&#41;&#41;
&#40;nw_rmd&#41;&#41;
nw_var '&#40;&#40;"CMDECHO"   . 0&#41; &#40;"MENUECHO"   . 0&#41;
&#40;"MENUCTL"   . 0&#41; &#40;"MACROTRACE" . 0&#41;
&#40;"OSMODE"    . 0&#41; &#40;"SORTENTS"   . 119&#41;
&#40;"MODEMACRO" . "."&#41;
&#40;"BLIPMODE"  . 0&#41; &#40;"EXPERT"     . 0&#41;
&#40;"SNAPMODE"  . 1&#41; &#40;"PLINEWID"   . 0&#41;
&#40;"ORTHOMODE" . 1&#41; &#40;"GRIDMODE"   . 0&#41;
&#40;"ELEVATION" . 0&#41; &#40;"THICKNESS"  . 0&#41;
&#40;"FILEDIA"   . 0&#41; &#40;"FILLMODE"   . 0&#41;
&#40;"SPLFRAME"  . 0&#41; &#40;"UNITMODE"   . 0&#41;
&#40;"TEXTEVAL"  . 0&#41; &#40;"ATTDIA"     . 0&#41;
&#40;"AFLAGS"    . 0&#41; &#40;"ATTREQ"     . 1&#41;
&#40;"ATTMODE"   . 1&#41; &#40;"UCSICON"    . 1&#41;
&#40;"HIGHLIGHT" . 1&#41; &#40;"REGENMODE"  . 1&#41;
&#40;"COORDS"    . 2&#41; &#40;"DRAGMODE"   . 2&#41;
&#40;"DIMZIN"    . 1&#41; &#40;"PDMODE"     . 0&#41;
&#40;"CECOLOR"   . "BYLAYER"&#41;
&#40;"CELTYPE"   . "BYLAYER"&#41;&#41;&#41;
&#40;foreach v nw_var
&#40;and &#40;getvar &#40;car v&#41;&#41;
&#40;setq nw_rst &#40;cons &#40;cons &#40;car v&#41; &#40;getvar &#40;car v&#41;&#41;&#41; nw_rst&#41;&#41;
&#40;setvar &#40;car v&#41; &#40;cdr v&#41;&#41;&#41;&#41;
&#40;princ &#40;strcat &#40;getvar "PLATFORM"&#41; " Release " &#40;ver&#41;
" -  Material Nesting Development Routine ....\n"&#41;&#41;
&#40;princ&#41;&#41;

&#40;PDot&#41;;++++++++++++ Return Modes & Error +++++++++++++++++++++++++++++++
&#40;defun nw_rmd &#40;&#41;
&#40;SetLayer oldlay&#41;
&#40;setq *error* olderr&#41;
&#40;foreach v nw_rst &#40;setvar &#40;car v&#41; &#40;cdr v&#41;&#41;&#41;
&#40;command "_.UNDO" "_END"&#41;
&#40;prin1&#41;&#41;

&#40;PDot&#41;;++++++++++++ Set And Start An Undo Group ++++++++++++++++++++++++
&#40;defun SetUndo &#40;&#41;
&#40;and &#40;zerop &#40;getvar "UNDOCTL"&#41;&#41;
&#40;command "_.UNDO" "_ALL"&#41;&#41;
&#40;and &#40;= &#40;logand &#40;getvar "UNDOCTL"&#41; 2&#41; 2&#41;
&#40;command "_.UNDO" "_CONTROL" "_ALL"&#41;&#41;
&#40;and &#40;= &#40;logand &#40;getvar "UNDOCTL"&#41; 8&#41; 8&#41;
&#40;command "_.UNDO" "_END"&#41;&#41;
&#40;command "_.UNDO" "_GROUP"&#41;&#41;

&#40;PDot&#41;;++++++++++++ Make Layer Current +++++++++++++++++++++++++++++++++

&#40;defun SetLayer &#40;name / ldef flag&#41;
&#40;command "_.LAYER"&#41;
&#40;if &#40;not &#40;tblsearch "LAYER" name&#41;&#41;
&#40;command "_Make" name&#41;
&#40;progn
&#40;setq ldef &#40;tblsearch "LAYER" name&#41;
flag &#40;cdr &#40;assoc 70 ldef&#41;&#41;&#41;
&#40;and &#40;= &#40;logand flag  1&#41;  1&#41;
&#40;command "_Thaw" name&#41;&#41;
&#40;and &#40;minusp &#40;cdr &#40;assoc 62 ldef&#41;&#41;&#41;
&#40;command "_On" name&#41;&#41;
&#40;and &#40;= &#40;logand flag  4&#41;  4&#41;
&#40;command "_Unlock" name&#41;&#41;
&#40;and &#40;= &#40;logand flag 16&#41; 16&#41;
&#40;princ "\nCannot Set To XRef Dependent Layer"&#41;
&#40;quit&#41;&#41;
&#40;command "_Set" name&#41;&#41;&#41;
&#40;command ""&#41;
name&#41;

&#40;PDot&#41;;************ Main Program ***************************************
&#40;defun nw_ &#40;/ olderr oldlay nw_var nw_rst x y w file&#41;
&#40;nw_smd&#41;

;  &#40;*debug* 32 "nw_"&#41;

&#40;initget 6&#41;
&#40;setq x &#40;getdist "\nMaterial X Axis Size <96>&#58;   "&#41;&#41;
&#40;and &#40;not x&#41;
&#40;setq x 96.&#41;&#41;

&#40;initget 6&#41;
&#40;setq y &#40;getdist "\nMaterial Y Axis Size <48>&#58;   "&#41;&#41;
&#40;and &#40;not y&#41;
&#40;setq y 48.&#41;&#41;

&#40;initget 6&#41;
&#40;setq w &#40;getdist "\nBlade Thickness <0.125>&#58;   "&#41;&#41;
&#40;and &#40;not w&#41;
&#40;setq w 0.125&#41;&#41;

&#40;while &#40;not file&#41;
&#40;setq file &#40;getfiled "ASCII DATA File To Import" "/acad/" "dat" 2&#41;&#41;&#41;

;  &#40;*break*&#41;

;  &#40;*debug* 0 "nw_"&#41;

&#40;nw_rmd&#41;&#41;

&#40;defun C&#58;NW &#40;&#41; &#40;nw_&#41;&#41;
&#40;prin1&#41;
;|================== End Program =======================================```

At the command line
Command: NW

It is a start. -David

10. Registered forum members do not see this ad.

Okay, seeing how this is a teaching forum, lets develop this in steps, if it is okay with CadTutor.

Step 0 was the AutoLisp and Data file templates.

Step1 was to get the user input:

Code:
```&#40;defun step1 &#40;&#41;

&#40;initget 6&#41;
&#40;setq x &#40;getdist "\nMaterial X Axis Size <96>&#58;   "&#41;&#41;
&#40;and &#40;not x&#41;
&#40;setq x 96.&#41;&#41;

&#40;initget 6&#41;
&#40;setq y &#40;getdist "\nMaterial Y Axis Size <48>&#58;   "&#41;&#41;
&#40;and &#40;not y&#41;
&#40;setq y 48.&#41;&#41;

&#40;initget 6&#41;
&#40;setq w &#40;getdist "\nBlade Thickness <0.125>&#58;   "&#41;&#41;
&#40;and &#40;not w&#41;
&#40;setq w 0.125&#41;&#41;

&#40;while &#40;not file&#41;
&#40;setq file &#40;getfiled "ASCII DATA File To Import" "" "dat" 2&#41;&#41;&#41;

&#40;list x y w file&#41;&#41;```
Step2 will be to load and verify tha data:
Code:
```&#40;defun step2 &#40;file / i pn xv yv rt&#41;
&#40;setq i 0&#41;

&#40;exit&#41;&#41;
&#40;&#40;not data&#41;
&#40;exit&#41;&#41;
&#40;&#40;/= &#40;type data&#41; 'LIST&#41;
&#40;exit&#41;&#41;
&#40;&#40;foreach a data
&#40;cond &#40;&#40;/= &#40;type a&#41; 'LIST&#41;
&#40;alert &#40;strcat "Atom nth " &#40;rtos i 2 0&#41; " Invalid"&#41;&#41;
&#40;exit&#41;&#41;
&#40;&#40;/= &#40;length a&#41; 4&#41;
&#40;alert &#40;strcat "Atom nth " &#40;rtos i 2 0&#41; " Invalid"&#41;&#41;
&#40;exit&#41;&#41;&#41;
&#40;setq pn &#40;nth 0 a&#41;
xv &#40;nth 1 a&#41;
yv &#40;nth 2 a&#41;
rt &#40;nth 3 a&#41;&#41;
&#40;cond &#40;&#40;or &#40;/= &#40;type pn&#41; 'STR&#41;
&#40;= &#40;substr pn 1 1&#41; "0"&#41;&#41;
&#40;alert &#40;strcat "Atom nth " &#40;rtos i 2 0&#41; " Part Number Invalid"&#41;&#41;
&#40;exit&#41;&#41;
&#40;&#40;not &#40;numberp xv&#41;&#41;
&#40;alert &#40;strcat "Atom nth " &#40;rtos i 2 0&#41; " X Value Invalid"&#41;&#41;
&#40;exit&#41;&#41;
&#40;&#40;not &#40;numberp yv&#41;&#41;
&#40;alert &#40;strcat "Atom nth " &#40;rtos i 2 0&#41; " Y Value Invalid"&#41;&#41;
&#40;exit&#41;&#41;
&#40;&#40;not &#40;or &#40;= rt 1&#41;
&#40;= rt 0&#41;&#41;&#41;
&#40;alert &#40;strcat "Atom nth " &#40;rtos i 2 0&#41; " Rotation Value Invalid"&#41;&#41;
&#40;exit&#41;&#41;&#41;
&#40;setq i &#40;1+ i&#41;&#41;&#41;&#41;&#41;
&#40;length data&#41;&#41;```
We will update the main program as it evolves:

Code:
```&#40;defun nw_ &#40;/ olderr oldlay nw_var nw_rst x y w file&#41;
&#40;nw_smd&#41;

&#40;trace step1 step2&#41;

;;;Get USER INPUT
&#40;step1&#41;

&#40;step2 file&#41;

&#40;nw_rmd&#41;&#41;```
I prefer to have each subroutine return a value. It can prove helpful in debugging the program. Also the (trace) function helps with this as well.

I also choose to exit the program when bad data is encountered. Having to try a correct the stuff usually isn't worth the effort. Also, you may want to run the same data file time and again during production work. So I force the user to fix the data file. -David

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts