7

This is a follow-up to naming paths inside a TikZ foreach loop

I want to plot a series of plots with names generated for each plot (usingname path global) in a foreach loop and place a coordinate at the intersection of each plot with a reference line. The coordinates name is also generated in the loop. The names are generated from \ksdlist, the reference line is called RefLine:

\documentclass{standalone}

\usepackage{tikz,pgfplots}

\usetikzlibrary{intersections}%,backgrounds,calc}

\def\ksdList{5e-2,3e-2,2e-2,1e-2,4e-3,1e-3,4e-4,1e-4,1e-5}

\begin{document}
  \begin{tikzpicture}
    \begin{loglogaxis}[
      xmin=2300,xmax=1e8,ymin=0.008,ymax=0.1
      ]
      \path[draw,name path global=RefLine] (rel axis cs:1,0) -- (rel axis cs:1,1);
      \foreach \ksd in \ksdList {
        \edef\plotopt{name path global=plot-\ksd}
        \expandafter\addplot\expandafter[\plotopt,raw gnuplot] gnuplot {
          set xrange [2300:1e8];
          set yrange [0.008:0.1];
          set logscale xy;
          set samples 100;
          f(R,L) = -2*log10(2.51/(R*sqrt(L))+\ksd/3.71)-1/sqrt(L);
          set cont base;
          set cntrparam levels discrete 0;
          unset surface;
          splot f(x,y) smooth unique;
        };
        \edef\intersectionsopt{name intersections={of plot-\ksd and RefLine}}
        % -----------
        % This fails:
        \expandafter\pgfplotsextra{\expandafter\path\expandafter[\intersectionsopt] (intersection-1) coordinate (end-\ksd);};
      }
      % -----------------------------------------------
      % This is how I can place the coordinate manually
      \pgfplotsextra{\path[name intersections={of=plot-5e-2 and RefLine}] (intersection-1) coordinate (end-5e-2);}
    \end{loglogaxis}
    % ---------------------------
    % And I can now place a label
    \path (end-5e-2) node[right] {0.05};
  \end{tikzpicture}
\end{document}

The options for creating the intersections are in \intersectionsopt, but they include a pair of braces, which I think is the cause for errors during compilation.

Christoph
  • 2,913

1 Answers1

6

Instead of going to all that trouble with the \edefs, you can just use \pgfplotsinvokeforeach{<list>}{<code, where the current list element is available as #1>}, which executes the loop code directly (instead of accumulating the commands and executing them at the same time, as \foreach does).

\documentclass{standalone}

\usepackage{pgfplots}

\usetikzlibrary{intersections}

\begin{document}
  \begin{tikzpicture}
    \begin{loglogaxis}[clip=false,
      xmin=2300,xmax=1e8,ymin=0.008,ymax=0.1
      ]
      \path[draw,name path global=RefLine] (rel axis cs:1,0) -- (rel axis cs:1,1);
      \pgfplotsinvokeforeach{5e-2,3e-2,2e-2,1e-2,4e-3,1e-3,4e-4,1e-4,1e-5}{
       \addplot[name path global=plot-#1,raw gnuplot] gnuplot {
          set xrange [2300:1e8];
          set yrange [0.008:0.1];
          set logscale xy;
          set samples 100;
          f(R,L) = -2*log10(2.51/(R*sqrt(L))+#1/3.71)-1/sqrt(L);
          set cont base;
          set cntrparam levels discrete 0;
          unset surface;
          splot f(x,y) smooth unique;
        };
        \pgfplotsextra{\path[name intersections={of=plot-#1 and RefLine}] (intersection-1) node [right] {#1};};
      }
    \end{loglogaxis}
  \end{tikzpicture}
\end{document}

If you need to have the list as a macro, you can \edef the plot command.

\documentclass{standalone}

\usepackage{pgfplots}

\usetikzlibrary{intersections}

\def\ksdList{{5e-2,3e-2,2e-2,1e-2,4e-3,1e-3,4e-4,1e-4,1e-5}}

\begin{document}
  \begin{tikzpicture}
    \begin{loglogaxis}[clip=false,
      xmin=2300,xmax=1e8,ymin=0.008,ymax=0.1
      ]
      \path[draw,name path global=RefLine] (rel axis cs:1,0) -- (rel axis cs:1,1);
      \edef\doplot{
      \noexpand\pgfplotsinvokeforeach{\ksdList}{
       \noexpand\addplot[name path global=plot-\noexpand##1,raw gnuplot] gnuplot {
          set xrange [2300:1e8];
          set yrange [0.008:0.1];
          set logscale xy;
          set samples 100;
          f(R,L) = -2*log10(2.51/(R*sqrt(L))+\noexpand##1/3.71)-1/sqrt(L);
          set cont base;
          set cntrparam levels discrete 0;
          unset surface;
          splot f(x,y) smooth unique;
        };
        \noexpand\pgfplotsextra{\noexpand\path[name intersections={of=plot-\noexpand##1 and RefLine}] (intersection-1) node [right] {\noexpand##1};};
      }}
      \doplot
    \end{loglogaxis}
  \end{tikzpicture}
\end{document}
Jake
  • 232,450
  • Definitely helpful, but I'd like to reuse \ksdList in several parts of the code. Is there any way to do that in your solution? – Christoph Feb 09 '12 at 12:52
  • That approach (\edefing the whole loop) is something I didn't expect to work and couldn't have come up with anyway, but it work perfectly! Thank you. – Christoph Feb 09 '12 at 13:44