xxxxxxxxxx
341
//Automatic Shadowbox Generator
//by Philip Sutherland
//www.psuth.art
//This utility generates .svg files that can be used with a laser cutter to create shadowboxes for printed art. To use, configure the below variables to your specifications, and run the program. It will generate and download .svg files for the front and back panels, as well as for the middle dividers. It will also display a preview of the background fractal it generated. Some assembly required post-cut.
// -- //
//Configurable variables:
//The width and height of the center boundary of the frame, in inches.
//Width must be < 9.4 inches and > 2.5 inches
//Height must be < 14.2 inches and > 2.5 inches
let artWidthInches = 5
let artHeightInches = 4.6
//Set the thickness in inches of the frame and backing material (wood) and the middle layer material (acrylic).
let woodThicknessInches = 0.11
let acrylicThicknessInches = 0.18
//if false, only generates a cut for a single acrylic panel.
let doubleAcrylicPanels = true
//Set the radius of the box's rounded corners.
let edgeRoundingRadius = 20
//if false, does not generate the three mounting holes on the back of the box.
let mountingCircles = true
//End configurable variables
// -- //
let distance = 5;
let engraveColor;
let cutColor;
let artWidth
let artHeight
let materialThickness
let angle1
let angle2
function setup() {
//1728 px = 24 in, 1296 px = 18 in
createCanvas(1728, 1296, SVG);
angleMode(DEGREES);
colorMode(RGB)
engraveColor = color(0,0,255);
cutColor = color(255,0,0);
artWidth = artWidthInches * 72
artHeight = artHeightInches * 72
materialThickness = (woodThicknessInches * 72)
angle1 = random(360)
angle2 = random(360)
print('angle1: ' + angle1 + " angle2: " + angle2)
}
function draw() {
noLoop();
noFill();
strokeWeight(0.001);
stroke(cutColor);
//Draws acrylic dividers
push()
translate(10, 10)
rect(0, 0, artWidth + (artWidth/4), artHeight + (artHeight/4), edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius)
//back panel inner frame
stroke(engraveColor)
rect((artWidth/8), (artHeight/8), artWidth, artHeight)
stroke(cutColor)
notchPanel(true);
pop()
if (doubleAcrylicPanels){
//Draws acrylic dividers
push()
translate(20 + artWidth + (artWidth/4), 10)
rect(0, 0, artWidth + (artWidth/4), artHeight + (artHeight/4), edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius)
//back panel inner frame
stroke(engraveColor)
rect((artWidth/8), (artHeight/8), artWidth, artHeight)
stroke(cutColor)
notchPanel(true);
pop()
}
save("export/artDividers." + artWidthInches + "x" + artHeightInches + ".svg");
clear()
stroke(cutColor);
//Draws frame
push()
translate(10, 10)
rect(0, 0, artWidth + (artWidth/4), artHeight + (artHeight/4), edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius)
//frame inner
rect((artWidth/8), (artHeight/8), artWidth, artHeight)
notchPanel(false)
//cuts vertical connecting pieces from the frame
let connectorHeight;
let connectorsTranslated;
if(doubleAcrylicPanels){
connectorHeight = 2 * woodThicknessInches * 72 + 2 * acrylicThicknessInches * 72
}
else{
connectorHeight = 2 * woodThicknessInches * 72 + acrylicThicknessInches * 72
}
if (connectorHeight * 2 > artWidth){
connectorsTranslated = true
push()
translate((2 * (artWidth + (artWidth/4))), -(artHeight/8))
rect((artWidth/8), (artHeight/8), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8), (artHeight/8) + ((artHeight + (artHeight/4))/4), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8) + ((artHeight + (artHeight/4))/4), connectorHeight, ((artHeight + (artHeight/4))/4))
push()
translate(2*connectorHeight,0)
rect((artWidth/8), (artHeight/8), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8), (artHeight/8) + ((artWidth + (artWidth/4))/4), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8) + ((artWidth + (artWidth/4))/4), connectorHeight, ((artWidth + (artWidth/4))/4))
pop()
pop()
}
else if (connectorHeight * 4 > artWidth){
connectorsTranslated = true
rect((artWidth/8), (artHeight/8), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8), (artHeight/8) + ((artHeight + (artHeight/4))/4), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8) + ((artHeight + (artHeight/4))/4), connectorHeight, ((artHeight + (artHeight/4))/4))
push()
translate((2 * (artWidth + (artWidth/4))), -(artHeight/8))
// translate(2*connectorHeight,0)
rect((artWidth/8), (artHeight/8), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8), (artHeight/8) + ((artWidth + (artWidth/4))/4), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8) + ((artWidth + (artWidth/4))/4), connectorHeight, ((artWidth + (artWidth/4))/4))
pop()
}
else{
rect((artWidth/8), (artHeight/8), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8), (artHeight/8) + ((artHeight + (artHeight/4))/4), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8), connectorHeight, ((artHeight + (artHeight/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8) + ((artHeight + (artHeight/4))/4), connectorHeight, ((artHeight + (artHeight/4))/4))
push()
translate(2*connectorHeight,0)
rect((artWidth/8), (artHeight/8), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8), (artHeight/8) + ((artWidth + (artWidth/4))/4), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8), connectorHeight, ((artWidth + (artWidth/4))/4))
rect((artWidth/8) + connectorHeight, (artHeight/8) + ((artWidth + (artWidth/4))/4), connectorHeight, ((artWidth + (artWidth/4))/4))
pop()
}
pop()
//Draws back panel
push()
translate(20 + artWidth + (artWidth/4), 10)
rect(0, 0, artWidth + (artWidth/4), artHeight + (artHeight/4), edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius)
//back panel inner frame
stroke(engraveColor)
rect((artWidth/8), (artHeight/8), artWidth, artHeight)
stroke(cutColor)
notchPanel(true);
//Draws fractal pattern
// fractal((artWidth + (artWidth/4))/2,(artHeight + (artHeight/4))/2,100,90, 0)
fractal(0,0,artHeight/3,45, 0)
fractal((artWidth + (artWidth/4)),(artHeight + (artHeight/4)),artHeight/3,-135, 0)
pop()
save("export/artFrontBack." + artWidthInches + "x" + artHeightInches + ".svg");
strokeWeight(1)
//Draws back panel
push()
translate(20 + artWidth + (artWidth/4), 10)
rect(0, 0, artWidth + (artWidth/4), artHeight + (artHeight/4), edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius,edgeRoundingRadius)
//back panel inner frame
stroke(engraveColor)
rect((artWidth/8), (artHeight/8), artWidth, artHeight)
stroke(cutColor)
notchPanel(true);
//Draws fractal pattern
// fractal((artWidth + (artWidth/4))/2,(artHeight + (artHeight/4))/2,100,90, 0)
fractal(0,0,artHeight/3,45, 0)
fractal((artWidth + (artWidth/4)),(artHeight + (artHeight/4)),artHeight/3,-135, 0)
pop()
}
//draw notches on all panel sides, optionally with circles
function notchPanel(circles) {
//top notches
push()
translate(0,0)
rotate(0)
//create notches at material thickness, at 1/4 frame length
if (circles){
drawNotches(true, true);
}
else{
drawNotches(false, true);
}
pop()
//right notches
push()
translate(artWidth + (artWidth/4),0)
rotate(90)
//create notches at material thickness, at 1/4 frame length
if (circles){
drawNotches(true, false);
}
else{
drawNotches(false, false);
}
pop()
//bottom notches
push()
translate(artWidth + (artWidth/4), artHeight + (artHeight/4))
rotate(180)
//create notches at material thickness, at 1/4 frame length
drawNotches(false, true);
pop()
//left notches
push()
translate(0, artHeight + (artHeight/4))
rotate(270)
//create notches at material thickness, at 1/4 frame length
if (circles){
drawNotches(true, false);
}
else{
drawNotches(false, false);
}
pop()
}
//create notches at material thickness, at 1/4 frame length
function drawNotches(circles, horizontal) {
if (horizontal){
rect(((artWidth + (artWidth/4))/8),0,((artWidth + (artWidth/4))/4), materialThickness)
rect(5*((artWidth + (artWidth/4))/8),0,((artWidth + (artWidth/4))/4), materialThickness)
//create mounting circle
if (circles && mountingCircles){
circle(4*((artWidth + (artWidth/4))/8),(artHeight/8)/2, ((artHeight/8)/3))
}
}
else{
rect(((artHeight + (artHeight/4))/8),0,((artHeight + (artHeight/4))/4), materialThickness)
rect(5*((artHeight + (artHeight/4))/8),0,((artHeight + (artHeight/4))/4), materialThickness)
//create mounting circle
if (circles && mountingCircles){
circle(4*((artHeight + (artHeight/4))/8),(artHeight/8)/2, ((artHeight/8)/3))
}
}
}
function fractal(x, y, length, angle, gen){
stroke(engraveColor);
let x2 = x + cos(angle) * length;
let y2 = y + sin(angle) * length;
gen++;
if(gen < 10 && x2 < artWidth + (artWidth/4) && y2 < artHeight + (artHeight/4) && x2 > 0 && y2 > 0){
line(x, y, x2, y2)
fractal(x2, y2, length * 0.8, angle + angle1, gen)
fractal(x2, y2, length * 0.8, angle + angle2, gen)
}
}
// function keyPressed() {
// if (keyCode == 83) {
// // s
// save("artFrameTest.svg");
// }
// }