$fn=64; // --- Parameters --- // Bin dimensions bin_width = 200; bin_depth = 150; bin_height = 150; wall_thickness = 3; corner_radius = 8; // Rail Mount dimensions (French cleat style for PetStation) mount_width = 120; mount_depth = 18; lip_thickness = 6; gap_height = 10; hook_drop = 30; // --- Modules --- module rounded_rect(w, d, h, r) { hull() { translate([r, r, 0]) cylinder(r=r, h=h); translate([w-r, r, 0]) cylinder(r=r, h=h); translate([r, d-r, 0]) cylinder(r=r, h=h); translate([w-r, d-r, 0]) cylinder(r=r, h=h); } } // --- Main Assembly --- union() { // Main Storage Bin difference() { // Outer shell rounded_rect(bin_width, bin_depth, bin_height, corner_radius); // Inner hollow translate([wall_thickness, wall_thickness, wall_thickness]) rounded_rect( bin_width - 2*wall_thickness, bin_depth - 2*wall_thickness, bin_height + 1, // +1 ensures clean cut at the top max(0.1, corner_radius - wall_thickness) ); // Front access scoop translate([bin_width/2, -30, bin_height + 60]) rotate([0, 90, 0]) cylinder(r=100, h=bin_width + 20, center=true); } // Back Wall Rail Mount (Printable without supports) translate([(bin_width - mount_width)/2, bin_depth - 0.1, bin_height - gap_height]) { // Base extension from the bin cube([mount_width, mount_depth, gap_height]); // Downward locking lip translate([0, mount_depth - lip_thickness, -hook_drop]) cube([mount_width, lip_thickness, hook_drop]); // 45-degree support chamfer for 3D printability hull() { // Top edge against the base extension cube([mount_width, mount_depth - lip_thickness, 0.1]); // Bottom edge against the bin wall translate([0, 0, -(mount_depth - lip_thickness)]) cube([mount_width, 0.1, 0.1]); } } }