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
|
||||
edges.RoundedTriangleEdgeSettings(self.thickness, True,
|
||||
**self.edgesettings.get("RoundedTriangleEdge", {})).edgeObjects(self)
|
||||
# Grooved Edge
|
||||
edges.GroovedSettings(self.thickness, True,
|
||||
**self.edgesettings.get("Grooved", {})).edgeObjects(self)
|
||||
|
||||
# HexHoles
|
||||
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
|
||||
|
||||
|
||||
#############################################################################
|
||||
#### 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
|
||||
#############################################################################
|
||||
|
|
|
@ -25,6 +25,7 @@ class UnevenHeightBox(Boxes):
|
|||
def __init__(self):
|
||||
Boxes.__init__(self)
|
||||
self.addSettingsArgs(edges.FingerJointSettings)
|
||||
self.addSettingsArgs(edges.GroovedSettings)
|
||||
self.buildArgParser("x", "y", "outside", bottom_edge="F")
|
||||
self.argparser.add_argument(
|
||||
"--height0", action="store", type=float, default=50,
|
||||
|
@ -44,12 +45,19 @@ class UnevenHeightBox(Boxes):
|
|||
self.argparser.add_argument(
|
||||
"--lid_height", action="store", type=float, default=0,
|
||||
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):
|
||||
|
||||
x, y = self.x, self.y
|
||||
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:
|
||||
x = self.adjustSize(x)
|
||||
y = self.adjustSize(y)
|
||||
|
@ -61,10 +69,10 @@ class UnevenHeightBox(Boxes):
|
|||
h0, h1, h2, h3 = heights
|
||||
b = self.bottom_edge
|
||||
|
||||
self.trapezoidWall(x, h0, h1, [b, "F", "e", "F"], move="right")
|
||||
self.trapezoidWall(y, h1, h2, [b, "f", "e", "f"], move="right")
|
||||
self.trapezoidWall(x, h2, h3, [b, "F", "e", "F"], move="right")
|
||||
self.trapezoidWall(y, h3, h0, [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", edge_types[1], "f"], move="right")
|
||||
self.trapezoidWall(x, h2, h3, [b, "F", edge_types[2], "F"], move="right")
|
||||
self.trapezoidWall(y, h3, h0, [b, "f", edge_types[3], "f"], move="right")
|
||||
|
||||
with self.saved_context():
|
||||
if b != "e":
|
||||
|
@ -79,14 +87,17 @@ class UnevenHeightBox(Boxes):
|
|||
self.rectangularWall(x, y, edges, move="up")
|
||||
|
||||
if self.lid:
|
||||
self.moveTo(0, maxh+self.lid_height+self.edges["F"].spacing()+self.edges[b].spacing()+3*self.spacing, 180)
|
||||
self.trapezoidWall(y, h0, h3, "Ffef", move="right" +
|
||||
self.moveTo(0, maxh+self.lid_height+self.edges["F"].spacing()+self.edges[b].spacing()+1*self.spacing, 180)
|
||||
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 ""))
|
||||
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 ""))
|
||||
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 ""))
|
||||
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 ""))
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue