Add HandleEdge
This commit is contained in:
parent
4966ec631f
commit
bfaabc2619
|
@ -479,7 +479,7 @@ class Boxes:
|
||||||
if default is None: default = "e"
|
if default is None: default = "e"
|
||||||
self.argparser.add_argument(
|
self.argparser.add_argument(
|
||||||
"--top_edge", action="store",
|
"--top_edge", action="store",
|
||||||
type=ArgparseEdgeType("efFhcESŠikvLtG"), choices=list("efFhcESŠikvfLtG"),
|
type=ArgparseEdgeType("efFhcESŠikvLtGyY"), choices=list("efFhcESŠikvfLtGyY"),
|
||||||
default=default, help="edge type for top edge")
|
default=default, help="edge type for top edge")
|
||||||
elif arg == "outside":
|
elif arg == "outside":
|
||||||
if default is None: default = True
|
if default is None: default = True
|
||||||
|
@ -600,6 +600,9 @@ class Boxes:
|
||||||
# Mounting Edge
|
# Mounting Edge
|
||||||
edges.MountingSettings(self.thickness, True,
|
edges.MountingSettings(self.thickness, True,
|
||||||
**self.edgesettings.get("Mounting", {})).edgeObjects(self)
|
**self.edgesettings.get("Mounting", {})).edgeObjects(self)
|
||||||
|
# Handle Edge
|
||||||
|
edges.HandleEdgeSettings(self.thickness, True,
|
||||||
|
**self.edgesettings.get("HandleEdge", {})).edgeObjects(self)
|
||||||
# HexHoles
|
# HexHoles
|
||||||
self.hexHolesSettings = HexHolesSettings(self.thickness, True,
|
self.hexHolesSettings = HexHolesSettings(self.thickness, True,
|
||||||
**self.edgesettings.get("HexHoles", {}))
|
**self.edgesettings.get("HexHoles", {}))
|
||||||
|
|
142
boxes/edges.py
142
boxes/edges.py
|
@ -23,6 +23,39 @@ import abc
|
||||||
|
|
||||||
from boxes import gears
|
from boxes import gears
|
||||||
|
|
||||||
|
def argparseSections(s):
|
||||||
|
"""
|
||||||
|
Parse sections parameter
|
||||||
|
|
||||||
|
:param s: string to parse
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = []
|
||||||
|
|
||||||
|
s = re.split(r"\s|:", s)
|
||||||
|
|
||||||
|
try:
|
||||||
|
for part in s:
|
||||||
|
m = re.match(r"^(\d+(\.\d+)?)/(\d+)$", part)
|
||||||
|
if m:
|
||||||
|
n = int(m.group(3))
|
||||||
|
result.extend([float(m.group(1)) / n] * n)
|
||||||
|
continue
|
||||||
|
m = re.match(r"^(\d+(\.\d+)?)\*(\d+)$", part)
|
||||||
|
if m:
|
||||||
|
n = int(m.group(3))
|
||||||
|
result.extend([float(m.group(1))] * n)
|
||||||
|
continue
|
||||||
|
result.append(float(part))
|
||||||
|
except ValueError:
|
||||||
|
raise argparse.ArgumentTypeError("Don't understand sections string")
|
||||||
|
|
||||||
|
if not result:
|
||||||
|
result.append(0.0)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def getDescriptions():
|
def getDescriptions():
|
||||||
d = {edge.char: edge.description for edge in globals().values()
|
d = {edge.char: edge.description for edge in globals().values()
|
||||||
if inspect.isclass(edge) and issubclass(edge, BaseEdge)
|
if inspect.isclass(edge) and issubclass(edge, BaseEdge)
|
||||||
|
@ -2465,3 +2498,112 @@ class RoundedTriangleFingerHolesEdge(RoundedTriangleEdge):
|
||||||
def __call__(self, length, **kw):
|
def __call__(self, length, **kw):
|
||||||
self.fingerHolesAt(0, 0.5*self.settings.thickness, length, 0)
|
self.fingerHolesAt(0, 0.5*self.settings.thickness, length, 0)
|
||||||
super().__call__(length, **kw)
|
super().__call__(length, **kw)
|
||||||
|
|
||||||
|
|
||||||
|
class HandleEdgeSettings(Settings):
|
||||||
|
|
||||||
|
"""Settings for HandleEdge
|
||||||
|
Values:
|
||||||
|
|
||||||
|
* absolute_params
|
||||||
|
|
||||||
|
* height : 20. : height above the wall in mm
|
||||||
|
* radius : 10. : radius of corners in mm
|
||||||
|
* hole_width : "40:40" : width of hole(s) in percentage of maximum hole width (width of edge - (n+1) * material thickness)
|
||||||
|
* hole_height : 75. : height of hole(s) in percentage of maximum hole height (handle height - 2 * material thickness)
|
||||||
|
* on_sides : True, : added to side panels if checked, to front and back otherwise (only used with top_edge parameter)
|
||||||
|
|
||||||
|
* relative
|
||||||
|
|
||||||
|
* outset : 1. : extend the handle along the length of the edge (multiples of thickness)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
absolute_params = {
|
||||||
|
"height" : 20.,
|
||||||
|
"radius" : 10.,
|
||||||
|
"hole_width" : "40:40",
|
||||||
|
"hole_height" : 75.,
|
||||||
|
"on_sides": True,
|
||||||
|
}
|
||||||
|
|
||||||
|
relative_params = {
|
||||||
|
"outset" : 1.,
|
||||||
|
}
|
||||||
|
|
||||||
|
def edgeObjects(self, boxes, chars="yY", add=True):
|
||||||
|
edges = [HandleEdge(boxes, self),
|
||||||
|
HandleHoleEdge(boxes, self)]
|
||||||
|
return self._edgeObjects(edges, boxes, chars, add)
|
||||||
|
|
||||||
|
# inspiration came from https://www.thingiverse.com/thing:327393
|
||||||
|
|
||||||
|
class HandleEdge(Edge):
|
||||||
|
"""Extends an 'edge' by adding a rounded bumpout with optional holes"""
|
||||||
|
description = "Handle for e.g. a drawer"
|
||||||
|
char = "y"
|
||||||
|
extra_height = 0.0
|
||||||
|
|
||||||
|
def __call__(self, length, **kw):
|
||||||
|
length += 2 * self.settings.outset
|
||||||
|
extra_height = self.extra_height * self.settings.thickness
|
||||||
|
|
||||||
|
r = self.settings.radius
|
||||||
|
if r > length / 2:
|
||||||
|
r = length / 2
|
||||||
|
if r > self.settings.height:
|
||||||
|
r = self.settings.height
|
||||||
|
|
||||||
|
widths = argparseSections(self.settings.hole_width)
|
||||||
|
|
||||||
|
if self.settings.outset:
|
||||||
|
self.polyline(0, -180, self.settings.outset, 90)
|
||||||
|
else:
|
||||||
|
self.corner(-90)
|
||||||
|
|
||||||
|
if self.settings.hole_height and sum(widths) > 0:
|
||||||
|
if sum(widths) < 100:
|
||||||
|
slot_offset = ((1 - sum(widths) / 100) * (length - (len(widths) + 1) * self.thickness)) / (len(widths) * 2)
|
||||||
|
else:
|
||||||
|
slot_offset = 0
|
||||||
|
|
||||||
|
slot_height = (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) * (length - (len(widths) + 1) * self.thickness)
|
||||||
|
else:
|
||||||
|
slotwidth = w / 100 * (length - (len(widths) + 1) * self.thickness)
|
||||||
|
slot_x += slotwidth / 2
|
||||||
|
with self.saved_context():
|
||||||
|
self.moveTo((self.settings.height / 2) + extra_height, slot_x, 0)
|
||||||
|
self.rectangularHole(0,0,slot_height,slotwidth,slot_height/2,True,True)
|
||||||
|
slot_x += slotwidth / 2 + slot_offset + self.thickness + slot_offset
|
||||||
|
|
||||||
|
self.edge(self.settings.height - r + extra_height, tabs=1)
|
||||||
|
self.corner(90, r, tabs=1)
|
||||||
|
self.edge(length - 2 * r, tabs=1)
|
||||||
|
self.corner(90, r, tabs=1)
|
||||||
|
self.edge(self.settings.height - r + extra_height, tabs=1)
|
||||||
|
|
||||||
|
if self.settings.outset:
|
||||||
|
self.polyline(0, 90, self.settings.outset, -180)
|
||||||
|
else:
|
||||||
|
self.corner(-90)
|
||||||
|
|
||||||
|
def margin(self):
|
||||||
|
return self.settings.height
|
||||||
|
|
||||||
|
class HandleHoleEdge(HandleEdge):
|
||||||
|
"""Extends an 'edge' by adding a rounded bumpout with optional holes and holes for parallel finger joint"""
|
||||||
|
description = "Handle with holes for parallel finger joint"
|
||||||
|
char = "Y"
|
||||||
|
extra_height = 1.0
|
||||||
|
|
||||||
|
def __call__(self, length, **kw):
|
||||||
|
self.fingerHolesAt(0, -0.5*self.settings.thickness, length, 0)
|
||||||
|
super().__call__(length, **kw)
|
||||||
|
|
||||||
|
def margin(self):
|
||||||
|
return self.settings.height + self.extra_height*self.settings.thickness
|
||||||
|
|
|
@ -30,6 +30,7 @@ class AllEdges(Boxes):
|
||||||
self.addSettingsArgs(edges.LidSettings)
|
self.addSettingsArgs(edges.LidSettings)
|
||||||
self.addSettingsArgs(edges.ClickSettings)
|
self.addSettingsArgs(edges.ClickSettings)
|
||||||
self.addSettingsArgs(edges.FlexSettings)
|
self.addSettingsArgs(edges.FlexSettings)
|
||||||
|
self.addSettingsArgs(edges.HandleEdgeSettings)
|
||||||
|
|
||||||
self.buildArgParser(x=100)
|
self.buildArgParser(x=100)
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ class StorageShelf(_TopEdge):
|
||||||
#if top_edge is t put the handle on the x walls
|
#if top_edge is t put the handle on the x walls
|
||||||
if(self.top_edge=='t'):
|
if(self.top_edge=='t'):
|
||||||
t1,t2,t3,t4=(t2,t1,t4,t3)
|
t1,t2,t3,t4=(t2,t1,t4,t3)
|
||||||
self.closedtop = self.top_edge in "fFhŠ"
|
self.closedtop = self.top_edge in "fFhŠY"
|
||||||
|
|
||||||
# x sides
|
# x sides
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ class _TopEdge(Boxes):
|
||||||
|
|
||||||
def addTopEdgeSettings(self, fingerjoint={}, stackable={}, hinge={},
|
def addTopEdgeSettings(self, fingerjoint={}, stackable={}, hinge={},
|
||||||
cabinethinge={}, lid={}, click={},
|
cabinethinge={}, lid={}, click={},
|
||||||
roundedtriangle={}, mounting={}):
|
roundedtriangle={}, mounting={}, handle={}):
|
||||||
self.addSettingsArgs(edges.FingerJointSettings, **fingerjoint)
|
self.addSettingsArgs(edges.FingerJointSettings, **fingerjoint)
|
||||||
self.addSettingsArgs(edges.StackableSettings, **stackable)
|
self.addSettingsArgs(edges.StackableSettings, **stackable)
|
||||||
self.addSettingsArgs(edges.HingeSettings, **hinge)
|
self.addSettingsArgs(edges.HingeSettings, **hinge)
|
||||||
|
@ -101,6 +101,7 @@ class _TopEdge(Boxes):
|
||||||
self.addSettingsArgs(edges.ClickSettings, **click)
|
self.addSettingsArgs(edges.ClickSettings, **click)
|
||||||
self.addSettingsArgs(edges.RoundedTriangleEdgeSettings, **roundedtriangle)
|
self.addSettingsArgs(edges.RoundedTriangleEdgeSettings, **roundedtriangle)
|
||||||
self.addSettingsArgs(edges.MountingSettings, **mounting)
|
self.addSettingsArgs(edges.MountingSettings, **mounting)
|
||||||
|
self.addSettingsArgs(edges.HandleEdgeSettings, **handle)
|
||||||
|
|
||||||
def topEdges(self, top_edge):
|
def topEdges(self, top_edge):
|
||||||
t1 = t2 = t3 = t4 = self.edges.get(top_edge, self.edges["e"])
|
t1 = t2 = t3 = t4 = self.edges.get(top_edge, self.edges["e"])
|
||||||
|
@ -128,6 +129,18 @@ class _TopEdge(Boxes):
|
||||||
t4 = "G"
|
t4 = "G"
|
||||||
else: #PARAM_BACK
|
else: #PARAM_BACK
|
||||||
t2 = "G"
|
t2 = "G"
|
||||||
|
elif t1.char == "y":
|
||||||
|
t1 = t2 = t3 = t4 = "e"
|
||||||
|
if self.edges["y"].settings.on_sides == True:
|
||||||
|
t1 = t3 = "y"
|
||||||
|
else:
|
||||||
|
t2 = t4 = "y"
|
||||||
|
elif t1.char == "Y":
|
||||||
|
t1 = t2 = t3 = t4 = "h"
|
||||||
|
if self.edges["Y"].settings.on_sides == True:
|
||||||
|
t1 = t3 = "Y"
|
||||||
|
else:
|
||||||
|
t2 = t4 = "Y"
|
||||||
return [t1, t2, t3, t4]
|
return [t1, t2, t3, t4]
|
||||||
|
|
||||||
def drawLid(self, x, y, top_edge, bedBolts=[None, None]):
|
def drawLid(self, x, y, top_edge, bedBolts=[None, None]):
|
||||||
|
@ -136,7 +149,7 @@ class _TopEdge(Boxes):
|
||||||
self.rectangularWall(x, y, "CCCC", bedBolts=[d2, d3, d2, d3], move="up", label="top")
|
self.rectangularWall(x, y, "CCCC", bedBolts=[d2, d3, d2, d3], move="up", label="top")
|
||||||
elif top_edge == "f":
|
elif top_edge == "f":
|
||||||
self.rectangularWall(x, y, "FFFF", move="up", label="top")
|
self.rectangularWall(x, y, "FFFF", move="up", label="top")
|
||||||
elif top_edge in "FhŠ":
|
elif top_edge in "FhŠY":
|
||||||
self.rectangularWall(x, y, "ffff", move="up", label="top")
|
self.rectangularWall(x, y, "ffff", move="up", label="top")
|
||||||
elif top_edge == "L":
|
elif top_edge == "L":
|
||||||
self.rectangularWall(x, y, "nlmE", move="up", label="lid top")
|
self.rectangularWall(x, y, "nlmE", move="up", label="lid top")
|
||||||
|
|
|
@ -61,6 +61,8 @@ A set of instances are kept the ``.edges`` attribute of the
|
||||||
* t : RoundedTriangleEdge
|
* t : RoundedTriangleEdge
|
||||||
* uUvV : CabinetHingeEdge
|
* uUvV : CabinetHingeEdge
|
||||||
* X : FlexEdge
|
* X : FlexEdge
|
||||||
|
* y : HandleEdge
|
||||||
|
* Y : HandleHoleEdge
|
||||||
* Z : GroovedEdgeCounterPart
|
* Z : GroovedEdgeCounterPart
|
||||||
* z : GroovedEdge
|
* z : GroovedEdge
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue