$fn=64; // --- Parameters --- roll_dia = 36; // Clearance diameter for standard poop bag roll roll_height = 65; // Clearance height for the roll wall = 3; // Wall thickness slot_width = 5; // Width of the dispensing slot slot_height = 45; // Height of the dispensing slot // --- Derived Dimensions --- outer_dia = roll_dia + wall * 2; outer_height = roll_height + wall; // --- Print Layout --- // Main dispenser body dispenser_body(); // Removable lid (placed side-by-side for printing) translate([outer_dia + 15, 0, 0]) lid(); // --- Modules --- module dispenser_body() { difference() { union() { // Main cylindrical body cylinder(d=outer_dia, h=outer_height); // Wall mount backplate rounded_backplate(); } // Inner cavity for the roll translate([0, 0, wall]) cylinder(d=roll_dia, h=outer_height + 1); // Vertical dispensing slot translate([-slot_width/2, -outer_dia, wall + 10]) cube([slot_width, outer_dia, slot_height]); // Easy-tear V-notch at the bottom of the slot // Catches the bag perforation for a clean tear translate([0, -outer_dia/2, wall + 10]) rotate([90, 0, 0]) linear_extrude(outer_dia, center=true) polygon([[-slot_width/2, 0.1], [slot_width/2, 0.1], [0, -8]]); // Mounting screw holes (Top and Bottom) // Positioned above and below the main cylinder for screwdriver access screw_hole(75); screw_hole(-15); } } module rounded_backplate() { // Backplate overlaps the cylinder slightly to ensure a manifold mesh translate([0, outer_dia/2 + 3.5, 0]) rotate([90, 0, 0]) linear_extrude(4) // 4mm thickness hull() { translate([-15, -20]) circle(d=10); translate([15, -20]) circle(d=10); translate([-15, 85]) circle(d=10); translate([15, 85]) circle(d=10); } } module screw_hole(z_pos) { // Countersunk screw hole cutouts (sized for standard #8 or 4mm screws) translate([0, outer_dia/2 + 5, z_pos]) rotate([90, 0, 0]) { cylinder(d=4.5, h=10); // Main screw shaft translate([0, 0, 5]) cylinder(d1=4.5, d2=8.5, h=2.01); // Countersink angle translate([0, 0, 7]) cylinder(d=8.5, h=10); // Screw head clearance } } module lid() { // Simple drop-in lid to keep the roll contained difference() { union() { // Outer resting flange cylinder(d=outer_dia, h=wall); // Inner alignment plug (with 0.4mm clearance gap) translate([0, 0, wall]) cylinder(d=roll_dia - 0.8, h=wall * 2); } // Center finger hole for easy removal translate([0, 0, -1]) cylinder(d=16, h=wall * 4); } }