Low resolution with RegionPlot3D [duplicate]

To draw a cuboid with RegionPlot3D I can simply specify a function:

cuboidQ[{x_, y_, z_}, dim1_, dim2_, dim3_, center_: {0, 0, 0}] :=
(Abs[x - center[[1]]] <= dim1 &&
Abs[y - center[[2]]] <= dim2 && Abs[z - center[[3]]] <= dim3)


and the plot it with RegionPlot3D. Or, if I need to draw a cuboid that can be rotated by a certain angle around a specific axis I can simply change the function to this:

cuboidQ2[{x_, y_, z_}, dim1_, dim2_, dim3_, center_: {0, 0, 0}, ang_,
axis_, p_] := Module[{r, x1, y1, z1},
r = RotationTransform[ang, axis, p];
{x1, y1, z1} = r[{x, y, z}];
(Abs[x1 - center[[1]]] <= dim1 && Abs[y1 - center[[2]]] <= dim2 &&
Abs[z1 - center[[3]]] <= dim3)
]


and plot it:

RegionPlot3D[
cuboidQ2[{x, y, z}, 25, 25, 25, {0, 0, 0},
Pi/8, {0, 0, 1}, {0, 0, 0}], {x, -50, 50}, {y, -50, 50}, {z, -50, 50},
MaxRecursion -> 0, Mesh -> None, PlotPoints -> 50]


However, the resolution is very bad. Of course, it can be improved by increasing the PlotPoints to about 250, but it seems unreasonable to have to turn the PlotPoints so high to get a decent resolution for such a simple shape.

Is there any better way to render this kind of shape with RegionPlot3D?

• Have you quit your kernel? Your code works fine for me on 10.4. Commented Mar 30, 2016 at 14:02
• I second Martin here: your code works fine on 10.4 (Win7-64). Commented Mar 30, 2016 at 14:09
• @MartinBüttner Argh. Yes, it works.
– VLC
Commented Mar 30, 2016 at 14:10
• Um, it may work technically, but it looks awful: i.sstatic.net/7IxZY.png I have to increase the PlotPoints to 100 and it only looks marginally better. Commented Mar 30, 2016 at 14:16
• @MarcoB - Does it look better in version 10.4? In 10.3 it's just awful, you can see the same problem with DiscretizeRegion@ ImplicitRegion[ cuboidQ[{x Cos[π/8] - y Sin[π/8], y Cos[π/8] + x Sin[π/8], z}, 25, 25, 25], {x, y, z}] Commented Mar 30, 2016 at 14:21

Update

The original method I proposed took advantage of the fact that the region created by applying DiscretizeRegion to a simple Cuboid object was represented perfectly by RegionPlot3D, even after applying any geometric transformation via TransformedRegion. This results in a very fast RegionPlot3D that is superior to the (much slower) plot produced when you feed a series of predicates to RegionPlot3D directly. However, the resulting 3D MeshRegions can not be fed to any of the constructive solid geometry (CSG) operations like RegionDifference, RegionUnion, and RegionIntersection (maybe in version 11?).

So I will revert to this answer by Simon Woods and pointed out by J.M. See below for the fast implementation that lacks CSG implementation.

First, there is a shortened version of the OP's function cuboidQ2, followed by Simon's contourRegionPlot3D function, and finally I define two arbitrary rotated cuboids.

cuboidQ2[{x_, y_, z_}, {dim1_, dim2_, dim3_}, center_: {0, 0, 0},
ang_: 0, axis_: {0, 0, 1}, p_: {0, 0, 0}] :=

Module[{r, x1, y1, z1},
r = TranslationTransform[-center]@*
RotationTransform[ang, axis, p];
{x1, y1, z1} = r[{x, y, z}];
And @@ Thread[Abs[{x1, y1, z1}] <= {dim1, dim2, dim3}]
];
contourRegionPlot3D[
region_, {x_, x0_, x1_}, {y_, y0_, y1_}, {z_, z0_, z1_},
opts : OptionsPattern[]] := Module[{reg, preds},
reg =
LogicalExpand[
region && x0 <= x <= x1 && y0 <= y <= y1 && z0 <= z <= z1];
preds =
Union@Cases[
reg, _Greater | _GreaterEqual | _Less | _LessEqual, -1];
Show @ Table[ContourPlot3D[

Evaluate[Equal @@ p], {x, x0, x1}, {y, y0, y1}, {z, z0, z1},

RegionFunction ->
Function @@ {{x, y, z}, Refine[reg, p] && Refine[! reg, ! p]},
opts], {p, preds}]];
{r1, r2} = {cuboidQ2b[{x, y, z}, {25, 35, 17}, {15, 5, -5}, \[Pi]/
7, {1, 1, 1}],
cuboidQ2b[{x, y, z}, {25, 35, 17}, {15, 5, -5}, \[Pi]/2, {1, 1,
1}]};


Here is a plot of the intersection, union, and difference regions:

