• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Script. Insert text number in the middle of visible bounds of the each object

Explorer ,
Feb 14, 2016 Feb 14, 2016

Copy link to clipboard

Copied

Hello! Adobe Illustrator CS 6

I have script, wich groups filled paths by colors. Link to script and traced image. Traced_image.rar - Google Drive

I have traced image, it has 25 colors. The script creates 25 groups, paths of each color in each group.

I need to modify script, i want to insert text number in visible middle of the each filled path. So one group is one number. From 1 to 25.

Can anyone help me?

TOPICS
Scripting

Views

10.4K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Enthusiast , May 15, 2016 May 15, 2016

Hello all, here comes the final version.

This time "offset path effect" been used. I thought this is a possible way at beginning, but never give it a try, until today.

It deal with both Path and Compound Path. Test the sample document, it only took 31 seconds.

cap.PNG

Votes

Translate

Translate
Adobe
Guide ,
Feb 14, 2016 Feb 14, 2016

Copy link to clipboard

Copied

take a look at this thread.

Re: How do I copy the path name from the layers panel to the center of the path/object in my AI file...

it's not a simple task to get the gravitational center of an irregular object.

I'm sure its possible with some wiz bang algorithm.

but I am not going to try to tackle that with my math skills

if you need a hand modifying  it for your needs let me know.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 14, 2016 Feb 14, 2016

Copy link to clipboard

Copied

Thank you, but my skill is not enouth to modify and compute your script with this one. Can you take a look on algoritm? The problem is that script generating sub and sub layers, so your script can work with 1 level layers only.

many-levels.jpg

Look please on script:

#target illustrator

if (app.documents.length > 0)

{

if (app.activeDocument.pageItems.length > 0)

{

var release_to_layers_window; // make window global

var doc = app.activeDocument;

var doc_artboard = doc.artboards[0].artboardRect;

var unlocked_layers_count = 0; // number of unlocked layers in layer palette for progress bar

var msis_message_1 = "\nThis script will place each object within this current document into a new layer based on it's fill color. "+

                     "As the script currently does not detect locked layers and locked objects you need to unlock your layers and objects before you can run this script. " +

                     "Note that running this script will modify your document. You might want to save your document first.";

var doc = app.activeDocument;

var Counter = app.activeDocument.pageItems.length;

var LayerName = "";

var ReleaseMethod = 1;

// start dialog window

   release_to_layers_dialog();

}

// what if no document of no objects?

if (app.documents.length < 1)

{alert("No open documents found. Please open a document before you run this script");}

if (app.documents.length > 0 && app.activeDocument.pathItems.length < 1)

{alert("No objects found in this documents. Please add some objects before you run this script");}

}

// ********************************************************************************************************

// **                                                                                                    **

// ** find the most common value in an array                                                             **

// **                                                                                                    **

// ** http://www.experts-exchange.com/Programming/Languages/Scripting/JavaScript/Q_20871554.html         **

// ** var myArray = ["apple","banana","orange","banana","tomato","grape","apple"];                       **

// ** alert( GetMostCommonColor(myArray) );                                                                              **

// **                                                                                                    **

// ********************************************************************************************************

function GetMostCommonColor(theArray)

  {

  var tempArray = new Array();

  tempArray.length = 0;

  tempArray = theArray.slice(0,theArray.length);

  tempArray.sort();

  tempArray[tempArray.length] = "";

  mVal = aVal = "";

  mCnt = aCnt = 0;

  for(r=0;r<tempArray.length;r++)

    {

    if(aVal!=tempArray)

      {

      if(aCnt>mCnt)

    {

        mCnt = aCnt;

        mVal = aVal

       }

      aVal = tempArray;

      aCnt = 1;

    } else

  {

      aCnt++;

    }

  }

  // return [mVal, mCnt]; // returns value and count

  return mVal; // only returns value

}

// ********************************************************************************************************

// **                                                                                                    **

// ** create a layer name for the current object                                                         **

// **                                                                                                    **

// ********************************************************************************************************

function ConstructLayerNameBasedOnFillColor(myCurrentObject)

