← Back to Models
Soap dish v1

Soap dish v1

by Mach3 ·

Sports neat spherical cut out for a piece of soap, and bestagon ribs (of course!). Optional water collector tray: https://modelrift.com/models/soap-dish-v1-tray

Prompt

I want to turn this into soap holder.
1. make sure the hex structures are originating from the center of the shape;
2. I want to have a negative cut of huge sphere from the center of the shape

OpenSCAD Code

// Honeycomb Soap Dish
// Dimensions: 175mm x 175mm

// --- Parameters ---
frame_width = 135;
frame_height = 135;
frame_depth = 24;        
frame_border = 1.6;        
corner_radius = 35;      

hex_radius = 20;         // Size of individual honeycomb cells
hex_wall = 1.6;          // Thickness of the honeycomb ribs

// --- Dish Cutout Parameters ---
dish_radius = 220;       // Large radius for a gentle curve
dish_depth = 16;         // How deep the "scoop" goes into the frame

// --- Screw Hole Parameters (Optional) ---
show_screwholes = false; 
screw_radius = 2.5;      
screw_dist_apart = 80;   
screw_z_percent = 0.5;  

$fn = 80;               

// --- Calculations ---
// Position sphere so its bottom reaches the desired depth
sphere_z_offset = (frame_depth - dish_depth) + dish_radius;

// --- Main Render ---
difference() {
    union() {
        // 1. Outer Border Frame
        difference() {
            rounded_square(frame_width, frame_height, frame_depth, corner_radius);
            
            // Interior Cutout
            translate([0, 0, -1])
                rounded_square(frame_width - frame_border*2, frame_height - frame_border*2, frame_depth + 2, corner_radius - frame_border);
            
            // Optional Screwholes
            if (show_screwholes) {
                hole_y_pos = frame_height/2 - frame_border/2;
                z_pos = frame_depth * screw_z_percent;
                translate([screw_dist_apart/2, hole_y_pos, z_pos]) teardrop_hole(screw_radius, frame_border + 2);
                translate([-screw_dist_apart/2, hole_y_pos, z_pos]) teardrop_hole(screw_radius, frame_border + 2);
            }
        }

        // 2. Honeycomb Fill
        intersection() {
            rounded_square(frame_width - frame_border, frame_height - frame_border, frame_depth, corner_radius - frame_border/2);
            
            // Pattern centered at 0,0
            honeycomb_grid(frame_width, frame_height, frame_depth, hex_radius, hex_wall);
        }
    }

    // 3. The "Huge Sphere" Negative Cut
    translate([0, 0, sphere_z_offset])
        sphere(r = dish_radius);
}

// --- Modules ---

module rounded_square(w, h, z, r) {
    translate([-w/2 + r, -h/2 + r, 0])
    hull() {
        cylinder(h=z, r=r);
        translate([w - 2*r, 0, 0]) cylinder(h=z, r=r);
        translate([0, h - 2*r, 0]) cylinder(h=z, r=r);
        translate([w - 2*r, h - 2*r, 0]) cylinder(h=z, r=r);
    }
}

module honeycomb_grid(width, height, depth, r, wall) {
    x_spacing = r * 1.5;
    y_spacing = r * sqrt(3);
    
    // Calculate number of cells needed to cover area
    cols = ceil(width / x_spacing) + 1;
    rows = ceil(height / y_spacing) + 1;
    
    // Center the grid by offsetting half the total span
    translate([0, 0, 0])
    for (i = [-cols/2 : cols/2]) {
        for (j = [-rows/2 : rows/2]) {
            x_pos = i * x_spacing;
            y_offset = (abs(i) % 2 == 1) ? y_spacing / 2 : 0;
            y_pos = j * y_spacing + y_offset;
            
            translate([x_pos, y_pos, 0])
            difference() {
                cylinder(h=depth, r=r, $fn=6);
                translate([0, 0, -0.5])
                    cylinder(h=depth + 1, r=r - wall, $fn=6);
            }
        }
    }
}

module teardrop_hole(r, length) {
    rotate([90, 0, 0])
    translate([0, 0, -length/2])
    hull() {
        cylinder(h=length, r=r);
        rotate([0, 0, 45]) cube([r, r, length]);
    }
}