Four years / a day? What’s really the difference.
I was asked to design an undergravel filter. Let’s do it.
Prototype
Here’s the original prototype:

Not much to go on.
Version 1
And here’s where we ended up:
// Units
inch = 25.4;
// Requested dimensions (converted to mm)
box_x = 9 * inch;
box_y = 6 * inch;
box_z = 0.75 * inch;
// Piece thickness of walls and bottom (top?)
wall = 2;
bottom = 2;
// Size and space between centers for grid holes
hole_d = 2.5;
spacing = 10;
// Size of the larger tube hole in the corner
tube_hole_d = 18.4;
// --- Don't change anything below this line ---
// Derived cavity size
inner_x = box_x - 2 * wall;
inner_y = box_y - 2 * wall;
inner_z = box_z - bottom;
// Centered hole grid counts
nx = floor((inner_x - hole_d) / spacing) + 1;
ny = floor((inner_y - hole_d) / spacing) + 1;
// Offset to center hole grid
start_x = wall + (inner_x - (nx - 1) * spacing) / 2;
start_y = wall + (inner_y - (ny - 1) * spacing) / 2;
// Tube hole in the corner
tube_hole_x = start_x + spacing;
tube_hole_y = start_y + spacing;
difference() {
// Outer box
cube([box_x, box_y, box_z]);
// Hollow interior (cut from top)
translate([wall, wall, bottom])
cube([inner_x, inner_y, inner_z + 0.01]);
// Hole for the tube
translate([tube_hole_x, tube_hole_y, -1])
cylinder(h = inner_z + 2, d = tube_hole_d, $fn = 64);
// Hole array through bottom
for (i = [0:nx-1]) {
for (j = [0:ny-1]) {
x = start_x + i * spacing;
y = start_y + j * spacing;
// Skip grid hole if too near tube hole
dist = sqrt( (x - tube_hole_x)*(x - tube_hole_x) +
(y - tube_hole_y)*(y - tube_hole_y) );
if (dist - 1 > tube_hole_d/2) {
translate([x, y, -1])
cylinder(h = bottom + 2, d = hole_d, $fn = 32);
}
}
}
}

Tube tolerance
One thing that did take a while to get close enough was the tolerance of the larger hole. It had to fit fairly accurately around a tube. Luckily, if you set a few minor changes:
box_x = 1.5 * inch;
box_y = 1.5 * inch;
box_z = 0.2 * inch;
tube_hole_d = 18.4;

Version 2
In the end, I actually ended up going a different route with that:
// Units
inch = 25.4;
// Requested dimensions (converted to mm)
box_x = 9 * inch;
box_y = 6 * inch;
box_z = 0.75 * inch;
// Piece thickness of walls and bottom (top?)
wall = 2;
bottom = 2;
// Size and space between centers for grid holes
hole_d = 2.5;
spacing = 10;
// Size of the larger tube hole in the corner
tube_hole_d = 18.4;
tube_coller_depth = 0.25 * inch;
// --- Don't change anything below this line ---
// Derived cavity size
inner_x = box_x - 2 * wall;
inner_y = box_y - 2 * wall;
inner_z = box_z - bottom;
// Centered hole grid counts
nx = floor((inner_x - hole_d) / spacing) + 1;
ny = floor((inner_y - hole_d) / spacing) + 1;
// Offset to center hole grid
start_x = wall + (inner_x - (nx - 1) * spacing) / 2;
start_y = wall + (inner_y - (ny - 1) * spacing) / 2;
// Tube hole in the corner
tube_hole_x = start_x + spacing;
tube_hole_y = start_y + spacing;
difference() {
// Hollow cube
union() {
difference() {
cube([box_x, box_y, box_z]);
translate([wall, wall, bottom])
cube([inner_x, inner_y, inner_z + 0.01]);
}
// Collar for the tube
translate([tube_hole_x, tube_hole_y, 0])
cylinder(h = tube_coller_depth + bottom, d = tube_hole_d + wall, $fn = 64);
}
// Hole for the tube
translate([tube_hole_x, tube_hole_y, -1])
cylinder(h = inner_z + 2, d = tube_hole_d, $fn = 64);
// Hole array through bottom
for (i = [0:nx-1]) {
for (j = [0:ny-1]) {
x = start_x + i * spacing;
y = start_y + j * spacing;
// Skip grid hole if too near tube hole
dist = sqrt( (x - tube_hole_x)*(x - tube_hole_x) +
(y - tube_hole_y)*(y - tube_hole_y) );
if (dist - 1 > tube_hole_d/2) {
translate([x, y, -1])
cylinder(h = bottom + 2, d = hole_d, $fn = 32);
}
}
}
}

And that was it, time for a full 9x6" print! Which is pretty close to the limits of what I can print (without a crazy angle).
Unfortunately…

I had my first bed adhesion problems in quite a while and even worse it was in the corner that really needed to be accurate or it wouldn’t fit the air tube.
So I cleaned off the plate (warm water and soap) and dropped the initial layer print speeds by about 1/3. Version 2? A perfect print!

About 3 hours and 100g of filament. None too shabby at all.
(Now we’ll just have to finish setting up the tank and see how it works!)