2
$\begingroup$

This question already has an answer here:

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]

enter image description here

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?

$\endgroup$

marked as duplicate by J. M. will be back soon Apr 1 '16 at 1:13

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ Have you quit your kernel? Your code works fine for me on 10.4. $\endgroup$ – Martin Ender Mar 30 '16 at 14:02
  • $\begingroup$ I second Martin here: your code works fine on 10.4 (Win7-64). $\endgroup$ – MarcoB Mar 30 '16 at 14:09
  • $\begingroup$ @MartinBüttner Argh. Yes, it works. $\endgroup$ – VLC Mar 30 '16 at 14:10
  • $\begingroup$ Um, it may work technically, but it looks awful: i.stack.imgur.com/7IxZY.png I have to increase the PlotPoints to 100 and it only looks marginally better. $\endgroup$ – Jason B. Mar 30 '16 at 14:16
  • $\begingroup$ @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}] $\endgroup$ – Jason B. Mar 30 '16 at 14:21
7
$\begingroup$

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]]}

enter image description here

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.

Original answer

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]

enter image description here

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,

enter image description here

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}}]

enter image description here

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

enter image description here

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

enter image description here

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}}]

enter image description here

$\endgroup$
  • $\begingroup$ 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}}] $\endgroup$ – VLC Mar 31 '16 at 6:45
  • $\begingroup$ 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}]}]? $\endgroup$ – Jason B. Mar 31 '16 at 6:50
  • $\begingroup$ 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. $\endgroup$ – VLC Mar 31 '16 at 7:04
  • $\begingroup$ @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. $\endgroup$ – Jason B. Mar 31 '16 at 7:30
  • $\begingroup$ Ok. But now we are actually back to the original issue, where we had to turn PlotPoints up to get a decent plot. $\endgroup$ – VLC Mar 31 '16 at 8:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.