{

  var myLayerName = "Unknown";

  if (myCurrentObject.typename == "TextFrame") { myLayerName = "Text Objects"; }

  if (myCurrentObject.typename == "SymbolItem") { myLayerName = "Symbols"; }

  if (myCurrentObject.typename == "RasterItem") { myLayerName = "Raster Objects"; }

  if (myCurrentObject.typename == "PathItem")

     {

      if ( myCurrentObject.filled == true )

      {

       myLayerName = 'Object with unknown Fill Color'; // default name for if no color can be detected

       if (myCurrentObject.fillColor == "[CMYKColor]")  // CMYK color Item

             {

              myLayerName = "CMYK: " + Math.round(myCurrentObject.fillColor.cyan) + "," + Math.round(myCurrentObject.fillColor.magenta)  + "," + Math.round(myCurrentObject.fillColor.yellow) + "," + Math.round(myCurrentObject.fillColor.black);

             }

         if (myCurrentObject.fillColor == "[RGBColor]") // RGB color Item

             {

              myLayerName = "RGB: " + Math.round(myCurrentObject.fillColor.red) + "," + Math.round(myCurrentObject.fillColor.green)  + "," + Math.round(myCurrentObject.fillColor.blue);

             }

         if (myCurrentObject.fillColor == "[GrayColor]") // Gray color Item

             {

              myLayerName = "Gray: " + Math.round(myCurrentObject.fillColor.gray);

             }

         if (myCurrentObject.fillColor == "[LabColor]") // LabColor color Item

             {

              myLayerName = "Lab: " + Math.round(myCurrentObject.fillColor.a) + "," + Math.round(myCurrentObject.fillColor.b)  + "," + Math.round(myCurrentObject.fillColor.i);

             }

         if (myCurrentObject.fillColor == "[GradientColor]") // Gradient color Item

             {

              myLayerName = "Gradient Fill";

             }

         if (myCurrentObject.fillColor == "[NoColor]") // No Color Item

             {

              myLayerName = "No Color";

             }

         if (myCurrentObject.fillColor == "[PatternColor]") // Pattern Color Item

             {

              myLayerName = "Pattern Fill";

             }

         if (myCurrentObject.fillColor == "[SpotColor]") // Spot Color Item

             {

   // cmyk spot

           if (myCurrentObject.fillColor.spot.spotKind == SpotColorKind.SPOTCMYK)  // CMYK color Item

                 {

   myLayerName = "Spot CMYK: " + Math.round(myCurrentObject.fillColor.spot.color.cyan) + "," + Math.round(myCurrentObject.fillColor.spot.color.magenta)  + "," + Math.round(myCurrentObject.fillColor.spot.color.yellow) + "," + Math.round(myCurrentObject.fillColor.spot.color.black);

                 }

   // rgb spot

           if (myCurrentObject.fillColor.spot.spotKind == SpotColorKind.SPOTRGB)  // RGB color Item

                 {

                  myLayerName = "Spot RGB: " + Math.round(myCurrentObject.fillColor.spot.color.red) + "," + Math.round(myCurrentObject.fillColor.spot.color.green)  + "," + Math.round(myCurrentObject.fillColor.spot.color.blue);

                 }

   // lab spot

           if (myCurrentObject.fillColor.spot.spotKind == SpotColorKind.SPOTLAB)  // RGB color Item

                 {

                  myLayerName = "Spot Lab: " + Math.round(myCurrentObject.fillColor.spot.color.a) + "," + Math.round(myCurrentObject.fillColor.spot.color.b)  + "," + Math.round(myCurrentObject.fillColor.spot.color.i);

                 }

             } 

         }

     else

      {

       myLayerName = "Transparant Fill";

      }

     }

  if (myLayerName == undefined) {myLayerName = "Temporary Layer";}

  if (myLayerName == "") {myLayerName = "Temporary Layer";}

  if (myLayerName.length==0) {myLayerName = "Temporary Layer";}

     try

     {

             doc.layers.getByName(myLayerName);

            }

    catch (e)

         {

             doc.layers.add().name = myLayerName;

            }

  return myLayerName;

}

// ********************************************************************************************************

// **                                                                                                    **

// ** ungroup objects on current layer                                                                   **

// **                                                                                                    **

// ********************************************************************************************************

function Ungroup(WhereToUngroup, aGroup) // where to ungroup? layer, document, other group?

     {

    try

         {

       for (s=aGroup.pageItems.length-1; s>=0; s--)

       {

              WhereToUngroup = CreateLayerNameFill(myCurrentObject); // ????????? should be something like WhereToUngroup = CreateLayerNameFill(=aGroup.pageItems); // ???????????????????????????

   aGroup.pageItems.move(WhereToUngroup, ElementPlacement.PLACEATBEGINNING);

   }

  }

  catch(err)

  {

         }

     }

// ********************************************************************************************************

// **                                                                                                    **

// ** remove layerswith no objects                                                                   **

// **                                                                                                    **

// ********************************************************************************************************

function  RemoveEmptyLayers()

{

   var ThisDoc = app.activeDocument;

   var ActiveLayer = '';

    for (t = ThisDoc.layers.length-1; t>=0; t--)

      {

     ActiveLayer = ThisDoc.layers;

     if (ActiveLayer.pageItems.length == 0)

  {

   try

     {

      ActiveLayer.remove();

     }

    catch(err)

     {

     }

  }

      }

}

// ********************************************************************************************************

// **                                                                                                    **

// ** building and showing main dialog                                                                   **

// **                                                                                                    **

// ********************************************************************************************************

function release_to_layers_dialog() {

   // Export dialog

    release_to_layers_window = new Window('dialog', 'Release objects to layers based on object fill color');

    // PANEL with usage instructions

    release_to_layers_window.MessagePanel = release_to_layers_window.add('panel', undefined, 'Release Objects to Layers');

    // GROUP

    var Message_Group = release_to_layers_window.MessagePanel.add('group', undefined, '')

    Message_Group.orientation = 'column';

    Message_Group.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]

  // Labels

    var Message_Group_label_1 = Message_Group.add('statictext', undefined,  msis_message_1, {multiline:true});

    Message_Group_label_1.size = [500,80];

  // PANEL with group and compound path handling

  release_to_layers_window.OptionsPanel =  release_to_layers_window.add ('panel', undefined, 'Group and Compound Path Items:');

    // GROUP

  var Radio_Group = release_to_layers_window.OptionsPanel.add('group', undefined, '')

  Radio_Group.alignChildren = "left";

  Radio_Group.size = [500,65];

  Radio_Group.orientation = 'column';

  // Radio Boxes

  var RadioBox1 = Radio_Group.add ("radiobutton", undefined, "Do not process Group and Compound Path Items.");

  var RadioBox2 = Radio_Group.add ("radiobutton", undefined, "Release Groups and Compound Path Items by most common color.");

  var RadioBox3 = Radio_Group.add ("radiobutton", undefined, "Ungroup Group and Compound Path Items (caution: might alter shape appearance).");

  RadioBox2.value = true;

    // PANEL with Progressbar

    release_to_layers_window.ProgressPanel = release_to_layers_window.add('panel', undefined, 'Status:');

    // GROUP

    var Progress_Group = release_to_layers_window.ProgressPanel.add('group', undefined, '')

    Progress_Group.orientation = 'column';

    Progress_Group.alignment = [ScriptUI.Alignment.LEFT, ScriptUI.Alignment.TOP]

  Progress_Group.size = [500,5];

    // progressbar

  release_to_layers_window.ProgressProgressBar = release_to_layers_window.ProgressPanel.add( 'progressbar', undefined, 0, 100 );

    release_to_layers_window.ProgressProgressBar.size = [480,10];

  // label

  release_to_layers_window.ProgressLabel = release_to_layers_window.ProgressPanel.add('statictext', undefined, 'Found ' + Counter + ' objects in this document.' );

  release_to_layers_window.ProgressLabel.size = [ 480,20 ];

    // Buttons don't have a PANEL

    // GROUP

    Button_Group = release_to_layers_window.add('group', undefined, '');

    Button_Group.orientation = 'row'

    Button_Group.cancelBtn = Button_Group.add('button', undefined, 'Cancel', {name:'cancel'});

    Button_Group.cancelBtn.onClick = function() { msis_ai_dlg.close() };

    Button_Group.okBtn = Button_Group.add('button', undefined, 'Release', {name:'ok'});

    Button_Group.okBtn.onClick = function()

              { Button_Group.okBtn.enabled = false;

    Button_Group.cancelBtn.enabled = false;

    RadioBox1.enabled = false;

    RadioBox2.enabled = false;

    RadioBox3.enabled = false;

 

 

    if (RadioBox1.value == true)  {ReleaseMethod = 1;}

    if (RadioBox2.value == true)  {ReleaseMethod = 2;}

    if (RadioBox3.value == true)  {ReleaseMethod = 3;}

    Process_Objects();

  };

    release_to_layers_window.show();

}

//var textRef1 = myCurrentObject.textFrames.add();

//textRef1.contents = "1";

// ********************************************************************************************************

// **                                                                                                    **

// ** execute main routine when clicking the Release button                                            **

// **                                                                                                    **

// ********************************************************************************************************

function Process_Objects()

{

// Release to layers but skip Groups and Compound Paths Items OR move groups and compound paths but keep then as group objects

if (ReleaseMethod == 1 || ReleaseMethod == 2)

    {

     for ( i=0; i < Counter; i++ ) //123

          {

           LayerName = "0";

           try

              {

               CurrentItem = doc.pageItems;

            if (CurrentItem.typename != "GroupItem" && CurrentItem.typename != "CompoundPathItem" && CurrentItem.parent.typename != "GroupItem" && CurrentItem.parent.typename != "CompoundPathItem") // no need to create layers for objects within grouped items

               {

            LayerName = ConstructLayerNameBasedOnFillColor(CurrentItem);

                   CurrentItem.move( app.activeDocument.layers.getByName( LayerName ), ElementPlacement.PLACEATBEGINNING );

           }

              } // try

             catch(err)

              { // except

        alert("An error occured processing objects.\n(" + err + ").\n\nFunction: Process_Objects / method=1.");

              } // except

      release_to_layers_window.ProgressLabel.text = 'Processed ' + i + ' objects out of ' + Counter + ' objects in total.';

           release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * i;

           release_to_layers_window.update();

          }  // for

    } // end method 1

// Release to layers, move Group and Compound Path Items based on most common fill color

if (ReleaseMethod == 2)

    {

  // first move all group objects

  LayerName = "0";

     for ( j=0; j < doc.groupItems.length; j++ )

      {

   var CurrentGroupItem = doc.groupItems;

       var MyArray = new Array;

   var TempLayerName = "";

   for (m = CurrentGroupItem.pageItems.length-1; m>=0; m--)

       {

    TempLayerName = ConstructLayerNameBasedOnFillColor( CurrentGroupItem.pageItems );

    MyArray.push( TempLayerName );

   }

   LayerName = GetMostCommonColor(MyArray);

   CurrentGroupItem.moveToBeginning(app.activeDocument.layers.getByName( LayerName ) );

   release_to_layers_window.ProgressLabel.text = 'Processed ' + j + ' group objects out of ' + Counter + ' objects in total.';

          release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * j;

          release_to_layers_window.update();

         }

  // next move all compound path objects

  LayerName = "0";

     for ( j=0; j < doc.compoundPathItems.length; j++ )

      {

   var CurrentCompoundItem = doc.compoundPathItems;

       var MyArray = new Array;

   var TempLayerName = "";

   for (m = CurrentCompoundItem.pathItems.length-1; m>=0; m--)

       {

    TempLayerName = ConstructLayerNameBasedOnFillColor( CurrentCompoundItem.pathItems );

    MyArray.push( TempLayerName );

   }

   LayerName = GetMostCommonColor(MyArray);

   CurrentCompoundItem.moveToBeginning(app.activeDocument.layers.getByName( LayerName ) );

   release_to_layers_window.ProgressLabel.text = 'Processed ' + j + ' group objects out of ' + Counter + ' objects in total.';

   release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * j;

   release_to_layers_window.update();

         }

  }

// Release to layers and ungroup Group and Compound Path Items

if (ReleaseMethod == 3)

    {

     for ( k=0; k < Counter; k++ ) //123

          {

           LayerName = "0";

           try

              {

               CurrentItem = doc.pageItems;

        LayerName = ConstructLayerNameBasedOnFillColor(CurrentItem);

 

            if (CurrentItem.typename != "GroupItem" && CurrentItem.typename != "CompoundPathItem") // no need to create layers for objects within grouped items

               {

                   CurrentItem.move( app.activeDocument.layers.getByName( LayerName ), ElementPlacement.PLACEATBEGINNING );

                  } // try

  else

               {

    UnGroupLayer = app.activeDocument.layers.getByName( LayerName );

    Ungroup( UnGroupLayer , CurrentItem );

                  }

   }

             catch(err)

              { // except

        alert("An error occured processing objects.\n(" + err + ").\n\nFunction: Process_Objects / method=3.");

              } // except

 

      release_to_layers_window.ProgressLabel.text = 'Processed ' + k + ' objects out of ' + Counter + ' objects in total.';

           release_to_layers_window.ProgressProgressBar.value = (100 / Counter) * k;

           release_to_layers_window.update();

          }  // for

    } // end methode 3

      RemoveEmptyLayers();

      release_to_layers_dialog.close();

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 16, 2016 Feb 16, 2016

Copy link to clipboard

Copied

I'm not sure you will be happy with the outcome of this.

I can tack the 2 scripts together, but the method used for finding the center of an item is clunky and slow.

I am running a test now, and the script has been running for over 10 min already, I'll see how long it takes, if it even finishes...

Did you number the sample file by hand?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 16, 2016 Feb 16, 2016

Copy link to clipboard

Copied

It ran for an hour. before I quit it.
This is not a viable solution for this unless it can be made less clunky.

we could add the numbers for each item via a script.

but they would just be centered to the object, and not gravitationaly centered.

it would then be a manual process to move the numbers to a visually nice location.

I'll have another think about it and let you know if I can work something out...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Feb 17, 2016 Feb 17, 2016

Copy link to clipboard

Copied

you probably could use Jongware's circle-fill algorithms to at least get some bearing on the fill 'density' and then work an approximate placement for the center of the irregular path?

Unless this is what you're already trying out.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 17, 2016 Feb 17, 2016

Copy link to clipboard

Copied

this could be a good idea silly,
I still worry about how long this will take to run it 500 or 1000 times.

I'll have a play. not sure I'll have much luck getting a good understanding of that code to be able to trim it down.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Feb 17, 2016 Feb 17, 2016

Copy link to clipboard

Copied

Yes, my own math skills are less than what's needed to understand the circle-fill algorithm. But, with that algorithm alone, it is a gateway to do many 2-D manipulation techniques!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 18, 2016 Feb 18, 2016

Copy link to clipboard

Copied

I think I have a better way of doing this.
involving adding strokes and expanding...

I won't go in to the details now, but should be WAY more efficient then creating and destroying an action many times per object...

not as fast as pure math would be but better.

I'll post back when I have a working example

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 18, 2016 Feb 18, 2016

Copy link to clipboard

Copied

I found a function to find shape centroids

var idoc = app.activeDocument;

var ipath = idoc.selection[0];

var pps = ipath.pathPoints;

var pts = [];

for (var a=0; a<pps.length; a++) {

    var pp = pps.anchor;

    pts.push({x:pp[0], y:pp[1]});

}

      

//$.writeln(pts.toSource());

var c = get_polygon_centroid (pts);

//$.writeln(c.toSource());

var pt = idoc.pathItems.add();

pt.setEntirePath([[c.x, c.y], [c.x, c.y]]);

pt.stroked = true;

pt.filled = false;

pt.strokeCap = StrokeCap.ROUNDENDCAP;

pt.strokeWidth = 5;

// function by Myobis

// http://stackoverflow.com/questions/9692448/how-can-you-find-the-centroid-of-a-concave-irregular-poly...

function get_polygon_centroid(pts) {

  var first = pts[0], last = pts[pts.length-1];

  if (first.x != last.x || first.y != last.y) pts.push(first);

  var twicearea=0,

  x=0, y=0,

  nPts = pts.length,

  p1, p2, f;

  for ( var i=0, j=nPts-1 ; i<nPts ; j=i++ ) {

      p1 = pts; p2 = pts;

      f = p1.x*p2.y - p2.x*p1.y;

      twicearea += f;        

      x += ( p1.x + p2.x ) * f;

      y += ( p1.y + p2.y ) * f;

  }

  f = twicearea * 3;

  return { x:x/f, y:y/f };

}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 21, 2016 Feb 21, 2016

Copy link to clipboard

Copied

Nice looking script, but not sure its doing the correct thing.

in this image the black dot is produced by this script.

the blue scribble is where I would expect the point to land.

han.JPG

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 21, 2016 Feb 21, 2016

Copy link to clipboard

Copied

here is the working example I came up with.

it runs too slow but is way more reliable then the create action method.

I added a timer so you can see the run time.

on my sample file (12 shapes) it took 5 - 10 seconds to run.

THIS WILL RUN SLOW!!!

m.JPGa.JPG

function add_nums(){

    // fiddle with these values to adjust speed vs accuracy

    var percentage = 1; // take average betwenn hight and width and multiplies it by this to get starting stroke weight - 1 = 100%

    var increment = .8; // amount to add to percentage on each iteration

   

    var doc = app.activeDocument;

    var lays = doc.layers;

    var layNames = [];

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

        layNames.push(lays.name);

    }

    // new layers

    var WORK_LAY = doc.layers.add(); 

    WORK_LAY.name = "Working Layer";

    var NUM_LAY = doc.layers.add(); 

    NUM_LAY.name = "Numbers";

   

    // main working loop

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

        //process each layer

        var lay = lays.getByName(layNames);

        lay.name = lay.name + " Num:" + (i+1);

        for(var j=0; j<lay.pathItems.length; j++){

            // process each pathItem

            var pth = lay.pathItems;

            var per = percentage; // reset the path percentage for each shape

            var cent = [];

            var Count = 0;

            if(FatPart(pth) === "error"){

                alert("Loop Error, try resetting\npercentage to 1,\nand\nincroment to .8\nin the script file");

                return;

            }

             // Create the text frame

            var txt = NUM_LAY.textFrames.add();

            txt.contents = i+1; 

            txt.textRange.justification = Justification.CENTER;

            txt.position = [cent[0]-txt.width/2,cent[1]+txt.height/2];

            pth.filled = false;

            pth.stroked = true;

        }

    }

    //clean up

    WORK_LAY.remove();

    // find fat section of a shape

    function FatPart(pth){

        var success = false;

        while(!success){

            success = process();

            // if recursive function runs too many times give option to exit

            Count++;

             if(Count%100 === 0){

                var keepGoing = confirm("Process function has run " + Count + " times on current object.\nWould you like to continue trying?");

                if(!keepGoing){

                    return "error";

                }

            }

        }

        function process(){

            // make sure we start with nothing selected

            doc.selection = null;

           

            // make a copy of the shape to work on

            var item = pth.duplicate(WORK_LAY,ElementPlacement.PLACEATBEGINNING);

            item.filled = false;

            item.stroked = true;

           

            // scale works out how thick the stroke shold be

            var scale = ((item.height+item.width)/20)*per;

            item.strokeWidth = scale;

           

            // select the items and outline the stroke

            item.selected = true;

            app.executeMenuCommand ('OffsetPath v22');// = Outline Stroke

           

            var sel = doc.selection;

            if(sel[0].typename === "CompoundPathItem"){

                if(sel[0].pathItems.length>2){

                    // too many paths, increase stroke and retry

                    sel[0].remove()

                    per = per + increment;

                    return false;

                 }else{

                    // Remove the larger of the 2 shapes in the compoundPath

                    if(Math.abs(sel[0].pathItems[0].area)>Math.abs(sel[0].pathItems[1].area)){

                        sel[0].pathItems[0].remove();

                    }else{

                        sel[0].pathItems[1].remove();

                    }

                   

                    // compare size against original - Aiming for under 10%

                    if(Math.abs(sel[0].pathItems[0].area)>Math.abs(item.area)/10){ // the 10 is ten percent of original size

                        sel[0].pathItems[0].remove();

                        per = per + increment;

                        return false;

                    }else{

                        // now we should have correct size to center text to

                        // return X,Y of shapes Center

                        var B = sel[0].geometricBounds;

                        cent.push(B[0]+(B[2]-B[0])/2);

                        cent.push(B[1]+(B[3]-B[1])/2);

                        sel[0].remove()

                        return true;

                    }

                }

            }else{

                // shape filled completely, reduced stroke and retry

                sel[0].remove()

                    per = per - increment/10;

                    return false;

            }

        }

   

    }

}

var timer = Date.now();

add_nums();

var x = (Date.now()-timer);

alert('conversion completed in:\n'

        + Math.floor(x/1000/60) + ' Minutes, '

        + Math.floor(x/1000%60) + ' Seconds, and '

        + x%1000 + ' Milliseconds');

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 21, 2016 Feb 21, 2016

Copy link to clipboard

Copied

hi querty, my script finds the centroids, not the fat part like yours.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 21, 2016 Feb 21, 2016

Copy link to clipboard

Copied

it's a nice looking script, I would like to find some time so I can pull it apart so I understand it.

when I first started playing with this idea in a script I wrongly said "better to find gravitational center and not just the center" or something...
the centroid of a 2d object is in essence its center of mass, or gravitational center.

when applying a label to an arbitrary shape my thought is that it is best to be positioned, centered in the fattest part of the object.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 21, 2016 Feb 21, 2016

Copy link to clipboard

Copied

when applying a label to an arbitrary shape my thought is that it is best to be positioned, centered in the fattest part of the object.

and you did very well, brilliant way to find the fattest part.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 21, 2016 Feb 21, 2016

Copy link to clipboard

Copied

but its so slow!

there has to be a better way!

even if its just to tweak the values for a more efficient strokewidth.

but there has to be a nice clean Math based solution.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 26, 2016 Feb 26, 2016