contourRegionPlot3D[#, {x, -50, 50}, {y, -50, 50}, {z, -50, 50},
Mesh -> None] & /@ {And[r1, r2], Or[r1, r2], And[r1, Not[r2]]}


I didn't show the hollow region that you get by Xor[r1,r2] as it is visibly identical to the intersection region. The function is slow, but as far as quality goes, it is much much better than anything that can be achieved by RegionPlot3D.

I think there is a better way to make a rotated cube using RegionPlot3D. Take OP's function cuboidQ,

RegionPlot3D[
cuboidQ[{x , y, z}, 25, 25, 25], {x, -50, 50}, {y, -50, 50}, {z, -50,
50}, Mesh -> None, PlotPoints -> 100]


And just look at those blurry edges. When using these results for a 3D printing application, the OP had to set the PlotPoints all the way to 250 to get a decent edge,

The above plot, with the 250 setting, took a good deal of time to make and it is not perfect. That isn't right, this is the simplest geometric 3D region, it shouldn't take any processing power.

Compare the above to this, which plots perfect edges instantaneously,

RegionPlot3D[
DiscretizeGraphics@Cuboid[{25, 25, 25}, {-25, -25, -25}],
Axes -> True,
PlotRange -> {{-50, 50}, {-50, 50}, {-50, 50}}]


Likewise, compare the quality and execution time for the rotated version,

RegionPlot3D[
cuboidQ[{x Cos[π/8] - y Sin[π/8],
y Cos[π/8] + x Sin[π/8], z}, 25, 25, 25], {x, -50,
50}, {y, -50, 50}, {z, -50, 50}, MaxRecursion -> 10, Mesh -> None,
PlotPoints -> 100, PerformanceGoal -> "Quality"] // AbsoluteTiming


versus

RegionPlot3D[
TransformedRegion[
DiscretizeGraphics@Cuboid[{25, 25, 25}, {-25, -25, -25}],
RotationTransform[π/8, {0, 0, 1}]],
Axes -> True,
PlotRange -> {{-50, 50}, {-50, 50}, {-50, 50}}] // AbsoluteTiming


If the goal of the functions is to make a cuboid that can be fed to RegionPlot3D, then I would suggest the following

cuboidQ3[ dim1_, dim2_, dim3_, center_: {0, 0, 0}, ang_: 0,
axis_: {0, 0, 1}, p_: {0, 0, 0}] :=
Fold[
TransformedRegion,
DiscretizeGraphics@Cuboid[{-dim1, -dim2, -dim3}, {dim1, dim2, dim3}],
{RotationTransform[ang, axis, p], TranslationTransform[center]}
]


Then you can easily plot a rotated and translated cuboid,

RegionPlot3D[cuboidQ3[25, 35, 17, {15, 5, -5}, π/7, {1, 1, 1}],
Axes -> True,
PlotRange -> {{-50, 50}, {-50, 50}, {-50, 50}}]


• Nice and quick. The only drawback is that with this approach is not possible to use CSG operations (union, difference, intersection between objects). For example, this union operation fails: RegionPlot3D[ cuboidQ3[25, 35, 17, {15, 5, -5}, \[Pi]/7, {1, 1, 1}] || cuboidQ3[25, 35, 17, {15, 5, -5}, \[Pi]/2, {1, 1, 1}], Axes -> True, PlotRange -> {{-50, 50}, {-50, 50}, {-50, 50}}]
– VLC
Commented Mar 31, 2016 at 6:45
• I feel like you should be able to use RegionUnion but it's failing. Graphically, how would what you are trying to do there be different than Show[RegionPlot3D[#, Axes -> True, PlotRange -> {{-50, 50}, {-50, 50}, {-50, 50}}] & /@ {cuboidQ3[25, 35, 17, {15, 5, -5}, π/7, {1, 1, 1}], cuboidQ3[25, 35, 17, {15, 5, -5},π/2, {1, 1, 1}]}]? Commented Mar 31, 2016 at 6:50
• Graphically looks ok, but I don't think it solves my problem. How would you obtain the difference between objects? I'm usually using the difference between two objects to obtain a hollow object that can be then 3D printed.
– VLC
Commented Mar 31, 2016 at 7:04
• @VLC - well then you may have to build an ImplicitRegion until they can make RegionDifference, RegionUnion, RegionIntersection, etc work on 3D regions. This works, RegionPlot3D[ ImplicitRegion[ Or[{x, y, z} ∈ cuboidQ3[25, 35, 17, {15, 5, -5}, π/7, {1, 1, 1}], {x, y, z} ∈ cuboidQ3[25, 35, 17, {15, 5, -5}, π/2, {1, 1, 1}]], {x, y, z}], Axes -> True, PlotRange -> {{-50, 50}, {-50, 50}, {-50, 50}}] but you then have to increase the PlotPoints to get a decent plot. Commented Mar 31, 2016 at 7:30
• Ok. But now we are actually back to the original issue, where we had to turn PlotPoints up to get a decent plot.
– VLC
Commented Mar 31, 2016 at 8:22