Hello everyone!
I have a collection of circles and rectangles in my document. Is there any way to sort out circles from rectagles using JavaScript? Say i want to make my circles red and the rectangles blue. Yes, yes i am a total beginner in coding
Thank you in advance!
If you are certain that your document contains only rectangles and/or circles, you can inspect the paths of each objects to determine the what is what:
only circle path points will contain bezier (curved) points.
BUT if you have *any* number of *any* random kind of objects, you need to check MUCH more. A rectangle always will have at least four corner points (it may have more, if some points are colinear or even coincident); all corners need to have an angle of 90 degrees. You cannot just test for equal x/y coordinates because a rotated rectangle is still a rectangle.
A circle also has (at least) 4 points, but they all need to be of the bezier type. "Circles", by the way, are not an Illustrator primitive object; they are *approximated* through four bezier curves. Therefore you'd need to test the curvature of each bezier curve, and allow for some error in the approximation. (Draw a circle in Illustrator. Drag out one of the bezier control points by a small amount. Is it still a circle? ... Considering it wasn't one to begin with...)
I will hold my hands up and say when I first started with scripting with AI… I looked at making functions to determine/test basic shapes neadless to say it was actually far more complicated than I had originaly thought and duly gave up… Circle, rectangle & square all a 4 path point array [
,
,
,
] Feel free to work that up a little… ![]()
Take two! Now with most advanced-basic shape detection ever!
/*------------------------------------Circle or Rectangle---------------------------------------*/
// Finds perfect circles and/or rectangles in document and colors them.
// Silly-V
function makeCmykColor(c, m, y, k) // Handy color-making function.
{
var newCmykColor = new CMYKColor();
newCmykColor.cyan = c;
newCmykColor.magenta = m;
newCmykColor.yellow = y;
newCmykColor.black = k;
return newCmykColor;
}
if(app.documents.length > 0){
var doc = app.documents[0];
var myShapes = new Array();
for (i=0; i<doc.pageItems.length; i++){
var myShape = doc.pageItems[i];
myShapes.push(myShape);
if (myShape.typename == "PathItem"){
if (myShape.pathPoints.length == 4){ // RECTANGLE CHECKER
//--------------------2 diagonals-------------------------
var recEquaDistOne = parseInt(Math.pow((myShape.pathPoints[0].anchor[0] - myShape.pathPoints[2].anchor[0]),2) +
Math.pow((myShape.pathPoints[0].anchor[1] - myShape.pathPoints[2].anchor[1]),2)); // diagonal
var recEquaDistTwo = parseInt(Math.pow((myShape.pathPoints[1].anchor[0] - myShape.pathPoints[3].anchor[0]),2) +
Math.pow((myShape.pathPoints[1].anchor[1] - myShape.pathPoints[3].anchor[1]),2)); // diagonal
//---------------------4 sides of rectangle---------------
var sideA = parseInt(Math.pow((myShape.pathPoints[0].anchor[0] - myShape.pathPoints[1].anchor[0]),2) +
Math.pow((myShape.pathPoints[0].anchor[1] - myShape.pathPoints[1].anchor[1]),2));
var sideB = parseInt(Math.pow((myShape.pathPoints[1].anchor[0] - myShape.pathPoints[2].anchor[0]),2) +
Math.pow((myShape.pathPoints[1].anchor[1] - myShape.pathPoints[2].anchor[1]),2));
var sideC = parseInt(Math.pow((myShape.pathPoints[2].anchor[0] - myShape.pathPoints[3].anchor[0]),2) +
Math.pow((myShape.pathPoints[2].anchor[1] - myShape.pathPoints[3].anchor[1]),2));
var sideD = parseInt(Math.pow((myShape.pathPoints[3].anchor[0] - myShape.pathPoints[0].anchor[0]),2) +
Math.pow((myShape.pathPoints[3].anchor[1] - myShape.pathPoints[0].anchor[1]),2));
if (recEquaDistOne == recEquaDistTwo){ // If two diagonals connecting opposite points are same length, it's a 90 degree box
if ((sideA == sideC) && (sideB == sideD)){
for (j=0; j<4; j++){
var point = myShape.pathPoints[j];
if ((point.leftDirection[0] == point.anchor[0]) &&
(point.anchor[0] == point.rightDirection[0]) &&
(point.leftDirection[1] == point.anchor[1]) &&
(point.anchor[1] == point.rightDirection[1])){
myShape.isrectangle = true;
} else {
myShape.isrectangle = false;
break;
}
}
}
}
}
if (myShape.pathPoints.length == 4){ // CIRCLE CHECKER
if (myShape.isrectangle == false || myShape.isrectangle == null){
var circlePts = new Array();
var circleSlopes = new Array();
for (k=0; k<4; k++){
var point = myShape.pathPoints[k];
var leftHandleDist = parseInt(Math.pow((point.leftDirection[0] - point.anchor[0]),2) +
Math.pow((point.leftDirection[1] - point.anchor[1]),2));
var rightHandleDist = parseInt(Math.pow((point.rightDirection[0] - point.anchor[0]),2) +
Math.pow((point.rightDirection[1] - point.anchor[1]),2));
circlePts.push(leftHandleDist, rightHandleDist);
var leftHandleSlope = ((point.leftDirection[0] - point.anchor[0])/(point.leftDirection[1] - point.anchor[1])).toFixed(2);
var rightHandleSlope = ((point.rightDirection[0] - point.anchor[0])/(point.rightDirection[1] - point.anchor[1])).toFixed(2);
circleSlopes.push(leftHandleSlope, rightHandleSlope);
}
for (f=0; f<8; f++){ // Allows non-rotated circles.
if (circleSlopes[f] == "-0.00"){
circleSlopes[f] = "0.00";
}
if (circleSlopes[f] == "-Infinity"){
circleSlopes[f] = "Infinity";
}
}
//$.write(circleSlopes[0] + " , " + circleSlopes[1] + " | " + circleSlopes[2] + " , " + circleSlopes[3] +
//" | " + circleSlopes[4] + " , " + circleSlopes[5] + " | " + circleSlopes[6] + " , " + circleSlopes[7] + " " + myShape.name + " \r");
//$.write("(" + circlePts[0] + ", " + circlePts[1] + ") (" + circlePts[2] + ", " + circlePts[3]
//+ ") (" + circlePts[4] + ", " + circlePts[5] + ") (" + circlePts[6] + ", " + circlePts[7] + ")\r");
var cirEquaDistOne = parseInt(Math.pow((myShape.pathPoints[0].anchor[0] - myShape.pathPoints[2].anchor[0]),2) +
Math.pow((myShape.pathPoints[0].anchor[1] - myShape.pathPoints[2].anchor[1]),2));
var cirEquaDistTwo = parseInt(Math.pow((myShape.pathPoints[1].anchor[0] - myShape.pathPoints[3].anchor[0]),2) +
Math.pow((myShape.pathPoints[1].anchor[1] - myShape.pathPoints[3].anchor[1]),2));
if (circleSlopes[0] != "NaN"){ // Filters out asymmetric rhombus <><><>^^^^^^<><><>
if ((circlePts[0] == circlePts[1]) && // Filters out shapes with control handles not of equal distance from anchor point.
(circlePts[1] == circlePts[2]) &&
(circlePts[2] == circlePts[3]) &&
(circlePts[3] == circlePts[4]) &&
(circlePts[4] == circlePts[5]) &&
(circlePts[5] == circlePts[6]) &&
(circlePts[6] == circlePts[7]) &&
(circlePts[7] == circlePts[0])){
if((circleSlopes[0] == circleSlopes[1]) && // Filters out the equadistant 4-pointed Star shape (dismisses negative slopes).
(circleSlopes[2] == circleSlopes[3]) &&
(circleSlopes[4] == circleSlopes[5]) &&
(circleSlopes[6] == circleSlopes[7])){
if (cirEquaDistOne == cirEquaDistTwo){ // Filters out Ellipses (non-equadistant circles).
// Filters out the very RARE 4-pointed star which has all control points in its center on top of each other!
if (((myShape.pathPoints[0].leftDirection[0]).toFixed(2) != (myShape.pathPoints[1].leftDirection[0]).toFixed(2)) &&
((myShape.pathPoints[0].leftDirection[1]).toFixed(2) != (myShape.pathPoints[1].leftDirection[1]).toFixed(2))){
myShape.iscircle = true;
} else {
myShape.iscircle = false;
}
}
}
}
}
}
}
}
}
for (x=0; x<myShapes.length ; x++){ // PROCESSING --> Now that shapes are marked, do what you want!
// ** Compound Paths: They favor top-most shape color attributes **
if (myShapes[x].isrectangle == true){ //$.writeln("A rectangle has been detected! " + [x]);
if(myShapes[x].filled == true){
myShapes[x].fillColor = makeCmykColor (0, 100, 100, 0);
}
if(myShapes[x].stroked == true){
myShapes[x].strokeColor = makeCmykColor (0, 100, 100, 0);
}
}
if (myShapes[x].iscircle == true){ //$.writeln("A circle has been detected! " + [x]);
if(myShapes[x].filled == true){
myShapes[x].fillColor = makeCmykColor (100, 100, 0, 0);
}
if(myShapes[x].stroked == true){
myShapes[x].strokeColor = makeCmykColor (100, 100, 0, 0);
}
}
}
}else {
alert("Please open up a document with some circles and rectangles & re-run.");
}
North America
Europe, Middle East and Africa
Asia Pacific