<p>You can use the <code>difference()</code> function in OpenSCAD to subtract one or more 3D shapes from another. Source: <a href="https://www.openscad.info/index.php/2020/05/14/difference/" rel="nofollow noreferrer">The documentation for the difference() function</a>.</p>
<p>For reference, your code already does that several times. Something like this:</p>
<pre><code>module bottom_box () {
    difference(){
        // Existing code ...

        // Subtract the hole
        translate([hole_position_x, hole_position_y, hole_position_z])
            cube([hole_size, hole_depth, hole_size], center=true);
    }
    // Rest of the code ...
}
</code></pre>
<h3>Two cube examples</h3>
<p>Below are two examples of a cube with and without a hole (in the bottom) that, for testing, can be rendered in your browser on <a href="https://openscad.cloud/openscad/" rel="nofollow noreferrer">openscad.cloud</a>:</p>
<h4>1. Model without a hole</h4>
<pre><code>cube_size = 20;
module simple_cube() {
    cube(cube_size);
}
simple_cube();

</code></pre>
<p><a href="https://i.sstatic.net/vXxbJ.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/vXxbJ.png" alt="model without a hole" /></a></p>
<p>Example of <a href="https://openscad.cloud/openscad/?&amp;sharedFileLink=W3sibmFtZSI6Im1haW4uc2NhZCIsInR4dCI6ImN1YmVfc2l6ZSA9IDIwO1xubW9kdWxlIHNpbXBsZV9jdWJlKCkge1xuICAgIGN1YmUoY3ViZV9zaXplKTtcbiAgICB9XG4gICAgc2ltcGxlX2N1YmUoKTsifV0=" rel="nofollow noreferrer">a model without a hole on openscad. cloud</a>.</p>
<h4>2. Model with a hole</h4>
<pre><code>cube_size = 20;
hole_size = 2;
module cube_with_hole() {
    difference() {
        cube(cube_size);
        translate([cube_size / 2, cube_size / 2, 0])
        cube([hole_size, hole_size, cube_size], center=true);
    }
}
cube_with_hole();
</code></pre>
<p><a href="https://i.sstatic.net/AOBew.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/AOBew.png" alt="model with a hole" /></a></p>
<p>Example of a <a href="https://openscad.cloud/openscad/?&amp;sharedFileLink=W3sibmFtZSI6Im1haW4uc2NhZCIsInR4dCI6ImN1YmVfc2l6ZSA9IDIwO1xuaG9sZV9zaXplID0gMjtcbm1vZHVsZSBjdWJlX3dpdGhfaG9sZSgpIHtcbiAgICBkaWZmZXJlbmNlKCkge1xuICAgICAgICAgICAgY3ViZShjdWJlX3NpemUpO1xuICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGUoW2N1YmVfc2l6ZSAvIDIsIGN1YmVfc2l6ZSAvIDIsIDBdKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1YmUoW2hvbGVfc2l6ZSwgaG9sZV9zaXplLCBjdWJlX3NpemVdLCBjZW50ZXI9dHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdWJlX3dpdGhfaG9sZSgpOyAifV0=" rel="nofollow noreferrer">model with a hole in the bottom on openscad. cloud</a>.</p>

CC BY-SA 4.0
2023-11-30T09:37:13.323Z
I've added this to bottom box but no hole appears. Not sure where it's messing up.
stormist
CC BY-SA 4.0
2023-11-30T09:42:31.807Z
Are you sure all variables are correct and the positioning is correct? I would debug it step by step. First, make the shape appear solid in an obvious color, then position it correctly, and then try to incorporate it in the difference function.
Bob Ortiz
CC BY-SA 4.0
2023-12-21T07:59:21.050Z
@stormist The hole should be longer than the box. The hole should protrude the box on both sides ( translate may be needed to shift the hole ).
Uwe
CC BY-SA 4.0
2023-12-21T09:02:27.643Z
Modify this line: cube([hole_size, hole_size, cube_size], center=true); to this: cube([hole_size, hole_size, cube_size + hole_size], center=true); for a longer protruding hole.
Uwe
CC BY-SA 4.0
2023-11-30T09:03:21.920Z
2023-12-18T23:27:50.763Z
2023-12-18T23:27:50.763Z
Bob Ortiz
<p>You will also need to add this function whenever you need holes of a minimum size, otherwise they will <strong>ALWAYS</strong> be too small.</p>
<pre><code>// Segments used for circles/cylinders have their *endpoints* on the radius.  This means that 
//    cylinders used for holes will be too small; the *midpoints* need to be on the radius,
//    not the *endpoints*.  This function returns properly sized radii for holes with a required minimum radius.

function midpoint_radius (endpoint_radius, num_facets) = endpoint_radius / cos(360/(num_facets*2));
</code></pre>
<hr />
<p>Bonus routines</p>
<pre><code>// Sets rotation based on desired endpoint
function rotateto(x=1,y=1,z=1) = [0,acos(z/norm([x,y,z])),atan2(y,x)];

// Automatically switches to desired circle quality based on whether &lt;F5&gt; or &lt;F6&gt; is pressed.
draft_quality = 12; // [12:6:360]
final_quality = 72; // [12:6:360]
smoothness = <span class="math-container">$preview ? draft_quality : final_quality; 
// (Circles are divided in $</span>fn line segments.)
$fn = smoothness;
</code></pre>

CC BY-SA 4.0
2024-07-12T04:47:46.903Z
2024-07-12T04:47:46.903Z
Keith Olson
<p>I'm trying to modify this code to create a small 2 mm x 2 mm hole on the short side of the box (to fit 2 wires coming out of a battery):</p>
<pre><code>// Which one would you like to see?
part = &quot;both&quot;; // [box:Box only, top: Top cover only, both: Box and top cover]

// Size of your printer's nozzle in mm
nozzle_size = 0.35;

// Number of walls the print should have
number_of_walls = 3; // [1:5]

// Tolerance (use 0.2 for FDM)
tolerance = 0.2; // [0.1:0.1:0.4]

// Interior dimension X in mm
interior_x=70;

// Interior dimension Y in mm
interior_y=21;

// Interior dimension Z in mm
interior_z=17;

// interior corner radius in mm
radius=0; // [0:20]

// What fraction of the flat X side should the hook take up? (0 for no hook)
x_hook_fraction = 0.5; // [0:0.1:1.0]

// What fraction of the flat Y side should the hook take up? (0 for no hook)
y_hook_fraction = 0.5; // [0:0.1:1.0]

// What fraction of the hooks should have a slot behind them? (0 for no slot)
slot_length = 0.7; // [0:0.1:1]

/* Hidden */
$fn=100;

wall_thickness=nozzle_size*number_of_walls;

// Outer dimensions
x = interior_x + 2 * wall_thickness;
y = interior_y + 2 * wall_thickness;
z = interior_z + 2 * wall_thickness;

hook_thickness = 3 * nozzle_size;

top_cover_wall_thickness = hook_thickness + wall_thickness;

y_hook_length = (y - 2 * radius) * y_hook_fraction;
x_hook_length = (x - 2 * radius) * x_hook_fraction;

module box_interior () {
    offset(r=radius) {
        square([interior_x-2*radius, interior_y-2*radius], center=true);
    }
}

module box_exterior () {
    offset(r=wall_thickness) {
        box_interior();
    }
}

module bottom_box () {
    difference(){
        // Solid box
        linear_extrude(z-wall_thickness){
            box_exterior();
        }
        
        // Hollow out
        translate([0,0,wall_thickness]) linear_extrude(z){
            box_interior();
        }
        left_slot();
        rotate([180,180,0]) left_slot(); // right slot
        front_slot();
        rotate([180,180,0]) front_slot(); // back slot
    }
    left_hook(); // left hook
    rotate([180,180,0]) left_hook(); // right hook
    front_hook(); // front hook
    rotate([180,180,0]) front_hook(); // back hook
}

module left_hook () {
    translate([(x-2*wall_thickness)/2,-y_hook_length/2,z-wall_thickness]) rotate([0,90,90]) {
        base_hook(y_hook_length);
    }
}

