5

While making a more complicated picture, I stumbled upon unexpected behaviour from a plot command in a let operation. After quite some experimenting, I'm pretty sure I've identified the problem, but let me first show you what I'm talking about. The MWE below is a bit silly because the let operation really isn't necessary there, but it illustrates the issue well enough. And if I'm right, the plot isn't actually relevant, but this is the context in which I encountered the problem and I think it helps to show what's going on.

\documentclass[tikz,border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}

\begin{tikzpicture}
% A few values
\pgfmathsetmacro\freq{10}
\pgfmathsetmacro\zmax{2*pi}
\pgfmathsetmacro\zextra{pi/2}
% Denote the starting point
\draw[black!40,dashed] (0,-1) -- (0,1);
% Draw the angled sine curve from 0 to zmax
\draw[domain=0:\zmax,smooth,samples=100,variable=\z] plot ({\z},{sin(\freq*180*\z/pi)}) coordinate (midpoint);
% Draw the extra bit from zmax to zmax+zextra
% (in principle this should be (x1+z-zmax, y1+f(z)-f(zmax)) but the specific value of zmax and periodicity of the sine function render this unnecessary in this particular case)
\draw[red,domain=0:\zextra,smooth,samples=100,variable=\z] let \p1=(midpoint) in plot ({\x1+\z},{\y1+sin(\freq*180*\z/pi)});
% Draw the extra bit in another way, by explicitly calculating x1 and y1
\draw[green,domain=0:\zextra,smooth,samples=100,variable=\z] plot ({\z+\zmax},{sin(\freq*180*\z/pi)});
\end{tikzpicture}

\end{document}

Result: enter image description here

I've become convinced this is a units problem. Indeed, if I change the code for the red curve to

\draw[red,domain=0:\zextra,smooth,samples=100,variable=\z] let \p1=(midpoint) in plot ({\x1+1cm*\z},{\y1+1cm*sin(\freq*180*\z/pi)});

(and delete the green line), I do get the expected result: enter image description here

The PGF/TikZ manual mentions the let operation stores coordinates in units of TeX points, whereas the default units for TikZ coordinates are centimeters. So I guess since the \x1 above expands to something like 36pt and the second term in the sum has no units, the second term is probably assumed to be measured in units of points as well. Since the sine just oscillates between -1 and 1 I can simply multiply it with 1cm to obtain results that agree with the rest of the drawing. Alternatively, I could work with units of points in the rest of the drawing as well (I've tried, it works), but this seems unpractical.

So making a long story short, I guess my question is: can I change the default units for the let operation to agree with the units I'm using in the rest of my tikzpicture?

Wouter
  • 541
  • 1
    Currently no you can't change it but. I think you are looking for a version of \strip@pt that takes away the pt. – percusse May 23 '16 at 15:51
  • I suggest ([xshift=\x*<stuff>, yshift=\y*<stuff>] \z, \z*<stuff>) if you can't do ([shift={(midpoint)}] \z, \z*<stuff>) (you can even apply the shifting options to the path instead of the coordinate. – Qrrbrbirlbel May 23 '16 at 20:12
  • By the way, the pt can be stripped away by using the PGFMath function scalar but that won't help here. You will need to convert the values back into the canvas coordinate system (e.g. ({scalar(\x1/1cm)+\z},{scalar(\y1/1cm)+sin(…)})) or add these coordinates separately (see answer). – Qrrbrbirlbel Jun 24 '23 at 17:06

1 Answers1

1

This is the same problem as Continuing a line with a new line in tikz using the slope equation isn't working as expected.

Once a coordinate is part of your picture, PGF/TikZ only knows its position in the canvas coordinate system which you generally can't revert to the xyz coordinate system. (Though, in most use cases you could actually.)

But since all you're trying to do is just adding one coordinate to another you don't need any calculation or the coordinate's separate values. PGF/TikZ has you covered with the shift transformation.

Thus, instead of (x₁ + x₂, y₁ + y₂) you can just do ([shift=(p₁)] p₂). With the calc library, this can written as ($(p₁)+(p₂)$).
In this case though, since the shifting parameter is not dependent of \z, you can just move it out of the plot coordinate:

\draw[red, domain=0:zextra, shift=(midpoint)] plot (\z,{Sin(freq,\z)});

No calculation necessary (let PGF/TikZ do it).

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[
  variable=\z, smooth, samples=100,
  declare function={
    Sin(\freq,\t) = sin(deg(\freq)*\t);
    freq   = 10;
    zmax   = 2*pi;
    zextra = pi/2;}]
\draw[black!40,dashed] (0,-1) -- (0,1);
%
\draw[domain=0:zmax] plot (\z,{Sin(freq,\z)}) coordinate (midpoint);

\draw[domain=0:zextra, shift=(midpoint)] % recommended plot (\z,{Sin(freq,\z)}) [red];

% also possible: \draw[domain=0:zextra] plot ([shift={(midpoint)}]\z,{Sin(freq,\z)}) [blue]; \draw[domain=0:zextra] plot ({$(midpoint)+(\z,{Sin(freq,\z)})$}) [green]; \draw[domain=0:zextra] let \p0 = (midpoint) in plot ({$(\x0,\y0) +(\z,{Sin(freq,\z)})$}) [yellow]; \end{tikzpicture} \end{document}

Output (w/o alternatives)

enter image description here

Qrrbrbirlbel
  • 119,821
  • I'd forgotten about this question, but clearly you hadn't! Thanks for coming back with this full answer! – Wouter Jun 25 '23 at 08:04