[Tex/LaTex] TikZ: How to recalculate a command value variable in a foreach loop

foreachtikz-pgf

I am trying to diagram a light path through multiple homogeneous media if the velocity were a function of the height below initial height. This would consist of a path made of straight line segments.

The way I intended on doing this was:

  1. Define a starting coordinate, (A)

  2. Begin the foreach loop

  3. Find the next coordinate, (B), according to Snell's law and kinematics.(Shown below, also where is MathJax?)

  4. Draw path between (A) and (B). Then I would define (A) to have (B)'s value

  5. Continue the loop until it ends

Snell's Law,
sin(theta)/v = constant; v = sqrt(h)

Where h is the vertical distance from the starting point and theta is measured from the vertical so I use cos and acos in the calculation since the value \qq is measured off of horizontal.


The following is what I have, but it does not appear to update the value of \qq as it only generates a series of collinear arrows, when they should start to get less steep. I've considered using foreach with evaluate but the first angle is independent of the height and as a consequence, I don't think that will work.

\documentclass{article}
\usepackage{tikz}


\begin{document}
\pagestyle{empty}

\begin{figure*}[htp]
\centering
\begin{tikzpicture}[scale=4, >=latex]

\def\len{2} % box height

\def\hstep{0.1} % vert spacing between fluid interfaces
\def\qStart{45} % starting incidence angle


% init iteration variables to initial
\def\qq{\qStart}
\coordinate  (A) at (0, \len) node {A};

% start looping
\foreach \height in {0.1, 0.2, ..., 1.1}{
  % define (B) relative to (A) at some angle at fixed distance (\hstep*\len) below
  \path (A) +(-\qq : {\hstep*\len/sin(\qq)}) coordinate (B); 
  % generate line between the two (for debug, use arrowheads to identify where points are)
  \draw[->] (A) -- (B);
  % update (A) to next point
  \coordinate (A) at (B);
  % recalculate \q according to snell's law using pgf's math functions and \pfgmathsetmacro for real values
  \pgfmathsetmacro{\qq}{ {acos( 
  sqrt( 1+\hstep/\height )*cos(\qq) )} }
}   

\end{tikzpicture}
\end{figure*}


\end{document}

Best Answer

The math library provides a for-loop which doesn't scope each iteration allowing values retain their values between iterations.

Not sure if this is the required output, and I think the cos(\qq) should be cos(\qq)^2 (at least this enables compilation without errors).

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}[scale=4]
\tikzmath{%
  \len = 2;
  \hStep = 0.1;
  \qStart = 45;
  \qq = \qStart;
  { 
    \coordinate (A) at (0, \len);
  };
  for \h in {0.1, 0.2, ..., 1.1}{%
    {
      \path (A) ++ (-\qq : {\hStep * \len / (sin(\qq) + 1)}) coordinate (B);
      \draw[->] (A) -- (B);
      \coordinate (A) at (B); 
    };
    \qq = acos(sqrt( 1 + \hStep / \h ) * cos(\qq)^2 );
  };
}
\end{tikzpicture}
\end{document}

enter image description here