module front_hook () {
    translate([-x_hook_length/2,-y/2+wall_thickness,z-wall_thickness]) rotate([90,90,90]) {
        base_hook(x_hook_length);
    }
}

module base_hook (hook_length) {
    difference(){
        linear_extrude(hook_length){
            polygon(points=[[0,0],[2*hook_thickness,0],[hook_thickness,hook_thickness]]);
        }
        translate([hook_thickness, hook_thickness, 0]) rotate([45,0,0]) cube(2*hook_thickness, center=true);
        translate([hook_thickness, hook_thickness, hook_length]) rotate([45,0,0]) cube(2*hook_thickness, center=true);        
    }
}

module left_slot () {
    slot_length = y_hook_length*slot_length;
    epsilon=2; // ensure it definitely protrudes
    translate([x/2+epsilon,-slot_length/2,z]) rotate([0,90,90]) {
        cube([2*hook_thickness, wall_thickness+epsilon, slot_length]);
    }
}

module front_slot () {
    slot_length = x_hook_length*slot_length;
    epsilon=2; // ensure it definitely protrudes
    translate([-slot_length/2,-y/2-epsilon,z]) rotate([90,90,90]) {
        cube([2*hook_thickness, wall_thickness+epsilon, slot_length]);
    }
}

module right_groove () {
    translate([-tolerance/2+(x-2*wall_thickness)/2,-y_hook_length/2,wall_thickness+hook_thickness*2]) rotate([0,90,90]) linear_extrude(y_hook_length) {
        base_groove();
    }
}


module front_groove () {
    translate([-x_hook_length/2,-y/2+wall_thickness+tolerance/2,wall_thickness+hook_thickness*2]) rotate([90,90,90]) linear_extrude(x_hook_length){
        base_groove();
    }
}

module base_groove () {
    polygon(points=[[0,0],[0, -1], [2*hook_thickness, -1],[2*hook_thickness,0],[hook_thickness,hook_thickness]]);
}

module top_cover () {

    // Top face
    linear_extrude(wall_thickness) {
        box_exterior();
    }
    
    difference(){
        // Wall of top cover
        inset = wall_thickness + tolerance/2;
        linear_extrude(wall_thickness+hook_thickness*2){
            offset(r=-inset) {
                box_exterior();
            }
        }
        
        // Hollow out
        translate([0,0,wall_thickness]) linear_extrude(z){
            offset(r=-wall_thickness*2) {
                offset(r=-inset) {
                    box_exterior();
                }
            }
        }
        
        right_groove();
        rotate([180,180,0]) right_groove();
        front_groove();
        rotate([180,180,0])  front_groove();
    }
  

}

// left_hook();
print_part();

module print_part() {
    if (part == &quot;box&quot;) {
        bottom_box();
    } else if (part == &quot;top&quot;) {
        top_cover();
    } else if (part == &quot;both&quot;) {
        both();
    } else {
        both();
    }
}

module both() {
    translate([0,-(y/2+wall_thickness),0]) bottom_box();
    translate([0,+(y/2+wall_thickness),0]) top_cover();
}
</code></pre>
<p>I've tried something like this but it doesn't work:</p>
<pre><code>// Adding a hole to the short side of the box
translate([interior_x / 2, interior_y - hole_size / 2, interior_z / 2])
    cube([hole_size, hole_size, interior_z], center=true);
</code></pre>

<3d-models><3d-design><openscad>
How to add a 2x2 mm hole to a SCAD file?
stormist
# How to add a 2x2 mm hole to a SCAD file?

(Asked by: username_0 on 2023-11-29)

I'm trying to modify this code to create a small 2 mm x 2 mm hole on the short side of the box (to fit 2 wires coming out of a battery):
// Which one would you like to see?
part = "both"; // [box:Box only, top: Top cover only, both: Box and top cover]

// Size of your printer's nozzle in mm
nozzle_size = 0.35;

// Number of walls the print should have
number_of_walls = 3; // [1:5]

// Tolerance (use 0.2 for FDM)
tolerance = 0.2; // [0.1:0.1:0.4]

// Interior dimension X in mm
interior_x=70;

