7

I have this clumsy code to plot the height of a bouncing ball over time. Is there a possibility for optimization? Perhaps writing the functions directly with the tikz math library? Also at the moment negative time input can't be handled. And how can macros with more then one input argument call lua code?

\documentclass[tikz]{standalone}
\usepackage{fontspec}
\usepackage{pgfplots}
\usepackage{luatextra}

\begin{luacode}
  function height(h0, idx)
    return h0*(3/4)^(math.abs(idx))
  end
  function time(h0, idx)
    t = math.sqrt(2*height(h0, 0)/9.81)
    for i=1,idx,1 do
      t = t+2*math.sqrt(2*height(h0, i)/9.81)
    end
    return t
  end 
  function offset(h0, idx)
    o = 0
    if idx > 0 then
      o = time(h0, idx-1)+(time(h0, idx)-time(h0, idx-1))/2
    end
    return o
  end
\end{luacode}

\makeatletter
\pgfmathdeclarefunction{luaheight}{1}{%
  \begingroup
    \pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}%
    \pgfmathparse{#1}%
    \edef\pgfmathresult{\directlua{tex.print("" .. height(10,\pgfmathresult))}}%
    \pgfmathsmuggle\pgfmathresult%
  \endgroup
}%
\pgfmathdeclarefunction{luatime}{1}{%
  \begingroup
    \pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}%
    \pgfmathparse{#1}%
    \edef\pgfmathresult{\directlua{tex.print("" .. time(10,\pgfmathresult))}}%
    \pgfmathsmuggle\pgfmathresult%
  \endgroup
}%
\pgfmathdeclarefunction{luaoffset}{1}{%
  \begingroup
    \pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}%
    \pgfmathparse{#1}%
    \edef\pgfmathresult{\directlua{tex.print("" .. offset(10,\pgfmathresult))}}%
    \pgfmathsmuggle\pgfmathresult%
  \endgroup
}%
\makeatother

\begin{document}
\begin{tikzpicture}
\begin{axis}
  \addplot[domain=0:luatime(0)] {luaheight(0)-9.81/2*x^2};
  \foreach \p in {1,...,5} {
    \addplot[domain=luatime(\p-1):luatime(\p)] {luaheight(\p)-9.81/2*(x-luaoffset(\p))^2}; 
  }    
\end{axis}
\end{tikzpicture}
\end{document}

And it looks like this:

enter image description here

2 Answers 2

9

After some math (keyword is geometric series) I found an analytical solution to calculate the time passed. Now there is a neat solution, but it's way slower then the first one.

\documentclass[tikz]{standalone}
\usepackage{fontspec}
\usepackage{pgfplots}
\usepackage{luatextra}
\begin{document}
\begin{tikzpicture}[
  declare function={
    bounce(\hz,\idx) = \hz*(3/4)^\idx;
    duration(\hz,\idx) = sqrt(2*\hz/9.81)*(1+sqrt(3)*(1-sqrt(3/4)^\idx)/(1-sqrt(3/4)));
    offset(\hz,\idx) = duration(\hz,\idx-1)+(duration(\hz,\idx)-duration(\hz,\idx-1))/2;
    flight(\hz,\idx,\t) = bounce(\hz,\idx)-9.81/2*(\t-offset(\hz,\idx))^2;
  }
]
  \begin{axis}[
      xmin=0, xmax=20,
      ymin=0, ymax=12,
      thick,
      axis lines=left,
      xtick={14.047},
      %xtick={{duration(10,8)}},
      xticklabels={$t_c$},
      yticklabels={},
      xlabel={Zeit},
      ylabel={Höhe},
      tick style=transparent,
  ]
    \addplot[red,domain=0:{duration(10,0)}] {bounce(10,0)-9.81/2*\x^2};
    \addplot[dashed,gray]coordinates {({duration(10,8)},0) ({duration(10,8)},12)};
    \foreach \p in {9,...,20} {
      \addplot[domain={duration(10,\p-1)}:{duration(10,\p)}] {flight(10,\p,\x)}; 
    }
    \foreach \p in {1,...,8} {
      \addplot[red,domain={duration(10,\p-1)}:{duration(10,\p)}] {flight(10,\p,\x)}; 
    }
    \addplot[red]coordinates{({duration(10,8)},0) (20,0)};
  \end{axis}
\end{tikzpicture}
\end{document}

It looks like this:

enter image description here

Why can't I call a declared function in the xtick?

1
  • I found the problem with xtick, æpgfmath is not expandable: tex.stackexchange.com/questions/20265/… the solution is to use a macro and call it before setting the xtick with the result.
    – Reza
    Commented Feb 2, 2014 at 8:53
5

With PSTricks just for fun. The remaining trivial parts are intentionally left for the sake of simplicity.

\documentclass[pstricks,border=12pt]{standalone}
\SpecialCoor
\psset{linecolor=red}
\begin{document}
    \begin{pspicture}(11,10)
        \foreach \i in {0,...,10}{\parabola(\i,0)(!\i\space .5 add  10 .65 \i\space exp mul)}
    \end{pspicture}
\end{document}

enter image description here

2
  • I plot it y versus x rather than t. Sorry for misunderstanding! Commented Feb 1, 2014 at 16:49
  • No problem, a very swift solution with pstricks!
    – Reza
    Commented Feb 2, 2014 at 7:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .