Use OpenSCAD powerful hull() command and the simple offset() to create the easiest project box ever. Easy rounded corners. No complicated subtractions.

Although concept wise, this may not be “easy”, it is easy in the sense it is concise and demonstrates some efficient concepts

## Concepts Used:

- 2d Subsystem
- square()
- offset()

- 3d System
- hull()

- linear_extrude()
- rotate_extrude()
- scale()
- resize()

- Modules
- List Comprehension

## Get Started with Walls

We get started by making the walls using the 2d subsystem. But before we do this let’s add some global variables that we will use throughout the tutorial. Add these to your OpenSCAD ide. ( The comments are for the customizer )

BOX_W = 80; // Box Width BOX_L = 120;// Box Length BOX_H = 12; // Box Height SCREW_SIZE = 3; // Screw size in mm CORNER_RADIUS = 3; // Radius of corners WALL_THICKNESS = 2;// Wall Thickness

Then add a square() after the variables using the Width and Length

square( [BOX_W, BOX_L] );

We will round the corners with offset() command, place this offset() before square().

offset(r=CORNER_RADIUS) square( [BOX_W, BOX_L] );

Next we will remove the inner portion, with difference() and another square(). We will subtract the wall thickness to remove all but the wall.

difference(){ offset(r=CORNER_RADIUS) square( [BOX_W, BOX_L] ); square( [BOX_W-WALL_THICKNESS, BOX_L-WALL_THICKNESS] ); }

There are two things we will need to adjust. First the inner wall is not positioned well, so let’s center both squares

difference(){ offset(r=CORNER_RADIUS) square( [BOX_W, BOX_L],center=true); square( [BOX_W-WALL_THICKNESS, BOX_L-WALL_THICKNESS],center=true); }

Now let’s use offset() to add an inner radius. To calculate the inner radius we will subtract the wall thickness from the corner radius.

difference(){ offset(r=CORNER_RADIUS) square( [BOX_W, BOX_L], center=true );offset( r= CORNER_RADIUS - WALL_THICKNESS )square( [BOX_W-WALL_THICKNESS, BOX_L-WALL_THICKNESS], center=true); }

Lastly for the wall , we just nee to give it height. We can use lienar_extrude to give th box height. Add a linear_extrude() using BOX_H for the parameter, on the line above the difference.

linear_extrude( BOX_H )

## Adding the bottom.

We want a bottom that has rounded edges. This is where hull() comes in we can use hull() with four spheres() to create a rectangle with rounded edges. We want to add four, we we use list comprehension so we don’t have endless translates().

First we will create a list of coordinates.

coordinates = [ [0,0], [0,120], [80,120], [80,0] ];

Then we will use the coordinates variable in a for loop to iterate through using a for loop.

for (i = coordinates)

every time through the loop we will add a sphere and translate it by the coordinates. Here is the full piece of code to add:

coordinates = [ [0,0],[0,BOX_L],[BOX_W,BOX_L],[BOX_W,0] ]; for (i = coordinates) translate(i) sphere(CORNER_RADIUS);

Now let’s put that entire object into a hull() Notice how you don’t need to add brackets {} as the for loop is the direct child of the hull(). As a result hull works on the results for the for()

coordinates = [ [0,0],[0,BOX_L],[BOX_W,BOX_L],[BOX_W,0] ]; hull() for (i = coordinates) translate(i) sphere(CORNER_RADIUS);

We will need to translate the resulting hull so it is under the wall. Add a translate above the hull() using half the box width and half the box length. Let’s also ad $fn=25; at the very top of our code so we can see things a little better.

translate ( [-BOX_W/2, -BOX_L/2] )

We can add cylinders for screws the same way we made the four spheres. We already have the coordinates from the bottom so we can just use that. but we need to move them in some.

for (i = coordinates) translate(i) difference(){ cylinder(h=BOX_H,r=CORNER_RADIUS); cylinder(h=BOX_H,r=CORNER_RADIUS - SCREW_SIZE); }

I used rend ( f6 ) so we can see the holes.

NExt we need to move the posts to coincide with the box. place a translate() in front of the for() loop. This will move the whole”assembly” into position.

translate ( [-BOX_W/2, -BOX_L/2] )

That gives us cylinders, but they are to close to edge, we could create a second set of coordinates for the second loop, but it get’s pretty messy. It would look like this:

coordinates = [ [0+10,0+10],[0+10,BOX_L=-10],[BOX_W-10,BOX_L-10],[BOX_W-10,0+10] ];

Instead lets use resize() and scale() to do the same thing.

First use a resize() to set the four posts to their final position. The values will be the width and the length between the center of the posts . Add resize() in front of the for() loop for the cylinders. We will used fix values to start with.

resize([75,110,0])

You might notice that the posts are moved but they got smaller ( it is a small change). We can use scale to set the posts back to their original size. Add the scale command right before the difference for the cylinders.

scale([BOX_W/75,BOX_L/110])

Now the posts are the original size.

Here is a before and after. Really hard to see the difference but it is there.

Lets create a variable and see the whole code block. **Add POST_OFFSET=10; to the top of your code.** We will have to subtract that in the resize() and scale() from the box width and box height, we will use intermediaries so it is easier to understand. We also need to divide the SCREW_SiZE by 2 so it represents a radius, not the diameter given Let’s look at the code:

POST_OFFSET=10; ... other code ... p_w = BOX_W - POST_OFFSET; p_l = BOX_L - POST_OFFSET; resize([p_w,p_l,0]) // Move the posts in from the edge translate([-BOX_W/2,-BOX_L/2,0]) for (i = coordinates) translate(i) scale([BOX_W/p_w,BOX_L/p_l]) difference(){ cylinder(h=BOX_H,r=CORNER_RADIUS); cylinder(h=BOX_H,r=SCREW_SIZE/2); }

That’s all there is! There are some improvements we can make but this will work pretty well for now. Here is the final entire code to play with. Some important changes we would need are :

- Setting the floor ( bottom ) to WALL_THICKNESS
- Using a separate value or calculation for the outer cylinder of the post

But we will have to have a part two for that as this post is getting long.

```
$fn=25;
BOX_W = 80; // Box Width
BOX_L = 120;// Box Length
BOX_H = 12; // Box Height
SCREW_SIZE = 1.5; // Screw size radius.
CORNER_RADIUS = 3; // Radius of corners
WALL_THICKNESS = 2;// Wall Thickness
POST_OFFSET=10;
linear_extrude( BOX_H )
difference(){
offset(r=CORNER_RADIUS)
square( [BOX_W, BOX_L], center=true );
offset( r= CORNER_RADIUS - WALL_THICKNESS )
square( [BOX_W-WALL_THICKNESS, BOX_L-WALL_THICKNESS], center=true );
}
coordinates = [ [0,0],[0,BOX_L],[BOX_W,BOX_L],[BOX_W,0] ];
translate ( [-BOX_W/2, -BOX_L/2] )
hull()
for (i = coordinates)
translate(i) sphere(CORNER_RADIUS);
p_w = BOX_W - POST_OFFSET;
p_l = BOX_L - POST_OFFSET;
resize([p_w,p_l,0]) // Move the posts in from the edge
translate([-BOX_W/2,-BOX_L/2,0])
for (i = coordinates)
translate(i)
scale([BOX_W/p_w,BOX_L/p_l])
difference(){
cylinder(h=BOX_H,r=CORNER_RADIUS);
cylinder(h=BOX_H,r=SCREW_SIZE/2);
}
```