// Interior dimension Y in mm
interior_y=21;

// Interior dimension Z in mm
interior_z=17;

// interior corner radius in mm
radius=0; // [0:20]

// What fraction of the flat X side should the hook take up? (0 for no hook)
x_hook_fraction = 0.5; // [0:0.1:1.0]

// What fraction of the flat Y side should the hook take up? (0 for no hook)
y_hook_fraction = 0.5; // [0:0.1:1.0]

// What fraction of the hooks should have a slot behind them? (0 for no slot)
slot_length = 0.7; // [0:0.1:1]

/* Hidden */
$fn=100;

wall_thickness=nozzle_size*number_of_walls;

// Outer dimensions
x = interior_x + 2 * wall_thickness;
y = interior_y + 2 * wall_thickness;
z = interior_z + 2 * wall_thickness;

hook_thickness = 3 * nozzle_size;

top_cover_wall_thickness = hook_thickness + wall_thickness;

y_hook_length = (y - 2 * radius) * y_hook_fraction;
x_hook_length = (x - 2 * radius) * x_hook_fraction;

module box_interior () {
    offset(r=radius) {
        square([interior_x-2*radius, interior_y-2*radius], center=true);
    }
}

module box_exterior () {
    offset(r=wall_thickness) {
        box_interior();
    }
}

module bottom_box () {
    difference(){
        // Solid box
        linear_extrude(z-wall_thickness){
            box_exterior();
        }
        
        // Hollow out
        translate([0,0,wall_thickness]) linear_extrude(z){
            box_interior();
        }
        left_slot();
        rotate([180,180,0]) left_slot(); // right slot
        front_slot();
        rotate([180,180,0]) front_slot(); // back slot
    }
    left_hook(); // left hook
    rotate([180,180,0]) left_hook(); // right hook
    front_hook(); // front hook
    rotate([180,180,0]) front_hook(); // back hook
}

module left_hook () {
    translate([(x-2*wall_thickness)/2,-y_hook_length/2,z-wall_thickness]) rotate([0,90,90]) {
        base_hook(y_hook_length);
    }
}

module front_hook () {
    translate([-x_hook_length/2,-y/2+wall_thickness,z-wall_thickness]) rotate([90,90,90]) {
        base_hook(x_hook_length);
    }
}

module base_hook (hook_length) {
    difference(){
        linear_extrude(hook_length){
            polygon(points=[[0,0],[2*hook_thickness,0],[hook_thickness,hook_thickness]]);
        }
        translate([hook_thickness, hook_thickness, 0]) rotate([45,0,0]) cube(2*hook_thickness, center=true);
        translate([hook_thickness, hook_thickness, hook_length]) rotate([45,0,0]) cube(2*hook_thickness, center=true);        
    }
}

module left_slot () {
    slot_length = y_hook_length*slot_length;
    epsilon=2; // ensure it definitely protrudes
    translate([x/2+epsilon,-slot_length/2,z]) rotate([0,90,90]) {
        cube([2*hook_thickness, wall_thickness+epsilon, slot_length]);
    }
}

module front_slot () {
    slot_length = x_hook_length*slot_length;
    epsilon=2; // ensure it definitely protrudes
    translate([-slot_length/2,-y/2-epsilon,z]) rotate([90,90,90]) {
        cube([2*hook_thickness, wall_thickness+epsilon, slot_length]);
    }
}

module right_groove () {
    translate([-tolerance/2+(x-2*wall_thickness)/2,-y_hook_length/2,wall_thickness+hook_thickness*2]) rotate([0,90,90]) linear_extrude(y_hook_length) {
        base_groove();
    }
}


module front_groove () {
    translate([-x_hook_length/2,-y/2+wall_thickness+tolerance/2,wall_thickness+hook_thickness*2]) rotate([90,90,90]) linear_extrude(x_hook_length){
        base_groove();
    }
}

module base_groove () {
    polygon(points=[[0,0],[0, -1], [2*hook_thickness, -1],[2*hook_thickness,0],[hook_thickness,hook_thickness]]);
}

module top_cover () {

