Copy link to clipboard
Copied
A while back I asked if anyone had messed about with scripting paths in Photoshop. I got little response. Anyway I persevered with the hope of creating a circle. Just for kicks, you understand (I must get out more). Turns out there isn't much info out there on the subject only that it's not possible to create a true circle with bezier curves. I've had a look it into it and I've managed a circular approximation with paths.
// draw circular path
// use at your own risk
// Author: ghoulfool
// Thanks to G. Adam Stanislav for the kappa explanation
// Kappa Kappa Hey!
app.preferences.rulerUnits = Units.PIXELS;
// OPTIONALS
var radius = 150; // radius of the circle to be drawn
var circX = 160; // centre of circle X
var circY = 160; // centre of circle Y
// create a document to work with
var docRef = app.documents.add("320px", "320px", 72, "Circle");
// call the source document
var srcDoc = app.activeDocument;
// create new layer
var layerRef = srcDoc.artLayers.add()
layerRef.name = "circle"
layerRef.blendMode = BlendMode.NORMAL
//draw circle
drawCircle(circX , circY, radius, "circle")
function drawCircle(X,Y,rad, pathName)
{
var K = (4 * (Math.sqrt(2) - 1) / 3)* rad
// define circle points
var C = new Array();
C = [X, Y - rad, X + rad, Y, X, Y + rad, X - rad, Y, X + K, Y - rad, X + rad, Y - K, X + rad, Y + K, X - K, Y + rad, X + K, Y + rad, X - rad, Y + K, X - rad, Y - K, X - K, Y - rad];
// create the array of PathPointInfo objects
var lineArray = new Array();
lineArray.push(new PathPointInfo());
lineArray[0].kind = PointKind.CORNERPOINT;
lineArray[0].anchor = new Array(C[0], C[1]); // A
lineArray[0].leftDirection = [C[8], C[9]];
lineArray[0].rightDirection = lineArray[0].anchor;
lineArray.push(new PathPointInfo());
lineArray[1].kind = PointKind.CORNERPOINT;
lineArray[1].anchor = new Array(C[2], C[3]); // B
lineArray[1].leftDirection = [C[12], C[13]];
lineArray[1].rightDirection = [C[10], C[11]];
lineArray.push(new PathPointInfo());
lineArray[2].kind = PointKind.CORNERPOINT;
lineArray[2].anchor = new Array(C[4], C[5]); // C
lineArray[2].leftDirection = [C[14], C[15]];
lineArray[2].rightDirection = [C[16], C[17]];
lineArray.push(new PathPointInfo());
lineArray[3].kind = PointKind.CORNERPOINT;
lineArray[3].anchor = new Array(C[6], C[7]); // D
lineArray[3].leftDirection = [C[20], C[21]];
lineArray[3].rightDirection = [C[18], C[19]];
lineArray.push(new PathPointInfo());
lineArray[4].kind = PointKind.CORNERPOINT;
lineArray[4].anchor = new Array(C[0], C[1]);
lineArray[4].leftDirection = lineArray[4].anchor;
lineArray[4].rightDirection = [C[22], C[23]];
// create a SubPathInfo object, which holds the line array in its entireSubPath property.
var lineSubPathArray = new Array();
lineSubPathArray.push(new SubPathInfo());
lineSubPathArray[0].operation = ShapeOperation.SHAPEXOR;
lineSubPathArray[0].closed = false;
lineSubPathArray[0].entireSubPath = lineArray;
//create the path item, passing subpath to add method
var myPathItem = docRef.pathItems.add(pathName, lineSubPathArray);
// set foreground colour to green
var fgColor = new SolidColor;
fgColor.rgb.hexValue="00ff80" //green colour
foregroundColor = fgColor
//fill the path
myPathItem.fillPath(fgColor,ColorBlendMode.NORMAL,100,false,0,true,true);
//deselect path
// =======================================================
var id630 = charIDToTypeID( "Dslc" );
var desc154 = new ActionDescriptor();
var id631 = charIDToTypeID( "null" );
var ref127 = new ActionReference();
var id632 = charIDToTypeID( "Path" );
ref127.putClass( id632 );
desc154.putReference( id631, ref127 );
executeAction( id630, desc154, DialogModes.NO );
}
This was my second attempt. The first was on a semi circle basis with two points - but the circles looked very oval. This is much better I feel.
Enjoy!
Copy link to clipboard
Copied
Turns out there isn't much info out there on the subject only that it's not possible to create a true circle with bezier curves.
Is that so indeed?
The Ellipse Tool (constrained) seems to create a decent crircular Path and if that is pasted above itself and rotated I cannot notice any misalignments.
Copy link to clipboard
Copied
I was well aware that you can convert the ellipsis tool to a path (make work path) but the resulting path is perfectly circular, but rather messy (in terms of point placement)
The whole point of the exercise was for me to gain a better understanding on how bezier paths work within scripting. So i'm happy.
Copy link to clipboard
Copied
The result of the Ellipse Tool is a Path (with 4 points), did you mean the Elliptical Marquee Tool?
Edit: I mean the Ellipse Tool which is tertiary to the Rectangle Tool (U).
Copy link to clipboard
Copied
c.pfaffenbichler:
You're right about the ellipse tool. It does a good job. Yes....and there was a bit of confusion with Ellipse tool and Elliptical Marquee Tool.
Copy link to clipboard
Copied
This would be very easy to do with scriptlistner code using either the elliptical marquee tool or elliptical tool. The elliptical tool can create a Path directly and the elliptical marquee tool can create selection which in turn can be turned in a path all can be transformed. The elliptical tool would create a better Path a circle would have 4 point. Converting a slection is to a path would not work that well.
I created a plug-in script based on "Fit Image.jsx" that combine the rectangle and elliptical selection tools so you can record making aspect ratio selection for documents in actions. The plugin http://www.mouseprints.net/old/dpr/AspectRatioSelection.jsx
/* ==========================================================
// Christmass 2007 John J. McAssey (JJMack) and the
// Day I descovered Photoshop had what I wanted
// a way to pass Prams to Scripts throught menu File>Automate
// ======================================================= */
/* SetMarqueeSelection function from Scriptlistner plugin
// ========================================================================== */
function setMarqueeSelection(x1, y1, x2, y2, type, shape, feather, antiAlias) {
var SelectionType =null;
if (type ==null) { var SelectionType = "setd" }
if (type ==diminish) { var SelectionType = "SbtF" }
if (type ==extend) { var SelectionType = "AddT" }
if (type ==intersect) { var SelectionType = "IntW" }
if (type ==replace) { var SelectionType = "setd" }
var id3 = charIDToTypeID( SelectionType );
var desc2 = new ActionDescriptor();
var id4 = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var id5 = charIDToTypeID( "Chnl" );
var id6 = charIDToTypeID( "fsel" );
ref1.putProperty( id5, id6 );
desc2.putReference( id4, ref1 );
var id7 = charIDToTypeID( "T " );
var desc3 = new ActionDescriptor();
var id8 = charIDToTypeID( "Top " );
var id9 = charIDToTypeID( "#Pxl" );
desc3.putUnitDouble( id8, id9, y1 );
var id10 = charIDToTypeID( "Left" );
var id11 = charIDToTypeID( "#Pxl" );
desc3.putUnitDouble( id10, id11, x1 );
var id12 = charIDToTypeID( "Btom" );
var id13 = charIDToTypeID( "#Pxl" );
desc3.putUnitDouble( id12, id13, y2 );
var id14 = charIDToTypeID( "Rght" );
var id15 = charIDToTypeID( "#Pxl" );
desc3.putUnitDouble( id14, id15, x2 );
var id16 = charIDToTypeID( shape );
desc2.putObject( id7, id16, desc3 );
var id17 = charIDToTypeID( "Fthr" );
var id18 = charIDToTypeID( "#Pxl" );
desc2.putUnitDouble( id17, id18, feather );
var id19 = charIDToTypeID( "AntA" );
desc2.putBoolean( id19, antiAlias );
executeAction( id3, desc2, DialogModes.NO );
}