Added pear shaped mounting hole drawing function (#392)

and add them to BinTray and TrafficLight
Add labels to the parts of these generators
Add doc strings to all hole types
This commit is contained in:
SuksAE 2022-05-15 07:55:53 +02:00 committed by GitHub
parent 88ea5f8385
commit 1bb4b8c0c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 131 additions and 14 deletions

View File

@ -1237,6 +1237,17 @@ class Boxes:
@restore
@holeCol
def dHole(self, x, y, r=None, d=None, w=None, rel_w=0.75, angle=0):
"""
Draw a hole for a shaft with flat edge - D shaped hole
:param x: center position
:param y: center position
:param r: radius (overrides d)
:param d: diameter
:param w: width measured against flat side in mm
:param rel_w: width in percent
:param angle: orentation (rotation) of the flat side
"""
if r is None:
r = d / 2.0
if w is None:
@ -1257,6 +1268,18 @@ class Boxes:
@restore
@holeCol
def flatHole(self, x, y, r=None, d=None, w=None, rel_w=0.75, angle=0):
"""
Draw a hole for a shaft with two opposed flat edges - ( ) shaped hole
:param x: center position
:param y: center position
:param r: radius (overrides d)
:param d: diameter
:param w: width measured against flat side in mm
:param rel_w: width in percent
:param angle: orientation (rotation) of the flat sides
"""
if r is None:
r = d / 2.0
if w is None:
@ -1278,6 +1301,40 @@ class Boxes:
self.edge(2*r*math.sin(math.radians(a)))
self.corner(-a)
@restore
@holeCol
def mountingHole(self, x, y, d_shaft, d_head=0.0, angle=0, tabs=0):
"""
Draw a pear shaped mounting hole for sliding over a screw head. Total height = 1.5* d_shaft + d_head
:param x: position
:param y: postion
:param d_shaft: diameter of the screw shaft
:param d_head: diameter of the screw head
:param angle: rotation angle of the hole
"""
if d_shaft < (2 * self.burn):
return # no hole if diameter is smaller then the capabilities of the machine
if not d_head or d_head < (2 * self.burn): # if no head diameter is given
self.hole(x, y ,d=d_shaft, tabs=tabs) # only a round hole is generated
return
rs = d_shaft / 2
rh = d_head / 2
self.moveTo(x, y, angle)
self.moveTo(0, rs - self.burn, 0)
self.corner(-180, rs, tabs)
self.edge(2 * rs,tabs)
a = math.degrees(math.asin(rs / rh))
self.corner(90 - a, 0, tabs)
self.corner(-360 + 2 * a, rh, tabs)
self.corner(90 - a, 0, tabs)
self.edge(2 * rs, tabs)
@restore
def text(self, text, x=0, y=0, angle=0, align="", fontsize=10, color=[0.0, 0.0, 0.0], font="Arial"):
"""

View File

@ -55,7 +55,8 @@ class BinTray(Boxes):
self.argparser.add_argument(
"--front", action="store", type=float, default=0.4,
help="fraction of bin height covert with slope")
self.argparser.add_argument("--hole_dD", action="store", type=argparseSections, default="3.5:6.5", help="mounting hole diameter (shaft:head) in mm [\U0001F6C8](https://florianfesti.github.io/boxes/html/usermanual.html#mounting-holes)")
def xSlots(self):
posx = -0.5 * self.thickness
for x in self.sx[:-1]:
@ -73,6 +74,23 @@ class BinTray(Boxes):
for x in self.sx:
self.fingerHolesAt(posy, posx, x)
posx += x + self.thickness
def addMount(self):
ds = self.hole_dD[0]
if len(self.hole_dD) < 2: # if no head diameter is given
dh = 0 # only a round hole is generated
y = max (self.thickness * 1.25, self.thickness * 1.0 + ds) # and we assume that a typical screw head diameter is twice the shaft diameter
else:
dh = self.hole_dD[1] # use given head diameter
y = max (self.thickness * 1.25, self.thickness * 1.0 + dh / 2) # and offset the hole to have enough space for the head
dx = sum(self.sx) + self.thickness * (len(self.sx) - 1)
x1 = dx * 0.125
x2 = dx * 0.875
self.mountingHole(x1, y, ds, dh, -90)
self.mountingHole(x2, y, ds, dh, -90)
def xHoles(self):
posx = -0.5 * self.thickness
@ -102,6 +120,7 @@ class BinTray(Boxes):
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
y = sum(self.sy) + self.thickness * (len(self.sy) - 1)
h = self.h
hi = self.hi = h
t = self.thickness
@ -124,7 +143,7 @@ class BinTray(Boxes):
self.rectangularWall(y, h, "FFBF", move="up only")
# floor
self.rectangularWall(x, y, "ffff", callback=[self.xSlots, self.ySlots],move="right", label="back")
self.rectangularWall(x, y, "ffff", callback=[self.xSlots, self.ySlots, self.addMount], move="right", label="back")
# Inner walls
for i in range(len(self.sx) - 1):
e = [edges.SlottedEdge(self, self.sy, "f"), "f", "B", "f"]
@ -139,6 +158,3 @@ class BinTray(Boxes):
for i in range(len(self.sy)):
e = [edges.SlottedEdge(self, self.sx, "g"), "F", "e", "F"]
self.rectangularWall(x, self.sy[i]*self.front*2**0.5, e, callback=[self.frontHoles(i)], move="up", label="retainer " + str(i+1))

View File

@ -63,6 +63,8 @@ When turned by 90°, it can be also used to create a bottle holder."""
"--upright", action="store", type=boolarg, default=True,
help="stack lights upright (or side by side)")
self.argparser.add_argument("--hole_dD", action="store", type=argparseSections, default="3.5:6.5", help="mounting hole diameter (shaft:head) in mm [\U0001F6C8](https://florianfesti.github.io/boxes/html/usermanual.html#mounting-holes)")
def backCB(self):
t = self.thickness
for i in range(1, self.n):
@ -85,13 +87,13 @@ When turned by 90°, it can be also used to create a bottle holder."""
def frontCB(self):
self.hole(self.h/2, self.h/2, self.h/2-self.thickness)
def wall(self, h1, h2, w, edges="ffef", callback=None, move="", label = ""):
def wall(self, h1, h2, w, edges="ffef", callback=None, move="", label=""):
edges = [self.edges.get(e, e) for e in edges]
edges += edges # append for wrapping around
overallwidth = w + edges[-1].spacing() + edges[1].spacing()
overallheight = max(h1, h2) + edges[0].spacing() + edges[2].spacing()
if self.move(overallwidth, overallheight, move, before=True, label= label):
if self.move(overallwidth, overallheight, move, before=True, label=label):
return
a = math.atan((h2-h1)/float(w))
@ -112,7 +114,45 @@ When turned by 90°, it can be also used to create a bottle holder."""
edges[3](h1)
self.edgeCorner(edges[3], edges[3 + 1], 90)
self.move(overallwidth, overallheight, move, label = label)
self.move(overallwidth, overallheight, move, label=label)
def addMountH(self, width, height):
ds = self.hole_dD[0]
if len(self.hole_dD) < 2: # if no head diameter is given
dh = 0 # only a round hole is generated
y = height - max (self.thickness * 1.25, self.thickness * 1.0 + ds) # and we assume that a typical screw head diameter is twice the shaft diameter
else:
dh = self.hole_dD[1] # use given head diameter
y = height - max (self.thickness * 1.25, self.thickness * 1.0 + dh / 2) # and offset the hole to have enough space for the head
dx = width
x1 = dx * 0.125
x2 = dx * 0.875
self.mountingHole(x1, y, ds, dh, 90)
self.mountingHole(x2, y, ds, dh, 90)
def addMountV(self, width, height):
if self.hole_dD[0] < 2 * self.burn:
return # no hole if no diameter is given
ds = self.hole_dD[0]
if len(self.hole_dD) < 2: # if no head diameter is given
dh = 0 # only a round hole is generated
x = max (self.thickness * 2.75, self.thickness * 2.25 + ds) # and we assume that a typical screw head diameter is twice the shaft diameter
else:
dh = self.hole_dD[1] # use given head diameter
x = max (self.thickness * 2.75, self.thickness * 2.25 + dh / 2) # and offset the hole to have enough space for the head
dy = height
y1 = self.thickness * 0.75 + dy * 0.125
y2 = self.thickness * 0.75 + dy * 0.875
self.mountingHole(x, y1, ds, dh, 180)
self.mountingHole(x, y2, ds, dh, 180)
def render(self):
# adjust to the variables you want in the local scope
@ -126,12 +166,15 @@ When turned by 90°, it can be also used to create a bottle holder."""
self.addPart(ShadyEdge(self, None))
# back
self.rectangularWall(th, h, "FFFF", callback=[self.backCB], move="up", label = "back")
if self.upright:
self.rectangularWall(th, h, "FFFF", callback=[self.backCB, self.addMountV(th, h)], move="up", label="back")
else:
self.rectangularWall(th, h, "FFFF", callback=[self.backCB, self.addMountH(th, h)], move="up", label="back")
if self.upright:
# sides
self.rectangularWall(th, d, "fFsF", callback=[self.sideCB], move="up", label = "left")
self.rectangularWall(th, d, "fFsF", callback=[self.sideCB], move="up", label = "right")
self.rectangularWall(th, d, "fFsF", callback=[self.sideCB], move="up", label="left")
self.rectangularWall(th, d, "fFsF", callback=[self.sideCB], move="up", label="right")
# horizontal Walls / blinds tops
e = edges.CompoundEdge(self, "fF", (d, s))
@ -164,6 +207,4 @@ When turned by 90°, it can be also used to create a bottle holder."""
# Colored windows
for i in range(n):
self.parts.disc(h-2*t, move="right", label="colored window " + str(i+1))
self.parts.disc(h-2*t, move="right") # , label="colored windows") --> todo

View File

@ -165,6 +165,9 @@ Most generators will add walls between the comparments, so the total size might
The sizes of the sections are divided by a colon (``:``) e.g. ``30:25.5:70``. Instead of repeating the same value they can be replaced by ``value*numberofsections`` e.g. ``50*3`` meaning the same as ``50:50:50``. To equally divide a length into several sections ``overallwidth/numberofsections`` can be used - e.g. ``120/4`` being the same as ``30:30:30:30``. All these formats can be freely mixed.
mounting_holes
..................
Some generators provide the option to create pear shaped mounting holes. To generate the right size holes, the shaft and the head diameter of the mounting screw must be configured. The format is "shaft:head", both diameters given in mm (e.g ``3.5:6.5``). If only the shaft diameter is given (e.g. ``3.5``), a round mounting hole is generated. Setting the mounting hole diameter parameter to ``0`` disables the creation of mounting holes.
outside
.......