    // Top face
    linear_extrude(wall_thickness) {
        box_exterior();
    }
    
    difference(){
        // Wall of top cover
        inset = wall_thickness + tolerance/2;
        linear_extrude(wall_thickness+hook_thickness*2){
            offset(r=-inset) {
                box_exterior();
            }
        }
        
        // Hollow out
        translate([0,0,wall_thickness]) linear_extrude(z){
            offset(r=-wall_thickness*2) {
                offset(r=-inset) {
                    box_exterior();
                }
            }
        }
        
        right_groove();
        rotate([180,180,0]) right_groove();
        front_groove();
        rotate([180,180,0])  front_groove();
    }
  

}

// left_hook();
print_part();

module print_part() {
    if (part == "box") {
        bottom_box();
    } else if (part == "top") {
        top_cover();
    } else if (part == "both") {
        both();
    } else {
        both();
    }
}

module both() {
    translate([0,-(y/2+wall_thickness),0]) bottom_box();
    translate([0,+(y/2+wall_thickness),0]) top_cover();
}

I've tried something like this but it doesn't work:
// Adding a hole to the short side of the box
translate([interior_x / 2, interior_y - hole_size / 2, interior_z / 2])
    cube([hole_size, hole_size, interior_z], center=true);

**Tags:** 3d-models, 3d-design, openscad

---

## 2 answers

### Answer by username_1 on 2023-11-30. Score: 1 | Accepted answer

You can use the difference() function in OpenSCAD to subtract one or more 3D shapes from another. Source: The documentation for the difference() function.
For reference, your code already does that several times. Something like this:
module bottom_box () {
    difference(){
        // Existing code ...

        // Subtract the hole
        translate([hole_position_x, hole_position_y, hole_position_z])
            cube([hole_size, hole_depth, hole_size], center=true);
    }
    // Rest of the code ...
}

Two cube examples
Below are two examples of a cube with and without a hole (in the bottom) that, for testing, can be rendered in your browser on openscad.cloud:
1. Model without a hole
cube_size = 20;
module simple_cube() {
    cube(cube_size);
}
simple_cube();



Example of a model without a hole on openscad. cloud.
2. Model with a hole
cube_size = 20;
hole_size = 2;
module cube_with_hole() {
    difference() {
        cube(cube_size);
        translate([cube_size / 2, cube_size / 2, 0])
        cube([hole_size, hole_size, cube_size], center=true);
    }
}
cube_with_hole();


Example of a model with a hole in the bottom on openscad. cloud.

> **Comments:**
> **username_0**: I've added this to bottom box but no hole appears. Not sure where it's messing up.  
> **username_1**: Are you sure all variables are correct and the positioning is correct? I would debug it step by step. First, make the shape appear solid in an obvious color, then position it correctly, and then try to incorporate it in the difference function.  
> **username_2**: @stormist The hole should be longer than the box. The hole should protrude the box on both sides ( translate may be needed to shift the hole ).  
> **username_2**: Modify this line: cube([hole_size, hole_size, cube_size], center=true); to this: cube([hole_size, hole_size, cube_size + hole_size], center=true); for a longer protruding hole.  

---

### Answer by username_3 on 2024-07-12. Score: 0

You will also need to add this function whenever you need holes of a minimum size, otherwise they will ALWAYS be too small.
// Segments used for circles/cylinders have their *endpoints* on the radius.  This means that 
//    cylinders used for holes will be too small; the *midpoints* need to be on the radius,
//    not the *endpoints*.  This function returns properly sized radii for holes with a required minimum radius.

function midpoint_radius (endpoint_radius, num_facets) = endpoint_radius / cos(360/(num_facets*2));


Bonus routines
// Sets rotation based on desired endpoint
function rotateto(x=1,y=1,z=1) = [0,acos(z/norm([x,y,z])),atan2(y,x)];

// Automatically switches to desired circle quality based on whether  or  is pressed.
draft_quality = 12; // [12:6:360]
final_quality = 72; // [12:6:360]
smoothness = $preview ? draft_quality : final_quality; 
// (Circles are divided in $fn line segments.)
$fn = smoothness;


---

