This commit is contained in:
J-Waal 2023-04-21 22:51:54 +02:00
commit c71a0cc41c
13 changed files with 160 additions and 197 deletions

View File

@ -25,6 +25,7 @@ class CardHolder(Boxes):
def __init__(self) -> None:
Boxes.__init__(self)
self.addSettingsArgs(edges.StackableSettings)
self.addSettingsArgs(edges.GroovedSettings)
self.addSettingsArgs(edges.FingerJointSettings, surroundingspaces=1.0)

View File

@ -15,8 +15,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from boxes import *
from boxes.generators.typetray import TypeTray
class CompartmentBox(Boxes):
class CompartmentBox(TypeTray):
"""Type tray variation with sliding lid"""
description = """Sliding lid rests on inner walls,
@ -26,7 +27,7 @@ class CompartmentBox(Boxes):
ui_group = "Unstable"
def __init__(self) -> None:
Boxes.__init__(self)
Boxes.__init__(self) # avoid TypeTray.__init__
self.buildArgParser("sx", "sy", "h", "outside", "bottom_edge")
self.argparser.add_argument(
"--handle", action="store", type=str, default="lip",
@ -40,59 +41,18 @@ class CompartmentBox(Boxes):
default="70",
help="width of hole(s) in percentage of maximum hole width")
def xSlots(self):
posx = -0.5 * self.thickness
for x in self.sx[:-1]:
posx += x + self.thickness
posy = 0
for y in self.sy:
self.fingerHolesAt(posx, posy, y)
posy += y + self.thickness
def ySlots(self):
posy = -0.5 * self.thickness
for y in self.sy[:-1]:
posy += y + self.thickness
posx = 0
for x in reversed(self.sx):
self.fingerHolesAt(posy, posx, x)
posx += x + self.thickness
def xHoles(self):
posx = -0.5 * self.thickness
for x in self.sx[:-1]:
posx += x + self.thickness
self.fingerHolesAt(posx, 0, self.h)
def yHoles(self):
posy = -0.5 * self.thickness
for y in self.sy[:-1]:
posy += y + self.thickness
self.fingerHolesAt(posy, 0, self.h)
def render(self):
t = self.thickness
if self.outside:
self.sx = self.adjustSize(self.sx)
self.sy = self.adjustSize(self.sy)
self.h = self.adjustSize(self.h) - 2 * t
self.hi = self.h = self.adjustSize(self.h) - 2 * t
x = sum(self.sx) + self.thickness * (len(self.sx) - 1)
y = sum(self.sy) + self.thickness * (len(self.sy) - 1)
h = self.h
# Create new Edges here if needed E.g.:
s = edges.FingerJointSettings(self.thickness, relative=False,
style = "rectangular")
p = edges.FingerJointEdge(self, s)
p.char = "a" # 'a', 'A', 'b' and 'B' is reserved for beeing used within generators
self.addPart(p)
# outer walls
b = self.bottom_edge
tl, tb, tr, tf = "FEFe"
@ -146,14 +106,13 @@ class CompartmentBox(Boxes):
# y walls
# outer walls - left/right
self.sideWall(
y, h+t, "left", [b, "f", tl, "f"], callback=[self.yHoles, ],
move="up", label="left side")
self.sideWall(
y, h+t, "right", [b, "f", tr, "f"],
callback=[self.mirrorX(self.yHoles, y), ],
move="up", label="right side")
f = edges.CompoundEdge(self, "fE", [h+self.edges[b].startwidth(), t])
self.rectangularWall(y, h+t, [b, f, tl, "f"], callback=[self.yHoles, ],
ignore_widths=[1,5,6],
move="up", label="left side")
self.rectangularWall(y, h+t, [b, f, tl, "f"], callback=[self.yHoles, ],
ignore_widths=[1,5,6],
move="mirror up", label="right side")
# inner walls
for i in range(len(self.sx) - 1):
@ -161,98 +120,13 @@ class CompartmentBox(Boxes):
"f", "e", "f"]
self.rectangularWall(y, h, e, move="up", label=f"inner y {i+1}")
lipy = y-t if self.handle == "lip" else y
self.rectangularWall(lipy, t, "eefe", move="up", label="Lip Left")
self.rectangularWall(lipy, t, "feee", move="up", label="Lip Right")
def sideWall(self, x, y, side, edges="eeee",
holesMargin=None, holesSettings=None,
bedBolts=None, bedBoltSettings=None,
callback=None,
move=None,
label=""):
if len(edges) != 4:
raise ValueError("four edges required")
if side not in {"left", "right"}:
raise ValueError("side must be left or right")
b = edges[0]
edges = [self.edges.get(e, e) for e in edges]
edges += edges # append for wrapping around
overallwidth = x + edges[-1].spacing() + edges[1].spacing()
overallheight = y + edges[0].spacing() + edges[2].spacing()
t = self.thickness
if self.move(overallwidth, overallheight, move, before=True):
return
self.moveTo(edges[-1].spacing(), edges[0].margin())
for i, l in enumerate((x, y, x, y)):
self.cc(callback, i, y=edges[i].startwidth() + self.burn)
e1, e2 = edges[i], edges[i + 1]
if i == 3 and side == "right":
l -= t
self.edges.get('e')(t)
l += edges[i+1].startwidth()
e2 = self.edges["e"]
edges[i](l,
bedBolts=self.getEntry(bedBolts, i),
bedBoltSettings=self.getEntry(bedBoltSettings, i))
elif i == 1 and side == "left":
l -= t
l += edges[i-1].startwidth()
edges[i](l,
bedBolts=self.getEntry(bedBolts, i),
bedBoltSettings=self.getEntry(bedBoltSettings, i))
self.edges.get('e')(t)
else:
if i == 3 and side == "left":
l += edges[i+1].startwidth() + edges[i-1].startwidth()
e2 = self.edges["e"]
if i == 1 and side == "right":
l += edges[i+1].startwidth() + edges[i-1].startwidth()
e2 = self.edges["e"]
if i == 2 and self.handle == "lip":
if b != "s":
l -= t
print(b)
if side == "left":
self.edges.get('e')(t)
edges[i](l,
bedBolts=self.getEntry(bedBolts, i),
bedBoltSettings=self.getEntry(bedBoltSettings, i))
elif side == "right":
edges[i](l,
bedBolts=self.getEntry(bedBolts, i),
bedBoltSettings=self.getEntry(bedBoltSettings, i))
self.edges.get('e')(t)
else:
self.edges.get('S')(l)
self.fingerHolesAt(0 if side == "left" else -t, 1.5*t, l-t, angle=180)
else:
edges[i](l,
bedBolts=self.getEntry(bedBolts, i),
bedBoltSettings=self.getEntry(bedBoltSettings, i))
if i == 2 and side == "left":
e1 = self.edges["e"]
if i == 0 and side == "right":
e1 = self.edges["e"]
if i == 0 and side == "left":
e1 = self.edges["e"]
if self.handle == "lip":
lip_edges = "eefe"
else:
lip_edges = "eefE"
self.edgeCorner(e1, e2, 90)
if holesMargin is not None:
self.moveTo(holesMargin,
holesMargin + edges[0].startwidth())
self.hexHolesRectangle(x - 2 * holesMargin, y - 2 * holesMargin, settings=holesSettings)
self.move(overallwidth, overallheight, move, label=label)
self.rectangularWall(y, t, lip_edges, move="up", label="Lip Left")
self.rectangularWall(y, t, lip_edges, move="mirror up", label="Lip Right")
def gripHole(self):
if not self.radius:
@ -283,6 +157,3 @@ class CompartmentBox(Boxes):
#self.moveTo(20, slot_x, 0)
self.rectangularHole(slot_x,radius+t,slotwidth,slot_height,radius,True,True)
slot_x += slotwidth / 2 + slot_offset + self.thickness + slot_offset
#todo stackable top/bottom

View File

@ -15,13 +15,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from boxes import *
from boxes.edges import Edge
from boxes.edges import Edge, CompoundEdge
class USlotEdge(Edge):
def __call__(self, length, bedBolts=None, bedBoltSettings=None, **kw):
l = length
d = self.settings
o = self.settings
d = length * (1-o/100) / 2
r = min(3*self.thickness, (l-2*d)/2)
self.edges["f"](d)
self.polyline(0, 90, 0, (-90, r), l-2*d-2*r, (-90, r), 0, 90)
@ -61,15 +62,26 @@ class NotesHolder(Boxes):
Boxes.__init__(self)
self.addSettingsArgs(edges.FingerJointSettings, surroundingspaces=1)
self.addSettingsArgs(edges.StackableSettings)
self.buildArgParser(x=78, y=78, h=35, bottom_edge="s")
self.buildArgParser(sx="78", y=78, h=35, bottom_edge="s")
self.argparser.add_argument(
"--opening", action="store", type=float, default=40,
help="percent of front that's open")
def fingerHoleCB(self, lengths, height, posy=0.0):
def CB():
t = self.thickness
px = -0.5 * t
for x in lengths[:-1]:
px += x + t
self.fingerHolesAt(px, posy, height, 90)
return CB
def render(self):
x, y, h = self.x, self.y, self.h
sx, y, h = self.sx, self.y, self.h
t = self.thickness
x = sum(sx) + (len(sx) - 1) * t
o = max(0, min(self.opening, 100))
sides = x * (1-o/100) / 2
@ -77,19 +89,39 @@ class NotesHolder(Boxes):
if self.bottom_edge == "s":
b2 = HalfStackableEdge(self, self.edges["s"].settings,
self.edges["f"].settings)
b3 = self.edges["h"]
else:
b2 = b
b3 = b
b4 = Edge(self, None)
b4.startwidth = lambda: b3.startwidth()
with self.saved_context():
self.rectangularWall(y, h, [b, "F", "e", "F"],
ignore_widths=[1, 6], move="right")
# front walls
if self.opening == 0.0:
self.rectangularWall(x, h, [b, "f", "e", "f"],
ignore_widths=[1, 6], move="right")
else:
self.rectangularWall(sides, h, [b2, "e", "e", "f"],
self.rectangularWall(sx[0] * (1-o/100) / 2, h,
[b2, "e", "e", "f"],
ignore_widths=[1, 6], move="right")
self.rectangularWall(sides, h, [b2, "e", "e", "f"],
for ix in range(len(sx)-1):
left = sx[ix] * (1-o/100) / 2
right = sx[ix+1] * (1-o/100) / 2
h_e = t
bottom_edge = CompoundEdge(
self, [b3, b4, b3], [left, t, right])
self.rectangularWall(
left+right+t, h,
[bottom_edge, "e", "e", "e"],
callback=[lambda: self.fingerHolesAt(left+t/2, 0, h, 90)],
move="right")
self.rectangularWall(sx[-1] * (1-o/100) / 2, h,
[b2, "e", "e", "f"],
ignore_widths=[1, 6], move="right mirror")
self.rectangularWall(x, h, [b, "F", "e", "F"],
@ -97,12 +129,26 @@ class NotesHolder(Boxes):
with self.saved_context():
self.rectangularWall(y, h, [b, "F", "e", "F"], ignore_widths=[1, 6], move="right")
self.rectangularWall(x, h, [b, "f", "e", "f"], ignore_widths=[1, 6], move="right")
self.rectangularWall(x, h, [b, "f", "e", "f"],
callback=[self.fingerHoleCB(sx, h)],
ignore_widths=[1, 6], move="right")
self.rectangularWall(y, h, [b, "F", "e", "F"], move="up only")
if self.bottom_edge != "e":
if self.opening == 0.0:
self.rectangularWall(x, y, ["f", "f", "f", "f"], move="up")
else:
self.rectangularWall(x, y, [USlotEdge(self, sides), "f", "f", "f"], move="up")
u_edge = USlotEdge(self, o)
print([l for x in sx for l in (x, t)])
front = CompoundEdge(
self,
([u_edge, "e"]*len(sx))[:-1],
([l for x in sx for l in (x, t)])[:-1])
self.rectangularWall(x, y, [front, "f", "f", "f"],
callback=[self.fingerHoleCB(sx, y)],
move="up")
# innner walls
for i in range(len(sx)-1):
self.rectangularWall(
y, h, ("e" if self.bottom_edge=="e" else "f") + "fef",
move="right")

View File

@ -235,7 +235,7 @@ class BServer:
</head>
<body onload="initPage({len(box.argparser._action_groups) - 3})">
<div class="container" style="background-color: #FFF8EA;">
<div class="container">
<div style="float: left;">
<a href="./{langparam}"><h1>{_("Boxes.py")}</h1></a>
</div>
@ -316,29 +316,15 @@ class BServer:
{self.genHTMLJS()}
</head>
<body onload="initPage()">
<div class="container" style="background-color: #FFF8EA;">
<div class="container">
<div style="width: 75%; float: left;">
<h1>{_("Boxes.py")}</h1>
<p>{_("Create boxes and more with a laser cutter!")}</p>
<p>
{_('''
<a href="https://hackaday.io/project/10649-boxespy">Boxes.py</a> is an <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">Open Source</a> box generator written in <a href="https://www.python.org/">Python</a>. It features both finished parametrized generators as well as a Python API for writing your own. It features finger and (flat) dovetail joints, flex cuts, holes and slots for screws, hinges, gears, pulleys and much more.''')}
</p>
{self.genPagePartHeader(lang)}
<div class="modenav">
<span class="modebutton"><a href="Gallery">{_("Gallery")}</a></span>
<span class="modebutton modeactive">{_("Menu")}</span>
</div>
<div style="width: 25%; float: left;">
<img alt="self-Logo" src="{self.static_url}/boxes-logo.svg" width="250">
</div>
<div>
<div class="clear"></div>
<hr>
<div class="search">
\U0001f50d <input autocomplete="off" type="search" oninput="filterSearchItems();" name="search" id="search" placeholder="Search">
</div>
<br>
<div class="menu" style="width: 100%">
<img style="width: 200px;" id="sample-preview" src="{self.static_url}/nothing.png" alt="">
"""]
@ -428,18 +414,46 @@ class BServer:
</form>
"""
def genPagePartHeader(self, lang) -> str:
_ = lang.gettext
lang_name = lang.info().get('language', None)
langparam = ""
if lang_name:
langparam = "?language=" + lang_name
return f"""
<h1><a href="./{langparam}">{_("Boxes.py")}</a></h1>
<p>{_("Create boxes and more with a laser cutter!")}</p>
<p>
{_('''
<a href="https://hackaday.io/project/10649-boxespy">Boxes.py</a> is an <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">Open Source</a> box generator written in <a href="https://www.python.org/">Python</a>. It features both finished parametrized generators as well as a Python API for writing your own. It features finger and (flat) dovetail joints, flex cuts, holes and slots for screws, hinges, gears, pulleys and much more.''')}
</p>
</div>
<div style="width: 25%; float: left;">
<img alt="self-Logo" src="{self.static_url}/boxes-logo.svg" width="250">
</div>
<div>
<div class="clear"></div>
<div class="search">
\U0001f50d <input autocomplete="off" type="search" oninput="filterSearchItems();" name="search" id="search" placeholder="Search">
</div>"""
def genPagePartFooter(self, lang) -> str:
_ = lang.gettext
return """
<div class="footer container">
<div class="footer">
<ul>
<li>""" + self.genHTMLLanguageSelection(lang) + """</li>
<li><a href="https://florianfesti.github.io/boxes/html/usermanual.html" target="_blank" rel="noopener">""" + _("Help") + """</a></li>
<li><a href="https://hackaday.io/project/10649-boxespy" target="_blank" rel="noopener">""" + _("Home Page") + """</a></li>
<li><a href="https://florianfesti.github.io/boxes/html/index.html" target="_blank" rel="noopener">""" + _("Documentation") + """</a></li>
<li><a href="https://github.com/florianfesti/boxes" target="_blank" rel="noopener">""" + _("Sources") + """</a></li>
<li><a href="Gallery">""" + _("Gallery") + """</a></li>
</ul>
</div>
"""
@ -532,17 +546,13 @@ class BServer:
{self.genHTMLJS()}
</head>
<body onload="initPage()">
<div class="container" style="background-color: #FFF8EA;">
<div class="container">
<div style="width: 75%; float: left;">
<h1><a href="/">{_("Boxes.py")}</a></h1>
<h2>{_("Gallery")}</h2>
{self.genPagePartHeader(lang)}
<div class="modenav">
<span class="modebutton modeactive">{_("Gallery")}</span>
<span class="modebutton"><a href="Menu">{_("Menu")}</a></span>
</div>
<div style="width: 25%; float: left;">
<img alt="self-Logo" src="{self.static_url}/boxes-logo.svg" width="250">
</div>
<div class="clear"></div>
"""]
for nr, group in enumerate(self.groups):
result.append(f"<h2>{_(group.title)}</h2>\n")
@ -554,11 +564,13 @@ class BServer:
alt = f"{_(name)}"
href = f"{name}{langparam}"
if not os.path.exists(static_filename):
result.append(f""" <span class="gallery_missing"><a href="{href}">{_(name)}<br><br>{_(box.__doc__)}</a></span>\n""")
result.append(f""" <span class="gallery_missing" id="search_id_{name}"><a href="{href}">{_(name)}<br><br>{_(box.__doc__)}</a></span>\n""")
else:
result.append(f""" <span class="gallery"><a title="{_(name)} - {_(box.__doc__)}" href="{href}"><img alt="{alt}" src="{thumbnail}"/></a></span>\n""")
result.append(f""" <span class="gallery" id="search_id_{name}"><a title="{_(name)} - {_(box.__doc__)}" href="{href}"><img alt="{alt}" src="{thumbnail}"/></a></span>\n""")
result.append(f"""
</div><div style="width: 5%; float: left;"></div>
<div class="clear"></div><hr></div>
{self.genPagePartFooter(lang)}
</body>
</html>
@ -587,7 +599,7 @@ class BServer:
lang = self.getLanguage(args, environ.get("HTTP_ACCEPT_LANGUAGE", ""))
_ = lang.gettext
if name == "Gallery":
if not name or name == "Gallery":
return self.serveGallery(environ, start_response, lang)
box_cls = self.boxes.get(name, None)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
static/samples/Desksign.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/samples/Shoe.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -138,3 +138,6 @@ eedccf62c193224e2b86e52be8cd02faddf97d565330e2d5770390141da35069 ../static/samp
e9ee43e336401d3a0cb8e141c3a0b87a84e90f99eed30bdd420dcaead92940e1 ../static/samples/NemaPattern.jpg
3070eb2ed89461497d4dcc67021a0619338ab6d4d4d89d3cd1f83160da3c7920 ../static/samples/FanHole.jpg
c8adb0661956430ccec7fc00aa4b8e3c42d02083e17a9307541bc0160251cb96 ../static/samples/HolePattern.jpg
7c399c1cd235c3c044f676a31aa5215109e815055f2f69aef5d0cb1a24dfae41 ../static/samples/Desksign.jpg
fda14ba0920ef7ea0579117a30b5bb4a05ab3be4da3d87a4fc03fc40b085992b ../static/samples/PirateChest.jpg
125033a02263e74d5688287936f54cd83e917276b7c35f3fd37e6cb86efc0dcc ../static/samples/Shoe.jpg

View File

@ -79,6 +79,7 @@ table tr p {
/* Container */
.container {
background-color: #FFF8EA;
margin-top: 20px;
margin-left: auto;
margin-right: auto;
@ -124,7 +125,12 @@ video {
}
.footer {
box-shadow: none;
margin-left: auto;
margin-right: auto;
padding: 10px;
padding-bottom: 15px;
width: 996px;
border-radius: 30px;
text-align: center;
margin-top: 0px;
}
@ -141,6 +147,7 @@ video {
.search {
float : right;
padding-top: 10px;
}
.footer ul li a {
@ -206,3 +213,25 @@ textarea {
max-width : 200px;
margin : 5px;
}
.modenav {
overflow: hidden;
}
.modebutton {
float: left;
border: none;
outline: none;
padding: 10px 16px;
margin-right: 10px;
text-align : center;
border-radius: 10px;
font-size: 17px;
width: 25%;
background-color: #EFE8DA;
}
.modeactive {
background-color: #DFD8BA;
}

View File

@ -274,7 +274,7 @@ function expandAll() {
function showAll(str) {
let matching_ids = document.querySelectorAll('[id^="search_id_"]')
for (let id of matching_ids) {
id.hidden = false;
id.style.display = "inline-block";
}
}
@ -283,10 +283,11 @@ function showOnly(str) {
let matching_ids = document.querySelectorAll('[id^="search_id_"]')
for (let id of matching_ids) {
name = id.id.replace("search_id_", "").toLowerCase();
if (name.includes(str) || id.textContent.toLowerCase().includes(str))
id.hidden = false;
else
id.hidden = true;
if (name.includes(str) || id.textContent.toLowerCase().includes(str)) {
id.style.display = "inline-block";
} else {
id.style.display = "none";
}
}
}