Allow full grid layouting for inserts

This commit is contained in:
2026-06-12 13:41:29 +02:00
parent cab17d08e9
commit 6151df81b3
+46 -34
View File
@@ -57,7 +57,7 @@ thumb_grooves = true;
// How the lid is held shut. "latch": snap latches hinged on
// short pieces of filament (see README). "friction": original
// push fit.
lid_style = "latch"; // [latch, friction]
lid_style = "friction"; // [latch, friction]
// Latches per long (front/back) wall, spread out evenly
latches_per_side = 2;
// Diameter of the filament used as hinge pin
@@ -95,19 +95,27 @@ notch_d = 22;
// ------------------------------------------------------------
// Compartment layout
// ------------------------------------------------------------
// One entry per row (front to back). Each entry is
// [row_depth_weight, [column_width_weights]]
// Weights are relative, so the layout always fills the insert
// exactly no matter what the box dimensions are.
// The layout is a recursive grid. Each cell is one of
// * a number -> a compartment, sized by that weight
// * [weight, [cells]] -> a cell split perpendicular to its
// parent into the given sub-cells
// * [cells] -> shorthand for [1, [cells]]
// The top level splits the insert front-to-back into rows, each
// row splits left-to-right into columns, and so on, alternating
// direction at every nesting level. Weights are relative, so the
// layout always fills the insert exactly.
// Caveat: a two-element list whose second element is a list is
// always read as [weight, [cells]]; use the explicit weight form
// if that's not what you mean.
//
// Default: a wide slot for measuring tapes across the back,
// and two rows of token compartments in front.
// Default: one full-depth bay on the left (weight 2, ~67 mm wide
// here - fits a deck of standard cards lying flat), two medium
// bays, and a right column split into three equal token bins.
layout = [
[1.0, [1, 1, 1, 1]], // front row: 4 small token bins
[1.0, [2, 1, 1]], // middle row: 1 medium + 2 small
[0.8, [1]] // back row: full-width slot (tapes etc.)
[1.0, [2, 1, 1, [1, 1, 1]]],
];
$fn = $preview ? 32 : 64;
// ------------------------------------------------------------
@@ -165,7 +173,12 @@ function sum(v, i = 0) = i >= len(v) ? 0 : v[i] + sum(v, i + 1);
// sum of the first n elements
function psum(v, n) = n <= 0 ? 0 : v[n - 1] + psum(v, n - 1);
function row_weights() = [for (r = layout) r[0]];
// layout cell accessors (see "Compartment layout" above)
function cell_weight(c) = is_num(c) ? c
: len(c) == 2 && is_list(c[1]) ? c[0] : 1;
function cell_children(c) = is_num(c) ? undef
: len(c) == 2 && is_list(c[1]) ? c[1] : c;
function cell_weights(cells) = [for (c = cells) cell_weight(c)];
// rounded-corner rectangle, centered at origin corner (0,0)
module rrect(x, y, r) {
@@ -356,34 +369,12 @@ module placed_latch(x0) {
module insert() {
iw_x = ins_x - 2 * insert_wall; // usable interior
iw_y = ins_y - 2 * insert_wall;
n_rows = len(layout);
rw = row_weights();
avail_y = iw_y - (n_rows - 1) * divider_t;
difference() {
rbox(ins_x, ins_y, ins_h, inner_r);
// compartment cavities
for (ri = [0 : n_rows - 1]) {
row_y0 = insert_wall
+ avail_y * psum(rw, ri) / sum(rw)
+ ri * divider_t;
row_dy = avail_y * rw[ri] / sum(rw);
cols = layout[ri][1];
n_cols = len(cols);
avail_x = iw_x - (n_cols - 1) * divider_t;
for (ci = [0 : n_cols - 1]) {
col_x0 = insert_wall
+ avail_x * psum(cols, ci) / sum(cols)
+ ci * divider_t;
col_dx = avail_x * cols[ci] / sum(cols);
translate([col_x0, row_y0, insert_floor])
cube([col_dx, row_dy, ins_h]);
}
}
carve(layout, insert_wall, insert_wall, iw_x, iw_y, false);
// finger notches on the short (left/right) walls
if (finger_notches)
@@ -395,6 +386,27 @@ module insert() {
}
}
// carve the cells into the region [x0, y0]..[x0+dx, y0+dy],
// split along x or y; nested cells recurse on the other axis
module carve(cells, x0, y0, dx, dy, split_x) {
n = len(cells);
w = cell_weights(cells);
avail = (split_x ? dx : dy) - (n - 1) * divider_t;
for (i = [0 : n - 1]) {
off = avail * psum(w, i) / sum(w) + i * divider_t;
sz = avail * w[i] / sum(w);
cx = split_x ? x0 + off : x0;
cy = split_x ? y0 : y0 + off;
cdx = split_x ? sz : dx;
cdy = split_x ? dy : sz;
sub = cell_children(cells[i]);
if (is_undef(sub))
translate([cx, cy, insert_floor]) cube([cdx, cdy, ins_h]);
else
carve(sub, cx, cy, cdx, cdy, !split_x);
}
}
// ------------------------------------------------------------
// Output
// ------------------------------------------------------------