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

Grouping only specific paths using a Script.

Engaged ,
May 15, 2023 May 15, 2023

I have a script that looks at the active selection.  Always an outlined letter with dots inside.  It then checks to see if there are two paths that are on the exact same Y axis.  If it finds any paths it creates groups of two path items.   I'm having two issues I could use help with.
1. I'm getting an error - Error 1302: No Such Element 

2. I'd love to just select the whole layout and have it loop through each outlined character.

The dots are always black, but to illustrate which dots would get grouped I colored them in the example file.

Thank you!

 

if (app.documents.length > 0) {
  if (app.activeDocument.selection.length > 0) {
    // group items by vertical separation (line)
    var groups = groupObjectsByLine(app.activeDocument.selection);
    if (groups) {
      var paths;
      // iterate over each group of objects
      for (var i = 0; i < groups.length; i++) {
        paths = [];
        // capture all pageItems within the group
        // so that a standard array can be passed to adjustOffset
        for (var j = 0; j < groups[i].pageItems.length; j++) {
          paths.push(groups[i].pageItems[j]);
        }
        // if a group has 2 items already, create a new group
        if (groups[i].pageItems.length === 2) {
          var matchingSize = groups[i].pageItems.every(function(p) {
            return p.width === groups[i].pageItems[0].width && p.height === groups[i].pageItems[0].height;
          });
          if (matchingSize) {
            var g = app.activeDocument.groupItems.add();
            groups.push(g);
            g.pageItems.add(paths[0]);
            g.pageItems.add(paths[1]);
            groups[i].remove();
            i--;
          }
        }
      }
    }
  }
} 

/**
 * Take an array of Adobe Illustrator pageItems and group them by vertical separation.
 * @Param   {Array} sel Adobe Illustrator pageItems
 * @Returns {Array}     Array of Adobe Illustrator groupItems
 */

function groupObjectsByLine(sel) {
  var groups = [];
  // sort the selected page items by their position (left to right, top to bottom)
  sel.sort(function (a, b) {
    if (a.top === b.top) {
      return a.left - b.left;
    } else {
      return a.top - b.top;
    }
  });
  // check if each page item shares bounds with others
  var item, placed;
  while (sel.length > 0) {
    item = sel.pop();
    placed = false;
    for (var i = 0; i < groups.length; i++) {
      var group = groups[i];
      if (overlappingBounds(item, group)) {
        item.move(group, ElementPlacement.PLACEATEND);
        placed = true;
        group.pageItems.add(item);
        break;
      }
    }
    // if an item didn't fit into any current groups make a new group
    if (!placed) {
      var g = app.activeDocument.groupItems.add();
            groups.push(g);
            item.move(g, ElementPlacement.PLACEATEND);
    }
  }
  return groups;
}

/**
 * Check if a pageItems bounds overlaps with a groupItem.
 * @Param {pageItem}  item  Adobe Illustrator pageItem
 * @Param {groupItem} group Adobe Illustrator groupItem
 * @Returns {Boolean}
 */
function overlappingBounds(item, group) {
  var top = item.geometricBounds[1];
  var bottom = item.geometricBounds[3];
  var gTop = group.geometricBounds[1];
  var gBottom = group.geometricBounds[3];
  if (gTop !== top) {
    return false;
  }
  return true;
}

 

 

TOPICS
Scripting
385
Translate
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
Adobe
Community Expert ,
May 15, 2023 May 15, 2023
LATEST

So, the reason for the "No Such Element" error is that line 64 `group.pageItems.add(item)` shouldn't be there. The item was already added to the group 2 lines before that `item.move(group, ElementPlacement.PLACEATEND)` and the `add()` method is not for moving paths into groups, it is for adding a new path into the group. There's a cleaner version of the function you are using below.

 

As a side note, since the function was originally designed to group all of your text characters so it will need some help to work for this application if you just want to select everything. You have a few options, if you only want the dots/studs grouped by line, then you could just ignore any paths with large areas (characters), or if the characters are always outlined like in the example file, you can ignore paths that have a stroke.

 

/*
GroupObjectsByRow.jsx for Adobe Illustrator
-------------------------------------------

Take a selection of objects that are separated by a unknown
vertical gap and group all that vertically overlap.

Note: This script was designed to group text characters but
works just fine for most types of pageItems.
*/

(function () {
  var doc = app.activeDocument;
  groups = groupObjectsByRow(doc.selection);
  if (groups) {
    alert("Groups Created:\n" + groups.length);
  }

  /**
   * Take an array of Adobe Illustrator pageItems and group them by vertical separation.
   * @Param   {Array} sel Adobe Illustrator pageItems
   * @Returns {Array}     Array of Adobe Illustrator groupItems
   */
  function groupObjectsByRow(sel) {
    var groups = [];
    // sort the selected page items by their height (tallest to shortest)
    sel.sort(function (a, b) {
      var aHeight = a.geometricBounds[3] - a.geometricBounds[1];
      var bHeight = b.geometricBounds[3] - b.geometricBounds[1];
      return bHeight - aHeight;
    });
    // check if each page item shares bounds with others
    var item, placed;
    while (sel.length > 0) {
      item = sel.pop();
      placed = false;
      for (var i = 0; i < groups.length; i++) {
        group = groups[i];
        // check if item bounds overlaps a groups bounds
        if (
          item.geometricBounds[3] <= group.geometricBounds[1] &&
          item.geometricBounds[1] >= group.geometricBounds[3]
        ) {
          item.move(group, ElementPlacement.PLACEATEND);
          placed = true;
        }
      }
      // if an item didn't fit into any current groups make a new group
      if (!placed) {
        g = app.activeDocument.groupItems.add();
        groups.push(g);
        item.move(g, ElementPlacement.PLACEATEND);
      }
    }
    return groups;
  }
})();

 

Translate
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