diff --git a/boxes/generators/shoe.py b/boxes/generators/shoe.py new file mode 100644 index 0000000..5745771 --- /dev/null +++ b/boxes/generators/shoe.py @@ -0,0 +1,146 @@ +#!/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 . + +from boxes import * + +class Shoe(Boxes): + """Shoe shaped box""" + + description = """Shoe shaped box with flat sides and rounded top. + Works best if flex if under slight compression. + Make sure that the following conditions are met: + y > tophole + r + fronttop; + height > frontheight.""" + + ui_group = "Misc" + + def __init__(self) -> None: + Boxes.__init__(self) + + self.addSettingsArgs(edges.FingerJointSettings) + self.addSettingsArgs(edges.FlexSettings) + + self.argparser.add_argument( + "--width", action="store", type=float, default=65, + help="width of the shoe") + self.argparser.add_argument( + "--length", action="store", type=float, default=175, + help="length front to back") + self.argparser.add_argument( + "--height", action="store", type=float, default=100, + help="height at the back of the shoe") + 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): + x, y, h = self.width, self.length, self.height + t = self.thickness + + hf = self.frontheight + yg = self.tophole + tf = self.fronttop + r=self.radius + + if (hf > h): + # Give an error because the result will be wrong with possible unconnected paths + raise ValueError("Height at front of shoe must be less than height at back of shoe.") + + 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) diff --git a/static/samples/Shoe-thumb.jpg b/static/samples/Shoe-thumb.jpg new file mode 100644 index 0000000..06d2aca Binary files /dev/null and b/static/samples/Shoe-thumb.jpg differ diff --git a/static/samples/Shoe.jpg b/static/samples/Shoe.jpg new file mode 100644 index 0000000..9bb6cbf Binary files /dev/null and b/static/samples/Shoe.jpg differ diff --git a/static/samples/samples.sha256 b/static/samples/samples.sha256 index 87484d7..94f1292 100644 --- a/static/samples/samples.sha256 +++ b/static/samples/samples.sha256 @@ -140,3 +140,4 @@ e9ee43e336401d3a0cb8e141c3a0b87a84e90f99eed30bdd420dcaead92940e1 ../static/samp c8adb0661956430ccec7fc00aa4b8e3c42d02083e17a9307541bc0160251cb96 ../static/samples/HolePattern.jpg 7c399c1cd235c3c044f676a31aa5215109e815055f2f69aef5d0cb1a24dfae41 ../static/samples/Desksign.jpg fda14ba0920ef7ea0579117a30b5bb4a05ab3be4da3d87a4fc03fc40b085992b ../static/samples/PirateChest.jpg +125033a02263e74d5688287936f54cd83e917276b7c35f3fd37e6cb86efc0dcc ../static/samples/Shoe.jpg