Loic.Aigon wrote … Possibly doable with some bezier algoritm implementation. |
Hi Loic,
I bet it is and you'll proof it :-)
Thank you very much for working on a solution!
Regards,
Uwe
Ok, so here is a possible approach :
//A script from Loic Aigon @ ozalto.com
//retrieves the length of a selected path within InDesign
//Such as what Illustrator provides in the info panel.
//Widely inspired from http://www.iscriptdesign.com/?sketch=tutorial/splitbezier
//length is not warrantied as perfect as curve length computation are always approximations
//Pretty compliant to Illustrator results though.
#include "Bezier.jsinc"
//Main routine
var main = function() {
//VARS================================================//
var doc = app.properties.activeDocument, path, pps,
sum = 0, isClosed, p1, p2, i = 0;
if ( !doc ) return;
if ( app.selection.length!=1 || app.selection[0].properties.paths ) {
alert("You must select a path please.");
return;
}
//Retrieving path points data
path = app.selection[0].paths[0],
pps = path.entirePath;
n = pps.length;
//Is the path closed ?
isClosed = path.pathType == PathType.CLOSED_PATH;
//Looping through InDesign path points
while ( i<n ) {
//If path is not closed and last point is reached, loop breaks.
//Otherwise we compute and add the length between endpoint and startpoint to the final result
if ( i+1==n && !isClosed ) break;
//p1 is the current point
//p2 the following point if any or the first one if the path is closed
p1 = pps;
p2 = pps[i+1]? pps[i+1] : pps[0];
//Iteratingly adding curves length to the final path length result
sum+=getPathLength(p1,p2);
//Keeping on moving
i++;
}
//Yelling the result
alert( "This measures about "+Math.round (sum*1000)/1000+" units" );
}
function getPathLength (pA,pB) {
var
sqA = typeof ( pA[0] ) == "number",
sqB = typeof ( pB[0] ) == "number",
x1 = sqA? pA[0] : pA[1][0],
x2 = sqA? pA[0] : pA[2][0],
x3 = sqB? pB[0] : pB[0][0],
x4 = sqB? pB[0] : pB[1][0],
y1 = sqA? pA[1] : pA[1][1],
y2 = sqA? pA[1] : pA[2][1],
y3 = sqB? pB[1] : pB[0][1],
y4 = sqB? pB[1] : pB[1][1],
p1 = {x:x1,y:y1},
cp1 = {x:x2,y:y2},
cp2 = {x:x3,y:y3},
p2 = {x:x4,y:y4},
d = 0;
return Bezier.getLength ( p1, cp1, cp2, p2 );
}
var u;
app.doScript ( "main()",u,u,UndoModes.ENTIRE_SCRIPT, "The Script" );
And the Bezier.jsinc lib :
//Bezier.jsinc by Loic Aigon @ ozalto.com
//A library to compute Bezier Cubic curves items properties
//Highly derivated from http://www.iscriptdesign.com/?sketch=tutorial/splitbezier
//More infos on Bezier Cubic curves here : https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B%C3%A9zier_curves
var Bezier = (function(){
return {
//Retrieve [x,y] point on a cubic bezier curve
//percent stands for the location of the point regarding of the curve length expressed in %
//0 means at the beginning of the curve
//1 means at the end of the curve
getBezier:function(percent,p1,cp1,cp2,p2) {
//Specific algoritms factor computations
function b1(t) { return t*t*t }
function b2(t) { return 3*t*t*(1-t) }
function b3(t) { return 3*t*(1-t)*(1-t) }
function b4(t) { return (1-t)*(1-t)*(1-t) }
//Return x,y values for the point at "percent" lcoation of the curve
return {
x: p1.x*b1(percent) + cp1.x*b2(percent) + cp2.x*b3(percent) + p2.x*b4(percent),
y: p1.y*b1(percent) + cp1.y*b2(percent) + cp2.y*b3(percent) + p2.y*b4(percent)
};
},
//Retrieves curve length
//p1, p2, cp1 & cp2 with specifi structure:
//{x:…,y:…} where values are real numbers
getLength:function(p1,cp1,cp2,p2) {
var i = 0, max = 100,
bz, pvBz, d = 0;
//Compute x/y location for the 100 points between start point and end point
while ( i<=max ) {
//Sets initial bezier point
if ( !pvBz ) {
pvBz = this.getBezier ( (i)/100,p1,cp1,cp2,p2);
}
//Sets next point a,d compute distance regarding to previous point
else {
bz = this.getBezier ( (i)/100,p1,cp1,cp2,p2);
//Simple trigonometry to compute distance between two points (x1,y1 to x2,y2)
d+=Math.sqrt (Math.pow(bz.x-pvBz.x,2)+Math.pow(bz.y-pvBz.y,2));
pvBz = bz;
}
i++;
}
//return computed distance
return d;
}
}
})();
Voilà.

I have this feeling that area computation is just 1.000.000 steps higher.