Copy link to clipboard

Copied

Hi Qwertyfly!

Thanks for the work you've done! I tried to run a script on a bigger file, where the objects count are much more than in your example. The script worked for more than 4 hours and produced an error. "Loop Error, try resetting percentage to 1, and incroment to .8 in the script file".

I have a very powerful computer core i7, but a few restarts gave the result a maximum number 1 on one layer and no longer moved. In addition, the script has fulfilled so many cycles, I was even able to correct the code to the confirmation was sought after not 100 cycles, but 10000. In the end, nothing came of it. Perhaps it really is due to the file size, but my files will not be less than 1000 objects.

Please try find out what else you can do to script to work. Even if it will work slow, but correct.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 28, 2016 Feb 28, 2016

Copy link to clipboard

Copied

You should not get that message unless you press no on the dialog that tells you the "Process function has run ... times on current object."

it does not care how many items are in the document.
this count topping out at 100 is how many time it tries to find the center of each shape.

increasing this will probably not fix the issue.

there are a few values which may fix this.

would it be possible for you to send me the file in question?
I would be happy to test it out for you.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 28, 2016 Feb 28, 2016

Copy link to clipboard

Copied

Yes please, u can download 2 files, this is my simplest one example.

The first file is original, second is result that i want to have.

Traced_image.rar - Google Drive

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 29, 2016 Feb 29, 2016

Copy link to clipboard

Copied

even before it hangs up on a shape it does strange things.

the positions are all off.

this is due to the poor job illustrator does of expanding outlines.

This will actually take a bit of time to nut out the best way to get around the odd points illustrator adds.

I'll let you know once I have it working.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Mar 10, 2016 Mar 10, 2016

Copy link to clipboard

Copied

Dear Qwertyfly, if you happen to find the time to view the file, please let me know.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Mar 10, 2016 Mar 10, 2016

Copy link to clipboard

Copied

I viewed the files and was getting the errors you mentioned above.

it seems to be due to the way illustrator produces strange spiked anomalies when expanding outlines.
this involves a rethink as to how to achieve this.
at this point I am unsure as to the best way to make this work.

when I get a chance I will tackle this again. if I come up with anything I will let you know.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Mar 10, 2016 Mar 10, 2016

Copy link to clipboard

Copied

Hey did you already make sure to use "rounded corners" when using a stroke?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Mar 10, 2016 Mar 10, 2016

Copy link to clipboard

Copied

I did not!,

I'm not sure it will make a difference as it's one of those buggy things illustrator does.

But would be worth a try.
I'll give this a go over the next few days.

Thanks again Silly

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Mar 12, 2016 Mar 12, 2016

Copy link to clipboard

Copied

Or set the Miter Limit of the stroke to something low line 1 or 2.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines