boxespy/boxes/generators/shoe.py

147 lines
5.2 KiB
Python

#!/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):
"""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)