Drawing a cuboid with rounded corners
ClearAll[roundedCuboidF]
roundedCuboidF[hprof_: 10, vprof_: 10, taper_: 1][box_] :=
ChartElementDataFunction["DoubleProfileCube", "HorizontalProfile" -> hprof,
"VerticalProfile" -> vprof, "TaperRatio" -> taper][box]
Graphics3D[roundedCuboidF[][{{0, 1}, {0, 1}, {0, 1}}], Boxed -> False]
or
ContourPlot3D[Norm[{x, y, z}, 4], {x, -1, 1}, {y, -1, 1}, {z, -1, 1},
Mesh -> None, Boxed -> False, Axes -> False, Lighting -> "Neutral",
ContourStyle -> Directive[Orange, Opacity[0.8], Specularity[White, 30]]]
Two more options. These allow direct control of the box dimensions and the rounding radius.
Using ContourPlot3D
:
signedDistance[p_, p0_, p1_] := Piecewise[
{{-Min[p - p0, p1 - p], And @@ Thread[p0 <= p <= p1]},
{EuclideanDistance[p, MapThread[Min[Max[#1, #2], #3] &, {p, p0, p1}]], True}}]
roundedCuboidPlot[p0 : {x0_, y0_, z0_}, p1 : {x1_, y1_, z1_}, r_, opts : OptionsPattern[]] :=
ContourPlot3D[signedDistance[{x, y, z}, p0 + r, p1 - r] == r,
{x, x0 - r, x1 + r}, {y, y0 - r, y1 + r}, {z, z0 - r, z1 + r}, opts]
roundedCuboidPlot[{0, 0, 0}, {1, 2, 3}, 1/4, BoxRatios -> Automatic, Mesh -> None]
Using Graphics3D
primitives:
roundedCuboid[p0 : {x0_, y0_, z0_}, p1 : {x1_, y1_, z1_}, r_] :=
{EdgeForm[None],
Cuboid[p0 + {0, r, r}, p1 - {0, r, r}],
Cuboid[p0 + {r, 0, r}, p1 - {r, 0, r}],
Cuboid[p0 + {r, r, 0}, p1 - {r, r, 0}],
Table[Cylinder[{{x0 + r, y, z}, {x1 - r, y, z}}, r],
{y, {y0 + r, y1 - r}}, {z, {z0 + r, z1 - r}}],
Table[Cylinder[{{x, y0 + r, z}, {x, y1 - r, z}}, r],
{x, {x0 + r, x1 - r}}, {z, {z0 + r, z1 - r}}],
Table[Cylinder[{{x, y, z0 + r}, {x, y, z1 - r}}, r],
{x, {x0 + r, x1 - r}}, {y, {y0 + r, y1 - r}}],
Table[Sphere[{x, y, z}, r],
{x, {x0 + r, x1 - r}}, {y, {y0 + r, y1 - r}}, {z, {z0 + r, z1 - r}}]}
Graphics3D[{roundedCuboid[{0, 0, 0}, {1, 2, 3}, 1/4]}]
Rahul's otherwise fine approach has a drawback that can be seen if you include an Opacity[]
directive:
Graphics3D[{Opacity[2/3, Pink], roundedCuboid[{0, 0, 0}, {1, 2, 3}, 1/4]},
Boxed -> False]
The "ribs" may or may not be desirable in an application, so I sought an alternative that does not use too many Polygon[]
s (as with the solutions based on plotting) and yet looks fine when made translucent.
The following routine is not quite Mr. Wizard's wish in the comments, but it is certainly built from BSplineSurface[]
+ Polygon[]
components:
roundedCuboid[p1_?VectorQ, p2_?VectorQ, r_?NumericQ] :=
Module[{csk, csw, cv, ei, fi, ocp, osk, owt},
cv = Tuples[Transpose[{p1 + r, p2 - r}]];
ocp = {{{1, 0, 0}, {1, 1, 0}, {0, 1, 0}},
{{1, 0, 1}, {1, 1, 1}, {0, 1, 1}},
{{0, 0, 1}, {0, 0, 1}, {0, 0, 1}}};
osk = {{0, 0, 0, 1, 1, 1}, {0, 0, 0, 1, 1, 1}};
owt = {{1, 1/Sqrt[2], 1}, {1/Sqrt[2], 1/2, 1/Sqrt[2]},
{1, 1/Sqrt[2], 1}};
ei = {{{4, 8}, {2, 6}, {1, 5}, {3, 7}},
{{6, 8}, {2, 4}, {1, 3}, {5, 7}},
{{7, 8}, {3, 4}, {1, 2}, {5, 6}}};
csk = {{0, 0, 1, 1}, {0, 0, 0, 1, 1, 1}};
csw = {{1, 1/Sqrt[2], 1}, {1, 1/Sqrt[2], 1}};
fi = {{8, 6, 5, 7}, {8, 7, 3, 4}, {8, 4, 2, 6},
{4, 3, 1, 2}, {2, 1, 5, 6}, {1, 3, 7, 5}};
Flatten[{EdgeForm[], BSplineSurface3DBoxOptions ->
{Method -> {"SplinePoints" -> 35}},
MapIndexed[BSplineSurface[Map[
AffineTransform[{RotationMatrix[π Mod[#2[[1]] - 1, 4]/2,
{0, 0, 1}], #1}],
ocp.DiagonalMatrix[r {1, 1, If[Mod[#2[[1]] - 1, 8] < 4,
1, -1]}], {2}],
SplineDegree -> 2, SplineKnots -> osk, SplineWeights -> owt] &,
cv[[{8, 4, 2, 6, 7, 3, 1, 5}]]],
MapIndexed[Function[{idx, pos},
BSplineSurface[Outer[Plus, cv[[idx]],
Composition[Insert[#, 0, pos[[1]]] &,
RotationTransform[π (pos[[2]] - 1)/2]] /@
(r {{1, 0}, {1, 1}, {0, 1}}), 1], SplineDegree -> {1, 2},
SplineKnots -> csk, SplineWeights -> csw]], ei, {2}],
Polygon[MapThread[Map[TranslationTransform[r #2], cv[[#1]]] &,
{fi, Join[#, -#] &[IdentityMatrix[3]]}]]}]]
Using this version instead in the first snippet yields the following picture:
Some more examples:
Graphics3D[{Yellow, roundedCuboid[{0, 0, 0}, {1, 3, 1}, 1/10],
Blue, roundedCuboid[{2, 1, 1}, {4, 2, 3}, 1/4]}, Boxed -> False]
Graphics3D[{{EdgeForm[Gray], Opacity[1/2, Green], Cuboid[{2, 1, 1}, {4, 2, 3}]},
{Pink, roundedCuboid[{2, 1, 1}, {4, 2, 3}, 1/5]}},
Boxed -> False, Lighting -> "Neutral"]