Skip to content

Instantly share code, notes, and snippets.

@groovenectar
Last active April 6, 2024 04:40
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save groovenectar/92174cb1c98c1089347e to your computer and use it in GitHub Desktop.
Save groovenectar/92174cb1c98c1089347e to your computer and use it in GitHub Desktop.
roundedcube.scad - Fork me and make me better!
// More information: https://danielupshaw.com/openscad-rounded-corners/
// Set to 0.01 for higher definition curves (renders slower)
$fs = 0.15;
module roundedcube(size = [1, 1, 1], center = false, radius = 0.5, apply_to = "all") {
// If single value, convert to [x, y, z] vector
size = (size[0] == undef) ? [size, size, size] : size;
translate_min = radius;
translate_xmax = size[0] - radius;
translate_ymax = size[1] - radius;
translate_zmax = size[2] - radius;
diameter = radius * 2;
obj_translate = (center == false) ?
[0, 0, 0] : [
-(size[0] / 2),
-(size[1] / 2),
-(size[2] / 2)
];
translate(v = obj_translate) {
hull() {
for (translate_x = [translate_min, translate_xmax]) {
x_at = (translate_x == translate_min) ? "min" : "max";
for (translate_y = [translate_min, translate_ymax]) {
y_at = (translate_y == translate_min) ? "min" : "max";
for (translate_z = [translate_min, translate_zmax]) {
z_at = (translate_z == translate_min) ? "min" : "max";
translate(v = [translate_x, translate_y, translate_z])
if (
(apply_to == "all") ||
(apply_to == "xmin" && x_at == "min") || (apply_to == "xmax" && x_at == "max") ||
(apply_to == "ymin" && y_at == "min") || (apply_to == "ymax" && y_at == "max") ||
(apply_to == "zmin" && z_at == "min") || (apply_to == "zmax" && z_at == "max")
) {
sphere(r = radius);
} else {
rotate =
(apply_to == "xmin" || apply_to == "xmax" || apply_to == "x") ? [0, 90, 0] : (
(apply_to == "ymin" || apply_to == "ymax" || apply_to == "y") ? [90, 90, 0] :
[0, 0, 0]
);
rotate(a = rotate)
cylinder(h = diameter, r = radius, center = true);
}
}
}
}
}
}
}
@groovenectar
Copy link
Author

Usage:

// A single integer creates a cube with the specified wall distance. Default [1, 1, 1]
size = 5;

// An [x, y, z] vector specifies distance on each axis. Default [1, 1, 1]
size = [2, 3, 5];

// Whether or not to place the object centered on the origin. Default false
center = true|false;

// Specify a rounding radius. Default 0.5
radius = 0.5

// Specify where to apply the rounded corners. Default "all"
apply_to = "all"|"x"|"y"|"z"|"zmax"|"zmin"|"xmax"|"xmin"|"ymax"|"ymin"

roundedcube(size, center, radius, apply_to);

Examples:

color("Yellow")
roundedcube(3, true, 0.7, "xmin");

translate(v = [1, 0, 2])
color("Pink")
roundedcube([4, 2, 2], false, 0.6, "zmax");

translate(v = [-4, -1, 2])
color("Lightblue")
roundedcube(2, false);

translate(v = [0, 0, 6])
color("Orange")
roundedcube([3, 2, 2], true, 0.2);

translate(v = [2.5, -0.5, 5])
color("Green")
roundedcube([3, 2, 2], false, 0.4, "z");

Output:

Output

@thunfischbrot
Copy link

Hi Daniel,

thank you for your work! If I am not mistaken there is a bug which doesn't let you create a shape with rounded corners which extends into any direction for less than twice the radius of the rounded corners. The bug is that the x|y|z >= radius*2 should only apply to the dimensions which you apply the rounded corners to. Or am I mistaken?

Demo:

use <roundedcube.scad>

translate([0,-30,0])
color("Green")
roundedcube([40,10,1], true, .1, "z");

translate([0,-15,0])
color("Orange")
roundedcube([40,10,1], true, .5, "z");

color("Blue")
roundedcube([40,10,1], true, 1, "z");

translate([0,15,0])
color("Red")
roundedcube([40,10,1], true, 4, "z");

bildschirmfoto 2015-12-20 um 11 22 17

@rbuckland
Copy link

rbuckland commented Jan 8, 2017

Brilliant !thank you. I have been meaning to write an uber version (optional rounded faces etc). You nailed it :-)

@Diaoul
Copy link

Diaoul commented Feb 3, 2018

Forked to add scaling for when you don't want the radius to be the same for x and y for example.

roundedcube([41, 22, 23], radius=6, scale_y=1/2, apply_to="z");

capture d ecran de 2018-02-03 15-06-19

@rfinz
Copy link

rfinz commented Jan 18, 2019

excellent little script! consider this a +1!
👍

@jon-zu
Copy link

jon-zu commented Jan 15, 2020

@groovenectar

use <roundedcube.scad>

wall = 2;
frame = 3;
plate = 10;

