$fn = 64; // --- Parameters --- cols = 6; // Number of columns (width) rows = 3; // Number of rows (depth) hole_diameter = 16; // Diameter of the slots (16mm fits most standard markers/pens) hole_depth = 60; // Depth of the slots wall_thickness = 2.5; // Thickness of walls between slots base_thickness = 3; // Thickness of the bottom base // --- Calculated Dimensions --- width = cols * hole_diameter + (cols + 1) * wall_thickness; depth = rows * hole_diameter + (rows + 1) * wall_thickness; height = hole_depth + base_thickness; // --- Main Object --- union() { // Main Holder Body difference() { // Solid block cube([width, depth, height]); // Subtract grid of holes for (c = [0 : cols - 1]) { for (r = [0 : rows - 1]) { x_pos = wall_thickness + hole_diameter/2 + c * (hole_diameter + wall_thickness); y_pos = wall_thickness + hole_diameter/2 + r * (hole_diameter + wall_thickness); // Main hole (extends slightly above top to ensure a clean cut) translate([x_pos, y_pos, base_thickness]) cylinder(h = hole_depth + 1, d = hole_diameter); } } } // Mounting Bracket (Universal Cleat / Rail Style) // Designed with 45-degree angles for support-free 3D printing // Shifted slightly into the main body (-0.1 in Y) to ensure manifold geometry translate([0, depth - 0.1, 0]) { // Top mounting hook hull() { // Overlaps back of the body translate([0, 0, height - 20]) cube([width, 0.2, 20]); // Outward extension forming the downward hook translate([0, 0, height - 10]) cube([width, 10.1, 10]); } // Bottom spacer to keep the holder vertical against the wall hull() { // Overlaps back of the body translate([0, 0, 0]) cube([width, 0.2, 10]); // Outward extension forming the spacer translate([0, 0, 0]) cube([width, 10.1, 5]); } } }