Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have an animated plot of the kind

Manipulate[
 plot1 = ParametricPlot3D[randomsample[s], {s, 0, t}, 
                          PlotStyle -> Red,
                          Evaluated -> True];
 plot2 = ListPointPlot3D[coord3D[t]];
 Show[plot1,
      plot2,
      AxesOrigin -> {0, 0, 0}, 
      PlotRange -> {{-3, 3}, {-3, 3}, {-3, 3}},
      ImageSize -> Large,
      AspectRatio -> 1,
      ViewPoint -> viewpoint, 
      PlotLabel -> Style["time " <> ToString[NumberForm[t, {4, 2}]] <> " whatevers", 20]]
 ,
 {t, 0, 15, ControlType -> Animator},
 {{viewpoint, {Infinity, 0, 0}},
  {{3, 3, 1} -> "3D",
   {Infinity, 0, 0} -> "Front",
   {0, 0, Infinity} -> "Top",
   {0, Infinity, 0} -> "Side"}}]

making use of source data such as

coord3D0 = RandomReal[{-1, 1}, {450, 3}];
ρ0 = Norm /@ coord3D0;
θ0 = RandomReal[{0, 2 Pi}, 450];
vθ = RandomReal[{-10, 10}, 450];
θ[t_] = vθ/ρ0 t + θ0;
kvectors = Normalize /@ MapThread[
   Cross,
   {Evaluate[Normalize /@ RandomReal[{-1, 1}, {450, 3}]], coord3D0}];
