2

I have a strange problem with the "bend left=..." option for arrows in TikZ which I can't seem to find an existing solution for.

EDITED:

Basically I want to create this kind of diagram. That is, both red and blue arrows bend upward (90 deg) relative to the two points connecting each arc.

enter image description here

I have created my own command, \myarrows, for this since I'll be wanting to make lots of this with variable length (number of arcs) and offsettings. My idea was that if the requested number of loops is negative (first argument), then the loops are drawn in the opposite direction (to the left). In that case I should simply multiply the bend angle with the sign of the first argument (number of loops). This, however, does not seem to work. What am I doing wrong here? Note that if I specify the angles directly in the code (commented out), it works fine.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc} 
\pgfplotsset{compat=newest}

\pgfplotsset{ /pgf/declare function={
    logkn(\n)   = log10(1.3^\n);
    N           = 120;
    dN          = 12;
    sgn(\x)     = \x/abs(\x);
    y(\n)       = 1.07^\n * 5e-2;
}}

\pgfplotsset{xlabel=$\log x$, ylabel=$\log y$,ytick=\empty,xtick=\empty,axis lines=left,xmin=logkn(1),xmax=logkn(N), domain=1:N,samples=1e2}

\newcommand{\myarrows}[3]{  % \myarrows{NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}

    \pgfplotsinvokeforeach{0,...,#1}{ 

        % CORRECTLY BENDS IN ONE DIRECTION
%       \draw[mystyle,#3] (axis cs:{logkn( #2+dN*##1 )}, {y( #2+dN*##1 )}) to [bend left=+90.0, distance=0.5cm] ( axis cs: {logkn( #2+dN*(##1+sgn(#1)) )}, {y( #2+dN*(##1+sgn(#1)) )});
        % CORRECTLY BENDS IN OTHER DIRECTION
%       \draw[mystyle,#3] (axis cs:{logkn( #2+dN*##1 )}, {y( #2+dN*##1 )}) to [bend left=-90.0, distance=0.5cm] ( axis cs: {logkn( #2+dN*(##1+sgn(#1)) )}, {y( #2+dN*(##1+sgn(#1)) )});
        % MY ATTEMPT TO GENERALIZE USING THE SIGN OF #1 -- DOES NOT WORK
        \draw[mystyle,#3] (axis cs:{logkn( #2+dN*##1 )}, {y( #2+dN*##1 )}) to [bend left={90*sgn(#1)}, distance=0.5cm] ( axis cs: {logkn( #2+dN*(##1+sgn(#1)) )}, {y( #2+dN*(##1+sgn(#1)) )});
    }       
    \node[] at ({logkn(#2+dN*#1)},1e-1) {\scriptsize bend left$=\pgfmathparse{90*sgn(#1)}\pgfmathresult$};
}

\begin{document}
\begin{tikzpicture}[scale=2, mystyle/.style={thick,->,black}]
\begin{semilogyaxis}[ymin=1e-2,ymax=1e2]
        \myarrows{2}{60}{blue}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
        \myarrows{-2}{60}{red}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
\end{semilogyaxis}
\end{tikzpicture}
\end{document}

which produces

enter image description here

Thank you!

  • Welcome! Is the top picture what you want? – cfr Mar 13 '17 at 23:45
  • @cfr not quite. I want both red and blue arrows to bend upward. I've updated my question to clarify, in particular why I need to use bend left/right and not in/out keys. – nicholasr Mar 14 '17 at 10:37
1

(This bug has been fixed since version 3.1 of pgf/TikZ.)

The bug

It's a bug in bend left (ticket):

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \draw [red,->] (0,0) to[bend left=90*-1] (1,0);
\end{tikzpicture}
\end{document}

enter image description here

Edited answer

Use in, out, and relative:

\documentclass[tikz,border=3mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc} 
\pgfplotsset{compat=newest}

\pgfplotsset{ /pgf/declare function={
    logkn(\n)   = log10(1.3^\n);
    N           = 120;
    dN          = 12;
    sgn(\x)     = \x/abs(\x);
    y(\n)       = 1.07^\n * 5e-2;
}}

\pgfplotsset{xlabel=$\log x$, ylabel=$\log y$,ytick=\empty,xtick=\empty,axis lines=left,xmin=logkn(1),xmax=logkn(N), domain=1:N,samples=1e2}

\newcommand{\myarrows}[3]{  % \myarrows{NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}

  \pgfplotsinvokeforeach{0,...,#1}{ 
    \draw[mystyle,#3] (axis cs:{logkn( #2+dN*##1 )}, {y( #2+dN*##1 )}) to [out=90*sgn(#1),in=90*sgn(#1),relative, distance=0.5cm] ( axis cs: {logkn( #2+dN*(##1+sgn(#1)) )}, {y( #2+dN*(##1+sgn(#1)) )});
  }       
  \node[] at ({logkn(#2+dN*#1)},1e-1) {\scriptsize bend left$=\pgfmathparse{90*sgn(#1)}\pgfmathresult$};
}

  \begin{document}
\begin{tikzpicture}[scale=2, mystyle/.style={thick,->,black}]
\begin{semilogyaxis}[ymin=1e-2,ymax=1e2]
        \myarrows{2}{60}{blue}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
        \myarrows{-2}{60}{red}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
\end{semilogyaxis}
\end{tikzpicture}
\end{document}

enter image description here

First answer

Don't use bend left as you want only out=90,in=90:

\documentclass[tikz,border=3mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc} 
\pgfplotsset{compat=newest}

\pgfplotsset{ /pgf/declare function={
    logkn(\n)   = log10(1.3^\n);
    N           = 120;
    dN          = 12;
    sgn(\x)     = (\x/abs(\x));
  }}

\pgfplotsset{xlabel=$\log x$, ylabel=$\log y$,ytick=\empty,xtick=\empty,axis lines=left,xmin=logkn(1),xmax=logkn(N), domain=1:N,samples=1e2}

\newcommand{\myarrows}[3]{  % \myarrows{NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
  \pgfplotsinvokeforeach{0,...,#1}{ 
    \draw[mystyle,#3]
    (axis cs:{logkn(#2+dN*##1},1e0)
    to [out=90, in=90, distance=0.5cm]
    ( axis cs:{logkn(#2+dN*(##1+sgn(#1)))}, 1e0);
  }

  \node[] at ({logkn(#2+dN*#1)},1e-1) {\scriptsize bend left$=\pgfmathparse{90*sgn(#1)}\pgfmathresult$};
}

\begin{document}
\begin{tikzpicture}[scale=2, mystyle/.style={thick,->,black}]
  \begin{semilogyaxis}[ymin=1e-2,ymax=1e2]
    \myarrows{2}{60}{blue}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
    \myarrows{-2}{60}{red}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
  \end{semilogyaxis}
\end{tikzpicture}
\end{document}

enter image description here

  • The reason why I want bend left/right is shown in my edited question above (I want tilted lines superimposed with the arrows). This solution gives out/in going angles always 90 deg to the coordinate axes, which is not quite what I'm seeking. Any suggestions? – nicholasr Mar 14 '17 at 10:40
0

Do you want something like this?

better-behaved arcs

I am not sure why your code does not work, but the following does.

\documentclass{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc}
\pgfplotsset{compat=newest}

\pgfplotsset{ /pgf/declare function={
    logkn(\n)   = log10(1.3^\n);
    N           = 120;
    dN          = 12;
    sgn(\x)     = \x/abs(\x);
}}

\pgfplotsset{xlabel=$\log x$, ylabel=$\log y$,ytick=\empty,xtick=\empty,axis lines=left,xmin=logkn(1),xmax=logkn(N), domain=1:N,samples=1e2}

\newcommand{\myarrows}[3]{% \myarrows{NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
  \pgfplotsinvokeforeach{0,...,#1}{
    \pgfmathsetmacro\mysgn{90*sgn(#1)}%
%     \draw [mystyle,#3,green] (axis cs:{logkn(#2+dN*##1},1e0) to [bend left=+90.0, distance=0.5cm] ( axis cs:{logkn(#2+dN*(##1+sgn(#1)))}, 1e0); % Works correctly for #1 > 0
%     \draw [mystyle,#3,orange] (axis cs:{logkn(#2+dN*##1},1e0) to [bend left=-90.0, distance=0.5cm] ( axis cs:{logkn(#2+dN*(##1+sgn(#1)))}, 1e0); % Works correctly for #1 < 0
    \draw [mystyle,#3] (axis cs:{logkn(#2+dN*##1},1e0) to [bend left=\mysgn, distance=0.5cm] ( axis cs:{logkn(#2+dN*(##1+sgn(#1)))}, 1e0);  % Does not work. How come?
  }
  \node[] at ({logkn(#2+dN*#1)},1e-1) {\scriptsize bend left$=\pgfmathparse{90*sgn(#1)}\pgfmathresult$};
}

\begin{document}
\begin{tikzpicture}[scale=2, mystyle/.style={thick,->,black}]
  \begin{semilogyaxis}[ymin=1e-2,ymax=1e2]
    \myarrows{2}{60}{blue}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
    \myarrows{-2}{60}{red}  % {NUMBER OF LOOPS -1}{XAXIS OFFSET}{COLOR}
  \end{semilogyaxis}
\end{tikzpicture}
\end{document}

Let me know if this is not helpful and I will delete it.

  • I have updated my question above with an example image of what I want to do with my newcommand (and updated the example too). – nicholasr Mar 14 '17 at 10:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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