# How to make a ParametricPlot3D curve rotate smoothly?

I'm trying to make the complicated ParametricPlot3D curve rotate along the z-axis smoothly. I tried Rotate on a simple 3D object first.

Manipulate[Graphics3D[Rotate[Cuboid[], y, {0, 0, 1}], Boxed -> False], {y, 0, 180 Degree}]


It works fine. But it does not work on the ParametricPlot3D curve, because "Graphics3DBox is not a Graphics3D primitive or directive.".

Then I tried RotationMatrix on ParametricPlot3D curve and it works correctly on simple curves.

Manipulate[ParametricPlot3D[RotationMatrix[\[Theta], {x, y, z}] . {Cos[t], Sin[t], t/10}, {t, 0,10}, PlotRange -> All, AxesLabel -> {"X", "Y", "Z"}], {{\[Theta], 0}, 0, 2   \[Pi]}, {{x, 0}, -1, 1}, {{y, 0}, -1, 1}, {{z, 1}, -1, 1}]


But when the curve becomes complicated, it rotates slowly or ugly.

Manipulate[ParametricPlot3D[RotationMatrix[mm, {x, y, z}] . {Cos[t]  (3 + r  Cos[t/2]), Sin[t]  (3 + r  Cos[t/2]), r  Sin[t/2]}, {r, -1, 1}, {t, 0, 2  Pi}, Mesh -> {5, 10}, PlotStyle -> FaceForm[Red, Yellow], PlotRange -> {{-5, 5}, {-5, 5}, {-5, 5}}], {{mm, 0}, 0, 2   \[Pi], \[Pi]/20}, {{x, 0}, -1, 1}, {{y, 0}, -1, 1}, {{z, 1}, -1,1}]


Is it possible to make the rotation faster without deformation, like when we drag the object using the mouse?

• Precompute all needed arrangements of your plot into a table and then use Manipulate to display particular item of the table. Commented Mar 21 at 13:03

The use of Dynamic below keeps the ParametricPlot from reevaluating, which leads to smooth behavior:

Manipulate[
MapAt[
Dynamic@Rotate[#, mm, {x, y, z}] &,
ParametricPlot3D[{Cos[t]   (3 + r   Cos[t/2]),
Sin[t]   (3 + r   Cos[t/2]), r   Sin[t/2]}, {r, -1, 1}, {t, 0,
2   Pi}, Mesh -> {5, 10}, PlotStyle -> FaceForm[Red, Yellow],
PlotRange -> {{-5, 5}, {-5, 5}, {-5, 5}}],
1]
, {{mm, 0}, 0, 2    \[Pi], \[Pi]/20}, {{x, 0}, -1, 1}, {{y, 0}, -1,
1}, {{z, 1}, -1, 1}]

plot = ParametricPlot3D[{Cos[t] (3 + r Cos[t/2]),
Sin[t] (3 + r Cos[t/2]), r Sin[t/2]}, {r, -1, 1}, {t, 0, 2 Pi},
Mesh -> {5, 10}, PlotStyle -> FaceForm[Red, Yellow],
PlotRange -> {{-5, 5}, {-5, 5}, {-5, 5}}];
table = Table[
Graphics3D[
GeometricTransformation[plot[[1]],
RotationTransform[fi, {0, 1, 0}]], plot[[2]]], {fi, 0,
2 Pi, Pi/21}];
Manipulate[table[[i]], {i, 1, Length[table], 1}]


You just need to precompute your transformed curve! Otherwise, the transformation matrix and the dot product are recomputed every time you change the parameters, which is very computationally expensive.

curve[m_, x_, y_, z_] =
Refine[RotationMatrix[m, {x, y, z}], {x, y, z} ∈
Reals] . {Cos[t] (3 + r Cos[t/2]), Sin[t] (3 + r Cos[t/2]),
r Sin[t/2]} // Simplify

Manipulate[
ParametricPlot3D[
Evaluate@curve[mm, x, y, z], {r, -1, 1}, {t, 0, 2 Pi},
Mesh -> {5, 10}, PlotStyle -> FaceForm[Red, Yellow],
PlotRange -> {{-5, 5}, {-5, 5}, {-5, 5}}], {{mm, 0}, 0,
2 π, π/20}, {{x, 0}, -1, 1}, {{y, 0}, -1, 1}, {{z, 1}, -1, 1}]


Edit

• Or only use Evaluate and PerformanceGoal -> "Quality".
Manipulate[
ParametricPlot3D[
RotationMatrix[mm, {x, y, z}] . {Cos[t]    (3 + r    Cos[t/2]),
Sin[t]    (3 + r    Cos[t/2]), r    Sin[t/2]} //
Evaluate, {r, -1, 1}, {t, 0, 2    Pi}, Mesh -> {5, 10},
PlotStyle -> FaceForm[Red, Yellow],
PlotRange -> {{-5, 5}, {-5, 5}, {-5, 5}},
PerformanceGoal -> "Quality"], {{mm, 0}, 0,
2     π, π/20}, {{x, 0}, -1, 1}, {{y, 0}, -1,
1}, {{z, 1}, -1, 1}]


Original

• Use First to ParametricPlot3D to extract the graphics data and use GeometricTransformation to act on such object.

• Set PerformanceGoal -> "Quality" in ParametricPlot3D.

Manipulate[
Graphics3D[
GeometricTransformation[
First@ParametricPlot3D[{Cos[t]   (3 + r   Cos[t/2]),
Sin[t]   (3 + r   Cos[t/2]), r   Sin[t/2]}, {r, -1, 1}, {t, 0,
2   Pi}, Mesh -> {5, 10}, PlotStyle -> FaceForm[Red, Yellow],
PlotRange -> {{-5, 5}, {-5, 5}, {-5, 5}},
PerformanceGoal -> "Quality"],
RotationTransform[mm, {x, y, z}]]], {{mm, 0}, 0,
2    π, π/20}, {{x, 0}, -1, 1}, {{y, 0}, -1,
1}, {{z, 1}, -1, 1}]