$width = 220; $height = 100; difference() { linear_extrude(5) square([$width, $height]); for (i=[0:1:5]) { $even_row = i%2; translate([0, 10 + i * 16, -5]) row_cylinders(diameter=14, gap=6, x_offset=$even_row*4); } }; module row_cylinders(diameter=20, gap=10, x_offset=0, length=220) { // One spacing will be split between the start and the end. $count = floor((length - 2 * x_offset) / (diameter + gap)); // It's not always possible to perfectly fit all the columns, sometimes // you end up with extra space. In that case, the space will be split // into the start and the end. $leftover = (length - 2 * x_offset) % (diameter + gap); for (dx=[(diameter + gap + $leftover) / 2 + x_offset : diameter + gap : length - ((gap + $leftover) / 2 + x_offset) ]) { translate([dx, 0, 0]) cylinder(h=20, d=diameter); } }