Skip to main content
Inspiring
January 25, 2018
Answered

[CC 2018][JS] How to get length of path

  • January 25, 2018
  • 3 replies
  • 8038 views

Hi,

Does anyone know if it's possible to get the total length of a path drawn with the pen tool?

I can't find a property which contains this value. Is this something which can be calculated?

Or is there a Indesign plugin available somewhere which support this property so it can be retrieved using scripting ?

Thanks

This topic has been closed for replies.
Correct answer Loic.Aigon

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.

3 replies

_A_W_
Participant
February 7, 2019

Hi guys, there's actually something built into Illustrator that does what the OP is asking for.

Window / Document Info /  (open up the options in this new window) select Object

Voila - any path you need to measure will be calculated.

Community Expert
February 7, 2019

Hi lordchops ,

thanks for that hint.

Actually tmmls was asking if InDesign ( not Illustrator ) is able to calculate this using JavaScript.

Best,
Uwe

barbara_a7746676
Community Expert
Community Expert
January 26, 2018

There are two panels that may be what you're looking for.

Transform panel.

Or you could use the Measure tool. Drag over the line with the measure tool. The

The Info panel will appear.

Community Expert
January 26, 2018

tmmls  said:

Does anyone know if it's possible to get the total length of a path drawn with the pen tool?

Hi Barbara,

I think the shape of a path that should be measured in length is more like that:

In Adobe Illustrator you can read out it's length by addressing the path and ask for the value of property length.

pathItem.length will return a number in Points.

pathItem.area will return the area of a path in square points.

Both properties are missing in the InDesign document object model.

My suggestion would be to add a text path to the shape. Add some text, eg. "a b c", set it's formatting to fully justified and read out the values for startBracket and endBracket:

// Arbitrary shape selected.

// Add text path to selection:

var textPath = app.selection[0].textPaths.add();

// Add text with at least two blanks to the text path:

textPath.texts[0].contents = "a b c";

// Set the formatting of the text to fully justified:

textPath.texts[0].justification = Justification.FULLY_JUSTIFIED;

// The endBracket statement should show the length of the path in points:

alert

(

    "Length:"+"\r"+

    "startBracket:"+" "+textPath.startBracket +"\r"+

    "endBracket:"+" "+textPath.endBracket

);

Screenshot of the result:

Details of startBracket and endBracket:

Regards,
Uwe

barbara_a7746676
Community Expert
Community Expert
January 26, 2018

Thanks for the clarification, Uwe. Of course, it wouldn't be that simple.

Jongware
Community Expert
Community Expert
January 25, 2018

No built-in function but of course it can be calculated. Straight lines only, or curves as well? Straight lines is as straightforward as possibly can (assuming basic maths skills), but if you do a quick Google search on "bézier curve length" you will find that that is rather more difficult.

Alternative: use Illustrator for your vector operations. Its local version of the Info Panel can show the total length of a selected path.

Community Expert
January 25, 2018

Another idea to get the length of a path is to add a text path to the path and measure it's length by looking at the value of endBracket. But this is no precise business because there could be a little gap between startBracket and endBracket endBracket and startBracket. You'd also need some text on the path formatted with justification fully justified.

Regards,
Uwe

// Some edits…