Adding Grooved Edge (z, Z), example use in UnevenHeightBox
This commit is contained in:
parent
f38819307b
commit
dfc2f075d9
|
@ -541,6 +541,9 @@ class Boxes:
|
||||||
# Rounded Triangle Edge
|
# Rounded Triangle Edge
|
||||||
edges.RoundedTriangleEdgeSettings(self.thickness, True,
|
edges.RoundedTriangleEdgeSettings(self.thickness, True,
|
||||||
**self.edgesettings.get("RoundedTriangleEdge", {})).edgeObjects(self)
|
**self.edgesettings.get("RoundedTriangleEdge", {})).edgeObjects(self)
|
||||||
|
# Grooved Edge
|
||||||
|
edges.GroovedSettings(self.thickness, True,
|
||||||
|
**self.edgesettings.get("Grooved", {})).edgeObjects(self)
|
||||||
|
|
||||||
# HexHoles
|
# HexHoles
|
||||||
self.hexHolesSettings = HexHolesSettings(self.thickness, True,
|
self.hexHolesSettings = HexHolesSettings(self.thickness, True,
|
||||||
|
|
131
boxes/edges.py
131
boxes/edges.py
|
@ -342,6 +342,137 @@ class OutSetEdge(Edge):
|
||||||
return self.boxes.thickness
|
return self.boxes.thickness
|
||||||
|
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
#### GroovedEdge
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
class GroovedSettings(Settings):
|
||||||
|
"""Settings for Grooved Edge
|
||||||
|
Values:
|
||||||
|
|
||||||
|
* absolute_params
|
||||||
|
|
||||||
|
* style : "arc" : the style of grooves
|
||||||
|
* tri_angle : 30 : the angle of triangular cuts
|
||||||
|
* arc_angle : 120 : the angle of arc cuts
|
||||||
|
* width : 0.2 : the width of each groove (fraction of the edge length)
|
||||||
|
* gap : 0.1 : the gap between grooves (fraction of the edge length)
|
||||||
|
* margin : 0.3 : minimum space left and right without grooves (fraction of the edge length)
|
||||||
|
* inverse : False : invert the groove directions
|
||||||
|
* interleave : False : alternate the direction of grooves
|
||||||
|
"""
|
||||||
|
|
||||||
|
PARAM_ARC = "arc"
|
||||||
|
PARAM_FLAT = "flat"
|
||||||
|
PARAM_SOFTARC = "softarc"
|
||||||
|
PARAM_TRIANGLE = "triangle"
|
||||||
|
|
||||||
|
absolute_params = {
|
||||||
|
"style": (PARAM_ARC, PARAM_FLAT, PARAM_TRIANGLE, PARAM_SOFTARC),
|
||||||
|
"tri_angle": 30,
|
||||||
|
"arc_angle": 120,
|
||||||
|
"width": 0.2,
|
||||||
|
"gap": 0.1,
|
||||||
|
"margin": 0.3,
|
||||||
|
"inverse": False,
|
||||||
|
"interleave": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def edgeObjects(self, boxes, chars="zZ", add=True):
|
||||||
|
edges = [GroovedEdge(boxes, self),
|
||||||
|
GroovedEdgeCounterPart(boxes, self)]
|
||||||
|
return self._edgeObjects(edges, boxes, chars, add)
|
||||||
|
|
||||||
|
|
||||||
|
class GroovedEdgeBase(BaseEdge):
|
||||||
|
def is_inverse(self):
|
||||||
|
return self.settings.inverse != self.inverse
|
||||||
|
|
||||||
|
def __call__(self, length, **kw):
|
||||||
|
if length == 0.0:
|
||||||
|
return
|
||||||
|
|
||||||
|
def check_bounds(val, mn, mx, name):
|
||||||
|
if not mn <= val <= mx:
|
||||||
|
raise ValueError(f"{name} needs to be in [{mn}, {mx}] but is {val}")
|
||||||
|
|
||||||
|
style = self.settings.style
|
||||||
|
width = self.settings.width
|
||||||
|
margin = self.settings.margin
|
||||||
|
gap = self.settings.gap
|
||||||
|
interleave = self.settings.interleave
|
||||||
|
|
||||||
|
check_bounds(width, 0, 1, "width")
|
||||||
|
check_bounds(margin, 0, 0.5, "margin")
|
||||||
|
check_bounds(gap, 0, 1, "gap")
|
||||||
|
|
||||||
|
# Check how many grooves fit
|
||||||
|
count = max(0, int((1 - 2 * margin + gap) / (width + gap)))
|
||||||
|
inside_width = max(0, count * (width + gap) - gap)
|
||||||
|
margin = (1 - inside_width) / 2
|
||||||
|
|
||||||
|
# Convert to actual length
|
||||||
|
margin = length * margin
|
||||||
|
gap = length * gap
|
||||||
|
width = length * width
|
||||||
|
|
||||||
|
# Determine the initial inversion
|
||||||
|
inv = 1 if self.is_inverse() else -1
|
||||||
|
if interleave and self.inverse and count % 2 == 0:
|
||||||
|
inv = -inv
|
||||||
|
|
||||||
|
# The edge until the first groove
|
||||||
|
self.edge(margin, tabs=1)
|
||||||
|
|
||||||
|
# Grooves
|
||||||
|
for i in range(count):
|
||||||
|
if i > 0:
|
||||||
|
self.edge(gap)
|
||||||
|
if interleave:
|
||||||
|
inv = -inv
|
||||||
|
if style == GroovedSettings.PARAM_FLAT:
|
||||||
|
self.edge(width)
|
||||||
|
elif style == GroovedSettings.PARAM_ARC:
|
||||||
|
angle = self.settings.arc_angle / 2
|
||||||
|
side_length = width / math.sin(math.radians(angle)) / 2
|
||||||
|
self.corner(inv * -angle)
|
||||||
|
self.corner(inv * angle, side_length)
|
||||||
|
self.corner(inv * angle, side_length)
|
||||||
|
self.corner(inv * -angle)
|
||||||
|
elif style == GroovedSettings.PARAM_SOFTARC:
|
||||||
|
angle = self.settings.arc_angle / 2
|
||||||
|
side_length = width / math.sin(math.radians(angle)) / 4
|
||||||
|
self.corner(inv * -angle, side_length)
|
||||||
|
self.corner(inv * angle, side_length)
|
||||||
|
self.corner(inv * angle, side_length)
|
||||||
|
self.corner(inv * -angle, side_length)
|
||||||
|
elif style == GroovedSettings.PARAM_TRIANGLE:
|
||||||
|
angle = self.settings.tri_angle
|
||||||
|
side_length = width / math.cos(math.radians(angle)) / 2
|
||||||
|
self.corner(inv * -angle)
|
||||||
|
self.edge(side_length)
|
||||||
|
self.corner(inv * 2 * angle)
|
||||||
|
self.edge(side_length)
|
||||||
|
self.corner(inv * -angle)
|
||||||
|
else:
|
||||||
|
raise ValueError("Unknown GroovedEdge style: %s)" % style)
|
||||||
|
|
||||||
|
# The final edge
|
||||||
|
self.edge(margin, tabs=1)
|
||||||
|
|
||||||
|
|
||||||
|
class GroovedEdge(GroovedEdgeBase):
|
||||||
|
description = """Edge with grooves"""
|
||||||
|
char = 'z'
|
||||||
|
inverse = False
|
||||||
|
|
||||||
|
|
||||||
|
class GroovedEdgeCounterPart(GroovedEdgeBase):
|
||||||
|
description = """Edge with grooves (opposing side)"""
|
||||||
|
char = 'Z'
|
||||||
|
inverse = True
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
#### Gripping Edge
|
#### Gripping Edge
|
||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
|
@ -25,6 +25,7 @@ class UnevenHeightBox(Boxes):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Boxes.__init__(self)
|
Boxes.__init__(self)
|
||||||
self.addSettingsArgs(edges.FingerJointSettings)
|
self.addSettingsArgs(edges.FingerJointSettings)
|
||||||
|
self.addSettingsArgs(edges.GroovedSettings)
|
||||||
self.buildArgParser("x", "y", "outside", bottom_edge="F")
|
self.buildArgParser("x", "y", "outside", bottom_edge="F")
|
||||||
self.argparser.add_argument(
|
self.argparser.add_argument(
|
||||||
"--height0", action="store", type=float, default=50,
|
"--height0", action="store", type=float, default=50,
|
||||||
|
@ -44,12 +45,19 @@ class UnevenHeightBox(Boxes):
|
||||||
self.argparser.add_argument(
|
self.argparser.add_argument(
|
||||||
"--lid_height", action="store", type=float, default=0,
|
"--lid_height", action="store", type=float, default=0,
|
||||||
help="additional height of the lid")
|
help="additional height of the lid")
|
||||||
|
self.argparser.add_argument(
|
||||||
|
"--edge_types", action="store", type=str, default="eeee",
|
||||||
|
help="which edges are flat (e) or grooved (z,Z), counter-clockwise from the front")
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
|
||||||
x, y = self.x, self.y
|
x, y = self.x, self.y
|
||||||
heights = [self.height0, self.height1, self.height2, self.height3]
|
heights = [self.height0, self.height1, self.height2, self.height3]
|
||||||
|
|
||||||
|
edge_types = self.edge_types
|
||||||
|
if len(edge_types) != 4 or any(et not in "ezZ" for et in edge_types):
|
||||||
|
raise ValueError("Wrong edge_types style: %s)" % edge_types)
|
||||||
|
|
||||||
if self.outside:
|
if self.outside:
|
||||||
x = self.adjustSize(x)
|
x = self.adjustSize(x)
|
||||||
y = self.adjustSize(y)
|
y = self.adjustSize(y)
|
||||||
|
@ -61,10 +69,10 @@ class UnevenHeightBox(Boxes):
|
||||||
h0, h1, h2, h3 = heights
|
h0, h1, h2, h3 = heights
|
||||||
b = self.bottom_edge
|
b = self.bottom_edge
|
||||||
|
|
||||||
self.trapezoidWall(x, h0, h1, [b, "F", "e", "F"], move="right")
|
self.trapezoidWall(x, h0, h1, [b, "F", edge_types[0], "F"], move="right")
|
||||||
self.trapezoidWall(y, h1, h2, [b, "f", "e", "f"], move="right")
|
self.trapezoidWall(y, h1, h2, [b, "f", edge_types[1], "f"], move="right")
|
||||||
self.trapezoidWall(x, h2, h3, [b, "F", "e", "F"], move="right")
|
self.trapezoidWall(x, h2, h3, [b, "F", edge_types[2], "F"], move="right")
|
||||||
self.trapezoidWall(y, h3, h0, [b, "f", "e", "f"], move="right")
|
self.trapezoidWall(y, h3, h0, [b, "f", edge_types[3], "f"], move="right")
|
||||||
|
|
||||||
with self.saved_context():
|
with self.saved_context():
|
||||||
if b != "e":
|
if b != "e":
|
||||||
|
@ -79,14 +87,17 @@ class UnevenHeightBox(Boxes):
|
||||||
self.rectangularWall(x, y, edges, move="up")
|
self.rectangularWall(x, y, edges, move="up")
|
||||||
|
|
||||||
if self.lid:
|
if self.lid:
|
||||||
self.moveTo(0, maxh+self.lid_height+self.edges["F"].spacing()+self.edges[b].spacing()+3*self.spacing, 180)
|
self.moveTo(0, maxh+self.lid_height+self.edges["F"].spacing()+self.edges[b].spacing()+1*self.spacing, 180)
|
||||||
self.trapezoidWall(y, h0, h3, "Ffef", move="right" +
|
edge_inverse = {"e": "e", "z": "Z", "Z": "z"}
|
||||||
|
edge_types = [edge_inverse[et] for et in edge_types]
|
||||||
|
|
||||||
|
self.trapezoidWall(y, h0, h3, "Ff" + edge_types[3] + "f", move="right" +
|
||||||
(" only" if h0 == h3 == 0.0 else ""))
|
(" only" if h0 == h3 == 0.0 else ""))
|
||||||
self.trapezoidWall(x, h3, h2, "FFeF", move="right" +
|
self.trapezoidWall(x, h3, h2, "FF" + edge_types[2] + "F", move="right" +
|
||||||
(" only" if h3 == h2 == 0.0 else ""))
|
(" only" if h3 == h2 == 0.0 else ""))
|
||||||
self.trapezoidWall(y, h2, h1, "Ffef", move="right" +
|
self.trapezoidWall(y, h2, h1, "Ff" + edge_types[1] + "f", move="right" +
|
||||||
(" only" if h2 == h1 == 0.0 else ""))
|
(" only" if h2 == h1 == 0.0 else ""))
|
||||||
self.trapezoidWall(x, h1, h0, "FFeF", move="right" +
|
self.trapezoidWall(x, h1, h0, "FF" + edge_types[0] + "F", move="right" +
|
||||||
(" only" if h1 == h0 == 0.0 else ""))
|
(" only" if h1 == h0 == 0.0 else ""))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue