From 60d465c83ab4b028d995fb63518cdfb4401ce2bd Mon Sep 17 00:00:00 2001 From: Florian Festi Date: Wed, 25 May 2016 19:59:49 +0200 Subject: [PATCH] Add edges for hinges --- boxes/__init__.py | 7 +- boxes/edges.py | 212 ++++++++++++++++++++++++++++++++++++ documentation/src/edges.rst | 19 ++++ 3 files changed, 237 insertions(+), 1 deletion(-) diff --git a/boxes/__init__.py b/boxes/__init__.py index 510ab15..c1fc302 100755 --- a/boxes/__init__.py +++ b/boxes/__init__.py @@ -256,7 +256,7 @@ class Boxes: elif arg == "top_edge": self.argparser.add_argument( "--top_edge", action="store", - type=ArgparseEdgeType("ecES"), choices=list("ecES"), + type=ArgparseEdgeType("ecESi"), choices=list("ecESi"), default="e", help="edge type for top edge") else: raise ValueError("No default for argument", arg) @@ -324,6 +324,11 @@ class Boxes: s = edges.ClickSettings(self.thickness) self.addPart(edges.ClickConnector(self, s)) self.addPart(edges.ClickEdge(self, s)) + # Hinges + s = edges.HingeSettings(self.thickness) + for i in range(1, 4): + self.addPart(edges.Hinge(self, s, i)) + self.addPart(edges.HingePin(self, s, i)) # Nuts self.addPart(NutHole(self, None)) diff --git a/boxes/edges.py b/boxes/edges.py index 155588d..4df6003 100644 --- a/boxes/edges.py +++ b/boxes/edges.py @@ -550,6 +550,218 @@ class StackableEdgeTop(StackableEdge): description = "Stackable (top)" bottom = False +############################################################################# +#### Hinges +############################################################################# + +class HingeSettings(Settings): + + """Settings for Hinge and HingePin classes +Values: + +* absolute_params + + * style : B : currently "A" or "B" + * outset : False : have lid overlap at the sides (similar to OutSetEdge) + * pinwidth : 1.0 : set to lower value to get disks surrounding the pins + +* relative (in multiples of thickness) + + * hingestrength : 1 : thickness of the arc holding the pin in place + * axle : 2 : diameter of the pin hole + +""" + absolute_params = { + "style" : "B", + "outset" : False, + "pinwidth" : 0.5, + } + + relative_params = { + "hingestrength" : 1,#1.5-0.5*2**0.5, + "axle" : 2, + } + +class Hinge(BaseEdge): + + char = 'i' + description = "Straight edge with hinge eye" + + def __init__(self, boxes, settings=None, layout=1): + super(Hinge, self).__init__(boxes,settings) + self.layout = layout + self.char = "eijk"[layout] + self.description = self.description + ('', ' (start)', ' (end)', ' (both ends)')[layout] + + def margin(self): + return 3 * self.thickness + + def A(self, _reversed=False): + t = self.thickness + r = t*0.5*2**0.5 + hinge = ( + 0, + 45, 0, + (-360, r), 0, + 135, + t, + 90, + 0.5*t, + (180, 1.5*t), 0, + (-90, 0.5*t), 0 + ) + if _reversed: + hinge = reversed(hinge) + self.polyline(*hinge) + + def Alen(self): + return 2.5 * self.thickness + + def B(self, _reversed=False): + t = self.thickness + + hinge = ( + 0, -90, + 0.5*t, + (180, 0.5*self.settings.axle+self.settings.hingestrength), 0, + (-90, 0.5*t), 0 + ) + pos = 0.5*self.settings.axle+self.settings.hingestrength + if _reversed: + hinge = reversed(hinge) + self.hole(0.5*t+pos, -0.5*t, 0.5*self.settings.axle) + else: + self.hole(pos, -0.5*t, 0.5*self.settings.axle) + self.polyline(*hinge) + + def Blen(self): + return self.settings.axle + 2*self.settings.hingestrength + 0.5*self.thickness + + def __call__(self, l, **kw): + hlen = getattr(self, self.settings.style+'len')() + if self.layout & 1: + getattr(self, self.settings.style)() + self.edge(l - (self.layout & 1)*hlen - bool(self.layout & 2)*hlen) + if self.layout & 2: + getattr(self, self.settings.style)(True) + +class HingePin(BaseEdge): + char = 'I' + description = "Edge with hinge pin" + + def __init__(self, boxes, settings=None, layout=1): + super(HingePin, self).__init__(boxes,settings) + self.layout = layout + self.char = "EIJK"[layout] + self.description = self.description + ('', ' (start)', ' (end)', ' (both ends)')[layout] + + def startwidth(self): + if self.layout & 1: + return 0 + else: + return self.settings.outset * self.boxes.thickness + + def endwidth(self): + if self.layout & 2: + return 0 + else: + return self.settings.outset * self.boxes.thickness + + def margin(self): + return self.thickness + self.boxes.spacing + + def A(self, _reversed=False): + t = self.thickness + pin = (0, -90, + t, 90, + t, + 90, + t, + -90) + + if self.settings.outset: + pin += ( + 1.5*t, + -90, + t, + 90, + 0, + ) + else: + pin += (0.0,) + if _reversed: + pin = reversed(pin) + self.polyline(*pin) + + def Alen(self): + if self.settings.outset: + return 2.5* self.thickness + else: + return self.thickness + + def B(self, _reversed=False): + t = self.thickness + pinl = (self.settings.axle**2-t**2)**0.5 * self.settings.pinwidth + d = (self.settings.axle - pinl) / 2.0 + pin = (self.settings.hingestrength+d, -90, + t, 90, + pinl, + 90, + t, + -90, d) + + if self.settings.outset: + pin += ( + 0, + self.settings.hingestrength+0.5*t, + -90, + t, + 90, + 0, + ) + if _reversed: + pin = reversed(pin) + self.polyline(*pin) + + def parts(self, numhinges, move=''): + """Draw additional parts needed""" + if self.settings.pinwidth == 1.0: + return + pinl = (self.settings.axle**2-self.thickness**2)**0.5 * self.settings.pinwidth + + height = self.settings.axle + 2 * self.boxes.spacing + width = numhinges * (self.settings.axle + self.boxes.spacing) + self.boxes.spacing + a = (self.settings.axle - 0.05*self.thickness) + + if self.boxes.move(width, height, move, before=True): + return + self.ctx.save() + + self.boxes.moveTo(-0.5 * a) + for i in range(numhinges): + self.boxes.moveTo(self.boxes.spacing + a) + self.boxes.rectangularHole(0, a/2.0, pinl, self.thickness) + self.boxes.corner(360, a/2.0) + + self.ctx.restore() + self.boxes.move(width, height, move) + + def Blen(self): + l = self.settings.hingestrength+self.settings.axle + if self.settings.outset: + l += self.settings.hingestrength + 0.5 * self.thickness + return l + + def __call__(self, l, **kw): + plen = getattr(self, self.settings.style+'len')() + + if self.layout & 1: + getattr(self, self.settings.style)() + self.edge(l - (self.layout & 1)*plen - bool(self.layout & 2)*plen) + if self.layout & 2: + getattr(self, self.settings.style)(True) + + ############################################################################# #### Click Joints ############################################################################# diff --git a/documentation/src/edges.rst b/documentation/src/edges.rst index f6c5cde..ea6cc9f 100644 --- a/documentation/src/edges.rst +++ b/documentation/src/edges.rst @@ -14,6 +14,8 @@ callables. A set of instances are kept the ``.edges`` attribute of the * h : FingerHoleEdge * d : DoveTailJoint * D : DoveTailJointCounterPart +* ijk : Hinge (start, end, both sides) +* IJK : HingePin (start, end, both sides) Edges of the same type share a settings instance to make sure both sides match (when the same length is given). @@ -120,3 +122,20 @@ CompoundEdge ------------ .. autoclass:: boxes.edges.CompoundEdge +Hinges +------ + +Hinge Settings +.............. + +.. autoclass:: boxes.edges.HingeSettings + +Hinge +..... + +.. autoclass:: boxes.edges.Hinge + +HingePin +........ + +.. autoclass:: boxes.edges.HingePin