Copy link to clipboard
Copied
I like this image and don't want to straight up copy/steal it. Is there a way to EASILY get all dots and all possible connections drawn in Illustrator? I'd hate to manually draw hundreds of lines. Thanks for any help you might offer.
var n = prompt("Enter number ≥ 3", 3, "Number of points");
var d = app.activeDocument.artboards[0].artboardRect;
var paths = app.activeDocument.pathItems;
var polygon1 = paths.polygon(d[2]/2, d[3]/2, 250, n);
var points1 = polygon1.pathPoints;
for (var i = 0; i < points1.length; i++) {
for (var j = i + 1; j < points1.length; j++) {
var line1 = paths.add();
var points2 = [points1[i].anchor, points1[j].anchor];
line1.setEntirePath(points2);
}
}
polygon1.remove();
Yea, just use the Radial repeat to make enough circles, make sure to expand the object so you get the Radial Repeat split up into circle paths, and use this script, it should do what you want:
#target illustrator
function test () {
var doc = app.activeDocument;
var sel = doc.selection;
var pathUuids = [];
var thisItem;
for (var i = 0; i < sel.length; i++) {
thisItem = sel[i];
pathUuids.push(thisItem.uuid);
}
var thisPath, thisOtherPath, newLine;
var newGroup = doc.groupIte
...
Copy link to clipboard
Copied
var n = prompt("Enter number ≥ 3", 3, "Number of points");
var d = app.activeDocument.artboards[0].artboardRect;
var paths = app.activeDocument.pathItems;
var polygon1 = paths.polygon(d[2]/2, d[3]/2, 250, n);
var points1 = polygon1.pathPoints;
for (var i = 0; i < points1.length; i++) {
for (var j = i + 1; j < points1.length; j++) {
var line1 = paths.add();
var points2 = [points1[i].anchor, points1[j].anchor];
line1.setEntirePath(points2);
}
}
polygon1.remove();
Copy link to clipboard
Copied
You beat me to it! lol!
Copy link to clipboard
Copied
Nice and clean! I just put that text into a .js file and ran the script. The prompt for how many points to create was a nice touch!
My output:
Glad I got to select two right answers.
Copy link to clipboard
Copied
Yea, just use the Radial repeat to make enough circles, make sure to expand the object so you get the Radial Repeat split up into circle paths, and use this script, it should do what you want:
#target illustrator
function test () {
var doc = app.activeDocument;
var sel = doc.selection;
var pathUuids = [];
var thisItem;
for (var i = 0; i < sel.length; i++) {
thisItem = sel[i];
pathUuids.push(thisItem.uuid);
}
var thisPath, thisOtherPath, newLine;
var newGroup = doc.groupItems.add();
newGroup.name = "Lines";
for (var i = 0; i < pathUuids.length; i++) {
thisPath = doc.getPageItemFromUuid(pathUuids[i]);
for (var j = 0; j < pathUuids.length; j++) {
thisOtherPath = doc.getPageItemFromUuid(pathUuids[j]);
newLine = newGroup.pathItems.add();
newLine.setEntirePath([
[
thisPath.left + (thisPath.width / 2),
thisPath.top - (thisPath.height / 2)
],
[
thisOtherPath.left + (thisOtherPath.width / 2),
thisOtherPath.top - (thisOtherPath.height / 2)
],
]);
newLine.stroked = true;
}
}
};
test();
It is not handling duplicated lines, so there are a lot of duplicated lines on top of each other as the lines are drawn from each and every shape to each other shape - like in the case of the triangle it would make 6 lines total. Matter of fact, it also draws a line to itself - haha.
Hey, you can come up with cool jellyfish art using some effects on this.
Copy link to clipboard
Copied
Great use of uuids. Thanks for showing! - Mark
Copy link to clipboard
Copied
Nice scripts! To get rid of the duplicate lines, you could make it a Live Paint object and expand the Live Paint.
Copy link to clipboard
Copied
Ton, is it possible to make it a Live Paint object via script? I'd like to try it when I get a chance.
Copy link to clipboard
Copied
Sorry, you are asking the wrong person, I know how to use scripts, but unfortunately not how to write them 😞
I let Femkeblanco or Silly-V answer that one.
Copy link to clipboard
Copied
Well you got me thinking about it, so thanks for that! 🙂
Copy link to clipboard
Copied
You can make a live paint group from selected pathItems with
app.executeMenuCommand("Make Planet X");
but you will have to paint it manually with the Live Paint Bucket tool. Apart from expanding the live paint group ( app.executeMenuCommand("Expand Planet X") ), there's not much you can do with scripting.
Copy link to clipboard
Copied
Wonderful. Thanks.
Took me a little to figure out the Radial thing. Got that. Then, saved your code in file with .js extension.
Last thing I had to do was select all my yellow circles before running script. Got the desired result! Thanks!
Copy link to clipboard
Copied
This seemed like a good exercise so I figured I'd also give it a shot:
// You can set direct property values for the appearance here:
var options = {
anchor: {
size: 20,
filled: true,
stroked: true,
strokeWidth: 2,
fillColor: [255, 0, 0]
},
line: {
stroked: true,
strokeWidth: 2,
strokeCap: StrokeCap.ROUNDENDCAP,
strokeColor: "#ff0000"
}
};
/**
* Utilities
*/
Array.prototype.forEach = function (callback) {
for (var i = 0; i < this.length; i++) callback(this[i], i, this);
};
if (!Array.isArray)
Array.isArray = function (arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
};
RGBColor.prototype.create = function (params) {
if (/string/i.test(typeof params)) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(params);
this.red = parseInt(result[1], 16);
this.green = parseInt(result[2], 16);
this.blue = parseInt(result[3], 16);
return this;
} else if (Array.isArray(params)) {
this.red = +params[0];
this.green = +params[1];
this.blue = +params[2];
return this;
}
};
function get(type, parent) {
parent = parent ? parent : app.activeDocument;
var result = [];
if (!parent[type]) return [];
for (var i = 0; i < parent[type].length; i++)
result.push(parent[type][i]);
return result;
}
/**
* Main functions
*/
get('selection', app).forEach(function (pathItem) {
var group = app.activeDocument.groupItems.add();
get('pathPoints', pathItem).forEach(function (pathPoint, i, list) {
drawLinesFrom(pathPoint, list.slice(i + 1), group);
setAppearance(group.pathItems.ellipse(
pathPoint.anchor[1] + options.anchor.size / 2,
pathPoint.anchor[0] - options.anchor.size / 2,
options.anchor.size,
options.anchor.size
), 'anchor');
})
pathItem.remove();
})
function setAppearance(shape, type) {
for (var key in options[type])
shape[key] = (/Color$/.test(key))
? new RGBColor().create(options[type][key])
: options[type][key];
}
function drawLinesFrom(point, list, parent) {
list.forEach(function (sibling) {
var shape = parent.pathItems.add();
shape.setEntirePath([point.anchor, sibling.anchor]);
setAppearance(shape, 'line');
})
}
I've found myself doing things like this often but I'd personally rather just draw a polygon or closed shape, not the circles. So this script works off the currently selected shapes:
Converts them with configurable options to set stroke/fill colors, line widths, size of anchor shapes, etc:
It also groups the resulting shapes, removes the original path, and doesn't produce any redundant paths (triangle here is 6 paths, 3 lines + 3 ellipses):
Copy link to clipboard
Copied
I'm learning a lot from this thread! Thanks everyone.
Copy link to clipboard
Copied
Not a script guy. All I can tell is that it didn't work. Was it something I said? Wrong latitude?
Copy link to clipboard
Copied
Just edited, try now. Illustrator can be picky when it comes to prototypes.
Not really meant for an ellipse since this doesn't account for bezier handles, that's going to produce the same as a 4-sided polygon.
Copy link to clipboard
Copied
Yup, that's got it, thank you.
Peter
Copy link to clipboard
Copied
@Inventsablethis is really fun code to read and there's some super cool stuff going on in there, so thanks for sharing! If you don't mind a random question for my learning... Does the line
return result || [];
in the get function need the || [] ? At a quick glance I would think that result would always be an empty array at least. Is there something I'm missing?
- Mark
Copy link to clipboard
Copied
Good catch! This is actually a simplified version of a much larger recursive function that I normally use, I'd copy/pasted then deleted a large chunk of it when I'd placed it in here since we don't need recursion or the full function, though now that you mention it, that's probably unnecessary even in that one.
There's probably a few other mistakes or ways it could be improved still. I tend to write in Typescript, not .jsx, so I normally use ES6 syntax like arrow functions which is why my code looks a lot different than what people normally post like nested functions inside other function arguments and prototype extensions.
Copy link to clipboard
Copied
That's cool. I'm interested in Typescript. Have you managed to get set up so that you can code in TypeScript/ES6 and generate ExendScript code from it automatically?
Copy link to clipboard
Copied
Yea, that's how it work is you get your typescript set up and then you can open VSCode in that folder and ensure the ts.config file is in there - then you can run the command tsc
which generates the normal js files from it, but make sure that your ts config has the setting to output ES3-compatible code. They can start at ES5 by default. The file that is put out will have some edits and possibly make the code more verbose - but at that point you're not worried about that because the script will run as fast as ever and the code you really care about now will be your typescript code. (However, as seen proven by @Inventsable , to paste things for non-TS users takes some back-translation).
The running of the tsc command can be made to automatically run when a ts file is saved, but I've not done that yet, so maybe I'll ask @Inventsable on what the steps are.
Copy link to clipboard
Copied
Thanks Silly-V, I found it: compileOnSave in tsconfig.json.
{
"compileOnSave": true,
"compilerOptions": {
"target": "es3",
"module": "CommonJS",
"outDir": "out",
"sourceMap": true
}
}