Copy link to clipboard
Copied
Hi,
Does anyone know if it's possible to calculate the total coverage of an irregular polygon shape in Adobe Indesign?
Something like this:
Is there a way to calculate the area of a shape?
Thanks
1 Correct answer
Hi all,
In case your splines do not auto-intersect, try this:
...var pathArea = function(/*[x,y][3][]*/ep, r,n,i,P,Q,xa,ya,xb,yb,xc,yc,xd,yd)
//----------------------------------
// Based on http://www.gust.org.pl/bachotex/2011-en/presentations/JackowskiB_3c_2011
// Return AREA x 20 ; result is signed.
{
for( r=0, n=ep.length, i=-1 ; ++i < n ; )
{
3 == (P=ep).length ?
( xa=P[1][0], ya=P[1][1], xb=P[2][0], yb=P[2][1] ) :
( xa=xb=P[0], ya=yb=P[1]);
3 == (Q=ep[(1+i
Copy link to clipboard
Copied
Maybe the best I can offer is cross-scripting with Illustrator.
There should be an area property, I think.
For that you would need to copy the polygon over to Illustrator.
With InDesign you would do that in a very time-consuming way. Just possible workarounds, no direct way.
One would be:
1. Do a text wrap with the shape.
2. Move a tiny text frame square with tiny contents step by step along.
3. Check after every move if the text frame is overset.
This works like a scanning mechanism and you are counting squares that add up to an area.
Regards,
Uwe
Copy link to clipboard
Copied
Another idea: Export to a pixel format with high resolution and count drawing pixels in PhotoShop.
That should also be possible by scripting.
Search for BridgeTalk here in the Scripting forum.
Kasyan Servetsky has some nice examples for cross-scripting InDesign with PhotoShop.
Regards,
Uwe
Copy link to clipboard
Copied
Hi,
Is this something that can be used to calculate the surface area in Indesign, without using any additional applications ?
javascript - How can I calculate the area of a bezier curve? - Stack Overflow
Thanks
Copy link to clipboard
Copied
Hi all,
In case your splines do not auto-intersect, try this:
var pathArea = function(/*[x,y][3][]*/ep, r,n,i,P,Q,xa,ya,xb,yb,xc,yc,xd,yd)
//----------------------------------
// Based on http://www.gust.org.pl/bachotex/2011-en/presentations/JackowskiB_3c_2011
// Return AREA x 20 ; result is signed.
{
for( r=0, n=ep.length, i=-1 ; ++i < n ; )
{
3 == (P=ep).length ?
( xa=P[1][0], ya=P[1][1], xb=P[2][0], yb=P[2][1] ) :
( xa=xb=P[0], ya=yb=P[1]);
3 == (Q=ep[(1+i)%n]).length ?
( xc=Q[0][0], yc=Q[0][1], xd=Q[1][0], yd=Q[1][1] ) :
( xc=xd=Q[0], yc=yd=Q[1]);
r += (xb-xa)*(10*ya + 6*yb + 3*yc + yd)
+ (xc-xb)*( 4*ya + 6*yb + 6*yc + 4*yd)
+ (xd-xc)*( ya + 3*yb + 6*yc + 10*yd);
}
return r;
};
var splineArea = function(/*SplineItem*/o, a,r,i,n,t)
//----------------------------------
// Visit every closed path and calculate the total area.
{
const CLOSED = +PathType.CLOSED_PATH;
a = o.paths.everyItem().getElements();
for( r=0, n=a.length, i=-1 ; ++i < n && (t=a).pathType==CLOSED ; r+=pathArea(t.entirePath) );
if( i < n ) throw "All paths must be closed.";
return (r/=20), 0 < r ? r : -r;
};
var getArea = function(/*obj|obj[]*/a,t,mu,i,r)
//----------------------------------
// Main function. Return the area in the form "<value> <unit>²".
// This function does not address splines that auto-intersect.
{
callee.Q||(callee.Q={
Q: 'q',
U: 'u',
POINTS: 'pt',
PIXELS: 'px',
PICAS: 'p',
MILS: 'mils',
MILLIMETERS: 'mm',
INCHES_DECIMEL: 'in',
INCHES: 'in',
HA: 'ha',
CICEROS: 'c',
CENTIMETERS: 'cm',
BAI: 'bai',
AMERICAN_POINTS: 'ap',
AGATES: 'ag',
});
(a instanceof Array) || (a=);
// Set consistent measurement unit.
// ---
while( 1 )
{
if( !(t=a[0]) || 'function' != typeof t.toSpecifier ) throw "Invalid input."
t = t.toSpecifier().match(/^\/document\[@id=\d+\]/);
if( !t || !(t=resolve(t[0])) || !(t instanceof Document) ) throw "Invalid input.";
t = t.viewPreferences.horizontalMeasurementUnits;
app.scriptPreferences.measurementUnit = t;
mu = callee.Q[t.toString()]||'';
mu && (mu = ' ' + mu + '\xB2');
break;
}
for( r=0, i=a.length ; i-- ; (o=a)&&o.hasOwnProperty('paths')&&(r+=splineArea(o)) );
return String(r) + mu;
};
// TEST. (Assuming something is selected.)
//========================================
var sel = app.selection;
alert( getArea(sel) );
Hope that helps.
Best,
Marc
Copy link to clipboard
Copied
Hi Marc,
I've tested your code and it works great. Many thanks for sharing this script with us.
Awesome job! This is very helpful.
Copy link to clipboard
Copied
Nice one, Marc!
Not sure though that I understand what you mean by 'In case your splines do not auto-intersect'. Could you elaborate?
P.
Copy link to clipboard
Copied
Hi Peter,
The following image shall illustrate the problem:
The SplineItem is made of two path points whose tangents are strictly opposed (so the shape crosses itself.) Since the algorithm relies on an algebraic calculation of area elements along a closed path, it concludes that the entire area is zero
You may think that considering the absolute value of each sub-calculation and adding all these values would solve the problem, but this would simply destroy the integration routine. In integral terms the area above is actually zero—although that's obviously not what the user expects to be returned!
Best,
Marc
Copy link to clipboard
Copied
Thanks, Marc. The term 'auto-intersect' didn't mean much to me, but your illustration makes it clear.
P.
Copy link to clipboard
Copied
This is also why the returned surface area might be a negative number (Which Marc then negates, because computers can process that but humans cannot.)
Copy link to clipboard
Copied
Hi,
I just would like to mention that using the script on a default circle shape, the calculations seems not as accurate.
If you would like to get the area coverage of a circle, consider using pi * radius 2
For all other usages, the script Marc provided is awesome...
Copy link to clipboard
Copied
Set the circle's stroke to zero and its area is calculated correctly.
P.
Copy link to clipboard
Copied
Hi Peter,
I have created a circle, 100x100 mm. When calculating the surface area using 50 * 50 * 3,141592653, the result doesn't match with the script output. The stroke is set to zero.
Copy link to clipboard
Copied
And what do you get when you do (50*50)*Math.PI ?
Copy link to clipboard
Copied
Hi Peter,
The result is identical to the calculator :-), and not the output of the script... 🙂
Copy link to clipboard
Copied
Hi tmmls,
Don't forget that InDesign circles are not exact circles. In fact, there is no representation of a true circle based on a cubic Bezier curve and the best we can hope is approximation. It is well known that InDesign approx is not very good, but anyway, even assuming the best cubic interpolation known to date (bezier - How to create circle with Bézier curves? - Stack Overflow ), a typical “radial error” of 0.02% is still observed along the curve. In your example (R=50) that's an order of magnitude of about 0.01 mm.
So, if you want a fair estimation of the error, you need to try the script with R = 50 ± 0.01 mm, that is, with two diameters of respectively 99.98 and 100.02 mm. Then you get the following outputs:
• For D=99.98 mm, result is 7,853.03865981908 mm²
• For D=100.02 mm, result is 7,859.3236044734 mm²
These values enclose the theoretical result, πR² ≈ 7,853.981635.
Note also that the gap between the output for D=100 and the theoretical result is 7,856.180818 – 7,853.981635 ≈ 2.199 mm². This may seem 'great' at first, but this only represents a drift of 0.028% relative to the expected result. This error has the same order of magnitude than the radial error caused by the Bezier approximation!
Not so bad, in my opinion.
Best,
Marc
Copy link to clipboard
Copied
Hi Marc,
Thank you for your detailed explanation. I was not aware of the issue regarding circles build out of bezier curves.
Your totally right. A deviation of only 0.028% is pretty awesome.
Many many thanks for all your help.
Copy link to clipboard
Copied
Hello! I'm trying to test out the script, but I get an error. It seems I'm missing a value after "=" in the following line:
(a instanceof Array) || (a=);
What can I do to fix it? Thanks again!
Copy link to clipboard
Copied
Hi pjleveno,
I guess another bug with moving this thread to the new InDesign forum.
Better look into Marc's original code:
Nice Function for Computing Polygon Areas
Marc Autret
http://www.indiscripts.com/post/2019/06/indesign-scripting-forum-roundup-13#hd2sb2
Regards,
Uwe Laubender
( ACP )
Copy link to clipboard
Copied
Thanks! It works perfectly. I'm trying to locate unlabeled icons. Maybe I can find them based on their area, unless someone has another way to identify a path. Thanks again for these powerful tools and also your quick responses!

