Create a GridfinityTrayLayout object.
This is based on the TrayLayout2, but it designed to just give exactly the correct size boxes to fit into a gridfinity system. It has a modified TrayLayout setup, so it works in one step. It uses javascript to auto-generate the grid, which means it doesn't currently work for Inkscape or command line.
This commit is contained in:
parent
42944a015b
commit
bfc710698f
|
@ -0,0 +1,113 @@
|
|||
import boxes
|
||||
from boxes import Boxes
|
||||
from boxes.generators.traylayout import TrayLayout, TrayLayout2
|
||||
from boxes.Color import Color
|
||||
from boxes import restore
|
||||
|
||||
class GridfinityTrayLayout(TrayLayout2):
|
||||
"""A Gridfinity Tray Generator based on TrayLayout"""
|
||||
|
||||
description = """
|
||||
This is a general purpose gridfinity tray generator. You can create
|
||||
somewhat arbitrarily shaped trays, or just do nothing for simple grid
|
||||
shaped trays.
|
||||
|
||||
The dimensions are automatically calculated to fit perfectly into a
|
||||
gridfinity grid (like the GridfinityBase, or any other Gridfinity
|
||||
based base).
|
||||
|
||||
Edit the layout text graphics to adjust your tray.
|
||||
You can replace the hyphens and vertical bars representing the walls
|
||||
with a space character to remove the walls. You can replace the space
|
||||
characters representing the floor by a "X" to remove the floor for
|
||||
this compartment.
|
||||
"""
|
||||
def __init__(self) -> None:
|
||||
Boxes.__init__(self)
|
||||
self.addSettingsArgs(boxes.edges.FingerJointSettings)
|
||||
self.buildArgParser(h=50)
|
||||
self.outside = True # We're *always* outside for gridfinity
|
||||
self.pitch = 42.0 # gridfinity pitch is defined as 42.
|
||||
self.opening = 38
|
||||
self.opening_margin = 2
|
||||
self.argparser.add_argument("--hi", type=float, default=0, help="inner height of inner walls in mm (leave to zero for same as outer walls)")
|
||||
self.argparser.add_argument("--nx", type=int, default=3, help="number of gridfinity grids in X direction")
|
||||
self.argparser.add_argument("--ny", type=int, default=2, help="number of gridfinity grids in Y direction")
|
||||
self.argparser.add_argument("--countx", type=int, default=5, help="split x into this many grid sections. 0 means same as --nx")
|
||||
self.argparser.add_argument("--county", type=int, default=3, help="split y into this many grid sections. 0 means same as --ny")
|
||||
self.argparser.add_argument("--margin", type=float, default=0.75, help="Leave this much total margin on the outside, in mm")
|
||||
self.argparser.add_argument("--layout", type=str, help="You can hand edit this before generating", default="");
|
||||
|
||||
def generate_layout(self):
|
||||
layout = ''
|
||||
countx = self.countx
|
||||
county = self.county
|
||||
if countx == 0:
|
||||
countx = self.nx
|
||||
if county == 0:
|
||||
county = self.ny
|
||||
|
||||
stepx = self.x / countx
|
||||
stepy = self.y / county
|
||||
for i in range(countx):
|
||||
line = ' |' * i + f" ,> {stepx}mm\n"
|
||||
layout += line
|
||||
for i in range(county):
|
||||
layout += "+-" * countx + f"+\n"
|
||||
layout += "| " * countx + f"|{stepy}mm\n"
|
||||
layout += "+-" * countx + "+\n"
|
||||
return layout
|
||||
|
||||
@restore
|
||||
def rectangularEtching(self, x, y, dx, dy, r=0, center_x=True, center_y=True):
|
||||
"""
|
||||
Draw a rectangular hole
|
||||
|
||||
:param x: position
|
||||
:param y: position
|
||||
:param dx: width
|
||||
:param dy: height
|
||||
:param r: (Default value = 0) radius of the corners
|
||||
:param center_x: (Default value = True) if True, x position is the center, else the start
|
||||
:param center_y: (Default value = True) if True, y position is the center, else the start
|
||||
"""
|
||||
r = min(r, dx/2., dy/2.)
|
||||
x_start = x if center_x else x + dx / 2.0
|
||||
y_start = y - dy / 2.0 if center_y else y
|
||||
self.moveTo(x_start, y_start, 180)
|
||||
self.edge(dx / 2.0 - r) # start with an edge to allow easier change of inner corners
|
||||
for d in (dy, dx, dy, dx / 2.0 + r):
|
||||
self.corner(-90, r)
|
||||
self.edge(d - 2 * r)
|
||||
|
||||
def baseplate_etching(self):
|
||||
x = 0
|
||||
y = 0
|
||||
o = self.opening
|
||||
p = self.pitch
|
||||
m = self.opening_margin
|
||||
self.ctx.stroke()
|
||||
with self.saved_context():
|
||||
for xx in [0, self.nx-1]:
|
||||
for yy in [0, self.ny-1]:
|
||||
self.set_source_color(Color.ETCHING)
|
||||
self.rectangularEtching(x+p/2+xx*p, y+p/2+yy*p, o-m, o-m)
|
||||
self.ctx.stroke()
|
||||
|
||||
def render(self):
|
||||
# Create a layout
|
||||
self.x = self.pitch * self.nx - self.margin
|
||||
self.y = self.pitch * self.ny - self.margin
|
||||
self.outer_x = self.x
|
||||
self.outer_y = self.y
|
||||
super().render()
|
||||
# relies on still being at the place of the base plate
|
||||
self.baseplate_etching()
|
||||
foot = self.opening - self.opening_margin
|
||||
self.move(self.outer_x, self.outer_y, "right", before=False)
|
||||
n_grids = self.nx * self.ny
|
||||
if n_grids > 4:
|
||||
n_grids = 4
|
||||
for i in range(n_grids):
|
||||
self.rectangularWall(foot, foot, move="right")
|
||||
|
|
@ -368,7 +368,6 @@ You can replace the space characters representing the floor by a "X" to remove t
|
|||
if x < lx:
|
||||
posx += self.x[x] + self.thickness
|
||||
|
||||
|
||||
def parse(self, input):
|
||||
x = []
|
||||
y = []
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 181 KiB |
|
@ -122,3 +122,4 @@ cfec3b4f915befc29efc3913c131204948e63a444fd41370989173b0243617d7 ../static/samp
|
|||
6a5222b9d886454f6c4fda8ead777f2136f8c1d0231e145a30ea853430ee7baa ../static/samples/WallRollHolder.jpg
|
||||
cedf3c9ce40a379c4ca52089d0cda51cdf4c3899df1368c6374ed45afcb8cef8 ../static/samples/WallWrenchHolder.jpg
|
||||
5b123ea245e7670cd0a55cea8348aa1f2628080f5ec005902cdd86bab231aad1 ../static/samples/WallConsole.jpg
|
||||
d7b9c4a9ea70c2cc7ede5e992862fa4c001cff0f592a689ed4d5fab5ac339249 ../static/samples/GridfinityTrayLayout.jpg
|
||||
|
|
|
@ -76,4 +76,85 @@ function initPage(num_hide = null) {
|
|||
}
|
||||
const t = document.getElementsByClassName("thumbnail");
|
||||
for (let el of t) initThumbnail(el);
|
||||
}
|
||||
}
|
||||
|
||||
function GridfinityTrayLayout_GenerateLayout(x, y, nx, ny, countx, county) {
|
||||
// x = width in mm
|
||||
// y = height in mm
|
||||
// nx # of gridfinity grids in X
|
||||
// ny # of gridfinity grids in Y
|
||||
// countx split x into this many
|
||||
// county split y into this many
|
||||
layout = '';
|
||||
if (countx == 0)
|
||||
countx = nx;
|
||||
if (county == 0)
|
||||
county = ny
|
||||
stepx = x / countx;
|
||||
stepy = y / county;
|
||||
for (i = 0; i < countx; i++) {
|
||||
line = ' |'.repeat(i) + ` ,> ${stepx}mm\n`;
|
||||
layout += line;
|
||||
}
|
||||
for (i = 0; i < county; i++) {
|
||||
layout += "+-".repeat(countx) + "+\n";
|
||||
layout += "| ".repeat(countx) + `|${stepy}mm\n`;
|
||||
}
|
||||
layout += "+-".repeat(countx) + "+\n";
|
||||
return layout
|
||||
}
|
||||
|
||||
function GridfinityTrayUpdateLayout(event) {
|
||||
console.log("update");
|
||||
if (window.layoutUpdated == true) {
|
||||
// Don't do the update if the layout has been manually touched.
|
||||
if (confirm("You have manually updated the Layout. Do you wish to regenerate it?")) {
|
||||
window.layoutUpdated = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("updating");
|
||||
nx = document.getElementById('nx').value;
|
||||
ny = document.getElementById('ny').value;
|
||||
countx = document.getElementById('countx').value;
|
||||
county = document.getElementById('county').value;
|
||||
margin = document.getElementById('margin').value;
|
||||
x = nx*42 - margin
|
||||
y = ny*42 - margin
|
||||
layout_id = document.getElementById('layout');
|
||||
layout_id.value = GridfinityTrayLayout_GenerateLayout(x, y, nx, ny, countx, county);
|
||||
}
|
||||
|
||||
function setUpdated() {
|
||||
console.log("this was updated");
|
||||
window.layoutUpdated=true;
|
||||
}
|
||||
function GridfinityTrayLayoutInit() {
|
||||
console.log("update init");
|
||||
ids = ['nx', 'ny', 'countx', 'county', 'margin'];
|
||||
window.layoutUpdated=false;
|
||||
for (id_string of ids) {
|
||||
id = document.getElementById(id_string);
|
||||
id.addEventListener('input', GridfinityTrayUpdateLayout);
|
||||
}
|
||||
layout_id = document.getElementById('layout');
|
||||
layout_id.addEventListener('change', setUpdated);
|
||||
layout_id.addEventListener('input', setUpdated);
|
||||
|
||||
GridfinityTrayUpdateLayout();
|
||||
layout_id = document.getElementById('layout');
|
||||
layout_id.rows = 20;
|
||||
layout_id.cols = 24;
|
||||
}
|
||||
function addCallbacks() {
|
||||
if (window.location.href.includes("/GridfinityTrayLayout"))
|
||||
GridfinityTrayLayoutInit();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
addCallbacks();
|
||||
}, false);
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue