From cb8c4d92f0e9ba3cc7022315a8b3598a986b9dc3 Mon Sep 17 00:00:00 2001 From: Bofakin Date: Mon, 11 May 2026 22:23:28 +0200 Subject: [PATCH 1/2] Added TriFingerJoint --- boxes/__init__.py | 5 ++- boxes/edges.py | 55 ++++++++++++++++++++--- examples/AllEdges.svg | 102 ++++++++++++++++++++++-------------------- 3 files changed, 105 insertions(+), 57 deletions(-) diff --git a/boxes/__init__.py b/boxes/__init__.py index a760b12e4..c70c437c0 100755 --- a/boxes/__init__.py +++ b/boxes/__init__.py @@ -677,6 +677,7 @@ def _buildObjects(self): **self.edgesettings.get("FingerJoint", {})) s.edgeObjects(self) self.addPart(edges.FingerHoles(self, s), name="fingerHolesAt") + self.addPart(edges.TriFingerHoles(self, s), name="triFingerHolesAt") # Stackable edges.StackableSettings(self.thickness, True, **self.edgesettings.get("Stackable", {})).edgeObjects(self) @@ -2980,9 +2981,9 @@ def polygonWalls(self, borders, h, bottom="F", top="F", symmetrical=True): t = self.thickness # XXX edge.margin() leftsettings = copy.deepcopy(self.edges["f"].settings) - lf, lF, lh = leftsettings.edgeObjects(self, add=False) + lf, lF, _, _ = leftsettings.edgeObjects(self, add=False) rightsettings = copy.deepcopy(self.edges["f"].settings) - rf, rF, rh = rightsettings.edgeObjects(self, add=False) + rf, rF, _, _ = rightsettings.edgeObjects(self, add=False) length_correction = 0. angle = borders[-1] diff --git a/boxes/edges.py b/boxes/edges.py index 1037aae49..e02628882 100644 --- a/boxes/edges.py +++ b/boxes/edges.py @@ -894,20 +894,22 @@ def checkValues(self) -> None: if abs(self.space + self.finger) < 0.1: raise ValueError("FingerJointSettings: space + finger must not be close to zero") - def edgeObjects(self, boxes, chars: str = "fFh", add: bool = True): + def edgeObjects(self, boxes, chars: str = "fFhƒ", add: bool = True): edges = [FingerJointEdge(boxes, self), FingerJointEdgeCounterPart(boxes, self), FingerHoleEdge(boxes, self), + TriFingerJointEdge(boxes, self), ] return self._edgeObjects(edges, boxes, chars, add) class FingerJointBase(ABC): """Abstract base class for finger joint.""" + finger_factor = 1 def calcFingers(self, length: float, bedBolts) -> tuple[int, float]: space, finger = self.settings.space, self.settings.finger # type: ignore - fingers = int((length - (self.settings.surroundingspaces - 1) * space) // (space + finger)) # type: ignore + fingers = int((length - (self.settings.surroundingspaces - 1) * space) // (space + self.finger_factor * finger)) # type: ignore # shrink surrounding space up to half a thickness each side if fingers == 0 and length > finger + 1.0 * self.settings.thickness: # type: ignore fingers = 1 @@ -915,7 +917,7 @@ def calcFingers(self, length: float, bedBolts) -> tuple[int, float]: fingers = 0 if bedBolts: fingers = bedBolts.numFingers(fingers) - leftover = length - fingers * (space + finger) + space + leftover = length - fingers * (space + self.finger_factor * finger) + space if fingers <= 0: fingers = 0 @@ -983,6 +985,20 @@ def draw_finger(self, f, h, style, positive: bool = True, firsthalf: bool = True else: self.polyline(0, 90, h, -90, f, -90, h, 90) + def addTriFingerSpace(self, i, fingers, pattern) -> bool: + # no double finger - no space + if self.finger_factor == 1: + return False + # ensure symmetric pattern + j = min(i, fingers - i - 1) + # check if space is needed + if (j % 2) == 0 and pattern == 'A': + return True + if (j % 2) == 1 and pattern == 'B': + return True + # otherwise no space + return False + def __call__(self, length, bedBolts=None, bedBoltSettings=None, **kw): positive = self.positive @@ -1025,8 +1041,12 @@ def __call__(self, length, bedBolts=None, bedBoltSettings=None, **kw): self.bedBoltHole(s, bedBoltSettings) else: self.edge(s) + if self.addTriFingerSpace(i, fingers, 'B'): + self.edge(f) self.draw_finger(f, h, style, positive, i < fingers // 2) + if self.addTriFingerSpace(i, fingers, 'A'): + self.edge(f) self.edge(leftover / 2.0, tabs=1) @@ -1088,14 +1108,14 @@ def __call__(self, x, y, length, angle=90, bedBolts=None, bedBoltSettings=None): self.ctx.rectangle(b, -self.settings.width / 2 + b, length - 2 * b, self.settings.width - 2 * b) for i in range(fingers): - pos = leftover / 2.0 + i * (s + f) + pos = leftover / 2.0 + i * (s + self.finger_factor * f) if bedBolts and bedBolts.drawBolt(i): d = (bedBoltSettings or self.boxes.bedBoltSettings)[0] self.boxes.hole(pos - 0.5 * s, 0, d * 0.5) - self.boxes.rectangularHole(pos + 0.5 * f, 0, - f + p, self.settings.width + p) + self.boxes.rectangularHole(pos + 0.5 * self.finger_factor * f, 0, + self.finger_factor * f + p, self.settings.width + p) class FingerHoleEdge(BaseEdge): @@ -1156,6 +1176,29 @@ def startWidth(self) -> float: return self.outset +# The TriFingerJoint can be used to join two edges from oposing sides into a +# single wall. The holes in the wall have doubled length and the fingers have +# two spaces (one space sized and on finger sizes). For each hole the order of +# the fingers changes, to ensure a tight fit, if only one side is used. joint +# will like like the following: +# w = wall, l/r = fingers from left/right side +# lr w rl w lr w ... w rl w lr +# Note: the order of the pairs "lr" and "rl" is kepts symmetric. This causes a +# rectangularWall() with two opposing TriFingerJointEdges to cover the left and +# right sied, as the edges of an rectangularWall() are printed clockwise. +class TriFingerJointEdge(FingerJointEdge): + """Tri finger joint edge""" + char = 'ƒ' + description = "Tri Finger Joint" + finger_factor = 2 + + +class TriFingerHoles(FingerHoles): + """Hole matching a tri finger joint edge""" + description = "Edge (parallel Tri Finger Joint Holes)" + finger_factor = 2 + + ############################################################################# #### Stackable Joints ############################################################################# diff --git a/examples/AllEdges.svg b/examples/AllEdges.svg index 126314e98..df48f6517 100644 --- a/examples/AllEdges.svg +++ b/examples/AllEdges.svg @@ -1,5 +1,5 @@ - +