parent
7bd0ab9e7d
commit
0e6e5ff6a6
|
@ -0,0 +1,288 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2013-2014 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 *
|
||||
|
||||
class CompartmentBox(Boxes):
|
||||
"""Type tray variation with sliding lid"""
|
||||
|
||||
description = """Sliding lid rests on inner walls,
|
||||
so will not work if no inner walls are present.
|
||||
Suggested to place walls close to both sides for maximum stability."""
|
||||
|
||||
ui_group = "Unstable"
|
||||
|
||||
def __init__(self) -> None:
|
||||
Boxes.__init__(self)
|
||||
self.buildArgParser("sx", "sy", "h", "outside", "bottom_edge")
|
||||
self.argparser.add_argument(
|
||||
"--handle", action="store", type=str, default="lip",
|
||||
choices={"none","lip","hole"},
|
||||
help="how to grab the lid to remove")
|
||||
self.argparser.add_argument(
|
||||
"--radius", action="store", type=float, default=10,
|
||||
dest="radius", help="radius of the grip hole in mm")
|
||||
self.argparser.add_argument(
|
||||
"--holes", action="store", type=str,
|
||||
default="70",
|
||||
help="width of hole(s) in percentage of maximum hole width")
|
||||
|
||||
|
||||
|
||||
|
||||
def xSlots(self):
|
||||
posx = -0.5 * self.thickness
|
||||
for x in self.sx[:-1]:
|
||||
posx += x + self.thickness
|
||||
posy = 0
|
||||
for y in self.sy:
|
||||
self.fingerHolesAt(posx, posy, y)
|
||||
posy += y + self.thickness
|
||||
|
||||
def ySlots(self):
|
||||
posy = -0.5 * self.thickness
|
||||
for y in self.sy[:-1]:
|
||||
posy += y + self.thickness
|
||||
posx = 0
|
||||
for x in reversed(self.sx):
|
||||
self.fingerHolesAt(posy, posx, x)
|
||||
posx += x + self.thickness
|
||||
|
||||
def xHoles(self):
|
||||
posx = -0.5 * self.thickness
|
||||
for x in self.sx[:-1]:
|
||||
posx += x + self.thickness
|
||||
self.fingerHolesAt(posx, 0, self.h)
|
||||
|
||||
def yHoles(self):
|
||||
posy = -0.5 * self.thickness
|
||||
for y in self.sy[:-1]:
|
||||
posy += y + self.thickness
|
||||
self.fingerHolesAt(posy, 0, self.h)
|
||||
|
||||
def render(self):
|
||||
t = self.thickness
|
||||
if self.outside:
|
||||
self.sx = self.adjustSize(self.sx)
|
||||
self.sy = self.adjustSize(self.sy)
|
||||
self.h = self.adjustSize(self.h) - 2 * t
|
||||
|
||||
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
|
||||
y = sum(self.sy) + self.thickness * (len(self.sy) - 1)
|
||||
h = self.h
|
||||
|
||||
|
||||
# Create new Edges here if needed E.g.:
|
||||
s = edges.FingerJointSettings(self.thickness, relative=False,
|
||||
style = "rectangular")
|
||||
p = edges.FingerJointEdge(self, s)
|
||||
p.char = "a" # 'a', 'A', 'b' and 'B' is reserved for beeing used within generators
|
||||
self.addPart(p)
|
||||
|
||||
# outer walls
|
||||
b = self.bottom_edge
|
||||
tl, tb, tr, tf = "FEFe"
|
||||
tl, tb, tr, tf = "ŠSŠe" if b == "s" else "FEFe"
|
||||
|
||||
|
||||
# x sides
|
||||
|
||||
self.ctx.save()
|
||||
|
||||
# outer walls - front/back
|
||||
hb = h+t * (3 if tb == "S" else 1)
|
||||
self.rectangularWall(x, hb, [b, "F", tb, "F"],
|
||||
callback=[self.xHoles],
|
||||
ignore_widths=[1,2,5,6],
|
||||
move="up", label="back")
|
||||
|
||||
self.rectangularWall(x, h, [b, "F", tf, "F"],
|
||||
callback=[self.mirrorX(self.xHoles, x)],
|
||||
ignore_widths=[1,6],
|
||||
move="up", label="front")
|
||||
|
||||
# floor
|
||||
if b != "e":
|
||||
self.rectangularWall(x, y, "ffff", callback=[self.xSlots, self.ySlots], move="up", label="bottom")
|
||||
|
||||
# Inner walls
|
||||
|
||||
be = "f" if b != "e" else "e"
|
||||
|
||||
for i in range(len(self.sy) - 1):
|
||||
e = [edges.SlottedEdge(self, self.sx, be), "f",
|
||||
edges.SlottedEdge(self, self.sx[::-1], "e", slots=0.5 * h), "f"]
|
||||
self.rectangularWall(x, h, e, move="up", label=f"inner x {i+1}")
|
||||
|
||||
# top / lid
|
||||
handle = self.handle
|
||||
if handle == "lip":
|
||||
self.rectangularWall(x, y, "feee", move="up", label="lid")
|
||||
self.rectangularWall(x, t * (2 if b == "s" else 1), "fe" + ("S" if b == "s" else "e") + "e", move="up", label="lid lip")
|
||||
if handle == "hole":
|
||||
self.rectangularWall(x, y + t, move="up", label="lid", callback=[self.gripHole])
|
||||
if handle == "none":
|
||||
self.rectangularWall(x, y + t, move="up", label="lid")
|
||||
|
||||
|
||||
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(x, h, "ffff", move="right only")
|
||||
|
||||
# y walls
|
||||
|
||||
# outer walls - left/right
|
||||
self.sideWall(
|
||||
y, h+t, "left", [b, "f", tl, "f"], callback=[self.yHoles, ],
|
||||
move="up", label="left side")
|
||||
|
||||
self.sideWall(
|
||||
y, h+t, "right", [b, "f", tr, "f"],
|
||||
callback=[self.mirrorX(self.yHoles, y), ],
|
||||
move="up", label="right side")
|
||||
|
||||
# inner walls
|
||||
for i in range(len(self.sx) - 1):
|
||||
e = [edges.SlottedEdge(self, self.sy, be, slots=0.5 * h),
|
||||
"f", "e", "f"]
|
||||
self.rectangularWall(y, h, e, move="up", label=f"inner y {i+1}")
|
||||
|
||||
lipy = y-t if self.handle == "lip" else y
|
||||
self.rectangularWall(lipy, t, "eefe", move="up", label="Lip Left")
|
||||
self.rectangularWall(lipy, t, "feee", move="up", label="Lip Right")
|
||||
|
||||
def sideWall(self, x, y, side, edges="eeee",
|
||||
holesMargin=None, holesSettings=None,
|
||||
bedBolts=None, bedBoltSettings=None,
|
||||
callback=None,
|
||||
move=None,
|
||||
label=""):
|
||||
|
||||
if len(edges) != 4:
|
||||
raise ValueError("four edges required")
|
||||
if side not in {"left", "right"}:
|
||||
raise ValueError("side must be left or right")
|
||||
b = edges[0]
|
||||
edges = [self.edges.get(e, e) for e in edges]
|
||||
edges += edges # append for wrapping around
|
||||
overallwidth = x + edges[-1].spacing() + edges[1].spacing()
|
||||
overallheight = y + edges[0].spacing() + edges[2].spacing()
|
||||
t = self.thickness
|
||||
|
||||
if self.move(overallwidth, overallheight, move, before=True):
|
||||
return
|
||||
|
||||
self.moveTo(edges[-1].spacing(), edges[0].margin())
|
||||
|
||||
for i, l in enumerate((x, y, x, y)):
|
||||
self.cc(callback, i, y=edges[i].startwidth() + self.burn)
|
||||
e1, e2 = edges[i], edges[i + 1]
|
||||
|
||||
if i == 3 and side == "right":
|
||||
l -= t
|
||||
self.edges.get('e')(t)
|
||||
l += edges[i+1].startwidth()
|
||||
e2 = self.edges["e"]
|
||||
edges[i](l,
|
||||
bedBolts=self.getEntry(bedBolts, i),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i))
|
||||
elif i == 1 and side == "left":
|
||||
l -= t
|
||||
l += edges[i-1].startwidth()
|
||||
edges[i](l,
|
||||
bedBolts=self.getEntry(bedBolts, i),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i))
|
||||
self.edges.get('e')(t)
|
||||
else:
|
||||
if i == 3 and side == "left":
|
||||
l += edges[i+1].startwidth() + edges[i-1].startwidth()
|
||||
e2 = self.edges["e"]
|
||||
if i == 1 and side == "right":
|
||||
l += edges[i+1].startwidth() + edges[i-1].startwidth()
|
||||
e2 = self.edges["e"]
|
||||
|
||||
if i == 2 and self.handle == "lip":
|
||||
if b != "s":
|
||||
l -= t
|
||||
print(b)
|
||||
if side == "left":
|
||||
self.edges.get('e')(t)
|
||||
edges[i](l,
|
||||
bedBolts=self.getEntry(bedBolts, i),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i))
|
||||
elif side == "right":
|
||||
edges[i](l,
|
||||
bedBolts=self.getEntry(bedBolts, i),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i))
|
||||
self.edges.get('e')(t)
|
||||
else:
|
||||
self.edges.get('S')(l)
|
||||
self.fingerHolesAt(0 if side == "left" else -t, 1.5*t, l-t, angle=180)
|
||||
else:
|
||||
edges[i](l,
|
||||
bedBolts=self.getEntry(bedBolts, i),
|
||||
bedBoltSettings=self.getEntry(bedBoltSettings, i))
|
||||
|
||||
if i == 2 and side == "left":
|
||||
e1 = self.edges["e"]
|
||||
if i == 0 and side == "right":
|
||||
e1 = self.edges["e"]
|
||||
if i == 0 and side == "left":
|
||||
e1 = self.edges["e"]
|
||||
|
||||
|
||||
self.edgeCorner(e1, e2, 90)
|
||||
|
||||
if holesMargin is not None:
|
||||
self.moveTo(holesMargin,
|
||||
holesMargin + edges[0].startwidth())
|
||||
self.hexHolesRectangle(x - 2 * holesMargin, y - 2 * holesMargin, settings=holesSettings)
|
||||
|
||||
self.move(overallwidth, overallheight, move, label=label)
|
||||
|
||||
def gripHole(self):
|
||||
if not self.radius:
|
||||
return
|
||||
radius = self.radius
|
||||
t = self.thickness
|
||||
widths = argparseSections(self.holes)
|
||||
|
||||
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
|
||||
|
||||
if sum(widths) > 0:
|
||||
if sum(widths) < 100:
|
||||
slot_offset = ((1 - sum(widths) / 100) * (x - (len(widths) + 1) * self.thickness)) / (len(widths) * 2)
|
||||
else:
|
||||
slot_offset = 0
|
||||
|
||||
slot_height = 2* radius # (self.settings.height - 2 * self.thickness) * self.settings.hole_height / 100
|
||||
slot_x = self.thickness + slot_offset
|
||||
|
||||
for w in widths:
|
||||
if sum(widths) > 100:
|
||||
slotwidth = w / sum(widths) * (x - (len(widths) + 1) * self.thickness)
|
||||
else:
|
||||
slotwidth = w / 100 * (x - (len(widths) + 1) * self.thickness)
|
||||
slot_x += slotwidth / 2
|
||||
|
||||
with self.saved_context():
|
||||
#self.moveTo(20, slot_x, 0)
|
||||
self.rectangularHole(slot_x,radius+t,slotwidth,slot_height,radius,True,True)
|
||||
slot_x += slotwidth / 2 + slot_offset + self.thickness + slot_offset
|
||||
|
||||
|
||||
#todo stackable top/bottom
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (C) 2013-2014 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 *
|
||||
|
||||
class Desksign(Boxes):
|
||||
"""Simple diagonal plate with stands to show name or mesage"""
|
||||
|
||||
description = """Text to be engraved can be genarated by inputing the label and fontsize fields.
|
||||
height represents the area that can be used for writing text, does not match the actual
|
||||
height when standing. Generated text is put in the center. Currently only a single
|
||||
line of text is supported."""
|
||||
|
||||
ui_group = "Misc"
|
||||
|
||||
def __init__(self) -> None:
|
||||
Boxes.__init__(self)
|
||||
self.addSettingsArgs(edges.FingerJointSettings)
|
||||
#self.buildArgParser("x", "y", "h", "outside", "bottom_edge")
|
||||
|
||||
self.argparser.add_argument(
|
||||
"--width", action="store", type=float, default=150,
|
||||
help="plate width in mm (excluding holes)")
|
||||
self.argparser.add_argument(
|
||||
"--height", action="store", type=float, default=80,
|
||||
help="plate height in mm")
|
||||
self.argparser.add_argument(
|
||||
"--angle", action="store", type=float, default=60,
|
||||
help="plate angle in degrees (90 is vertical)")
|
||||
self.argparser.add_argument(
|
||||
"--label", action="store", type=str, default="",
|
||||
help="optional text to engrave (leave blank to omit)")
|
||||
self.argparser.add_argument(
|
||||
"--fontsize", action="store", type=float, default=20,
|
||||
help="height of text")
|
||||
|
||||
def render(self):
|
||||
width = self.width
|
||||
height = self.height
|
||||
angle = self.angle
|
||||
t = self.thickness
|
||||
|
||||
if not (0 < angle and angle < 90):
|
||||
raise ValueError("angle has to between 0 and 90 degrees")
|
||||
|
||||
base = math.cos(math.radians(angle)) * height
|
||||
h = math.sin(math.radians(angle)) * height
|
||||
|
||||
label = self.label
|
||||
fontsize = self.fontsize
|
||||
|
||||
if label and fontsize:
|
||||
self.rectangularWall(width, height, "eheh", move="right", callback=[
|
||||
lambda: self.text("%s" % label, width/2, (height-fontsize)/2,
|
||||
fontsize = fontsize, align="center", color=Color.ETCHING)]) # add text
|
||||
else:
|
||||
self.rectangularWall(width, height, "eheh", move="right") # front
|
||||
|
||||
self.rectangularTriangle(base, h, "eef", num=2, move="right") # stands at back/side
|
|
@ -0,0 +1,154 @@
|
|||
#!/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 *
|
||||
|
||||
class Piratechest(Boxes): # Change class name!
|
||||
"""Box with polygon lid with chest hinges."""
|
||||
|
||||
description = """Do not assemble sides before attaching the lid!
|
||||
Hinge of the lid has to be placed first because it is impossible
|
||||
to get it in position without removing the side wall. The lid can
|
||||
be a bit tricky to assemble. Keep track of how the parts fit together."""
|
||||
|
||||
ui_group = "Box" # see ./__init__.py for names
|
||||
|
||||
def __init__(self) -> None:
|
||||
Boxes.__init__(self)
|
||||
|
||||
# Uncomment the settings for the edge types you use
|
||||
# use keyword args to set default values
|
||||
self.addSettingsArgs(edges.FingerJointSettings, finger=1.0,space=1.0)
|
||||
# self.addSettingsArgs(edges.StackableSettings)
|
||||
self.addSettingsArgs(edges.HingeSettings)
|
||||
# self.addSettingsArgs(edges.LidSettings)
|
||||
# self.addSettingsArgs(edges.ClickSettings)
|
||||
# self.addSettingsArgs(edges.FlexSettings)
|
||||
|
||||
# remove cli params you do not need
|
||||
self.buildArgParser(x=100, y=100, h=100)
|
||||
# Add non default cli params if needed (see argparse std lib)
|
||||
self.argparser.add_argument(
|
||||
"--n", action="store", type=int, default=5,
|
||||
help="number of sides on the lid")
|
||||
|
||||
|
||||
def render(self):
|
||||
# adjust to the variables you want in the local scope
|
||||
x, y, h = self.x, self.y, self.h
|
||||
t = self.thickness
|
||||
n = self.n
|
||||
|
||||
# Create new Edges here if needed E.g.:
|
||||
s = edges.FingerJointSettings(self.thickness, relative=False,
|
||||
space = 10, finger=10,
|
||||
width=self.thickness)
|
||||
p = edges.FingerJointEdge(self, s)
|
||||
p.char = "a" # 'a', 'A', 'b' and 'B' is reserved for beeing used within generators
|
||||
self.addPart(p)
|
||||
# code from regularbox
|
||||
fingerJointSettings = copy.deepcopy(self.edges["f"].settings)
|
||||
fingerJointSettings.setValues(self.thickness, angle=180./(n-1))
|
||||
fingerJointSettings.edgeObjects(self, chars="gGH")
|
||||
# render your parts here
|
||||
|
||||
self.ctx.save()
|
||||
|
||||
self.rectangularWall(x, y, "FFFF", move="up", label="Bottom")
|
||||
frontlid, toplids, backlid = self.topside(y, n = n, move="only", bottem='P')
|
||||
|
||||
self.rectangularWall(x, backlid, "qFgF", move="up", label="lid back")
|
||||
for _ in range(n-2):
|
||||
self.rectangularWall(x, toplids, "GFgF", move="up", label="lid top")
|
||||
self.rectangularWall(x, frontlid, "GFeF", move="up", label="lid front")
|
||||
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(x, y, "FFFF", move="right only")
|
||||
|
||||
with self.saved_context():
|
||||
self.rectangularWall(x, h, "fFQF", ignore_widths=[2, 5], move="right", label="front")
|
||||
self.rectangularWall(y, h, "ffof", ignore_widths=[5], move="right", label="right")
|
||||
self.rectangularWall(0, h, "eeep", move="right only")
|
||||
self.rectangularWall(x, h, "fFoF", move="up only")
|
||||
self.rectangularWall(x, 0, "Peee", move="up only")
|
||||
|
||||
hy = self.edges["O"].startwidth()
|
||||
hy2 = self.edges["P"].startwidth()
|
||||
e1 = edges.CompoundEdge(self, "Fe", (h, hy))
|
||||
e2 = edges.CompoundEdge(self, "eF", (hy, h))
|
||||
e_back = ("f", e1, "e", e2)
|
||||
|
||||
with self.saved_context():
|
||||
#self.rectangularWall(x, h, "fFeF", ignore_widths=[2, 5], move="right", label="back")
|
||||
self.rectangularWall(x, h+hy, e_back, move="right", label="back") # extend back to correct height
|
||||
self.rectangularWall(0, h, "ePee", move="right only")
|
||||
self.rectangularWall(y, h, "ffOf", ignore_widths=[2], move="right", label="left")
|
||||
self.rectangularWall(x, h, "fFOF", move="up only")
|
||||
self.rectangularWall(x, 0, "peee", move="up only")
|
||||
|
||||
|
||||
self.topside(y, n = n, move="right", bottem='p', label="lid left")
|
||||
self.topside(y, n = n, move="right", bottem='P', label="lid right")
|
||||
|
||||
|
||||
|
||||
|
||||
def topside(self, y, n, bottem='e', move=None, label=""):
|
||||
radius, hp, side = self.regularPolygon((n - 1) * 2, h=y/2.0)
|
||||
t = self.thickness
|
||||
|
||||
#edge = self.edges.get('f')
|
||||
|
||||
tx = y + 2 * self.edges.get('f').spacing()
|
||||
lidheight = hp if n % 2 else radius
|
||||
ty = lidheight + self.edges.get('f').spacing() + self.edges.get(bottem).spacing()
|
||||
|
||||
if self.move(tx, ty, move, before=True):
|
||||
if bottem in "pP":
|
||||
return side/2 + self.edges.get(bottem).spacing(), side, side/2
|
||||
else:
|
||||
return side/2, side, side/2
|
||||
|
||||
self.moveTo(self.edges.get('f').margin(), self.edges.get(bottem).margin())
|
||||
|
||||
self.edges.get(bottem)(y)
|
||||
|
||||
self.corner(90)
|
||||
if bottem == 'p':
|
||||
self.edges.get('f')(side/2 + self.edges.get(bottem).spacing())
|
||||
else:
|
||||
self.edges.get('f')(side/2)
|
||||
|
||||
#self.edgeCorner(self.edges.get('f'), self.edges.get('f'), 180 / (n - 1))
|
||||
self.corner(180 / (n - 1))
|
||||
for i in range(n-2):
|
||||
self.edges.get('f')(side)
|
||||
#self.edgeCorner(self.edges.get('f'), self.edges.get('f'), 180 / (n - 1))
|
||||
self.corner(180 / (n - 1))
|
||||
|
||||
if bottem == 'P':
|
||||
self.edges.get('f')(side/2 + self.edges.get(bottem).spacing())
|
||||
else:
|
||||
self.edges.get('f')(side/2)
|
||||
|
||||
self.corner(90)
|
||||
|
||||
self.move(tx, ty, move, label=label)
|
||||
|
||||
if bottem in "pP":
|
||||
return side/2 + self.edges.get(bottem).spacing(), side, side/2
|
||||
else:
|
||||
return side/2, side, side/2
|
|
@ -0,0 +1,143 @@
|
|||
#!/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 *
|
||||
|
||||
class Shoe(Boxes): # Change class name!
|
||||
"""Shoe shaped box"""
|
||||
|
||||
description = """Shoe shaped box with flat sides and rounded top.
|
||||
Works best if flex if under slight compression.
|
||||
Also make sure that the following condition is met,
|
||||
y > tophole + r + fronttop."""
|
||||
|
||||
ui_group = "Misc" # see ./__init__.py for names
|
||||
|
||||
def __init__(self) -> None:
|
||||
Boxes.__init__(self)
|
||||
|
||||
# Uncomment the settings for the edge types you use
|
||||
# use keyword args to set default values
|
||||
self.addSettingsArgs(edges.FingerJointSettings)
|
||||
# self.addSettingsArgs(edges.StackableSettings)
|
||||
# self.addSettingsArgs(edges.HingeSettings)
|
||||
# self.addSettingsArgs(edges.LidSettings)
|
||||
# self.addSettingsArgs(edges.ClickSettings)
|
||||
self.addSettingsArgs(edges.FlexSettings)
|
||||
|
||||
# remove cli params you do not need
|
||||
self.buildArgParser(x=65, y=175, h=100)
|
||||
# Add non default cli params if needed (see argparse std lib)
|
||||
self.argparser.add_argument(
|
||||
"--frontheight", action="store", type=float, default=35,
|
||||
help="height at the front of the shoe")
|
||||
self.argparser.add_argument(
|
||||
"--fronttop", action="store", type=float, default=20,
|
||||
help="length of the flat part at the front of the shoe")
|
||||
self.argparser.add_argument(
|
||||
"--tophole", action="store", type=float, default=75,
|
||||
help="length of the opening at the top")
|
||||
self.argparser.add_argument(
|
||||
"--radius", action="store", type=float, default=30,
|
||||
help="radius of the bend")
|
||||
|
||||
|
||||
def render(self):
|
||||
# adjust to the variables you want in the local scope
|
||||
x, y, h = self.x, self.y, self.h
|
||||
t = self.thickness
|
||||
|
||||
hf = self.frontheight
|
||||
yg = self.tophole
|
||||
tf = self.fronttop
|
||||
r=self.radius
|
||||
|
||||
stretch = (self.edges["X"].settings.stretch)
|
||||
|
||||
self.ctx.save()
|
||||
self.rectangularWall(y, x, "FFFF", move="up", label="Bottom")
|
||||
lf,a=self.shoeside(y,h,hf,yg,tf,r, move="up", label="Side")
|
||||
self.shoeside(y,h,hf,yg,tf,r, move="mirror up", label="Side")
|
||||
self.ctx.restore()
|
||||
self.rectangularWall(y, x, "FFFF", move="right only")
|
||||
self.rectangularWall(x, h, "ffef", move="up", label="Back")
|
||||
self.rectangularWall(x, hf, "ffff", move="up", label="front")
|
||||
dr = a*(r-t)/stretch
|
||||
self.shoelip(x, tf, dr, lf, label="top")
|
||||
|
||||
|
||||
|
||||
def shoelip(self, x, tf, dr, lf, move=None, label=""):
|
||||
|
||||
w = self.edges["F"].spacing()
|
||||
|
||||
th = tf + dr + lf + self.edges["F"].spacing() + self.edges["e"].spacing()
|
||||
tw = x + 2*w
|
||||
if self.move(tw, th, move, True, label=label):
|
||||
return
|
||||
|
||||
self.moveTo(self.edges["F"].spacing(), self.edges["e"].spacing())
|
||||
|
||||
self.edges["F"](x)
|
||||
self.edgeCorner("F", "F")
|
||||
self.edges["F"](tf)
|
||||
self.edges["X"](dr, h=x+2*w)
|
||||
self.edges["F"](lf)
|
||||
self.edgeCorner("F", "e")
|
||||
self.edges["e"](x)
|
||||
self.edgeCorner("e", "F")
|
||||
self.edges["F"](lf)
|
||||
self.edges["E"](dr)
|
||||
self.edges["F"](tf)
|
||||
self.edgeCorner("F", "F")
|
||||
|
||||
self.move(tw, th, move, label=label)
|
||||
|
||||
def shoeside(self, y, h, hf, yg, tf, r, move=None, label=""):
|
||||
import math
|
||||
|
||||
tx = y + 2 * self.edges.get('F').spacing()
|
||||
ty = h + self.edges.get('f').spacing() + self.edges.get("e").spacing()
|
||||
|
||||
if self.move(tx, ty, move, before=True):
|
||||
return
|
||||
|
||||
lf = math.sqrt((h-hf)**2+(y-yg-tf)**2)
|
||||
af = 90-math.degrees(math.atan((h-hf)/(y-yg-tf)))
|
||||
|
||||
atemp = math.degrees(math.atan((h-hf-r)/(y-yg-tf)))
|
||||
dtemp = math.sqrt((h-hf-r)**2+(y-yg-tf)**2)
|
||||
lf = math.sqrt(dtemp**2-r**2)
|
||||
af = 90-atemp-math.degrees(math.atan(r/lf))
|
||||
|
||||
self.moveTo(self.edges.get('f').margin(), self.edges.get("f").margin())
|
||||
|
||||
self.edges.get('f')(y)
|
||||
self.edgeCorner(self.edges["f"],self.edges["F"],90)
|
||||
self.edges.get('F')(hf)
|
||||
self.edgeCorner(self.edges["F"],self.edges["f"],90)
|
||||
self.edges.get('f')(tf)
|
||||
self.corner(af-90,r)
|
||||
self.edges.get('f')(lf)
|
||||
self.edgeCorner(self.edges["f"],self.edges["e"],90-af)
|
||||
self.edges.get('e')(yg)
|
||||
self.edgeCorner(self.edges["e"],self.edges["F"],90)
|
||||
self.edges.get('F')(h)
|
||||
self.edgeCorner(self.edges["F"],self.edges["f"],90)
|
||||
|
||||
self.move(tx, ty, move, label=label)
|
||||
|
||||
return lf,math.radians(90-af)
|
Loading…
Reference in New Issue