New generator: SmallPartsTray
Tray for game tokens, small nuts and bolts or all other tiny items. It has a slant on the bottom for the side wall so such pieces can be picked up easily with one finger.
This commit is contained in:
parent
3511046ae1
commit
14c2a820c0
|
@ -0,0 +1,244 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2013-2016 Florian Festi
|
||||
#
|
||||
# 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.edges import CompoundEdge
|
||||
|
||||
class SmallPartsTray(Boxes):
|
||||
"""Tray with slants to easier get out game tokens or screws"""
|
||||
|
||||
ui_group = "Tray"
|
||||
ui_group = "Unstable"
|
||||
|
||||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
|
||||
self.addSettingsArgs(edges.FingerJointSettings)
|
||||
# self.addSettingsArgs(edges.StackableSettings)
|
||||
|
||||
self.buildArgParser(sx="50*3", y=100, h=30)
|
||||
self.argparser.add_argument(
|
||||
"--angle", action="store", type=float, default=45.,
|
||||
help="angle of the ramps")
|
||||
self.argparser.add_argument(
|
||||
"--rampheight", action="store", type=float, default=.5,
|
||||
help="height of the ramps relative to to total height")
|
||||
self.argparser.add_argument(
|
||||
"--two_sided", action="store", type=boolarg, default=True,
|
||||
help="have ramps on both sides")
|
||||
self.argparser.add_argument(
|
||||
"--front_panel", action="store", type=boolarg, default=True,
|
||||
help="have a vertical wall at the ramp")
|
||||
|
||||
|
||||
def innerWall(self, h, y, ramp_h, ramp_y, two_ramps, front=True,
|
||||
edges="ffeff", move=None):
|
||||
a = math.degrees(math.atan(ramp_h/ramp_y))
|
||||
l = (ramp_h**2 + ramp_y**2)**.5
|
||||
if two_ramps:
|
||||
self.polygonWall(
|
||||
[y-2*ramp_y, a, l, 90-a, h-ramp_h, 90, y,
|
||||
90, h-ramp_h, 90-a, l, a],
|
||||
"fffeff" if front else "ffeeef", move=move)
|
||||
else:
|
||||
self.polygonWall(
|
||||
[y-ramp_y, 90, h, 90, y, 90, h-ramp_h, 90-a, l, a],
|
||||
"ffeff" if front else "ffeef", move=move)
|
||||
|
||||
def outerWall(self, h, y, ramp_h, ramp_y, two_ramps, front=True,
|
||||
edges="ffeff", move=None):
|
||||
a = math.degrees(math.atan(ramp_h/ramp_y))
|
||||
l = (ramp_h**2 + ramp_y**2)**.5
|
||||
t = self.thickness
|
||||
|
||||
def cb():
|
||||
with self.saved_context():
|
||||
self.moveTo(ramp_y, 0, 180-a)
|
||||
self.fingerHolesAt(0, 0.5*t, l, 0)
|
||||
if two_ramps:
|
||||
self.moveTo(y-ramp_y, 0, a)
|
||||
self.fingerHolesAt(0, -0.5*t, l, 0)
|
||||
|
||||
if two_ramps:
|
||||
self.rectangularWall(
|
||||
y, h,
|
||||
[CompoundEdge(self, "EFE", (ramp_y, y-2*ramp_y, ramp_y)),
|
||||
CompoundEdge(self, "EF", (ramp_h, h-ramp_h)) if front else "e",
|
||||
"e",
|
||||
CompoundEdge(self, "FE", (h-ramp_h, ramp_h)) if front else "e"],
|
||||
callback=[cb], move=move)
|
||||
else:
|
||||
self.rectangularWall(
|
||||
y, h, [
|
||||
CompoundEdge(self, "EF", (ramp_y, y-ramp_y)) if front else "e",
|
||||
"F",
|
||||
"e",
|
||||
CompoundEdge(self, "FE", (h-ramp_h, ramp_h))],
|
||||
callback=[cb], move=move)
|
||||
|
||||
|
||||
def holeCB(self, sections, height):
|
||||
def CB():
|
||||
pos = -0.5 * self.thickness
|
||||
for l in sections[:-1]:
|
||||
pos += l + self.thickness
|
||||
self.fingerHolesAt(pos, 0, height)
|
||||
return CB
|
||||
|
||||
def render_simple_tray_divider(self, width, height, move):
|
||||
"""
|
||||
Simple movable divider. A wall with small feet for a little more stability.
|
||||
"""
|
||||
|
||||
if self.move(width, height, move, True):
|
||||
return
|
||||
|
||||
t = self.thickness
|
||||
self.moveTo(t)
|
||||
self.polyline(
|
||||
width - 2 * t,
|
||||
90,
|
||||
t,
|
||||
-90,
|
||||
t,
|
||||
90,
|
||||
height - t,
|
||||
90,
|
||||
width,
|
||||
90,
|
||||
height - t,
|
||||
90,
|
||||
t,
|
||||
-90,
|
||||
t,
|
||||
90,
|
||||
)
|
||||
|
||||
self.move(width, height, move)
|
||||
|
||||
def render_simple_tray_divider_feet(self, move=None):
|
||||
sqr2 = math.sqrt(2)
|
||||
t = self.thickness
|
||||
divider_foot_width = 2 * t
|
||||
full_width = t + 2 * divider_foot_width
|
||||
move_length = full_width / sqr2 + 2 * self.burn
|
||||
move_width = full_width / sqr2 + 2 * self.burn
|
||||
|
||||
if self.move(move_width, move_length, move, True):
|
||||
return
|
||||
|
||||
self.moveTo(self.burn)
|
||||
self.ctx.save()
|
||||
self.polyline(
|
||||
sqr2 * divider_foot_width,
|
||||
135,
|
||||
t,
|
||||
-90,
|
||||
t,
|
||||
-90,
|
||||
t,
|
||||
135,
|
||||
sqr2 * divider_foot_width,
|
||||
135,
|
||||
full_width,
|
||||
135,
|
||||
)
|
||||
self.ctx.restore()
|
||||
|
||||
self.moveTo(-self.burn / sqr2, self.burn * (1 + 1 / sqr2), 45)
|
||||
self.moveTo(full_width)
|
||||
|
||||
self.polyline(
|
||||
0,
|
||||
135,
|
||||
sqr2 * divider_foot_width,
|
||||
135,
|
||||
t,
|
||||
-90,
|
||||
t,
|
||||
-90,
|
||||
t,
|
||||
135,
|
||||
sqr2 * divider_foot_width,
|
||||
135,
|
||||
)
|
||||
|
||||
self.move(move_width, move_length, move)
|
||||
|
||||
|
||||
def render(self):
|
||||
# adjust to the variables you want in the local scope
|
||||
sx, y, h = self.sx, self.y, self.h
|
||||
t = self.thickness
|
||||
a = self.angle
|
||||
b = "e"
|
||||
|
||||
x = sum(sx) + (len(sx)-1) * t
|
||||
|
||||
ramp_h = h * self.rampheight
|
||||
ramp_y = ramp_h / math.tan(math.radians(a))
|
||||
|
||||
if self.two_sided and (2*ramp_y + 3*t > y):
|
||||
ramp_y = (y - 3*t) / 2
|
||||
ramp_h = ramp_y * math.tan(math.radians(a))
|
||||
elif ramp_y > y - t:
|
||||
ramp_y = y - t
|
||||
ramp_h = ramp_y * math.tan(math.radians(a))
|
||||
|
||||
ramp_l = (ramp_h**2 + ramp_y**2)**.5
|
||||
|
||||
with self.saved_context():
|
||||
self.outerWall(h, y, ramp_h, ramp_y,
|
||||
self.two_sided, self.front_panel, move="up")
|
||||
self.outerWall(h, y, ramp_h, ramp_y,
|
||||
self.two_sided, self.front_panel, move="mirror up")
|
||||
for i in range(len(sx)-1):
|
||||
self.innerWall(h, y, ramp_h, ramp_y,
|
||||
self.two_sided, self.front_panel, move="up")
|
||||
self.innerWall(h, y, ramp_h, ramp_y,
|
||||
self.two_sided, self.front_panel, move="right only")
|
||||
|
||||
if self.front_panel:
|
||||
self.rectangularWall(
|
||||
x, h-ramp_h, "efef",
|
||||
callback=[self.holeCB(sx, h-ramp_h)], move="up")
|
||||
self.rectangularWall(x, ramp_l, "efef",
|
||||
callback=[self.holeCB(sx, ramp_l)], move="up")
|
||||
if self.two_sided:
|
||||
self.rectangularWall(
|
||||
x, y-2*ramp_y, "efef",
|
||||
callback=[self.holeCB(sx, y-2*ramp_y)], move="up")
|
||||
self.rectangularWall(
|
||||
x, ramp_l, "efef",
|
||||
callback=[self.holeCB(sx, ramp_l)], move="up")
|
||||
if self.front_panel:
|
||||
self.rectangularWall(
|
||||
x, h-ramp_h, "efef",
|
||||
callback=[self.holeCB(sx, h-ramp_h)], move="up")
|
||||
else:
|
||||
self.rectangularWall(
|
||||
x, y-ramp_y, "efff",
|
||||
callback=[self.holeCB(sx, y-ramp_y)], move="up")
|
||||
self.rectangularWall(
|
||||
x, h, "Ffef",
|
||||
callback=[self.holeCB(sx, h)], move="up")
|
||||
|
||||
|
||||
if self.two_sided:
|
||||
for l in self.sx:
|
||||
self.render_simple_tray_divider(l, h, move="right")
|
||||
|
||||
self.partsMatrix(len(self.sx), 0, "right", self.render_simple_tray_divider_feet)
|
Loading…
Reference in New Issue