boxespy/boxes/generators/dicebox.py

125 lines
4.7 KiB
Python
Raw Normal View History

2022-08-10 20:20:04 +02:00
#!/usr/bin/env python3
# Copyright (C) 2022 Erik Snider (SniderThanYou@gmail.com)
#
# 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 *
class DiceBox(Boxes):
"""Box with lid and integraded hinge for storing dice"""
ui_group = "Box"
2022-08-10 20:20:04 +02:00
2023-01-08 19:41:02 +01:00
def __init__(self) -> None:
2022-08-10 20:20:04 +02:00
Boxes.__init__(self)
self.addSettingsArgs(
edges.FingerJointSettings,
surroundingspaces=2.0)
self.addSettingsArgs(
edges.ChestHingeSettings,
finger_joints_on_box=True,
finger_joints_on_lid=True)
self.buildArgParser(
x=100,
y=100,
h=18,
outside=True)
self.argparser.add_argument(
"--lidheight", action="store", type=float, default=18,
help="height of lid in mm")
self.argparser.add_argument(
"--hex_hole_corner_radius", action="store", type=float, default=5,
help="The corner radius of the hexagonal dice holes, in mm")
self.argparser.add_argument(
"--magnet_diameter", action="store", type=float, default=6,
help="The diameter of magnets for holding the box closed, in mm")
def diceCB(self):
t = self.thickness
xi = self.x - 2 * t
yi = self.y - 2 * t
xc = xi / 2
yc = yi / 2
cr = self.hex_hole_corner_radius
# -4*t because there are four gaps across:
# 2 between the outer holes and the finger joints
# 2 between the outer holes and the center hole
# /6 because there are 6 apothems across, 2 for each hexagon
apothem = (min(xi, yi) - 4 * t) / 6
r = apothem * 2 / math.sqrt(3)
# dice
centers = [[xc, yc]] # start with one in the center
polar_r = 2 * apothem + t # the full width of a hexagon, plus a gap of t width
for i in range(6):
theta = i * math.pi / 3 # 60 degrees each step
centers.append(
[
xc + polar_r * math.cos(theta),
yc + polar_r * math.sin(theta),
]
)
for center in centers:
self.regularPolygonHole(x=center[0], y=center[1], n=6, r=r, corner_radius=cr, a=30)
# magnets
d = self.magnet_diameter
mo = t + d/2
self.hole(mo, mo, d=d)
self.hole(xi-mo, mo, d=d)
def render(self):
x, y, h, hl = self.x, self.y, self.h, self.lidheight
if self.outside:
x = self.adjustSize(x)
y = self.adjustSize(y)
h = self.adjustSize(h)
hl = self.adjustSize(hl)
t = self.thickness
hy = self.edges["O"].startwidth()
hy2 = self.edges["P"].startwidth()
e1 = edges.CompoundEdge(self, "eF", (hy-t, h-hy+t))
e2 = edges.CompoundEdge(self, "Fe", (h-hy+t, hy-t))
e_back = ("F", e1, "F", e2)
p = self.edges["o"].settings.pin_height
e_inner_1 = edges.CompoundEdge(self, "fe", (y-p, p))
e_inner_2 = edges.CompoundEdge(self, "ef", (p, y-p))
e_inner_topbot = ("f", e_inner_1, "f", e_inner_2)
self.ctx.save()
self.rectangularWall(x, y, e_inner_topbot, move="up", callback=[self.diceCB])
self.rectangularWall(x, y, e_inner_topbot, move="up", callback=[self.diceCB])
self.rectangularWall(x, h, "FFFF", ignore_widths=[1,2,5,6], move="up")
self.rectangularWall(x, h, e_back, move="up")
self.rectangularWall(x, hl, "FFFF", ignore_widths=[1,2,5,6], move="up")
self.rectangularWall(x, hl-hy2+t, "FFqF", move="up")
self.ctx.restore()
self.rectangularWall(x, y, "ffff", move="right only")
self.rectangularWall(y, x, "ffff", move="up")
self.rectangularWall(y, x, "ffff", move="up")
self.rectangularWall(y, hl-hy2+t, "Ffpf", ignore_widths=[5,6], move="up")
self.rectangularWall(y, h-hy+t, "OfFf", ignore_widths=[5,6], move="up")
self.rectangularWall(y, h-hy+t, "Ffof", ignore_widths=[5,6], move="up")
self.rectangularWall(y, hl-hy2+t, "PfFf", ignore_widths=[5,6], move="up")