coord3D[t_] = Simplify@Chop[
   coord3D0*Cos[θ[t]] + MapThread[Cross, {kvectors, coord3D0}] Sin[θ[t]] + MapThread[#1 (#1.#2) &, {kvectors, coord3D0}] (1 - Cos[θ[t]])];
randomsample[t_] = RandomSample[coord3D[t], 30];

The point is, it works, but it runs reeeeeeally slow on my laptop. Now my question is threefold:

  1. How can I make it run faster?
  2. Did I do something specifically wrong or have I somehow run into Mathematica's limitations as regards 3D animated plotting? Could it be that this is not the way I'm supposed to be combining plots inside a Manipulate?
  3. What are Mathematica's "practical" limitations in this respect? I.e., how can I make a reasonable guess as whether an animated plot will be able to run smoothly? How much is too much?

EDIT: The problem seems linked to the ParametricPlot3D code, since the ListPointPlot3D runs smoothly by itself, while the parametric plot doesn't. Heretofore I have tried using a RegionFunction specification and an Exclusion specification in place of its dynamic upper limit, both unsuccessfully.

share|improve this question
1  
It is not really lethally slow on my machine - what kind of hardware do you use? Can you supply some useful Timings? –  Yves Klett Sep 25 '12 at 11:20
    
I use MMA 8.0.1.0 on an Intel i3 machine running Windows 7, with 4GB DDR3 and a NVIDIA GeForce 310M. I am not sure what kinds of Timings would be useful, since the problem is not that it takes time to start, but rather that the animation looks very much "stop motion"-like. However, I have noticed that it strongly depends on the number of "particles" whose trajectory I track: this slowing becomes negligible at a RandomSample of about 10. –  Andrea Colonna Sep 25 '12 at 11:29
    
Simplify is probably not necessary and you may try getting rid of that and see if it helps (no noticeable difference for me). –  Yves Klett Sep 25 '12 at 11:35
1  
Try to identify whatever slows this down (e.g. by elimination of plot components), then we can try to speed that up. –  Yves Klett Sep 25 '12 at 11:48
1  
I think Ives found the handle to use, you could e.g. use PerformanceGoal -> $PerformanceGoal which will use a faster version when animating and a more expensive variant when the animation is stopped. The two options PlotPoints and MaxRecursions would give somewhat more control about what "Speed" or "Performance" would mean, e.g.: PlotPoints -> ($PerformanceGoal /. {"Speed" -> 15, _ -> Automatic}), MaxRecursion -> ($PerformanceGoal /. {"Speed" -> 3, _ -> Automatic}). @Yves: would you want to write an answer? –  Albert Retey Sep 25 '12 at 13:39
show 4 more comments

2 Answers

up vote 4 down vote accepted

To speed up the animation - pre-compute and then animate:

coord3D0 = RandomReal[{-1, 1}, {450, 3}];
ρ0 = Norm /@ coord3D0;
θ0 = RandomReal[{0, 2 Pi}, 450];
vθ = RandomReal[{-10, 10}, 450];
θ[t_] = vθ/ρ0 t + θ0;
kvectors = Normalize /@ MapThread[
   Cross,
   {Evaluate[Normalize /@ RandomReal[{-1, 1}, {450, 3}]], coord3D0}];
coord3D[t_] = Simplify@Chop[
   coord3D0*Cos[θ[t]] + MapThread[Cross, {kvectors, coord3D0}] Sin[θ[t]] + 
   MapThread[#1 (#1.#2) &, {kvectors, coord3D0}] (1 - Cos[θ[t]])];
randomsample[t_] = RandomSample[coord3D[t], 30];


gl = Table[plot1 = ParametricPlot3D[randomsample[s], {s, 0, t}, PlotStyle -> Red, 
     Evaluated -> True];plot2 = ListPointPlot3D[coord3D[t]];
   Show[plot1, plot2, AxesOrigin -> {0, 0, 0}, PlotRange -> 
  {{-3, 3}, {-3, 3}, {-3, 3}}, ImageSize -> Large, AspectRatio -> 1, PlotLabel -> 
  Style["time " <> ToString[NumberForm[t, {4, 2}]] <> " whatevers", 20]], {t, .1, 15, .3}];


Manipulate[Show[gl[[n]], ViewPoint -> Dynamic@viewpoint], {n, 1, Length[gl], 1, 
  Animator, AnimationRate -> 10, AnimationRunning -> False}, 
 {{viewpoint, {Infinity, 0, 0}}, {{3, 3, 1} -> "3D", 
 {Infinity, 0, 0} -> "Front", {0, 0, Infinity} -> "Top", {0, Infinity, 0} -> "Side"}}]
share|improve this answer
add comment

If you are after a "final" high quality answer, I think Vitaly's suggestion to pre-compute is the best you can do. If you rather do some exploration and don't want to wait for the lengthy precomputing to finish before seeing the results you could try to speed up the ParametricPlot3D. The most simple version is to set PerformanceGoal -> "Speed" as Yves has suggested. You can get some finer control about what "Speed" actually does by using the options PlotPoints and MaxRecursions, as e.g. here:

Manipulate[
 plot1 = ParametricPlot3D[randomsample[s], {s, 0, t + $MachineEpsilon},
       PlotStyle -> Red, Evaluated -> True,
       PlotPoints -> ($PerformanceGoal /. {"Speed" -> 15, _ -> Automatic}), 
   MaxRecursion -> ($PerformanceGoal /. {"Speed" -> 3, _ -> Automatic})
   ];
 Show[plot1,
  AxesOrigin -> {0, 0, 0}, PlotRange -> {{-3, 3}, {-3, 3}, {-3, 3}},
  ImageSize -> Large, AspectRatio -> 1, ViewPoint -> viewpoint, 
  PlotLabel -> 
   Style["time " <> ToString[NumberForm[t, {4, 2}]] <> " whatevers", 
    20]
  ],
 {t, 0, 15, ControlType -> Animator},
 {{viewpoint, {Infinity, 0, 0}}, {
   {3, 3, 1} -> "3D",
   {Infinity, 0, 0} -> "Front",
   {0, 0, Infinity} -> "Top",
   {0, Infinity, 0} -> "Side"}
  }
 ]

Note that the global $PerformanceGoal is used to create a fast preview while the animation is running (or the controls are changing) but to show a precise version (using the default values) when the animation is stopped. You'll notice quite some differences in the two versions, so you might want to fine tune the values for PlotPoints and MaxRecursion so that your preview is a decent compromise between speed and quality for your application.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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