
1. Re: Sorting images based on their position on the page
DaveSofTypefi Sep 23, 2013 8:18 PM (in response to tusharde)At the level of detail you use to describe your script it works on the page you show. I suspect a mistake in the sorting code. Can you share it so we can react to it?
Dave

2. Re: Sorting images based on their position on the page
tusharde Sep 24, 2013 8:42 AM (in response to DaveSofTypefi)Hi Dave. Thanks for the quick response. The image above is an example of a script i have already written. The script takes all the selected images and creates a tightly fit grid like the image above. That's working perfectly.
Now, i am trying to add in a functionality where in a user can move the position of images just by dragging and dropping them in general area of where the image should be. Then, when you run the script again it sorts the array of the entire selection based on the each items postion on the page and then creates the same tightly fit grid.
I decided to do an individual test to see if the sorting works before i include it in the "image grid" script. Here's where i am with that test.
When i run the follwing script on two layouts (image below) it works perfectly well in "TEST 1" when all the boxes are aligned on the "Y" coordinate. But fails on "TEST 2" when they are slightly offset. This is critical because i would like to give the user the ease of use of just roughly placing the images, rather than perfectly aligning them.
var blocs = app.selection; var newArr = blocs.sort(byYX); function byYX(a,b) { var aY = a.geometricBounds[0], bY = b.geometricBounds[0], aX = a.geometricBounds[1], bX = b.geometricBounds[1], dy = aYbY, dx = aXbX; return dy?dy:dx; } for(var i = 0; i < newArr.length; i++) { $.write(newArr[i].contents + "\r") } // TEST 1 CONSOLE LOG: 123456789 // TEST 2 CONSOLE LOG: 251346789
I wracked my brain a little more and i think I may have some sort of solution. I added some Math.floor to the x/y values to get an average for the array sort. This seems to work in some cases, but the rounding value is very fickle and needs to be adjusted to get the right setting. Too high and it grabs boxes from rows beyond itself. Too low and it misses items in the same row. Any thoughts on this technique?
var value = .5; var blocs = app.selection; var newArr = blocs.sort(byYX); function byYX(a,b) { var aY = Math.floor(a.geometricBounds[0] * value) / value, bY = Math.floor(b.geometricBounds[0] * value) / value, aX = Math.floor(a.geometricBounds[1] * value) / value, bX = Math.floor(b.geometricBounds[1] * value) / value, dy = aYbY, dx = aXbX; return dy?dy:dx; } for(var i = 0; i < newArr.length; i++) { $.write(newArr[i].contents + "\r") }

3. Re: Sorting images based on their position on the page
Dave Saunders Sep 24, 2013 9:02 AM (in response to tusharde)If this doesn't help, I'll look more deeply this evening:
The first part of a a?b:c statement must be logical. But dy is a number.
Dave

4. Re: Sorting images based on their position on the page
Marc Autret Sep 24, 2013 4:07 PM (in response to tusharde)No time to test, but I think you have to make a important distinction between xprecision and yprecision:
var X_PRECISION = 1, Y_PRECISION = 50, mFLOOR = Math.floor; var byYX = function F(a, b) { a = F.data['_'+a.id]; b = F.data['_'+b.id]; return (a[1]b[1])(a[0]b[0]); }; byYX.data = {}; var value = .5, blocs = app.properties.selection  null, newArr, i, t, k, o; if( blocs ) { o = byYX.data; i = blocs.length; while(i) { k = '_'+(t=blocs[i]).id; t = t.geometricBounds; o[k] = [X_PRECISION*mFLOOR(t[1]/X_PRECISION), Y_PRECISION*mFLOOR(t[0]/Y_PRECISION)]; } newArr = blocs.sort(byYX); for( i=0 ; i < newArr.length ; ++i ) { app.select(newArr[i]); $.sleep(1000); } }
@+
Marc
EDIT: The code above is just a raw approximation of the algorithm to illustrate my point. With regard to your purpose, comparing xlocations is not a problem as soon as rows (viz. ylocations) are properly computed. Hence, the whole problem is to determine under which condition two items belong to the same row, in terms of ylocation constraint. In my routine I use a high Y_PRECISION factor (50) in order to attract elements with a similar ylocation to the same row. But this ysimilarity is only based on a basic Math.floor, so my algorithm isn't really smart. In fact, your introductory example shows that the property of belongingtothesamerow is much more complex and should take into consideration what xlocation is already occupied or still empty. Anyway, my code is intended to show you a way to precompute relevant locations before you sort the array. This has two advantages: first, you will significantly speed up the sorting—as the byYX function doesn't need to reaccess DOM objects and their geometric bounds. Secund, you can then separate the data to sort and the sort in itself, which allows you to refine the key values—row and col parameters—independently.

