Copy link to clipboard
Copied
Quick solution for this particular use-case, no charge. (DM me if you need something more sophisticated.)
(function() {
var items = app.activeDocument.activeLayer.pageItems
var clippingGroups = []
var otherItems = []
// find all of the clipping groups in this layer
for (var i = 0; i < items.length; i++) {
var item = items[i]
if (item.typename === "GroupItem" && item.pageItems[0].clipping) {
clippingGroups.push(item)
} else {
otherItems.push(item)
}
}
// now move all items that
...
Copy link to clipboard
Copied
Can you share the script or provide a link to it? It probably evaluates the bounding box coordinates of each object and groups accordingly.
This script does something very similar: It evaluates the left-most position of each item (symbolItem in this case) relative to the Artboard and groups items that share the same coordinate range. The number of columns is set when the function is called (we use Keyboard Maestro for this, but it could also be written into the function).
groupDNA_Columns(12);
function groupDNA_Columns(columns) {
//Groups symbol instances on current layer based on x coordinate.
var aDoc = app.activeDocument;
app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
var abWidth = aDoc.artboards[0].artboardRect[2];
var columnPos = abWidth / columns; //divide artboard width by number of columns
var iii = columnPos; //changes for each column
var i; //counter
var g;
var c = 0;
var b;
var j = 0;
var ii = 0;
//Group columns
while (c <= columns) {
c++;
for (i = 0; i < aDoc.symbolItems.length; i++) {
if (aDoc.symbolItems[i].position[0] < iii) {//If current symbol item left coordinate is less than column position
aDoc.symbolItems[i].selected = true;//Add to selection
}
}
ii = aDoc.groupItems.length;
app.executeMenuCommand('group');
b = aDoc.groupItems.length;
if (ii > 1 && ii != columns && ii == b) {
j = 1;
}
app.executeMenuCommand('deselectall');
iii = iii + columnPos;
}
aDoc.selection = null;
return (j);
}
Copy link to clipboard
Copied
Are you talking about a script that already exists, or are you looking for someone to write you one?
Copy link to clipboard
Copied
groupOverlappingObjects by John Wundes:
/////////////////////////////////////////////////////////////////
//Group Overlapping (Beta) -- CS, CS2, CS3
//>=--------------------------------------
//
// Groups all overlapping objects in selection into discreet groups.
// The definition for 'overlaping' is based on objects bounding boxes, not their actual geometry.
// Each new groups zOrder is determined by the depth of the front-most object in each group.
// There is no limit to the number of groups created.
// Any non-overlapping objects are ignored.
//
// Note: Currently, this is not very efficient code. It works well on small groups (less than 120 objects)
// and works faster on smaller groupings. Running this on a huge number of objects will likely crash illustrator.
// It serves my purposes, but test it's limits on your machine, and use at your own risk.
// On a 2.53GHz P4, a group of 100 objects took 20 seconds with 2 groups.
//
//
//>=--------------------------------------
// JS code (c) copyright: John Wundes ( john@wundes.com ) www.wundes.com
//copyright full text here: http://www.wundes.com/js4ai/copyright.txt
//////////////////////////////////////////////////////////////////
//this little section is just for testing
//the number of times each function is called.
var testmode = 0;
var t1=t2=t3=t4=t5=t6=t7=0;
var testmsg="";
//
//
//
var go=true;
if(selection.length>120){
go = confirm("You have selected "+selection.length+" objects. It is highly recommended that you select less than 120 objects at a time. Do you want to continue anyway?");
}
if(selection.length>1 && go == true){
var groups=0;
var slen = selection.length;
var hitList= new Array(slen);
var groupArr = new Array(slen);
// for each element in selection
for (var sx=0;sx<slen;sx++){
//t6++; //---------------------------------------------loop tracker
var tArr = new Array(0);
// for each element in selection (again)
for (var si=0;si<slen;si++){
//t7++; //-------------------------------------loop tracker
groupArr[sx] = tArr;
//note each object hits itself once.
if(hitTest(selection[sx],selection[si])){
groupArr[sx].push(selection[si]);
}
}
}
minimize(groupArr);
var zError = 0;
var gaLen = groupArr.length;
for(var each=0;each<gaLen;each++){
if(groupArr[each].length>1){
groupArr[each].sort(sortBy_zOrder);
}
if(zError==1){
alert("cannot read some objects zOrderPosition");
}
//alert("halftime");
for(var each =0;each<gaLen;each++){
t1++; //----------------------------------------------loop tracker
if(groupArr[each].length>1){
groups++;
groupAll(groupArr[each]);
}
}
//
//---all done with main code, now display statistics if you care...
//
testmsg="\nObjects processed: "+t1+"\nObjects grouped: "+t2+"\nObjects ignored: "+(t1-t2);
if(testmode==1){
testmsg+="\n\n---testmode data---\nhits compared: "+t5+"\nfunction 'minimize' called: "+t3+
"\nitems tested within 'minimize': "+t4;
"\nelements: "+t6+
"\nelements*elements: "+t7;
}
var x=0;
while(x<selection.length){
if(selection[x].name == "wundes_GO_group"){
selection[x].name = "";
}else{
selection[x].selected = false;
x--;
}
x++;
}
redraw();
alert(groups+" groups created.\n----------------"+testmsg);
}
}
//----------------------------------------------------------->
//--------------------------------functions------------------<
//----------------------------------------------------------->
function sortBy_zOrder(a, b) {
if(a.zOrderPosition==undefined){
alert(a.zOrderPosition);
zError = 1;
return 0;
}
var x = Number(a.zOrderPosition);
var y = Number(b.zOrderPosition);
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
function groupAll(arr){
var tempGroup = arr[0].parent.groupItems.add();
tempGroup.move(arr[0],ElementPlacement.PLACEBEFORE);
var max = arr.length;
for(var i=max-1;i>=0;i--){
t2++; //-----------------------------------------loop tracker
arr[i].move(tempGroup,ElementPlacement.INSIDE);
}
//name the object for selection at end... (will be removed later)
tempGroup.name = "wundes_GO_group";
tempGroup.selected = true;
}
//---------------hitTest functions ---------------
function hitTest(a,b){
var OK=0;
if(isWithinX(a,b) || isWithinX(b,a)){
OK++;
}
if(isWithinY(a,b) || isWithinY(b,a)){
OK++;
}
if (OK<2){
//alert("miss.");
return false;
}else{
//alert("Hit!")
return true;
}
}
function isWithinX(a,b){
var p1 = a.geometricBounds[0];
var p2 = b.geometricBounds[0];
if(p2<=p1 && p1<=p2+b.width){
return true;
}else{
return false;
}
}
function isWithinY(a,b){
var p3 = a.geometricBounds[1];
var p4 = b.geometricBounds[1];
if(p3>=p4 && p4>=(p3-a.height)){
return true;
}
return false;
}
/*
//-----------------------------------OK, finding groups is done, now do the grouping---------------
*/
function itemize(a){
var out="";
return(a.join("\n"));
}
function minimize(arr){
for(var e in arr){
t3++; //-----------------------------------------loop tracker
for (ot in arr){
t4++; //-------------------------------------loop tracker
if(arr[e]!=arr[ot]){
//if it's not THIS element,
//test for overlaps
if(overlaps(arr[e],arr[ot])){
merge(arr[e],arr[ot]);
arr[e] = new Array(0);
minimize(arr);
break;
}
}
}
}
}
function merge(a,b){
var alen = a.length;
for (var all=0;all<alen;all++){
if(contains(b,a[all])){
//do nothing
}else{
b.push(a[all]);
}
}
}
function contains(ar,i){
for (var all in ar){
if (ar[all] == i){
return true;
}
}
return false;
}
function overlaps(ar1,ar2){
for (var each in ar1){
t5++; //------------------------------------loop tracker
if(contains(ar2,ar1[each])){//
return true;
}
}
return false;
}
Copy link to clipboard
Copied
Hello femkeblanco, can you modify the script to support clipping mask object grouping? Thank you very much
Copy link to clipboard
Copied
I will make no promises, but if you upload a CS6-compatible version of your AI document, I will have a look.
Copy link to clipboard
Copied
Hello femkeblanco,This is an AI file. Please take a look. Thank you for your help
https://drive.google.com/file/d/1X9weP_Blz2MKpxZyPIt-tff3Kx4QDYFV/view?usp=sharing
Copy link to clipboard
Copied
Quick solution for this particular use-case, no charge. (DM me if you need something more sophisticated.)
(function() {
var items = app.activeDocument.activeLayer.pageItems
var clippingGroups = []
var otherItems = []
// find all of the clipping groups in this layer
for (var i = 0; i < items.length; i++) {
var item = items[i]
if (item.typename === "GroupItem" && item.pageItems[0].clipping) {
clippingGroups.push(item)
} else {
otherItems.push(item)
}
}
// now move all items that overlap a clipping group into that group
// this assumes page items always appear in stacking order, and preserves that order
// only items that lie fully within a clipping group’s rectangular bounds are moved into that group
// caution: any items hidden under a clipping group will be moved into that group, making them visible
// (we could compare zOrderPosition to skip them but that property is buggy)
for (var i = otherItems.length - 1; i >= 0; i--) {
var item = otherItems[i]
var bounds = item.geometricBounds
var il = bounds[0], it = bounds[1], ir = bounds[2], ib = bounds[3]
for (var j = 0; j < clippingGroups.length; j++) {
var group = clippingGroups[j]
var bounds = group.geometricBounds
var cl = bounds[0], ct = bounds[1], cr = bounds[2], cb = bounds[3]
if (il >= cl && ir <= cr && ib >= cb && it <= ct) {
item.move(group.pageItems[0], ElementPlacement.PLACEAFTER)
break
}
}
}
})()
Copy link to clipboard
Copied
hhas01's solution works nicely. So I think the job is done.
Copy link to clipboard
Copied
Thank you
Copy link to clipboard
Copied
thank you very much