Copy link to clipboard
Copied
Hi there all,
I'm currently using Photoshop CC to create a template for an astrology chart. I drew a circle and then drew lines at 30° increments so that my circle is cut into 12 slices. What I now need to do is create lines to mark each degree in the entire circle—in other words, I need to draw 29 lines within each of the 12 slices. Is there an automated way for me to do this or would I have to manually go in and draw every single line? Also, if I do have to draw them all manually, how would I be able to measure them to ensure that each line is a degree apart?
Thanks in advance for any tips and suggestions!
Copy link to clipboard
Copied
Ruler tool
Copy link to clipboard
Copied
Thank you for this suggestion! But as far as I understand, I can only measure with the ruler tool not draw with it. I'm wanting for each line on each degree to be visible (something like the image in this screenshot).
Copy link to clipboard
Copied
Personally, I would do this in a vector graphics editor like Illustrator or Inkscape as you have much more control.
Or you could look for a Template. I found this online.
Copy link to clipboard
Copied
Thank you for these suggestion! I unfortunately do not have either of the programs you mentioned. As far as using an already made template, I haven't been able to find one that is bare bones enough to meet my needs (as my intention is to draw in the details myself).
Copy link to clipboard
Copied
Inkscape is free.
Copy link to clipboard
Copied
Make a set of vertical ands horizontal guides that intersect at the center of the circle, and be sure Snap to Guides is set in the View menu.Use the Pen tool to make a short path with both end points on one of the guides.
Be sure Show Reference point When Using Transform is set in the preferences. Select the path with the Path Selection tool, and Control+Alt+T / Command+Option+T to transform a duplicate. Drag the reference point to the intersection of the guides. In the Angle field of the Transform options, enter 1.0°, and press Enter.
Now for every press of Shift+Control+Alt+t / Shift + Command + Option+T, you will get a new lie rotated by one degreee. For an entire circle, you would have to do this 359 times, so you'd likely want to make a Script for this.
Once you have a complete set of lines, yo can then stroke them with th Brush tool.
Copy link to clipboard
Copied
You could use a script like my RotateLayerAbout.jsx to rotate a line layer about a point. However for 360 lines you will need a thin line and a large radius. It will take some time to run and you cam merger the 360 layer in the layer group created.
Copy link to clipboard
Copied
Thank you so much for this thorough response! I will give what you've written a try, but I admit I am finding it just a tad hard to follow without any images and with my rather rudimentary knowledge of the program. I will write a follow up message once I've made my attempt!
Copy link to clipboard
Copied
The above response was meant in response to @Semaphoric, sorry for the confusion.
@JJMack this suggestion seems promising, thanks for sharing! I'm not quite sure I know what you mean by using the script, though—is it something I would have to type in somewhere?
Copy link to clipboard
Copied
Here is my script
// 2015 John J. McAssey (JJMack)
// ======================================================= */
// This script is supplied as is. It is provided as freeware.
// The author accepts no liability for any problems arising from its use.
// enable double-clicking from Mac Finder or Windows Explorer
#target photoshop // this command only works in Photoshop CS2 and higher
// bring application forward for double-click events
app.bringToFront();
// ensure at least one document open
if (!documents.length) alert('There are no documents open.', 'No Document');
else {
//Set First Time Defaults here
var dfltCpys = 12; // default number of copies including the original
var dfltPos = 4; // default Middle Center
//End Defaults
var Prefs ={}; //Object to hold preferences.
var prefsFile = File(Folder.temp + "/RotateLayerAboutPreferences.dat");
//If preferences do not exit use Defaults from above
if(!prefsFile.exists){
Prefs.Cpys = dfltCpys;
Prefs.Pos = dfltPos;
prefsFile.open('w');
prefsFile.write(Prefs.toSource());
prefsFile.close();
}
else{//Preferences exist so open them
prefsFile.open('r');
Prefs = eval(prefsFile.read());
prefsFile.close();
}
try {
function createDialog(){
// begin dialog layout
var DupRotateDialog = new Window('dialog');
DupRotateDialog.text = 'Duplicate and Rotate Layer';
DupRotateDialog.frameLocation = [78, 100];
DupRotateDialog.alignChildren = 'center';
DupRotateDialog.NumLayerPnl = DupRotateDialog.add('panel', [2, 2, 300, 56], 'Number of Layers and Rotation Anchor Point');
DupRotateDialog.NumLayerPnl.add('statictext', [10, 16, 50, 48], 'Copies ');
DupRotateDialog.NumLayerPnl.imgCpysEdt = DupRotateDialog.NumLayerPnl.add('edittext', [50, 13, 90, 34], Prefs.Cpys, {name:'imgCpys'});
DupRotateDialog.NumLayerPnl.imgCpysEdt.helpTip = 'Number of copies of selected Layer';
DupRotateDialog.NumLayerPnl.add('statictext',[96, 16, 240, 48],'Location');
var position =['Top Left','Top Center','Top Right','Center Left','Center','Center Right','Bottom Left','Bottom Center','Bottom Right','Doc Center','Samples','Path Points'];
DupRotateDialog.NumLayerPnl.dd1 = DupRotateDialog.NumLayerPnl.add('dropdownlist',[150, 13, 260, 34],position);
DupRotateDialog.NumLayerPnl.dd1.selection=Prefs.Pos;
var buttons = DupRotateDialog.add('group');
buttons.orientation = 'row';
var okBtn = buttons.add('button');
okBtn.text = 'OK';
okBtn.properties = {name: 'ok'};
var cancelBtn = buttons.add('button');
cancelBtn.text = 'Cancel';
cancelBtn.properties = {name: 'cancel'};
return DupRotateDialog;
}
dispdlg(createDialog());
function dispdlg(DupRotateDialog){
// display dialog and only continues on OK button press (OK = 1, Cancel = 2)
DupRotateDialog.onShow = function() {
var ww = DupRotateDialog.bounds.width;
var hh = DupRotateDialog.bounds.height;
DupRotateDialog.bounds.x = 78;
DupRotateDialog.bounds.y = 100;
DupRotateDialog.bounds.width = ww;
DupRotateDialog.bounds.height = hh;
}
if (DupRotateDialog.show() == 1) {
//variables passed from user interface
var copies = String(DupRotateDialog.NumLayerPnl.imgCpys.text); if (copies=="") { copies = Prefs.Cpys;}
if (isNaN(copies)) { alert("Non numeric value entered"); dispdlg(createDialog());}
else {
if (copies<2 || copies>360) { alert("Number of layer allow is 2 to 360"); dispdlg(createDialog());} // Not in range
else {
var AnchorPoint = Number(DupRotateDialog.NumLayerPnl.dd1.selection.index) + 1;
cTID = function(s) { return app.charIDToTypeID(s); };
sTID = function(s) { return app.stringIDToTypeID(s); };
// Save the current preferences
Prefs.Cpys = copies;
Prefs.Pos = Number(DupRotateDialog.NumLayerPnl.dd1.selection.index);
prefsFile.open('w');
prefsFile.write(Prefs.toSource());
prefsFile.close();
var startRulerUnits = app.preferences.rulerUnits;
var startTypeUnits = app.preferences.typeUnits;
var startDisplayDialogs = app.displayDialogs;
// Set Photoshop to use pixels and display no dialogs
app.preferences.rulerUnits = Units.PIXELS;
app.preferences.typeUnits = TypeUnits.PIXELS;
app.displayDialogs = DialogModes.NO;
app.togglePalettes();
try { app.activeDocument.suspendHistory('RotateLayerAbout','main(copies, AnchorPoint)' );}
catch(e) {alert(e + ': on line ' + e.line);}
// Return the app preferences
app.togglePalettes();
app.preferences.rulerUnits = startRulerUnits;
app.preferences.typeUnits = startTypeUnits;
app.displayDialogs = startDisplayDialogs;
}
}
}
else {
//alert('Operation Canceled.');
}
}
}
catch(err){
// Lot's of things can go wrong, Give a generic alert and see if they want the details
if ( confirm("Sorry, something major happened and I can't continue! Would you like to see more info?" ) ) { alert(err + ': on line ' + err.line ); }
}
}
function main(stemsAmount, Position) {
if ( Position == 11 && app.activeDocument.colorSamplers.length==0 ) {
alert("No Color Sampler set");
return;
}
if ( Position == 12 ) {
var thePath = selectedPath();
if (thePath == undefined) {
alert("No Path Selected");
return;
}
var myPathInfo = extractSubPathInfo(thePath);
}
// Save selected layer to variable:
var originalStem = app.activeDocument.activeLayer;
// Run the copying process
if(stemsAmount != null){
// Calculate the rotation angle
var angle = 360 / parseInt(stemsAmount);
// Create a group for stems
var stemsGroup = app.activeDocument.layerSets.add();
stemsGroup.name = originalStem.name + " ("+stemsAmount+" stems)";
// Place original layer in group
originalStem.move(stemsGroup, ElementPlacement.INSIDE);
// Duplicate and rotate layers:
for(var i = 1; i < stemsAmount; i++){
// Duplicate original layer and save it to the variable
var newStem = originalStem.duplicate();
// Rotate new layer
switch (Position){
case 1 : newStem.rotate(angle * i, AnchorPosition.TOPLEFT); break;
case 2 : newStem.rotate(angle * i, AnchorPosition.TOPCENTER); break;
case 3 : newStem.rotate(angle * i, AnchorPosition.TOPRIGHT); break;
case 4 : newStem.rotate(angle * i, AnchorPosition.MIDDLELEFT); break;
case 5 : newStem.rotate(angle * i, AnchorPosition.MIDDLECENTER); break;
case 6 : newStem.rotate(angle * i, AnchorPosition.MIDDLERIGHT); break;
case 7 : newStem.rotate(angle * i, AnchorPosition.BOTTOMLEFT); break;
case 8 : newStem.rotate(angle * i, AnchorPosition.BOTTOMCENTER); break;
case 9 : newStem.rotate(angle * i, AnchorPosition.BOTTOMRIGHT); break;
case 10 : app.activeDocument.activeLayer = newStem; rotateAroundPosition(angle * i,activeDocument.width/2,activeDocument.height/2); break;
case 11 : for (var s=0,len=app.activeDocument.colorSamplers.length;s<len;s++) {
if (s!=0) {
// Duplicate original layer and save it to the variable
var newStem = originalStem.duplicate();
}
newStem.name = originalStem.name + " " + (i+1) + " p" + (s+1) ;
app.activeDocument.activeLayer = newStem;
var colorSamplerRef = app.activeDocument.colorSamplers[s];
//alert("angle=" + (angle * i) + " ,x=" + colorSamplerRef.position[0].value + " ,y=" + colorSamplerRef.position[1].value);
rotateAroundPosition(angle * i,colorSamplerRef.position[0].value,colorSamplerRef.position[1].value);
newStem.move(stemsGroup, ElementPlacement.PLACEATEND);
};
break;
case 12 : for(var k=0;k<myPathInfo.length;k++){
for(var j=0;j<myPathInfo[k].entireSubPath.length;j++){
if (k!=0 || j!=0) {
// Duplicate original layer and save it to the variable
var newStem = originalStem.duplicate();
}
newStem.name = originalStem.name + " " + (i+1) + " p" + (j+1) ;
app.activeDocument.activeLayer = newStem;
rotateAroundPosition(angle * i,myPathInfo[k].entireSubPath[j].anchor[0],myPathInfo[k].entireSubPath[j].anchor[1]);
newStem.move(stemsGroup, ElementPlacement.PLACEATEND);
}
}
break;
default : break;
}
// Add index to new layers
if (Position!=11) {
newStem.name = originalStem.name + " " + (i+1);
// Place new layer inside stems group
newStem.move(stemsGroup, ElementPlacement.PLACEATEND);
}
};
// Add index to the original layer
if (Position!=11) originalStem.name += " 1";
else originalStem.name += " 1 p1";
};
activeDocument.activeLayer = activeDocument.layers[0]; // Target top
var groupname = app.activeDocument.activeLayer.name // remember name of group
var idungroupLayersEvent = stringIDToTypeID( "ungroupLayersEvent" ); // this part from Script Listene -- ungroup group
var desc14 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref13 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref13.putEnumerated( idLyr, idOrdn, idTrgt );
desc14.putReference( idnull, ref13 );
executeAction( idungroupLayersEvent, desc14, DialogModes.NO );
var idMk = charIDToTypeID( "Mk " ); // this part from Script Listene -- group selected layers
var desc15 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref14 = new ActionReference();
var idlayerSection = stringIDToTypeID( "layerSection" );
ref14.putClass( idlayerSection );
desc15.putReference( idnull, ref14 );
var idFrom = charIDToTypeID( "From" );
var ref15 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref15.putEnumerated( idLyr, idOrdn, idTrgt );
desc15.putReference( idFrom, ref15 );
executeAction( idMk, desc15, DialogModes.NO );
app.activeDocument.activeLayer.name = groupname // recall group name
}
function rotateAroundPosition(_angle,x,y) {
var desc1 = new ActionDescriptor();
var desc2 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
desc1.putReference(charIDToTypeID('null'), ref1);
desc1.putEnumerated(charIDToTypeID('FTcs'), charIDToTypeID('QCSt'), stringIDToTypeID("QCSIndependent"));
desc2.putUnitDouble(charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x);
desc2.putUnitDouble(charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y);
desc1.putObject(charIDToTypeID('Pstn'), charIDToTypeID('Pnt '), desc2);
desc1.putUnitDouble(charIDToTypeID('Angl'), charIDToTypeID('#Ang'), _angle);
desc1.putEnumerated(charIDToTypeID('Intr'), charIDToTypeID('Intp'), charIDToTypeID('Bcbc'));
executeAction(charIDToTypeID('Trnf'), desc1, DialogModes.NO);
}
////// determine selected path //////
function selectedPath () {
try {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
var theName = desc.getString(charIDToTypeID("PthN"));
return app.activeDocument.pathItems.getByName(theName)
}
catch (e) {
return undefined
}
};
////// michael l hale’s code //////
function extractSubPathInfo(pathObj){
var pathArray = new Array();// each element can be used as the second arugment in pathItems.add ie doc.pathItems.add("myPath1", [pathArray[0]]);
var pl = pathObj.subPathItems.length;
for(var s=0;s<pl;s++){
var pArray = new Array();
for(var i=0;i<pathObj.subPathItems[s].pathPoints.length;i++){
pArray[i] = new PathPointInfo;
pArray[i].kind = pathObj.subPathItems[s].pathPoints[i].kind;
pArray[i].anchor = pathObj.subPathItems[s].pathPoints[i].anchor;
//alert("Anchor " + pathObj.subPathItems[s].pathPoints[i].anchor );
pArray[i].leftDirection = pathObj.subPathItems[s].pathPoints[i].leftDirection;
pArray[i].rightDirection = pathObj.subPathItems[s].pathPoints[i].rightDirection;
};
pathArray[pathArray.length] = new Array();
pathArray[pathArray.length - 1] = new SubPathInfo();
pathArray[pathArray.length - 1].operation = pathObj.subPathItems[s].operation;
pathArray[pathArray.length - 1].closed = pathObj.subPathItems[s].closed;
pathArray[pathArray.length - 1].entireSubPath = pArray;
};
return pathArray;
};
Copy link to clipboard
Copied
@JJMack thank you! I've never attempted to use a script before so I will likely be following up with comments/questions.
Copy link to clipboard
Copied
You never used Image processor, Load Layer into Stack, Delete All Empty Layers,Export Layers to Files, Photomerge, Fit Image, etc.? Adobe installs quite a few Photoshop scripts for users to use.
Copy link to clipboard
Copied
No, I have not. I am relatively new to the program and, in general, use it mostly to edit images.
Copy link to clipboard
Copied
Thank you so much for this thorough response! I will give what you've written a try, but I admit I am finding it just a tad hard to follow without any images and with my rather rudimentary knowledge of the program. I will write a follow up message once I've made my attempt!