9
$\begingroup$

I'm trying to draw a figure as shown below and make it rotate around the vertical axis (z-axis) automatically.

Figure to be rotated

This is how I generate the figure and make it rotate:

Δϕ = π 14.0/13.0;
p1 = 
  Show[
    Table[
      RegionPlot3D[
        x^2 + y^2 + (z - j)^2 < 0.5^2 && 
        (x - 0.4 Cos[j Δϕ]) Cos[j Δϕ] + (y - 0.4 Sin[j Δϕ]) Sin[j Δϕ] < 0, 
        {x, -0.5, 0.5}, {y, -0.5, 0.5}, {z, -0.5 + j, 0.5 + j}, 
        PlotStyle -> Blue, Mesh -> None], 
      {j, 0, 5}], 
      PlotRange -> All, BoxRatios -> Automatic];
p2 = 
  Graphics3D[
    Table[
      Arrow[{{0.4 Cos[j Δϕ], 0.4 Sin[j Δϕ], j}, {Cos[j Δϕ], Sin[j Δϕ], j}}], 
      {j, 0, 5}]];
p = 
  Show[{p1, p2}, 
    Boxed -> False, Axes -> False, 
    ViewPoint -> {0, -10, 0}, ViewCenter -> {0, 0, 2.5}, 
    ViewVertical -> {0, 0, 1}];
vc = AbsoluteOptions[p, ViewCenter][[1, 2]];
vp = AbsoluteOptions[p, ViewPoint][[1, 2]];
m = RotationMatrix [5 Degree, {0., 0., 1.}];
newvp = m.(vp - vc);
Export["a.gif", 
  Table[
    Show[p, 
      ViewPoint -> MatrixPower[m, j].(vp - vc) + vc, 
      PlotRange -> All], 
    {j, 0, 360/5 - 1}]];

This is how the gif file looks like The output gif file

I don't understand why the gif is kind of oscillating in the horizontal direction, and the arrows seem turn around when a cycle is done and the next cycle starts. What I want is to have the rotating axis (here the z-axis) fixed while the figure is rotating. Which part of my code is wrong?

$\endgroup$
6
  • 5
    $\begingroup$ I believe the image is centered in each frame, but because the arrows protrude at different times, the position of the balls changes. $\endgroup$ Commented Feb 24, 2016 at 23:39
  • 4
    $\begingroup$ You need to use a fixed PlotRange instead of PlotRange -> All, and maybe add a SphericalRegion -> True while you're at it. $\endgroup$ Commented Feb 25, 2016 at 0:38
  • $\begingroup$ I tried fixed PlotRange, but it didn't work. Adding SphericalRegion -> True only shows a tiny part of the figure. $\endgroup$
    – ruima86
    Commented Feb 25, 2016 at 1:46
  • $\begingroup$ I usually draw a white rectangle on the background that's larger than the animation region, so this remains centred. For the arrows, perhaps try with a tube, the one you are using is 2D so it has problems twice per turn. $\endgroup$ Commented Feb 25, 2016 at 3:51
  • $\begingroup$ Regarding the flipping arrowheads, you can either use 3D arrows or try to add something along the lines Arrowheads[Medium, Appearance -> "Projected"] in your 3D expression. $\endgroup$
    – Yves Klett
    Commented Feb 25, 2016 at 9:15

1 Answer 1

10
$\begingroup$

Perhaps the following will work for you. Since I worked it out more by trial-and-error than by expertise, there may be unnecessary code that remains. Mainly what I did was the following:

  1. Computed the camera position before doing the export by a better method. Your computation of the camera position was the source of the oscillation.

  2. Eliminated many options, some of which caused problems and others which were simply redundant. I also added a few options the improve the look of graphics.

Δϕ = π 14.0/13.0;

p1 =
  Table[
    RegionPlot3D[
      x^2 + y^2 + (z - j)^2 < 0.5^2 && 
      (x - 0.4 Cos[j Δϕ]) Cos[j Δϕ] + (y - 0.4 Sin[j Δϕ]) Sin[j Δϕ] < 0, 
      {x, -0.5, 0.5}, {y, -0.5, 0.5}, {z, -0.5 + j, 0.5 + j},
      PlotStyle -> Blue,  Lighting -> "Neutral", Mesh -> None],
    {j, 0, 5}];

p2 =
  Graphics3D[{
    Black,
    Table[
      Arrow @ Tube[{{0.4 Cos[j Δϕ], 0.4 Sin[j Δϕ], j}, {Cos[j Δϕ], Sin[j Δϕ], j}}], 
      {j, 0, 5}]}];

vp = 
  Table[
    RotationTransform[θ, {0, 0, 1}, {0, 0, 0}][{0, -50, 3}], 
    {θ, N[2 π Subdivide[36]]}];

Export[
  FileNameJoin[{$HomeDirectory, "Desktop", "RotatingSpheres.gif"}],
  Show[p1, p2,
    PlotRange -> {{-1, 1}, {-1, 1}, {-.5, 5.5}},
    Axes -> False,
    Boxed -> False,
    BoxRatios -> Automatic,
    SphericalRegion -> True,
    ViewPoint -> #] & /@ vp];

gif

Update

At Yves Klett's behest, I have made the arrows into 3D tube-based arrows.

$\endgroup$
7
  • $\begingroup$ you are really fast... love the use of vp to vectorise the command. $\endgroup$ Commented Feb 25, 2016 at 4:13
  • 1
    $\begingroup$ Perhaps the use of 3D arrow primitives would be useful to avoid the arrowheads spinning. $\endgroup$
    – Yves Klett
    Commented Feb 25, 2016 at 6:19
  • $\begingroup$ @YvesKlett. I agree. I didn't work on that part of problem. I think there already answers on the site that describe how to 3D primitives to make better 3D arrows. $\endgroup$
    – m_goldberg
    Commented Feb 25, 2016 at 7:21
  • 2
    $\begingroup$ @YvesKlett. OK, I did it. I admit I was just being lazy. $\endgroup$
    – m_goldberg
    Commented Feb 25, 2016 at 8:00
  • 1
    $\begingroup$ nice! There is also Arrowheads[Medium, Appearance -> "Projected"] for 2D arrowheads (I just put this here as a reminder). $\endgroup$
    – Yves Klett
    Commented Feb 25, 2016 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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