# Draw rounded cube

How can I draw a rounded cube using Asymptote, Metapost or anything that produces high quality graphics? A rounded cube is for example the boundary of the minkovski sum C+S where C=[-1,1]^3 and S is the unit sphere. It is possible using Asymptote, but I have to parametrize and plot about 26 surfaces to do that (which I will if I have to). I was wondering if there is a simpler way.

And I will like to be able to say where the center of this rounded cube is and if possible to be able to plot things like aC+rS where a,c are positive reals, i.e. to modify the radius of the sphere and of the cube. Maybe that's too much to ask... This is really the downfall of the first approach, i.e. plotting all the needed parametrized surfaces in Asymptote: that I have to do the same thing twice if I want to plot two such cubes with different parameters a,r.

-
It is weird how on tex.stackexchange TeX is not implemented... I was used to math.stackexchange, and put the dollars. – Beni Bogosel Apr 25 '12 at 12:13
It's because we often discuss TeX syntax and if parsed we cannot make our point to others while trying to show how we do it. – percusse Apr 25 '12 at 12:16
@percusse: Ok. I was just curious. I kind of understand now. :) – Beni Bogosel Apr 25 '12 at 12:20
@BeniBogosel: the good news is that most users of the site can read TeX source code well so you if you write `\$C=[-1,1]^3\$` everybody knows what you mean. :-) – Matthew Leingang Apr 25 '12 at 12:29

The easiest way in Asymptote (as in fewest lines of code and least amount of human brain needed), I think, is to use the `contour3` package (which unfortunately is not too well documented). The function defines the surface that is the set of zeroes for a given function of the `(x,y,z)` coordinates. So something like the following (perhaps with minor adjustments) would work:

``````import graph3;
import contour3;

size(200,0);
currentprojection=orthographic((6,8,2),up=Y);

real abs(real z) { return (z > 0) ? z : 0 - z; }
real trunc(real z, real w) { return ( z > w) ? z - w: 0;}

real abstractroundedcube( real x, real y, real z, real a, real r) {
return trunc(abs(x),a)^2 + trunc(abs(y),a)^2 + trunc(abs(z),a)^2 - r^2;
}

real aroundedcube( real x, real y, real z) {
return abstractroundedcube( x,y,z,2,1);
}

draw( surface( contour3( aroundedcube,(-4,-4,-4),(4,4,4),50)),blue+opacity(0.75),render(merge=true));
``````

We first import `graph3` and `contour3`. The next two lines are just basic setups chosen arbitrarily. The meat is in the definition of the functions `abs`, `trunc`, and `abstractroundedcube`. The function `abs` is just the absolute value function, the `trunc` function takes two real values. It returns `z-w` if `z > w` and `0` otherwise, in other words it truncates the first `w` units from `z`.

For the `abstractroundedcube` function, given a coordinate `(x,y,z)` and two parameters `(a,r)`, the first half of the `return` statement gives the (squared) distance of the point `(x,y,z)` to the surface of the cube \$[-a,a]^3\$ (where if the point is inside the cube the distance is set to be 0). We then subtract from that `r^2`. Hence this function vanishes precisely on the surface of the rounded cube aC + rS as you desired.

The `aroundedcube` function is just a dummy function, since the `contour3` function only takes a function of 3 real arguments as the first input, so I have somewhere to specify the parameters `a = 2` and `r = 1` for the example.

And the last call is to draw the cube. The output looks something like this:

Unfortunately you can see a bit of artifact from the rendering. You can try increasing the resolution (the last parameter in the call to `contour3`); this may also require you give `asymptote` more memory to run.

OTOH, presumably if you define the parametrisation of the surface explicitly (rather than implicitly through `contour3`) you can probably get a better quality output. For the rounded sphere, even through there are 26 surfaces, they are broken down to 12 edges, 8 corners, and 6 faces. Each of them can be done identically. The corners are just 1/8 spheres of radius r, the edges are quarter cylinders of radius r and length 2a, while the faces are the faces of the cube [-a,a]^3 displaced outward by distance r. It should not be too difficult to exactly parametrise them while factoring in the (a,r) parameters.

-
Thank you very much for your answer. – Beni Bogosel Apr 25 '12 at 16:22
I tried to run your code, but it is not working on my machine... (1.6Gh single core). Probably the program needs more power. I'll try and write the 26 parametrizations. Is there any way to define a surface with parameters in Asymptote, like a function of (center,a,r) so that I can use the same function to plot multiple cubes? – Beni Bogosel Apr 25 '12 at 16:42
"it is not working on my machine" what is the error? If you get something about increasing heap size, try reducing the resolution (drop from 50 to 10 to start). If you see what I have done above in the `abstractroundedcube` function, I've defined a function with extra parameters. You can easily do the same thing for surfaces. – Willie Wong Apr 26 '12 at 7:26
When I compiled it it just sat there for about 10 minutes. – Beni Bogosel Apr 26 '12 at 8:58
Did it wait to let it finish or crash? (And what is the command you issued? try modifying the last parameter of `contour3` to 20 to reduce quality and see if it runs.) It takes 22.9 seconds on a quad core Xeon @ 3.1 Ghz, I wouldn't rule out it taking more than 10 minutes on a single core 1.6G box.... – Willie Wong Apr 26 '12 at 9:10