Copy link to clipboard
Copied
The script overlays hexagonal tiles above a selected path. It's a little slow, but I've tested it to up to a thousand tiles and it got the job done (in four minutes). Still, proceed within reason, as there is no error handling. It's based on this script from the defunct Scriptographer plugin.
/*
* Hexagonal Tiles by Femke Blanco
* Beta 23/06/2021
* Based on Hexagonal Rasterizer by xoihazard @ http://scriptographer.org
* License: https://scriptographer.org/license/
*/
var grid;
(app.activeDocument.groupItems.add()).name = "group";
var Grid = function(cellShape, cellSize, contentScale) {
this.cellShape = cellShape;
this.cellSize = cellSize;
this.contentScale = contentScale;
this.originX;
this.originY;
};
Grid.prototype = {
draw: function() {
app.activeDocument.groupItems["group"].remove();
var group = app.activeDocument.groupItems.add();
group.name = "group";
var source1 = app.selection[0];
var source2 = source1.duplicate(app.activeDocument);
var fence = app.activeDocument.pathItems.rectangle(
source2.top + this.cellSize, source2.left - this.cellSize,
source2.width + this.cellSize * 2, source2.height + this.cellSize * 2,
);
fence.stroked = false;
fence.filled = false;
var hypotenuse = Math.sqrt(
Math.pow(fence.width / 2, 2) + Math.pow(fence.height / 2, 2)
);
var radius = Math.ceil(hypotenuse / this.cellSize * 4 / 3);
var bounds1 = source1.geometricBounds;
var bounds2 = fence.geometricBounds;
this.originX = bounds1[0] + (bounds1[2] - bounds1[0]) / 2;
this.originY = bounds1[1] + (bounds1[3] - bounds1[1]) / 2;
var size1 = this.cellSize / 2;
var size2 = this.cellSize * Math.sqrt(3) / 2;
var size3 = this.cellSize * 3 / 4;
var counter = 1;
for (var i = 0; i < radius; i++) {
var cells = this.getCells(i);
for (var j = 0; j < cells.length; j++) {
var paths = [];
cells[j].getXY();
if (cells[j].x > bounds2[0] && cells[j].x < bounds2[2] &&
cells[j].y < bounds2[1] && cells[j].y > bounds2[3]) {
if (this.cellShape.text == "Hexagon") {
paths[j] = app.activeDocument.pathItems.polygon(
cells[j].x, cells[j].y, size1, 6
);
paths[j].rotate(90);
} else if (this.cellShape.text == "Circle") {
paths[j] = app.activeDocument.pathItems.ellipse(
cells[j].y + size2 / 2, cells[j].x - size2 / 2,
size2, size2
);
} else {
paths[j] = app.activeDocument.pathItems.rectangle(
cells[j].y + size3 / 2, cells[j].x - size2 / 2,
size2, size3
);
}
if (this.testForOverlap(paths[j], source2)) {
if (this.contentScale != 1) {
paths[j].resize(
this.contentScale * 100, this.contentScale * 100
);
}
paths[j].moveToBeginning(group);
paths[j].name = counter;
counter += 1;
} else {
paths[j].remove();
}
}
}
}
fence.remove();
source2.remove();
app.redraw();
source1.selected = true;
},
getCells: function(radius) {
var cells = [];
var cell = new Cell(-radius/2, radius);
if (radius == 0) {
cells.push(cell);
} else {
for (var i = 0; i < 6; i++) {
for (var j = 0; j < radius; j++) {
cells.push(cell);
var addend = [[1, 0], [0.5, -1], [-0.5, -1], [-1, 0], [-0.5, 1], [0.5, 1]];
cell = new Cell(cell.dx + addend[i][0], cell.dy + addend[i][1]);
}
}
}
return cells;
},
testForOverlap: function(a, b) {
var path1 = a.duplicate();
var path2 = b.duplicate();
app.selection = null;
path1.selected = true;
path2.selected = true;
app.executeMenuCommand("group");
app.executeMenuCommand("Live Pathfinder Intersect");
app.executeMenuCommand("expandStyle");
app.executeMenuCommand("ungroup");
var n = app.selection.length;
while (app.selection[0]) {
app.selection[0].remove();
}
return n == 1;
}
};
var Cell = function(dx, dy) {
this.dx = dx;
this.dy = dy;
this.x;
this.y;
};
Cell.prototype = {
getXY: function() {
this.x = grid.originX + this.dx * grid.cellSize * Math.sqrt(3) / 2;
this.y = grid.originY + this.dy * grid.cellSize * 3 / 4;
}
};
var UI = function() {
var w = new Window("dialog", "Hexagon Tiles");
var group1 = w.add("group");
group1.orientation = "row";
var group2 = group1.add("group");
group2.preferredSize.width = 81;
group2.orientation = "column";
group2.alignChildren = ["right","center"];
group2.add("statictext", undefined, "Cell Shape");
group2.add("statictext", undefined, "Cell Size");
group2.add("statictext", undefined, "Content Scale");
var group3 = group1.add("group");
group3.preferredSize.width = 81;
group3.orientation = "column";
group3.alignChildren = ["left","center"];
var drop1 = group3.add(
"dropdownlist", undefined, ["Hexagon", "Circle", "Rectangle"]
);
drop1.selection = 0;
var cellShape = drop1.selection;
drop1.onChange = function () {
cellShape = drop1.selection;
};
var edittext1 = group3.add("edittext", undefined, "10");
edittext1.characters = 7;
edittext1.active = true;
var cellSize = Number(edittext1.text);
edittext1.onChange = function () {
cellSize = Number(edittext1.text);
};
var edittext2 = group3.add("edittext", undefined, "1");
edittext2.characters = 7;
var contentScale = Number(edittext2.text);
edittext2.onChange = function () {
contentScale = Number(edittext2.text);
};
var button1 = w.add("button", undefined, "Preview");
button1.onClick = function () {
grid = new Grid(cellShape, cellSize, contentScale);
grid.draw();
};
var button2 = w.add("button", undefined, "Done");
button2.onClick = function () {
w.close();
};
w.show();
};
if (app.selection.length == 1 && app.selection[0].typename == "PathItem") {
UI();
} else {
alert("Select one path item.");
}
Copy link to clipboard
Copied
ah the great Scriptographer, brings back memories.
I was getting a somewhat inconsistent error at the line that removes the "group", I added a try/catch to fix
draw: function() {
try {
app.activeDocument.groupItems["group"].remove();
}
catch (e) {}
var group = app.activeDocument.groupItems.add();
Copy link to clipboard
Copied
Redrawing app.redraw(); the interface always slows down the script. If there is no way to do without it here, I suggest using this trick. Remember the current state of the view and temporarily bring it to full screen. Then there is no interface left on the user's monitor, which is updated every time.
button1.onClick = function () {
var userView = app.activeDocument.views[0].screenMode;
app.activeDocument.views[0].screenMode = ScreenMode.FULLSCREEN;
grid = new Grid(cellShape, cellSize, contentScale);
grid.draw();
app.activeDocument.views[0].screenMode = userView;
};
Copy link to clipboard
Copied
also, if you switch to Outline View, the screen redraws faster.