Copy link to clipboard
Copied
I make a lot of stencils that become .25" laser cut plates & I need a script to quickly calculate the surface area of the final 3D plate.
The total surface area of the 3D plate is: (Front Surface Area) + (Back Surface Area) + (Perimeter*Material Thickness.)
The script below will give me the Front + Back, so I'm half way there.
I just need help getting the script to output the value normally found in the "Document Info" pallete, under "Objects --> Length"
Can anyone assist?
Thanks!
/* Save this file with a jsx extension and place in your
Illustrator/Presets/en_US/Scripts folder. You can then
access it from the File > Scripts menu */
var decimalPlaces = 3;
if (app.documents.length > 0) {
if (app.activeDocument.selection.length < 1) {
alert('Select a path');
} else if (app.activeDocument.selection[0].area) {
// Individual Items
var objects = app.activeDocument.selection;
} else if (app.activeDocument.selection[0].pathItems) {
// Group/Compound Shape
var objects = app.activeDocument.selection[0].pathItems;
} else {
alert('Please select a path or group.');
}
// Collect info
var totalArea = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].area) {
var totalArea = totalArea + objects[i].area;
}
}
// Conversions
var ppi = 72;
var areaIn = totalArea / ppi / ppi;
if (areaIn < 0) var areaIn = -areaIn;
var areaCm = areaIn * 6.4516;
// Display
alert('Shape Area\n\
' + areaIn.toFixed(decimalPlaces) + ' in² \
' + areaIn.toFixed(decimalPlaces) * 2 + ' (in²)2 \n\
' + areaCm.toFixed(decimalPlaces) + ' cm² \
' + areaCm.toFixed(decimalPlaces) * 2 + ' (cm²)2 \n\
' + i + ' shapes');
}
2 Correct answers
Got it working!
The script now outputs the 3D surface area for a selected compound path, along with some other useful data.
I verified the values are correct by exporting a DXF, & creating a 3D model in solidworks.
It would be nice to add a dialog so users can input a 3D Thickness value. Most of the time I need .25" thickness so hard coded is fine for now.
Here's the final code.. Enjoy!
/* Save this file with a jsx extension and place in your
Illustrator/Presets/en_US/Scripts folder. You can then
...
This is probably my final update..
I added this updated Notice to the header of the script:
/* NOTICE: This tool only provides correct values when
the selection is either a single manifold shape, or a single
manifold compound shape, with no internal self-intersecting
geometry. Correct selection geometry will export to DXF,
import to solidworks & extrude to materialThickness as a
single body, with identical output for area & other values.
*/
updated code here:
/* Save this file with a jsx extension and p
...
Explore related tutorials & articles
Copy link to clipboard
Copied
to get the length of objects as shown in Document Info, use the length property
alert(selection[0].length);
Copy link to clipboard
Copied
Thanks for the quick reply.
I tried adding your string to my alert output and all it returns is "undefined"
I also tried running it in a new script with no other fucntions. Still only returns "undefined"
Here's a screenshot of the alert output:
& heres my updated code.. Let me know if you can help me get this going!
/* Save this file with a jsx extension and place in your
Illustrator/Presets/en_US/Scripts folder. You can then
access it from the File > Scripts menu */
var decimalPlaces = 3;
if (app.documents.length > 0) {
if (app.activeDocument.selection.length < 1) {
alert('Select a path');
} else if (app.activeDocument.selection[0].area) {
// Individual Items
var objects = app.activeDocument.selection;
} else if (app.activeDocument.selection[0].pathItems) {
// Group/Compound Shape
var objects = app.activeDocument.selection[0].pathItems;
} else {
alert('Please select a path or group.');
}
// Collect info
var totalArea = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].area) {
var totalArea = totalArea + objects[i].area;
}
}
// Conversions
var ppi = 72;
var areaIn = totalArea / ppi / ppi;
if (areaIn < 0) var areaIn = -areaIn;
var areaCm = areaIn * 6.4516;
// Display
alert('Shape Area\n\
' + areaIn.toFixed(decimalPlaces) + ' in² \
' + areaIn.toFixed(decimalPlaces) * 2 + ' (in²)2 \n\
' + areaCm.toFixed(decimalPlaces) + ' cm² \
' + areaCm.toFixed(decimalPlaces) * 2 + ' (cm²)2 \
' + selection[0].length + ' Perimeter\n\
' + i + ' shapes');
}
Thanks!
Copy link to clipboard
Copied
what kind of object is
selection[0];
?
maybe add another line to your alert like this:
alert('Shape Area\n\
' + areaIn.toFixed(decimalPlaces) + ' in² \
' + areaIn.toFixed(decimalPlaces) * 2 + ' (in²)2 \n\
' + areaCm.toFixed(decimalPlaces) + ' cm² \
' + areaCm.toFixed(decimalPlaces) * 2 + ' (cm²)2 \
' + selection[0].length + ' Perimeter\n\
' + 'selection[0].typename = ' + selection[0].typename + '\n' \
' + i + ' shapes');
Copy link to clipboard
Copied
Thanks for the reply.
The object is a compound path, vectors for a laser cut logo plate.
Adding this line broke the script:
' + 'selection[0].typename = ' + selection[0].typename + '\n' \undefined
I am what is called extreme novice in javascript & I appreciate any additional guidance.
Thanks!
Copy link to clipboard
Copied
- The line should be
' + 'selection[0].typename = ' + selection[0].typename + '\
- You're getting "undefined" because a compound path doesn't have a length property.
- At a quick glance, "length" of a compound path in Dcoument Info > Objects seems to be the sum of the lengths of the paths in a compound path. Is that what you want?
Copy link to clipboard
Copied
I posted a generic sample usage.
I think you have to apply it to one of your objects
objects[index].length; // you need to provide index
Copy link to clipboard
Copied
I appreciate your guidance & as stated above I am an extreme novice when it comes to scripting.
I am unclear what you mean when you say I "need to provide index".
can you explain further or show me how & where to insert the code objects[index].length; ?
The answer may be obvious to some & I appreaciate you taking the time to explain so I may better understand WTF I'm doing 🙂
Thanks again!
Copy link to clipboard
Copied
Got it working!
The script now outputs the 3D surface area for a selected compound path, along with some other useful data.
I verified the values are correct by exporting a DXF, & creating a 3D model in solidworks.
It would be nice to add a dialog so users can input a 3D Thickness value. Most of the time I need .25" thickness so hard coded is fine for now.
Here's the final code.. Enjoy!
/* Save this file with a jsx extension and place in your
Illustrator/Presets/en_US/Scripts folder. You can then
access it from the File > Scripts menu */
var decimalPlaces = 3;
var materialThickness = .25;
if (app.documents.length > 0) {
if (app.activeDocument.selection.length < 1) {
alert('Select a path');
} else if (app.activeDocument.selection[0].area) {
// Individual Items
var objects = app.activeDocument.selection;
} else if (app.activeDocument.selection[0].pathItems) {
// Group/Compound Shape
var objects = app.activeDocument.selection[0].pathItems;
} else {
alert('Please select a path or group.');
}
// Collect area info
var totalArea = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].area) {
var totalArea = totalArea + objects[i].area;
}
}
// Collect length info
var totalLength = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].length) {
var totalLength = totalLength + objects[i].length;
}
}
// Area Conversions
var ppi = 72;
var areaIn = totalArea / ppi / ppi;
if (areaIn < 0) var areaIn = -areaIn;
var areaCm = areaIn * 6.4516;
// Length Conversions
var ppi = 72;
var lengthIn = totalLength / ppi;
if (lengthIn < 0) var lengthIn = -lengthIn;
var lengthCm = lengthIn * 6.4516;
// Display
alert('3D Solid Surface Area Calculator\n\
' + i + ' Shapes \n\
' + areaIn.toFixed(decimalPlaces) + ' : Area in² \
' + areaIn.toFixed(decimalPlaces) * 2 + ' : Area (in²)2 \n\
' + lengthIn.toFixed(decimalPlaces) + ' : Perimeter Length(in) \
' + (lengthIn * materialThickness).toFixed(decimalPlaces) + ' : Perimeter Area (in²) \n\
' + materialThickness + ' : Material Thickness (in) \n\
' + ((areaIn * 2) + (lengthIn * materialThickness)).toFixed(decimalPlaces) + ' : Total 3D Area (in²)');
}
Copy link to clipboard
Copied
Attention.
Customers can create files that your script will not interpret properly.
Test file was created with Illu 24.2.1:
Copy link to clipboard
Copied
Thanks, I wasnt able to access your test file. ¯\_(ツ)_/¯
I added the following notice to the script's header:
/* NOTICE: This tool only provides correct values when
the selection is either a single contiguous path, or a single
compound shape. If multiple shapes are selected the tool
will only ouput values for the top shape in the selection.*/
For my purposes the tool works perfectly because I am always working with single, manifold, compound shapes -- the type of shape Solidworks can cleanly import & extrude into 3D geometry.
This hacked together script will only provide correct values for the top most object in the selection. If you have multiple shapes selected try creating a single compound shape
Its working for my needs & hope others can find it useful &/or adaptable!
Here's my up to date code (output now also includes 3D volume totals as well).
Enjoy!
/* Save this file with a jsx extension and place in your
Illustrator/Presets/en_US/Scripts folder. You can then
access it from the File > Scripts menu */
/* NOTICE: This tool only provides correct values when
the selection is either a single contiguous path, or a single
compound shape. If multiple shapes are selected the tool
will only ouput values for the top shape in the selection.*/
var decimalPlaces = 3;
var materialThickness = .25;
if (app.documents.length > 0) {
if (app.activeDocument.selection.length < 1) {
alert('Select a path');
} else if (app.activeDocument.selection[0].area) {
// Individual Items
var objects = app.activeDocument.selection;
} else if (app.activeDocument.selection[0].pathItems) {
// Group/Compound Shape
var objects = app.activeDocument.selection[0].pathItems;
} else {
alert('Please select a path or group.');
}
// Collect area info
var totalArea = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].area) {
var totalArea = totalArea + objects[i].area;
}
}
// Collect length info
var totalLength = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].length) {
var totalLength = totalLength + objects[i].length;
}
}
// Area Conversions
var ppi = 72;
var areaIn = totalArea / ppi / ppi;
if (areaIn < 0) var areaIn = -areaIn;
var areaCm = areaIn * 6.4516;
// Length Conversions
var ppi = 72;
var lengthIn = totalLength / ppi;
if (lengthIn < 0) var lengthIn = -lengthIn;
var lengthCm = lengthIn * 6.4516;
// Display
alert('3D Solid Surface Area Calculator\n\
' + i + ' Shapes \n\
' + materialThickness + ' : Material Thickness (in) \n\
' + areaIn.toFixed(decimalPlaces) + ' : Area in² \
' + areaIn.toFixed(decimalPlaces) * 2 + ' : Area (in²)2 \n\
' + lengthIn.toFixed(decimalPlaces) + ' : Perimeter Length(in) \
' + (lengthIn * materialThickness).toFixed(decimalPlaces) + ' : Perimeter Area (in²) \n\
' + (areaIn * materialThickness).toFixed(decimalPlaces) + ' : 3D Volume (in³)\n\
' + ((areaIn * 2) + (lengthIn * materialThickness)).toFixed(decimalPlaces) + ' : Total Surface Area (in²)');
}
Copy link to clipboard
Copied
Ok. I see.
xup has now an Adblock adblocker.
Try this Dropbox link.
https://www.dropbox.com/s/uvqyuvyz2si9ckt/wrong_calculation_CC2020.ai?dl=0
Copy link to clipboard
Copied
Ok, I see your file is not a single manifold component. The vectors intersect & so there are actually 2 manifold shapes here.
The script is only returning values for one of these shapes.
When I opened your file, I made zero changes & ran the script. The output values do appear incorrect...
Next, I created a compound shape using this method:
Select all & click the "Unite" button in the Pathfinder Pallet...
After using the "Unite" Command, I ran the script again & this time got the different output values. This time the values were correct, but only for one of the objects in the selection (the one on the upper left), since there are actually 2 shapes here.
The problem with this perticular part is that its not mainfold. If a laser were to follow these paths to cut a part from plate steel, you would end up with two parts (the upper left, & lower right.). For this script to work correctly, there must be only 1 single manifold compound shape that would produce only a single manifold 3d component when imported & Extruded in solidworks.
When I eliminated one of the objects and ran the script, the correct values are returned, as verified in solidworks.
In conculusion, this script only works on single manifold compound shapes with no internal self-intersecting lines that would result in multiple manifold objects in a real laser cutting situaion..
Enjoy!
...
Copy link to clipboard
Copied
This is probably my final update..
I added this updated Notice to the header of the script:
/* NOTICE: This tool only provides correct values when
the selection is either a single manifold shape, or a single
manifold compound shape, with no internal self-intersecting
geometry. Correct selection geometry will export to DXF,
import to solidworks & extrude to materialThickness as a
single body, with identical output for area & other values.
*/
updated code here:
/* Save this file with a jsx extension and place in your
Illustrator/Presets/en_US/Scripts folder. You can then
access it from the File > Scripts menu */
/* NOTICE: This tool only provides correct values when
the selection is either a single manifold shape, or a single
manifold compound shape, with no internal self-intersecting
geometry. Correct selection geometry will export to DXF,
import to solidworks & extrude to materialThickness as a
single body, with identical output for area & other values.
*/
var decimalPlaces = 3;
var materialThickness = .25;
if (app.documents.length > 0) {
if (app.activeDocument.selection.length < 1) {
alert('Select a path');
} else if (app.activeDocument.selection[0].area) {
// Individual Items
var objects = app.activeDocument.selection;
} else if (app.activeDocument.selection[0].pathItems) {
// Group/Compound Shape
var objects = app.activeDocument.selection[0].pathItems;
} else {
alert('Please select a path or group.');
}
// Collect area info
var totalArea = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].area) {
var totalArea = totalArea + objects[i].area;
}
}
// Collect length info
var totalLength = 0;
for (var i=0; i<objects.length; i++) {
if (objects[i].length) {
var totalLength = totalLength + objects[i].length;
}
}
// Area Conversions
var ppi = 72;
var areaIn = totalArea / ppi / ppi;
if (areaIn < 0) var areaIn = -areaIn;
var areaCm = areaIn * 6.4516;
// Length Conversions
var ppi = 72;
var lengthIn = totalLength / ppi;
if (lengthIn < 0) var lengthIn = -lengthIn;
var lengthCm = lengthIn * 6.4516;
// Display
alert('3D Solid Surface Area Calculator\n\
' + i + ' Shapes \n\
' + materialThickness + ' : Material Thickness (in) \n\
' + areaIn.toFixed(decimalPlaces) + ' : Area in² \
' + areaIn.toFixed(decimalPlaces) * 2 + ' : Area (in²)2 \n\
' + lengthIn.toFixed(decimalPlaces) + ' : Perimeter Length(in) \
' + (lengthIn * materialThickness).toFixed(decimalPlaces) + ' : Perimeter Area (in²) \n\
' + (areaIn * materialThickness).toFixed(decimalPlaces) + ' : 3D Volume (in³)\n\
' + ((areaIn * 2) + (lengthIn * materialThickness)).toFixed(decimalPlaces) + ' : Total Surface Area (in²)');
}
Copy link to clipboard
Copied
Everything is fine - when you know what you are doing.
And I think you know what you do.
😉
(I do a similar thing at work - we produce CNC-engraved hot stamping tools, but mostly with extremely complex motifs)
Copy link to clipboard
Copied
If I actually knew what I was doing in JS, I would add logic to:
A: Create a dialog for user input of the materialThickness variable.
B: Add logic to detect whether the selected geometry is a manifold.
This was a fun little project.. Glad it worked out & hope everyone enjoys!
Copy link to clipboard
Copied
A: is easy. There is no need to create a dialog. A simple prompt() is enough.
Replace your line:
var materialThickness = .25;
with:
var materialThickness = prompt ("Insert the material thickness", 0.25, "Material thickness");
if (materialThickness != null && isNaN (materialThickness*1) == false) {
materialThickness = materialThickness*1;
};
Your point B:
I never tried to detect such things.
Sorry
Copy link to clipboard
Copied
Today I found this property and I think it would be helpful for your needs:
compoundPath.pathItems[0].polarity
compoundPath.pathItems[1].polarity
and so on …

