22 Replies Latest reply on Feb 17, 2015 7:59 AM by Zantcor

    Is there a script available for arranging elements for optimal use of the printable area?

    RigRutgers

      I'm starting a sticker printing business using Illustrator as my main layout and illustration too. I was wondering if there's a script available for automatically arranging a set of elements on a page so that they optimally take up the available space. I figured this would save me some on material costs.

       

      If I were to create a script from scratch, can someone give me pointers? I'm a casual AI user but I have Javascript experience.

       

      Thanks.

        • 1. Re: Is there a script available for arranging elements for optimal use of the printable area?
          Larry G. Schneider Adobe Community Professional & MVP

          Look for a Packing script but don't get your hopes up.

          • 2. Re: Is there a script available for arranging elements for optimal use of the printable area?
            Muppet Mark Level 5

            I would agree with Larry this is intensive math work… and you will very lucky to find anything that doesn't require payment for… I would also expect this to be done with plug-in over script unless you only need to pack basic shapes… Jongware may have pointers it would be way over my head… Don't know of anything already about sorry…

            • 3. Re: Is there a script available for arranging elements for optimal use of the printable area?
              CarlosCanto Adobe Community Professional & MVP

              this is the holly grail of optimization, in the garment industry there are similar requirements for laying out the jeans pattern pieces to save on fabric, and  big companies have developed automated systems for it...but word says it is never as good as a human...but it works wonders for making pillows.

              • 4. Re: Is there a script available for arranging elements for optimal use of the printable area?
                Muppet Mark Level 5

                I did object collision once… cost me an R1… ouch

                • 5. Re: Is there a script available for arranging elements for optimal use of the printable area?
                  RigRutgers Level 1

                  Thanks everyone. Yeah, I was afraid it would involve math-instensive stuff. I guess for now I will do it all manually.

                  • 6. Re: Is there a script available for arranging elements for optimal use of the printable area?
                    W_J_T Level 4

                    @ RigRutgers , Larry G. Schneider, Muppet Mark, CarlosCanto,

                     

                    Hello everyone,

                     

                    I would like to kindly ask if someone would post a screen capture or two demonstrating a few examples, using just basic outlines of shapes (I presume manually assembled), for a common simple example and a more involved complex intense example of this principle and what the "would be" code should accomplish as an outcome, thus showing the outcome in the screenshot.

                     

                    Many thanks everyone!

                    • 7. Re: Is there a script available for arranging elements for optimal use of the printable area?
                      CarlosCanto Adobe Community Professional & MVP

                      something like this, the image below is the desired end result. The idea is to accommodate all pieces as tight as possible to save on fabric.

                       

                      2d-nesting-software-55072-2289313.jpg

                      • 8. Re: Is there a script available for arranging elements for optimal use of the printable area?
                        W_J_T Level 4

                        Thanks CarlosCanto, I really appreciate your response. I understood the workings of this already but was curious if I was on the same page when I saw this thread. I was wondering how interwoven people were imagining for optimization, thanks for the picture and confirmation. Thanks again for your response.

                         

                        To anyone's knowledge, does something commercial exist already for this with in Illustrator.

                        • 9. Re: Is there a script available for arranging elements for optimal use of the printable area?
                          CarlosCanto Adobe Community Professional & MVP

                          no idea if there is something for illustrator, I doub it. Are you giving it a shot? at writing up a program for simpler shapes peharps?

                          • 10. Re: Is there a script available for arranging elements for optimal use of the printable area?
                            W_J_T Level 4

                            I was not able to find anything for working directly within Illustrator for true shape nesting. I was just curious as most the software I researched is an external 3rd party program that mostly deals with basically shape outlines, thus for CNC, etc., not so much for actual full graphics as in Illustrator, like was initially discussed here, stickers, packaging, printing, etc... of couse some prepress / printing workflows and softwares offer nesting, etc..

                             

                            Not sure if I am giving it a shot even on a simple basis ;-) I just saw this thread the other day and was further curious about it. For basic shapes maybe, but for complex (even more than you showed in your screenshot) it would require a lot and I am not sure the Illustrator Scripting API itself has what it takes to do true shape nesting from a scripted approach, or could even get close beyond a basic style.

                             

                            ---

                             

                            @ Mark Muppet you were able to do Object level Collision detection in Illustrator?

                            • 11. Re: Is there a script available for arranging elements for optimal use of the printable area?
                              bigjobfaceman

                              Did anyone ever find anything that can do this? I work in the print industry as well and packing objects on the artboard to best use the space still remains  a mundane time consuming manual task. I'm looking for something like the Pack UV's tools common in 3D Software.

                               

                              Does it exist? A script that could just calculate the bounding box of every selected object and pack them onto the artboard, with a padding amount.

                               

                              s

                              • 12. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                miaoumix2013

                                Hi RigRutgers,

                                 

                                there is plenty of documentation for that kind of problem. If you are looking for a solution for rectangles and squares, I would advise you to search for the Lodi-Martello-Vigo TPRF (2BPRF) algorithm.

                                It is pretty simple to implement and works like a charm for rectangles.

                                 

                                You can download a VERY interesting document here...

                                 

                                If someone has a good solution (algorithm only, not script) for non rectangular objects, I'd enjoy to read it.

                                 

                                I hope it helped!

                                • 13. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                  bigjobfaceman Level 1

                                  Thanks for that, although its a bit out of my league! I muddle through with my scripting but I'm not a programmer. I'm sure there's a wizz out there who could knock it up, come on peeps! Best fit multiple selections to artboard with x padding! The printing industry will love you...

                                   

                                  S

                                  • 14. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                    [Jongware] Most Valuable Participant

                                    Even for simple rectangles there is no fast and (remotely) good solution for "best" fit ... Yup, it's one of those famous "holy grail" problems.

                                     

                                    bigjobfaceman wrote:

                                    ... something like the Pack UV's tools common in 3D Software ...

                                     

                                    Are all of your shapes rectangular? Is rotating allowed? Through 90 degrees only, or at any angle?

                                     

                                    bigjobfaceman wrote:

                                    Best fit multiple selections ...

                                     

                                    How would you select several objects, when some of themselves may consist of different objects? Every one on a separate layer? Every one grouped? Only "symbols"?

                                    • 15. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                      bigjobfaceman Level 1

                                      Damn those Holy Grails...

                                       

                                      They are not all rectangular but could be treated as such, just the overall width and height of a selection (even if its an oval you could take the width and height).

                                       

                                      They would be grouped or single elements..

                                       

                                      s

                                      • 16. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                        KennethWebb Level 1

                                        miaoumix2013,

                                        Thanks for this the link to the bin packing algorithm paper!

                                        I hadn't realize just how complex of a problem 2D bin packing was until I started reading through it.

                                        It looks like that paper has everything (and more) that you'd need to create a Holy Grail of scripts, or atleast a good approximation.

                                        Its definitely a very academic paper and I think I need to brush up on my greek characters a bit, but its pretty exciting to have a resource like this.

                                        I took your advice and googled Lodi-Martello-Vigo TPRF (2BPRF) and ran across this paper, another useful reference and quite a bit shorter. (Also more up to date)

                                        I look forward to eventually taking a crack at this script when I'm a bit better versed in the prerequisites... though part of me hopes some one else beats me to the punch. :-D

                                        • 18. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                          Kevin Parrott Level 2

                                          Hi

                                           

                                          you could look at Plato from Esko as an option, plug in for illustrator.

                                           

                                          they do charge like a wounded bull though, but they are top notch products

                                           

                                           

                                          http://www.esko.com/en/products/overview/plato/overview/

                                          • 20. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                            Zantcor Level 1

                                            We use a script to place our dies on an art board before sending them to get made.  We managed to narrow the sizes down 4 different ones and the script for making them will automatically scale depending on the size of the artwork.  This reduces waste of the material, and since it is automatic it makes work faster for the other artists.  I'll be posting snippets shortly.

                                            • 21. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                              Zantcor Level 1

                                              The below image shows the 4 different die sizes, the artwork fits inside the dotted box so make sure that we have room around the die and the drill holes are assigned as well.

                                               

                                              DEBOSS DIE SIZES.jpg

                                              The name of each die is listed above it, and the size is listed below it.

                                               

                                              The script is set to take each die and place it on the template until it is full, then it will save it and move it to the folder where it will be grabbed and preped for printing.

                                               

                                              Everything below the **** is the script.

                                               

                                              ****************************************************************************************** *************************************************************************

                                               

                                              #target illustrator   

                                                 

                                                  var tempDoc = app.activeDocument;

                                                  copy();

                                                  if (tempDoc.selection.length > 0)

                                                  {

                                                      var myFile = File("S:/TEMPLATES/IN USE/DB_TEMPLATE.ai");

                                                      app.open(myFile);

                                                     

                                                      var thisDoc = app.activeDocument;

                                                          thisDoc.views[0].centerPoint = [324,503];

                                                          thisDoc.views[0].zoom = .65;

                                                      var allGroups;

                                                      var horizontalCords = [0,180,360,540,0,180,360,540,0,180,360,540,0,180,360,540,0,180,360,540,0];

                                                      var verticalCords = [1012.5,1012.5,1012.5,1012.5,810,810,810,810,607.5,607.5,607.5,607.5,405,405,405,405,202. 5,202.5,202.5,202.5,202.5];

                                               

                                                      var oneGroups = new Array();

                                                      var twoGroups = new Array();

                                                      var oneAGroups = new Array();

                                                      var twoAGroups = new Array();

                                                      var makeNew1 = new Array();

                                                      var makeNew2 = new Array();

                                                      var twoACounter = 0;

                                                      var layerRemainder = [4,4,4,4];

                                                      var totalDies = 0;

                                                      var noGo = 0;

                                                      var caseTest;

                                               

                                                  if (thisDoc.pageItems.length == 0)

                                                      drawTemplate();

                                                     

                                                  var newLayer = thisDoc.layers.add();

                                                  newLayer.name = "Die Layer";

                                                 

                                                  paste();

                                                

                                              allGroups = thisDoc.groupItems;

                                               

                                                  for (i=0;i<allGroups.length;i++){// determine what dies are present

                                                      if (allGroups[i].name == "1"){

                                                          oneGroups.push(allGroups[i]);

                                                          }

                                                      else

                                                  if (allGroups[i].name == "1A"){

                                                          oneAGroups.push(allGroups[i]);

                                                          }

                                                  if (allGroups[i].name == "2") {

                                                      twoGroups.push(allGroups[i]);

                                                      }

                                                  else

                                                  if (allGroups[i].name == "2A"){

                                                      twoAGroups.push(allGroups[i]);

                                                      }

                                                  }// end FOR

                                               

                                              if (oneAGroups.length == 1)

                                                  oneAGroups[0].position = [540,101.5];   

                                              if (twoAGroups.length == 1)

                                                  twoAGroups[0].position = [360.25,101.25];

                                              if (oneAGroups.length == 1 && twoAGroups.length == 1)

                                                  oneAGroups[0].position = [360,203.5];   

                                                     

                                                 

                                               

                                                  if(oneAGroups.length == 2){

                                                  var add1Group = thisDoc.groupItems.add();

                                                      add1Group.name = "1";

                                                      oneAGroups[0].name = "1A changed";

                                                      oneAGroups[1].name = "1A changed";

                                                      oneAGroups[0].position = [0,0];

                                                      oneAGroups[1].position = [0,-100.75];

                                                      oneAGroups[0].moveToBeginning(add1Group);

                                                      oneAGroups[1].moveToBeginning(add1Group);       

                                                      oneGroups.push(add1Group);

                                                      oneAGroups.length = 0;

                                                      redraw();

                                                      }

                                               

                                                  if(twoAGroups.length == 2){

                                                   

                                                  var add2Group = thisDoc.groupItems.add();

                                                      add2Group.name = "2";

                                                      twoAGroups[0].name = "2A changed";

                                                      twoAGroups[1].name = "2A changed";

                                                      twoAGroups[0].position = [0,0];

                                                      twoAGroups[1].position = [0,-100.75];

                                                      twoAGroups[0].moveToBeginning(add2Group);

                                                      twoAGroups[1].moveToBeginning(add2Group);

                                                      twoGroups.push(add2Group);

                                                      twoAGroups.length = 0;

                                                      redraw();

                                                      }

                                               

                                               

                                                  

                                                  if (twoGroups.length > 0){

                                                          var h = 0;

                                                          var v = 0;

                                                          var dieCount = 0;

                                                          for (i = 0; i < twoGroups.length; i++) {

                                                              twoGroups[i].position = [horizontalCords[h],verticalCords[v]];

                                                              h = h + 2;

                                                              v = v + 2;

                                                              dieCount++

                                                              }//end FOR

                                                      }// end twoGroups length IF

                                                     

                                                     

                                                     

                                                      if (oneGroups.length > 0){

                                                      var h = 0+(twoGroups.length*2);

                                                      var v = 0 + (twoGroups.length*2);

                                                       for (i = 0; i < oneGroups.length; i++){

                                                         oneGroups[i].position = [horizontalCords[h],verticalCords[v]];

                                                            h = h +1;

                                                              v = v + 1;

                                                           }//  end FOR

                                                       }//  end onGroups IF

                                                     

                                                        redraw();//  redraws template so it updates changes on the page

                                                     //thisDoc.close(SaveOptions.SAVECHANGES);

                                                      }//  end noGo

                                               

                                              else

                                              alert("You have nothing selected...");

                                               

                                                  totalDies = (oneGroups.length + (twoGroups.length*2) + (twoAGroups.length/2) + (oneAGroups.length/2));

                                              if (totalDies < 20)

                                                  {

                                                  caseTest = 0

                                              }

                                                  else if (totalDies > 20)

                                                  caseTest = 1

                                                  else if (totalDies == 20)

                                                  caseTest = 2;

                                               

                                               

                                              switch (caseTest)

                                              {

                                                      case 0:

                                                          thisDoc.close(SaveOptions.SAVECHANGES);

                                                          break;

                                                      case 1:

                                                          alert ("Die will not fit on the Template at this time.  Try again later.");

                                                          thisDoc.close(SaveOptions.DONOTSAVECHANGES);

                                                          break;

                                                      case 2:

                                                              var answer = confirm ("The Template is full.  Do you want to clear it?");

                                                                  if (answer == true)

                                                                      printTheTemplate();

                                                                      break;

                                              }                       

                                                        

                                               

                                               

                                               

                                              function drawTemplate(){  //draws the template if the page is empty

                                                      var tempDoc = app.activeDocument;

                                                 

                                                  tempDoc.rulerOrigin = [0,0];

                                                  tempDoc.pageOrigin = [0,0];

                                                 

                                                  var newLayer = tempDoc.layers.add();

                                                  newLayer.name = "Template Layer";

                                                  var templateGroup = tempDoc.groupItems.add();

                                                  templateGroup.name = "Template Build";

                                               

                                                  var vertLoc = .25;

                                                  var horzLoc = -.25;

                                                  var topTemp = new Array();

                                                  var botTemp = new Array();

                                                  var leftTemp = new Array();

                                                  var rightTemp = new Array();

                                               

                                                  for (i=0;i<5;i++){

                                                      botTemp[i] = thisDoc.pathItems.rectangle(0,vertLoc,.5,21);

                                                      topTemp[i] = thisDoc.pathItems.rectangle(1033,vertLoc,.5,21);

                                                       botTemp[i].moveToBeginning(templateGroup);

                                                       topTemp[i].moveToBeginning(templateGroup);

                                                      vertLoc = vertLoc + 180;

                                                      }

                                               

                                                  for (j=0; j<6;j++){

                                                      leftTemp[j] = thisDoc.pathItems.rectangle(horzLoc,-21,21,.5);

                                                      rightTemp[j] = thisDoc.pathItems.rectangle(horzLoc,720,21,.5);

                                                       leftTemp[j].moveToBeginning(templateGroup);

                                                       rightTemp[j].moveToBeginning(templateGroup);

                                                      horzLoc = horzLoc +202.5;

                                                      }

                                                 

                                              return

                                              }//  end function drawTemplate

                                               

                                               

                                               

                                               

                                              function printTheTemplate()

                                              {

                                                        // October 16, 2012  Henry J. Klementovich

                                                      //var TemplatePath = File("C:/Users/henryk/Desktop/Illustrator Test Files/HS_TEMPLATE.ai");

                                                      //open(TemplatePath)

                                                      //open(myFile);

                                                      var thisDoc = app.activeDocument;

                                                          thisDoc.rulerOrigin = [0,0];

                                                          thisDoc.pageOrigin = [0,0]; 

                                                      var thePath = ("S:/TEMPLATES/PRINTED");

                                               

                                                      //  Will only continue if the artist has selected the art.  This step saved a lengthy FOR loop that would have had to select each page or path item of the

                                                      //  document.  Some of the templates had over 5,000 items, resulting in an un-exceptable wait-time for the loop to select them.

                                               

                                                      for (x=0;x<thisDoc.groupItems.length;x++)

                                                          thisDoc.groupItems[x].selected = true;

                                               

                                               

                                                      if (thisDoc.selection.length > 0)

                                                      {

                                               

                                                      //  This section pulls the date from the system for two purposes:  the date shown on the template and the date used to save the file to the ArtShare.

                                                      //  They are different b/c system filenames cannot include the  ":" char, which is used on the template for the time object.

                                                      var  theDate = new Date();

                                                              var day = theDate.getDate();

                                                              var month = theDate.getMonth() + 1;

                                                              var year = theDate.getFullYear();

                                                              var hours = theDate.getHours();

                                                              var min = theDate.getMinutes();

                                                                  if (min < 10)

                                                                      min = ("0" + min);

                                                              var morn;

                                                                  if (hours >= 12)

                                                                      {

                                                                          hours = hours - 12;

                                                                          morn = " PM";

                                                                      }

                                                                  else

                                                                      morn = " AM"

                                                      var saveDate = (month + "-" + day + "-" + year + "    " + hours + min + morn );

                                                             

                                                      var tempDate = thisDoc.textFrames.add();

                                                              tempDate.name = theDate;

                                                              tempDate.contents = (month+ "/" + day + "/ " + year + "    " + hours + ":" + min );

                                                              tempDate.top = 1026;

                                                              tempDate.left =40;

                                                              tempDate.filled = true;

                                               

                                                      var actGroups = thisDoc.selection;

                                               

                                                      var artGroup = thisDoc.groupItems.add();

                                                            artGroup.name = "Art Group";

                                                           

                                                      for (i=0;i<actGroups.length;i++)

                                                            actGroups[i].moveToEnd(artGroup);

                                               

                                                      tempDate.moveToEnd(artGroup);

                                                      artGroup.selected = true;

                                                      copy();

                                                      thisDoc.pageItems.removeAll();//  copies everything from the current template into the clipboard, clears the template, saves it and closes it.

                                                         

                                                      var layLen = app.activeDocument.layers.length;

                                                      //alert(layLen);

                                               

                                                      for (i=0;i<layLen;i++)

                                                      app.activeDocument.layers[0].remove();

                                                     

                                                      thisDoc.close(SaveOptions.SAVECHANGES);

                                               

                                                      app.documents.add();//  adds new document for the template to be saved in the Printed folder.

                                                      paste();

                                               

                                                      var thisDoc = app.activeDocument;  

                                                      var saveName = new File (thePath + "/" + saveDate);

                                                            saveOpts = new IllustratorSaveOptions();

                                                            saveOpts.compatibility = Compatibility.ILLUSTRATOR13;

                                                            saveOpts.generateThumbnails = true;

                                                            saveOpts.preserveEditability = true;

                                                            thisDoc.saveAs( saveName, saveOpts );

                                                                    

                                                      var actGroups = thisDoc.selection;

                                                      copy();

                                                      thisDoc.close(SaveOptions.SAVECHANGES);

                                               

                                                      $.sleep(10);

                                                      app.documents.add();

                                               

                                                      paste();

                                                      var nexDoc = app.activeDocument; 

                                                      var actGroups = nexDoc.selection;

                                                      var artGroup =nexDoc.groupItems.add();

                                                            artGroup.name = "Art Group";

                                                           

                                                      for (i=0;i<actGroups.length;i++)

                                                              actGroups[i].moveToEnd(artGroup);

                                                              //artGroup.selected = true;

                                                              artGroup.resize(70,70);

                                                              alert("The current template has been saved to the Printed Templates folder.  This page is to be printed and sent to editing.")

                                                  } 

                                              }

                                               

                                              ****************************************************************************************** *********************************

                                              Hope this helps someone get one created because if they can make one that doesn't depend on the premade dies that would help me out quite a bit because some of the dies that we make are an odd size so we have to place them manually.

                                              • 22. Re: Is there a script available for arranging elements for optimal use of the printable area?
                                                Zantcor Level 1

                                                This is the image of the finished product, all the ones that are auto placed are colored with an orange box, the ones that must be placed manually are brown.  The colors help people understand which ones need to be moved a lot easier.  I've removed the art files from the boxes as some of them are copyrighted so you can only see the boxes for this file.

                                                 

                                                2-17-2015    759 AM.jpg