Copy link to clipboard
Copied
Hi Scripter All
I want to group my selected object row/column wise it is possible to achieve this using javascript if yes, please give your input ow? to do? It is possible please see the below snapshots.
This snapshot is my selected object not grouping in row wise.
,
This output is after grouped in row wise see the below snapshot. this is i m done is manually. But i need to do this in javascript.

Please help any one have idea or technical methods i want this output using javascript.
thx
csm_phil
I just implemented my idea step by step and I think it totally fullfills your objective.
absqua is wrong -- overlaps are important. Here is a before–after screenshot; larger objects may overlap previously defined groups ('buckets'), and if they do they have to be added to that bucket and its information updated. Initially I saved both top and bottom extremas, but after some more consideration that's not even necessary, and I could write it out exactly as I suggested earlier.

...//DESCRIPTION:Group by
Copy link to clipboard
Copied
You've got to do it the hard way. Go through your objects, worry about whether they overlap, and find the boundaries the define the sets, and then group them. I think you might find a basic computer graphics textbook helpful here.
Copy link to clipboard
Copied
Hi John,
First, thanks for looking my problem.
Can you please explain brief, how to get the group in row wise,I am not clear, And also you mentioned basic computer graphics textbook helpful here, where i get this book.
It is possible to achieve my requirement.
Please help me i am waiting for your reply
thx
csm_phil
Copy link to clipboard
Copied
Can you please explain brief, how to get the group in row wise,I am not clear,
You have to compare the geometricBounds of each and every box in order to sort them into rows. This is really a pain.
And also you mentioned basic computer graphics textbook helpful here, where i get this book.
This is not my area, I can't give you a reference. Try google. You'll have to spend some time at it.
It is possible to achieve my requirement.
That's a very good question. If you were doing it from scratch I'd suspect it would take you several days-weeks of work. But if you're lucky you can find someone else's algorithm that solves this. (But I may be too pessimistic!)
It's well worth thinking that it is not worth it and just giving up though. We'll see what other people say.
Copy link to clipboard
Copied
This is not my area, I can't give you a reference. Try google. You'll have to spend some time at it.
See, for instance, Don Wakefield's answer (the 2nd one) at http://stackoverflow.com/questions/289779/calculating-a-boundary-around-several-linked-rectangles. There is a textbook citation.
This is not the same question, but is a related problem.
Copy link to clipboard
Copied
The scanline suggestion in there, using only the vertical position of each vertex, should work just nice. To visualize what the algorithm should do, select *all* of your objects and use "Align Horizontal Centres".
(I now realize a *very* brute force approach would be to align the centres by script, add everything up with the pathfinder, and examining the leftovers.)
Copy link to clipboard
Copied
(After 10 minutes of pondering.) Sort by vertical top position (also store vertical bottom position). Then examine this array for overlaps. Any consecutive run of objects should be in one group.
Actual implementation will be left to the OP as an exercise.
Copy link to clipboard
Copied
I think I'm missing something. Why do we care about overlaps? I've done a hacky version of this by just sorting the rectangles by their vertical centers then walking through them comparing those centers and starting a new array when the value jumped by more than a set amount. I think that approach would work for the example csm_phil shows. Sorry, some ugly and redundant code here:
var doc = app.activeDocument,
rectangles = doc.rectangles.everyItem().getElements(),
groups = [],
diff = 50,
center, lastCenter, i, l;
rectangles.sort(function(a, b){
var aCenter = ((a.geometricBounds[2] - a.geometricBounds[0]) / 2) + a.geometricBounds[0];
var bCenter = ((b.geometricBounds[2] - b.geometricBounds[0]) / 2) + b.geometricBounds[0];
return aCenter - bCenter;
});
groups[0] = [rectangles[0]];
lastCenter = ((rectangles[0].geometricBounds[2] - rectangles[0].geometricBounds[0]) / 2) + rectangles[0].geometricBounds[0];
for(i = 1, l = rectangles.length; i < l; i++) {
center = ((rectangles.geometricBounds[2] - rectangles.geometricBounds[0]) / 2) + rectangles.geometricBounds[0];
if((center - lastCenter) > diff){
groups.push([rectangles]);
}
else{
groups[groups.length - 1].push(rectangles);
}
lastCenter = center;
}
for(i = 0, l = groups.length; i < l; i++) {
doc.groups.add(groups);
}
Jeff
Edit: Is it just me or did the forum start adding random whitespace when you paste in code with tabs?
Copy link to clipboard
Copied
I think I'm missing something. Why do we care about overlaps?
Well, I mentioned them because they will frustrate many simple/naive attempts to do this, and it's hard to trust that the input to this script will always be what you expect. If you're willing to ignore them, well, then things are much easier.
I've done a hacky version of this by just sorting the rectangles by their vertical centers then walking through them comparing those centers and starting a new array when the value jumped by more than a set amount.
Sounds like "cheating" to me 🙂
Edit: Is it just me or did the forum start adding random whitespace when you paste in code with tabs?
I don't think this is new. I reduce them to 2-space or 4-space indents anyhow because I very much dislike forcing people to scroll horizontally to read code.
Copy link to clipboard
Copied
Sounds like "cheating" to me
"The perfect is the enemy of the barely adequate." --Voltaire (my own translation)
Copy link to clipboard
Copied
Hi All,
Thanks for your valuable inputs,
Still, my requirement not finish, Please try to solve my problem. I am get the selected object x,y value and sort it after that i can do that part i am struggled.
thx
csm_phil
Copy link to clipboard
Copied
I just implemented my idea step by step and I think it totally fullfills your objective.
absqua is wrong -- overlaps are important. Here is a before–after screenshot; larger objects may overlap previously defined groups ('buckets'), and if they do they have to be added to that bucket and its information updated. Initially I saved both top and bottom extremas, but after some more consideration that's not even necessary, and I could write it out exactly as I suggested earlier.

//DESCRIPTION:Group by horizontal extent
// A Jongware Script 26-Dec-2011
// grab selection
elements = app.selection;
// sort on tops
elements.sort (function(x,y)
{
return x.geometricBounds[0] - y.geometricBounds[0];
}
);
// put in simple buckets, saving bottom and contains:array of elements
buckets = [ ];
for (i=0; i<elements.length; i++)
{
e_top = elements.geometricBounds[0];
e_bottom = elements.geometricBounds[2];
b = 0;
while (b < buckets.length && (e_top > buckets.bottom) )
b++;
// not in an available bucket? add one!
if (b == buckets.length)
buckets.push ( {bottom:e_bottom, contains:[ elements ] } );
else
{
// put in bucket
buckets.contains.push ( elements );
// update range
if (e_bottom > buckets.bottom)
buckets.bottom = e_bottom;
}
}
// add label for debugging purposes:
for (i=0; i<buckets.length; i++)
{
app.activeDocument.textFrames.add ({geometricBounds:[ buckets.contains[0].geometricBounds[0], 0, buckets.bottom, 20 ], contents:String(i)+" => "+String(buckets.contains.length) } );
}
// deselect all
app.select(null);
// convert to groups and re-select
for (i=0; i<buckets.length; i++)
{
if (buckets.contains.length > 1)
app.select ([app.activeDocument.groups.add (buckets.contains)], SelectionOptions.ADD_TO);
else
app.select(buckets.contains, SelectionOptions.ADD_TO);
}
Copy link to clipboard
Copied
Hi Jongware,
Thanks its working perferct this what i needed.
Thanks a lot again!
thx
csm_phil
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more