This took about an hour to write, one step at a time:
- Handle either one single item, or a selection of items.
- Loop through the single path (for a simple object) or through all component paths (for a compound object) and gather all anchor points into a single array.
- Test every point against every other. I've thought about it and I don't think there is clever solution that may avoid this.
- Calculate the angle between the 2 most distant points.
- If the angle exceeds ±180°, clip it to avoid rotating too much.
- Rotate the selected object(s).
Result: above the dotted line the original, below after running the script. The leftmost object is your example. The vertical cyan lines are added manually to indicate the longest vertical distance points.
Some very complicated objects defy simple path exploration – and I have no idea why. See the fish bones for an example; it did not move, because the path finding functions returned nothing at all. The underlying problem could be that it originated as a Symbol, rather than drawn, but the reason eludes me.
//DESCRIPTION:Align object(s) on its longest axis
if (app.documents.length == 0 || app.selection.length < 1)
alert ("Please make sure to have something useful selected");
else
{
for (i=0; i<app.selection.length; i++)
{
if (app.selection[i].constructor.name=="PathItem" || app.selection[i].constructor.name=="CompoundPathItem")
realign (app.selection[i]);
}
}
function realign (obj)
{
var result, distx,disty,angle;
result = furthestSet (obj);
if (result.length == 3)
{
/* result[1] is point #1, result[2] = pt #2 */
/* now calculate angle and rotate */
disty = result[1][0] - result[2][0];
distx = result[1][1] - result[2][1];
angle = -Math.atan2 (distx, disty) - Math.PI/2;
angle = angle*180.0/Math.PI;
if (angle <= -180) angle += 180;
if (angle >= 180) angle -= 180;
obj.rotate (angle,true,true,true,false, Transformation.CENTER);
}
}
function distanceFromPointToPoint (A, B)
{
/* since we only need to know what point is furthest, the squared result is okay as well */
/* return Math.sqrt ( ((A[0]-B[0]) * (A[0]-B[0])) + ((A[1]-B[1]) * (A[1]-B[1])) ); */
return ((A[0]-B[0]) * (A[0]-B[0])) + ((A[1]-B[1]) * (A[1]-B[1]));
}
function pathToArray (obj)
{
var pt;
var flatpath = [];
if (!obj.hasOwnProperty ("pathPoints"))
return null;
for (pt=0; pt<obj.pathPoints.length; pt++)
{
flatpath.push (obj.pathPoints[pt].anchor);
}
/* once more for good luck */
flatpath.push (obj.pathPoints[0].anchor);
return flatpath;
}
function furthestSet (obj)
{
var flatpath = [], i,j, d, distance = -1, result = [];
if (obj.constructor.name == "CompoundPathItem")
{
for (p=0; p<obj.pathItems.length; p++)
{
flatpath = flatpath.concat(pathToArray (obj.pathItems[p]));
}
} else
{
flatpath = pathToArray (obj);
}
if (flatpath == [])
return [0, [0,0], [0,0]];
for (i=0; i < flatpath.length-1; i++)
{
for (j=i+1; j < flatpath.length; j++)
{
d = distanceFromPointToPoint (flatpath[i], flatpath[j]);
if (d > distance)
{
distance = d;
result = [d, flatpath[i], flatpath[j]];
}
}
}
return result;
}