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

How does the script group overlapping objects? Thank you

Participant ,
Nov 02, 2020 Nov 02, 2020

Copy link to clipboard

Copied

12.jpg

TOPICS
Scripting

Views

1.6K

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

Engaged , Nov 03, 2020 Nov 03, 2020

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 
...

Votes

Translate

Translate
Adobe
LEGEND ,
Nov 02, 2020 Nov 02, 2020

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);
}

 

 

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
Engaged ,
Nov 02, 2020 Nov 02, 2020

Copy link to clipboard

Copied

Are you talking about a script that already exists, or are you looking for someone to write you one?

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 ,
Nov 02, 2020 Nov 02, 2020

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;
}

 

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
Participant ,
Nov 02, 2020 Nov 02, 2020

Copy link to clipboard

Copied

Hello femkeblanco, can you modify the script to support clipping mask object grouping? Thank you very muchDemo.gif

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 ,
Nov 03, 2020 Nov 03, 2020

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. 

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
Participant ,
Nov 03, 2020 Nov 03, 2020

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

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
Engaged ,
Nov 03, 2020 Nov 03, 2020

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
        }
    }
}

})()

 

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 ,
Nov 03, 2020 Nov 03, 2020

Copy link to clipboard

Copied

hhas01's solution works nicely.  So I think the job is done. 

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
Participant ,
Nov 03, 2020 Nov 03, 2020

Copy link to clipboard

Copied

LATEST

Thank 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
Participant ,
Nov 03, 2020 Nov 03, 2020

Copy link to clipboard

Copied

thank you very much

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