nutradial
Explorer
nutradial
Explorer
Activity
Feb 03, 2025
08:49 PM
I agree that using the index values instead of the coordinates makes more sense. I guess what I am really after, and once I figure it out I can use it in many other ways, is to use the array to select the anchors. Push the pathItem name and anchor point index of the selected anchors to "selectedPoints" array and then use it to match and reselect the anchors at some other time.
... View more
Feb 03, 2025
09:49 AM
What I would like to do: Select pathItem anchor point(s) with Direct Selection Tool and store the coordinates to "selectedPoints" array (pathItems will have unique names). At some other point, select the same pathItem via script and by matching coordinates in "selectedPoints" array automatically select the matching anchor point(s). I will store the coordinates in their original form and understand that the pathItem can't move in order for the anchor point selection to work.
... View more
Feb 03, 2025
05:40 AM
Can you help me take this one step further? Assuming the pathItems are a new selection, using the "selectedPoints" array to match coordinates and select the achorpoints.
... View more
Feb 03, 2025
05:11 AM
I overlooked implementing the hasOwnProperty method along with PathPointSelection.ANCHORPOINT. Thank you for taking the time and the valuable feedback.
... View more
Feb 01, 2025
05:33 PM
Using the Direct Selection Tool I would like to target a single anchor point on multiple pathItems and return their index so I can push their respective X and Y coordinates to an array. I am enclosing a code snippet where the index is static and not stemming from the selection. var idoc = app.activeDocument;
var pathSelection = idoc.selection;
var pathAnchors = [];
for (var i = 0; i < pathSelection.length; i++) {
var selectedPath = pathSelection[i];
// anchor point of the selected path
var selectedAnchorPoint = selectedPath.pathPoints[0]; // help acquiring pathPoints index from selection
// x and y coordinates
var anchorX = selectedAnchorPoint.anchor[0];
var anchorY = selectedAnchorPoint.anchor[1];
pathAnchors.push({x: anchorX, y: anchorY});
alert("<<< Array Contents >>>\n\nX: " + pathAnchors[i].x + "\n\nY: " + pathAnchors[i].y);
}
... View more
Jan 31, 2025
08:47 AM
I am in need of a reliable solution to manipulate pathItems in a one-to-many relationship similar to that of how a relational database works. I am open to any method as long as it adheres to the following requirements: The parent pathItem (“File 1”) must reside in a separate layer with unknown layer hierarchy Exclusion of all other pageItems that are not pathItems The relational aspect of the pathItems would ideally be hidden from the end-user Names (pathItem.name) need to remain unchanged although could be temporarily manipulated “Assets” layer is to remain locked and will always be a top-level layer “Assets” layer pathItems (“File 1 Asset 1” and “File 2 Asset 1”) will always be hidden My current workflow generates unique ID numbers and assigns them to the parent pathItem and children automatically. My approach is to use hidden tags using the following method: // method to add hidden tag
var pathItemTagID = selectedItem.tags.add();
pathItemTagID.name = "pathItemID";
pathItemTagID.value = pathItemNumber;
// method to create ID pathItemNumber
var pathItemNumber = generateRandomNumber(1, 1000);
function generateRandomNumber(min, max) {
var randomValue = Math.random();
var randomNumber = Math.floor(randomValue * (max - min + 1)) + min;
return randomNumber;
}
// methods for accessing the hidden tags:
alert("<<< ID Match >>>\n\n" + selectedItem.tags.getByName("pathItemID").name + "\n\n" + selectedItem.tags.getByName(“pathItemID”).value);
alert("<<< ID Match >>>\n\n" + selectedItem.tags[0].name + "\n\n" + selectedItem.tags[0].value); To keep things simple all I need is the ability to delete pathItem (“File 1”) in the “Working Files” layer and consequently all of the related child pathItems (hidden or locked) in the “Assets” layer (“File 1 Asset 1”, “File 1 Asset 2” and “File 1 Asset 3”). I am in the hopes that this topic would be of value to others as well.
... View more
Jan 29, 2025
05:10 AM
1 Upvote
I am implementing pattern matches in several scripts once @m1b showed me their utility a while back. I've spent time on the RegEx and GREP reference materials and my patterns and group result have only grown in complexity. As they say "less is more" ... the nuances in this post are next-level: Matching a group after the main expression without including it in the result by using "lookarounds". Using "OR" and its ability to condense the pattern results. In the case of this post using the alternation produces a direct match without creating a group. Using word boundaries to match between a word character and non-word character or position. I'll be revising my patterns and surely condensing them as a result of this post.
... View more
Jan 28, 2025
04:25 PM
That's the one ... short and sweet. Thanks. // original
/(^TEST #(\d{1,2})(\s[\s\S]+)?)$/
// with OR
/^TEST #(\d{1,2})(?=\s|$)/
... View more
Jan 28, 2025
09:40 AM
1 Upvote
Better together ... thanks for your help and for teaching me the use of the positive lookahead and how it does not include it in the results. /(^TEST$)?(^TEST(?=\s))?/ This seems to work a little better ... it takes care of the TEST1 or TESTa as that they were being included in the original search pattern.
... View more
Jan 28, 2025
06:46 AM
I am trying to validate my RegEx GREP search match in the following way: Match results in the string (TEST) The word TEST starts the pattern (^TEST) but a white space (\s) is required for any other character to follow. Valid strings: TEST TEST 123 TEST abc Invalid strings: TEST1 TESTa Looking for a method where the pattern match returns the string (TEST) and not (TEST ) with the white space included. At the same time the match needs to fail if any character other than the white space immediatly follows TEST.
... View more
Jan 19, 2025
10:04 PM
I figured as much .. thanks for the confirmation. As a workaround I will figure out a way to create groups of the pathItems using RegExp search pattern matches instead of placing them inside sublayers.
... View more
Jan 19, 2025
01:39 AM
I have a script that adds a new parent layer and organises pageItems in sublayers. I wish for the view of the new layers to be collapsed rather than expanded and only show the parent layer. Thanks.
... View more
Jan 13, 2025
02:24 PM
I am in need of a script that adds arrow labels to pathItems. I would like to use Unicode characters in order to not rely on any pre-existing symbols or external configuration. I have included a sample of the code that I normally use to add labels to the bottom center of a path. I could use some help in adding the proper logic to have the Unicode arrow character point in the proper direction according to the index of the path's anchor points. #target illustrator;
var idoc = app.activeDocument;
middleBottom();
//========== (Create Label and Place Horizontal Center and Bottom of Path) ==========
function middleBottom() {
var labelMargin = 5;
var label = idoc.layers.getByName('Layer 1').textFrames.add();
label.name = "Path Label";
label.contents = "\u2190";
label.opacity = 25.0;
label.textRange.characterAttributes.textFont = textFonts.getByName('ArialMT');
label.textRange.characterAttributes.size = 12;
var refBnds = idoc.layers.getByName('Layer 1').pathItems[0].geometricBounds;
var objBnds = idoc.layers.getByName('Layer 1').pathItems[0];
var tg = idoc.layers.getByName('Layer 1').textFrames.getByName('Path Label');
var ct = (refBnds[0] - (tg.width / 2)) + (objBnds.width / 2); // center
var md = refBnds[1] - (tg.height - labelMargin); //bottom
tg.position = [ct, md];
idoc.selection = null;
}
... View more
Dec 23, 2024
08:21 AM
@m1b Nice update. I like how it splits up compoundPathItems and groupItems into new individual top-level layers. It does create an empty top-level layer when it does this which is not a big deal. Thanks again, I'm learinng a lot from your posts.
... View more
Dec 20, 2024
07:35 AM
To bring it all home and finish the lesson ... how about within a sublayer.
... View more
Dec 20, 2024
05:07 AM
What needs to change to have the "One Item Per Layer.js" script only affect a specific layer (i.e. Layer 2)?
... View more
Dec 18, 2024
05:34 PM
I am looking for a script that moves all individual items to their own layer using the same layer name.
... View more
Dec 14, 2024
07:15 AM
I added a third parameter to my search pattern and was wondering if "named capturing groups" in ExtendScript are fully supported? XX T7 L3 D0.125 ==> Pattern match 1 (XX T7) Pattern match 2 (L3) Pattern match 3 (D0.125) /(?<t>^XX T(\d{1,2}))?(?<l> ?L(\d{1,2}))?(?<d> ?D(\d*\.?\d{1,3}))?/g Examples of matches: XX T7 XX T7 L3 XX T7 D0.125 XX T7 L3 D0.125 XX T7 D0.125 L3 L3 D0.125 L3 D0.125 D0.125 L3 Named capturing groups: t = 7 l = 3 d = 0.125 If named capturing groups are viable can you please update your initial snippet of code for reference. I am using the search and match method to trigger events based on layer names. This thread has not only been of high utility but very educational. Thanks.
... View more
Dec 11, 2024
08:11 AM
I was able to make it work using: if ((!T) && layer.name !== ""). // for T is NaN if ((!!T) && layer.name !== ""). // for T has value
... View more
Dec 11, 2024
06:36 AM
This might be off topic and I'll gladly create a new thread if need be: T = match.length > 1 ? Number(match[2]) : undefined; When T is NaN in the match I would like to use it as follows but it fails to resolve: if (layer.name !== "" && T == null) { // this fails ==> while testing for NaN if (layer.name !== "" && (!!T)) { // this works ==> when T has value
... View more
Dec 11, 2024
04:49 AM
To me the best part of this post is how you structured the regex to return the T and L value. I appreciate it ...I learned something very useful. var regex = /^XX T(\d{1,2})(?: L(\d{1,2}))?/;
... View more
Dec 10, 2024
10:40 PM
Can the match method as implemented above be used outside an object? I am already iterating layer.name
... View more
Dec 10, 2024
09:15 PM
Nice!!! Thanks.
... View more
Dec 10, 2024
08:45 PM
// constraints are: // XX T will always be first and in caps ==> ^XX T // T will always have a value of max of 2 digits ==> {1,2} // L may or may not be present but if present will always have a value of max of 2 digits ==> {1,2} // the digits of L if present will always be the end of the string ==> (/\d+$/) var testName1 = "XX T3 L22"; // viable upper case search(/^XX T\d{1,2}( L\d{1,2}$)/g) var testName2 = "XX T44 L1"; var testName3 = "XX T5"; // viable upper case search(/^XX T\d{1,2}$/g) var testName4 = "XX T66; // for testName1 ==> lNumber1 = 22 if (testName1.toString().search(/^XX T\d{1,2}( L\d{1,2}$)/g) === 0) lNumber1 = testName1.toString().replace((/^XX T\d{1,2}( L\d{1,2}$)/g), testName1.toString().match(/\d+$/)); // how can I return the T value in all 4 examples? // results: // lNumber1 = 3 // lNumber2 = 44 // lNumber3 = 5 // lNumber4 = 66
... View more
Dec 05, 2024
06:26 PM
I am trying to create a script that iterates thru the selected pathItems on the artboard and adds their name to an array but at the start of each group of pathItems that have the same name I would like a header child. Artboard pathItems: 3 - pathItem.name = lemon 2 - pathItem.name = orange 3 - pathItem.name = peach Header child: pathObj.addChild("These are lemons:"); pathObj.addChild("These are oranges:"); pathObj.addChild("These are peaches:"); Resulting array: [These are lemons:, lemon, lemon, lemon, These are oranges:, orange, orange, These are peaches:, peach, peach, peach] Any help would be greatly appreciated.
... View more
Nov 12, 2024
05:06 AM
I thought my script was not working due to JavaScript compatibility but I now realize that that is not the case. Also, this is probably not the place to look for these kinds of answers but if anyone is curious I need the ExtendScript formula for a path's tangential angle that resolves in degrees.
... View more
Nov 11, 2024
11:19 AM
1 Upvote
I think it is not necessary to spend any more time on this given that from a utility perspective the initial solution works just fine and from an educational one we really would'nt be expanding on any new concepts. Thanks for your help.
... View more
Nov 11, 2024
10:55 AM
// cos(θ) = (a · b) / (||a|| * ||b||)
function angleBetweenVectors(x1, y1, x2, y2) {
// Calculate the dot product
const dotProduct = x1 * x2 + y1 * y2;
// Calculate the magnitudes
const magnitude1 = Math.sqrt(x1 * x1 + y1 * y1);
const magnitude2 = Math.sqrt(x2 * x2 + y2 * y2);
// Calculate the cosine of the angle
const cosTheta = dotProduct / (magnitude1 * magnitude2);
// Calculate the angle in radians
const angleInRadians = Math.acos(cosTheta);
// Convert to degrees (if needed)
const angleInDegrees = (angleInRadians * 180) / Math.PI;
return angleInDegrees;
}
// Example usage for your vectors:
const angle = angleBetweenVectors(0, 0, 0, 20);
console.log(angle); // Output: 90 degrees
... View more
Nov 11, 2024
10:46 AM
Help converting JavaScript code to ECMAScript 3 to solve the angle 𝑎⋅𝑏|𝑎||𝑏|=cos𝜃 where X0 Y0 . X0 Y20 // What is the angle?
// 𝑎⋅𝑏|𝑎||𝑏|=cos𝜃, X0 Y0 . X0 Y20
function cosineTheta(a, b) {
let dotProduct = 0;
let aMagnitude = 0;
let bMagnitude = 0;
// Calculate dot product
for (let i = 0; i < a.length; i++) {
dotProduct += a[i] * b[i];
}
// Calculate magnitudes
for (let i = 0; i < a.length; i++) {
aMagnitude += a[i] * a[i];
bMagnitude += b[i] * b[i];
}
aMagnitude = Math.sqrt(aMagnitude);
bMagnitude = Math.sqrt(bMagnitude);
// Calculate cosine
return dotProduct / (aMagnitude * bMagnitude);
}
// Example usage needs to solve for X0 Y0 . X0 Y20 in 2D plane
// where the resulting angle between the vectors a and b is 90°
const vectorA = [1, 2, 3];
const vectorB = [4, 5, 6];
const cosTheta = cosineTheta(vectorA, vectorB);
console.log(cosTheta);
... View more