5. Re: Sorting images based on their position on the page
Marc Autret Sep 25, 2013 2:19 AM (in response to tusharde)Hi again,
I found an idea that looks promising to address the issues mentioned above. The main problem, as you've probably noticed, is that we cannot simply rely on (x,y) coordinates 'as they are', even after having rounded the values, to extract the implied rows and columns.
When we study the disposition below:
our eyes instantly detect that there should be 3 columns and 5 rows, but this underlying order isn't instantly reached from just sorting the set of coordinates. We need to improve the algorithm.
What I suggest is to speculate on the gaps that occur on the ordered sequence of xcoordinates and ycoordinates, respectively. To reveal these gaps, let's sort data along the xaxis first:
The figure above only shows the widths of the rectangles. Each arrow represents a rectangle, and I've ordered the items by increasing xcenters. One can estimate that the element labelled #1 belongs to a new group from this simple fact: its left coordinate (red guide) is higher than the right coordinate (blue guide) of the element #0. This observation will give us a strategy to detect column gaps.
Then, the same method is applied to detect rows. (Sorting by yvalues, identifying gaps based on minmax progression.)
At the end of this process, every object has a (column, row) coordinate pair instead of sparse (x,y) values. So we can compute the final order, i.e. the weights for the comparison function.
Here is my implementation of this algorithm:
// ======================================================== // Up2Bottom and Left2Right Sorting Algorithm // addressing (weakly) sparse rectangles //  // Usage: Select the objects, then run the script // Target: InDesign CS4/CS5/CS6/CC // ======================================================== const CS = +CoordinateSpaces.SPREAD_COORDINATES, AP_MIN = +AnchorPoint.TOP_LEFT_ANCHOR, AP_CENTER = +AnchorPoint.CENTER_ANCHOR, AP_MAX = +AnchorPoint.BOTTOM_RIGHT_ANCHOR; var sel = app.properties.selection  null, data = [], r, i, j, k, t, n, w, vMax; if( sel && 1 < (n=sel.length) ) { // Collect coordinates and IDs // > {min:[xLeft, yTop], weight:[x,y], max:[xRight,yBottom], id}[] for(i=0 ; i < n && (t=sel[i]) ; ++i ) { data[i] = { min: t.resolve(AP_MIN,CS)[0], weight: t.resolve(AP_CENTER,CS)[0], max: t.resolve(AP_MAX,CS)[0], id: t.id }; } // Find rows and columns [i.e. yweights and xweights] //  for( j=0 ; j < 2 ; ++j ) { // Sort by center coordinate //  data.sort(function(a,b){return a.weight[j]  b.weight[j]}); // min > max ==> w++ //  for(vMax=(t=data[0]).max[j], t.weight[j]=(w=0), i=1 ; (i < n)&&(t=data[i]) ; ++i ) { if( t.min[j] > vMax ){ ++w; vMax=t.max[j]; } t.weight[j] = w; } } // Compute final weights, clean up data, create IDtoweight access //  for( i=0 ; (i < n)&&(t=data[i]) ; ++i ) { w = n*t.weight[1] + t.weight[0]; // final weight (y first) k = '_'+t.id; // ID key (t.min.length=0)(t.weight.length=0)(t.max.length=0); delete t.min; delete t.weight; delete t.max; delete t.id; delete data[i]; data[k] = w; // IDtoweight } // Apply sort > r //  r = sel.sort(function(a,b){return data['_'+a.id]data['_'+b.id];}); // Show the resulting order //  for( i=0 ; i < n ; ++i ) { app.select(r[i]); $.sleep(1000); } }
@+
Marc

6. Re: Sorting images based on their position on the page
tusharde Sep 25, 2013 7:51 AM (in response to Marc Autret)Marc,
Wow!! What is this, some kind of black magic? Kidding, of course. This is waaay out of my league. I'm blown away. Amazing.
Thank you so much. I tested it with a few scenarios and it worked flawlessly.
Your approach to the problem is smart and makes sense. I understood the logic, now i need to learn how you executed it. I'm going to read your code over and over to figure out what you did there.
Thanks again, Marc. Very cool.
Tushar