module straight(depth, height) {
    difference() {
    cube([2*wall+frame, depth, height+wall]);
        
    translate([wall, 0, wall])
    roundedcube([frame, depth, height], false, 0.7, "ymin");
}

straight(50, 5);

Do you have any idea why this is smaller than depth and height? Also there are some small dots which are not subtracted from the cube.

@drohhyn
Copy link

drohhyn commented Nov 21, 2020

Is there any reason for https://gist.github.com/groovenectar/92174cb1c98c1089347e/revisions#diff-47107763919164d8ef5b55b93722917acfe23e5e030f22954e057a03dc2c316c?
In the description you still as for forks and improvements. I really like your script und will still like to use it.

@groovenectar
Copy link
Author

I really like your script and will still like to use it.

I am consulting with Dan Fandrich, and we will be addressing this as soon as possible. Thank you in advance for your patience

@groovenectar
Copy link
Author

@drohhyn After consulting with Dan Fandrich, we have determined that you are now among the people in this world who are allowed to use roundedcube.scad.

It has come to my attention that Dan is of the opinion that everyone should be able to use roundedcube.scad -- we are having a political disagreement. As our newest member of the Board of Directors, do you have a weigh-in on this subject?

@drohhyn
Copy link

drohhyn commented Nov 24, 2020

As I did not provide any code or other contribution to it, who am I to have an opinion?
But I for myself would prefer an open source licence free to use for everybody, e.g. MIT or, if you want users to re-share the same way, CC BY-SA.

@RussNelson
Copy link

If someone has legally obtained a copyrighted work, they are free to use it in any way they want. The statement about use in the .scad file has no effect.
/Russ, 12 years as the VP in charge of License Approval for the Open Source Initiative.

@ggs67
Copy link

ggs67 commented Apr 27, 2021

I have forked and mostly rewritten the module in order to remove some limitations, one being the one reported above by thunfischbrot back in 2015:

// Changed to remove some limitations:
//
// 1. Allow radius>length for rounded corners in one axis only (problem reported on original page in 2015)
// 2. Remove limitation where for apply_to=(x|y|z)max or (x|y|z)min the dimension of the corresponding perpendicular
// axis had to be at least 3 times the radius because of fixed cylinder height. Now cylinder height is always computed not
// to interfere with opposite corner

@Darker
Copy link

Darker commented Oct 25, 2021

Thanks a lot for this. I just started using open scad and couldn't figure out how to make nice rounded edges. I tried minkowski but it totally messed up the dimensions and position of the object.

This works great. It's quite slow though, taking now few seconds to render when I change any parameteres.

@groovenectar
Copy link
Author

groovenectar commented Oct 25, 2021

Thanks a lot for this. I just started using open scad and couldn't figure out how to make nice rounded edges. I tried minkowski but it totally messed up the dimensions and position of the object.

This works great. It's quite slow though, taking now few seconds to render when I change any parameteres.

Thanks for the feedback!! Yes, quite slow, but.... there's a workflow to get around this... You can raise the $fs value while you're developing the model, then lower it when you're ready for a production build.. It's been a while so I can't remember the various effects... but I wonder if a value of $fs = 0.5; or more would be usable while working on the model

@odyzzeus
Copy link

I tried minkowski but it totally messed up the dimensions and position of the object.

This is not caused by an issue in the minkowski method. Instead this behaviour is inherent to it, because the two shapes are added to one another. If you want to correct for these shifts, I can present you a piece of code that "corrects" for shifts using rectangular shapes.

@pleappleappleap
Copy link

Hi Daniel.

I'm running into a bug which rears its ugly head when one tries to set a radius for the cylinder of a single-axis rounding and the radius is larger than one or more of the dimensions of the object. I have an object where the thickness is 0.125 and the radius is 0.325. It makes the thickness of the object larger to compensate, which kinda sucks. It seems like the problem lies with the definitions of the translate variables at the top. If I can find the time, I will see about submitting a fix later.

@pleappleappleap
Copy link

Hi Daniel.

I'm running into a bug which rears its ugly head when one tries to set a radius for the cylinder of a single-axis rounding and the radius is larger than one or more of the dimensions of the object. I have an object where the thickness is 0.125 and the radius is 0.325. It makes the thickness of the object larger to compensate, which kinda sucks. It seems like the problem lies with the definitions of the translate variables at the top. If I can find the time, I will see about submitting a fix later.

It looks like @ggs67's fork fixes this. I think it would be a good idea to replace your code with theirs.

@groovenectar
Copy link
Author

I'm running into a bug which rears its ugly head when one tries to set a radius for the cylinder of a single-axis rounding and the radius is larger than one or more of the dimensions of the object. I have an object where the thickness is 0.125 and the radius is 0.325. It makes the thickness of the object larger to compensate, which kinda sucks. It seems like the problem lies with the definitions of the translate variables at the top. If I can find the time, I will see about submitting a fix later.

It looks like @ggs67's fork fixes this. I think it would be a good idea to replace your code with theirs.

Yes, I'm glad you found that. It's been a while since I've been able to design or print but was aware of some forks... would you say that's the most ideal one to redirect people to when that issue crops up? https://gist.github.com/ggs67/ff6ba8caf5a1871d285c5c758dce0575

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment