Skip to content

Commit

Permalink
shadowbox
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliver Jensen committed Mar 28, 2024
1 parent e60c8d7 commit b9467ce
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 0 deletions.
112 changes: 112 additions & 0 deletions boxes/generators/shadowbox.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Copyright (C) 2024 Oliver Jensen
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from boxes import *
from boxes.lids import LidSettings


class Shadowbox(Boxes):
"""The frame and spacers necessary to display a shadowbox / lightbox."""

description = """
The frame needed to build a shadowbox from paper cutouts.
The cutout used in the photographs can be downloaded [here](https://3axis.co/laser-cut-my-neighbor-totoro-3d-lightbox-lamp-cdr-file/eoxldrxo/).
See the diagram below for dimensions.
![diagram](static/samples/Shadowbox-diagram.jpg)
![backlit](static/samples/Shadowbox-backlit.jpg)
"""

ui_group = "Misc"

def __init__(self) -> None:
Boxes.__init__(self)
self.addSettingsArgs(edges.FingerJointSettings)
self.addSettingsArgs(edges.DoveTailSettings, angle=10, depth=1.5, radius=0.1, size=1)
self.buildArgParser(x=200, y=260)
self.argparser.add_argument(
"--layers", action="store", type=int, default=7,
help="the number of paper layers; don't forget the back (blank) layer!")
self.argparser.add_argument(
"--framewidth", action="store", type=float, default=10,
help="the width of the paper layer frames")
self.argparser.add_argument(
"--frameheight", action="store", type=float, default=10,
help="the height of the paper layer frames")
self.argparser.add_argument(
"--extraheight", action="store", type=float, default=20,
help="cumulative height of your paper layers, play between frames, the LED strip, battery/wiring, anything else you want to fit in the case")
self.argparser.add_argument(
"--casejoinery", action="store", type=boolarg, default=True,
help="whether or not to join sides to front plate (disable if doing manual joins on fancy wood)")

def render(self):
x, y = self.x, self.y
t = self.thickness
extraheight = self.extraheight
frameheight = self.frameheight
framewidth = self.framewidth
casejoinery = self.casejoinery
layers = self.layers
height = layers * t + extraheight

# inner frames horizontal bars
for _ in range(2*layers):
self.polygonWall([
x, 90,
frameheight, 90,
framewidth, 0, x - framewidth*2, 0, framewidth, 90,
frameheight, 90],
"eeDeDe", move="up")

# inner frames vertical bars
for _ in range(2*layers):
self.rectangularWall(y - frameheight*2, framewidth, "eded", move="up")

# faceplate
hypotenuse = math.sqrt((frameheight+t)**2 + (framewidth+t)**2)
angle = math.degrees(math.acos((framewidth+t) / hypotenuse))
edgetypes = 'eFeeee' if casejoinery else 'eeeeee'

vframe_poly = [
t, 0, y, 0, t, 90+angle,
hypotenuse, 90-angle,
y - frameheight*2, 90-angle,
hypotenuse, 90+angle]
hframe_poly = [
t, 0, x, 0, t, 90+angle,
hypotenuse, 90-angle,
x - framewidth*2, 90-angle,
hypotenuse, 90+angle]

self.polygonWall(vframe_poly, edgetypes, move="up")
self.polygonWall(vframe_poly, edgetypes, move="up")

angle = 90 - angle
self.polygonWall(hframe_poly, edgetypes, move="up")
self.polygonWall(hframe_poly, edgetypes, move="up")

# case sides
print(height)
if casejoinery:
top_edge = 'f'
else:
top_edge = 'e'
self.rectangularWall(x, height, "ef{}f".format(top_edge), move="up")
self.rectangularWall(x, height, "ef{}f".format(top_edge), move="up")
self.rectangularWall(y, height, "eF{}F".format(top_edge), move="up")
self.rectangularWall(y, height, "eF{}F".format(top_edge), move="up")
Binary file added static/samples/Shadowbox-backlit-thumb.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/samples/Shadowbox-backlit.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/samples/Shadowbox-diagram-thumb.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/samples/Shadowbox-diagram.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/samples/Shadowbox-thumb.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/samples/Shadowbox.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b9467ce

Please sign in to comment.