7
$\begingroup$

I often met with the case where I want to show the past trajectory of a object. A way of demonstrating this is to plot the trajectory using ParametricPlot, and then change the time interval of the plot.

For example, consider a object moving on 2D trajectory given by two interpolating functions, I could use the following code to showcase the movement of the object:

f = Array[Interpolation[RandomReal[{0, 1}, 100]][t] &, 2]
Manipulate[ParametricPlot[f, {t,1,tt},PlotRange->{{0,1},{0,1}}],{tt,2,100}]

When dragging the slider, ParametricPlot will replot the figure again and again. And to reduce lagging, Mathematica will reduce the PlotPoints option when control is active, causing the lines to distort. Note that in real applications the function might be much more complicated, so it's not feasible to just increase the plot points like PlotPoints->10000.

However, in this particular case, we could plot the figure from t=1 to 100 and just display the part between 1 and tt, saving the replot process. So my question is, is this possible or are there any other way to improve the performance of such animations? Thanks!

$\endgroup$

2 Answers 2

1
$\begingroup$

One way to make it responsive:

f = Array[Interpolation[RandomReal[{0, 1}, 100]][t] &, 2];
data = SortBy[
   Reap[ParametricPlot[f, {t, 1, 100}, 
      EvaluationMonitor :> Sow[{t, f}, "data"]], "data"][[2, 1]],
   First];
Manipulate[
 ListLinePlot[
  Append[Take[data[[All, 2]], LengthWhile[data[[All, 1]], # < tt &]], 
   f /. t -> tt],
  PlotRange -> {{0, 1}, {0, 1}}, AspectRatio -> 1
  ]
 , {tt, 2, 100}]

Alternative 2 uses interpolation to avoid LengthWhile:

f = Array[Interpolation[RandomReal[{0, 1}, 100]][t] &, 2];
data = SortBy[
   Reap[ParametricPlot[f, {t, 1, 100}, 
      EvaluationMonitor :> Sow[{t, f}, "data"]], "data"][[2, 1]], 
   First];
idxIFN = 
  Interpolation[Transpose@{data[[All, 1]], Range@Length@data}, 
   InterpolationOrder -> 0];
Manipulate[
 ListLinePlot[
  Append[Take[data[[All, 2]], idxIFN[tt]], f /. t -> tt]
  , PlotRange -> {{0, 1}, {0, 1}}, AspectRatio -> 1]
 , {tt, 2, 100}]

Alternative 3 computes plot only once and trims it:

f = Array[Interpolation[RandomReal[{0, 1}, 100]][t] &, 2];
data = SortBy[
   Reap[ParametricPlot[f, {t, 1, 100}, 
      EvaluationMonitor :> Sow[{t, f}, "data"]], "data"][[2, 1]], 
   First];
plot = ListLinePlot[
  data[[All, 2]]
  , PlotRange -> All
  ]
idxIFN = 
  Interpolation[Transpose@{data[[All, 1]], Range@Length@data}, 
   InterpolationOrder -> 0];
Manipulate[
 Show[plot
   , PlotRange -> {{0, 1}, {0, 1}}, AspectRatio -> 1] /. 
  Line[p_] :> 
   GraphicsComplex[
    p, {Line[Range@Round@idxIFN[tt]], 
     Line[{p[[Round@idxIFN[tt]]], f /. t -> tt}]}]
 , {tt, 2, 100}]
$\endgroup$
1
  • $\begingroup$ The second seems to be the best in performance. But all approaches are helpful! This question has bugged me for years, but now you mentioned it, it is reasonable that Plot takes much more time comparing to just drawing the lines using ListLinePlot or Graphics. Thanks a lot! $\endgroup$
    – Wjx
    Apr 24 at 9:16
0
$\begingroup$

Increased PlotPoints avoid distortions:

Manipulate[
 ParametricPlot[t {Cos[t], Sin[t]}, {t, 0, tt},
  PlotPoints -> 100,
  PlotRange -> {{-100, 100}, {-100, 100}}], {tt, 1, 100}]
$\endgroup$

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.