1

This is going to be a slightly messy/unclear question, but here it goes.

Basically, I want to work with a plot in pgfplots, where I want to also generate programmatically some nodes (maybe as result of intersections with the plot); and then fill areas between the plot and nodes which may be derived from the intersection nodes.

I basically got a MWE to work (below); I'll try to explain the workflow:

  • I start with a plot of a function (here sin(x)) and a set of points (here \xPoints) which are predefined x coordinates
  • I want to set off vertical lines from \xPoints, and find intersections with sin(x), and store those points as nodes. That is not the problem here, so I avoided using intersections at all - as a stand in for those nodes, I use the (tnode\i) nodes (blue), which have x-positions at \xPoints, and an arbitrary y-position
  • I want to generate programmatically a second set of nodes, based on (tnode\i). In this case, those are the (txnode\i) nodes (red), which are simply the (tnode\i) nodes locations, but their y position changed to (tnode\i).y+\i*2.0; where \i is the index of the node (allowed by count). Thus, the position of the (txnode\i) depends on both the corresponding (tnode\i) element location, and on the index itself.
  • Based on the second set of nodes, (txnode\i), I want to derive a third set of points, such that their .x is the same, and their .y is again a formula (txnode\i).y+0.7 (in this particular case, it doesn't use the count index, but in general it might - hence the need for it to spin in a \foreach).
  • This third set of points does not need to be shown/rendered as a node, but it will be used in a fill area, between a point from the third set and corresponding pieces of the plot function sin(x).

The MWE generates this image:

test_pdf

... with the following problems:

  • If I don't use \pgfplotsextra, I cannot use \gettikzxy in a \foreach (Error: "No shape named" ... "is known")
  • (If don't want to use \pgfplotsforeachungrouped - it seems it doesn't have a [count=, which I need to generate node names)
  • If I do use \pgfplotsextra, I cannot use stuff like domain=\x:\upx where \x, \upx are provided by a \foreach, because then I get "... ill-formatted floating point number '97.191'" (which is even weirder, because '97.191', '0.0' etc should not be ill-formatted floats?)
  • I can try to run that \foreach code after the \pgfplotsextra - but then again I cannot use \gettikzxy inside, as I will get "No shape named" error again; however, if I simply directly refer to the node in the \addplot command, then it works ???!

Obviously, the last solution doesn't quite cut it for me, because I'd like to calculate stuff based on the nodes (like it is shown in the snippet near "%\temp % the problem line ...").

So, my question is - how to write the code, so in the end I can get a reference to the txnode\i nodes (the red ones on the image), calculate some coordinates based on them, and use those calculations in an \addplot?

Below is the code:

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/33703/86}
\usepackage{pgfplots}
\usepackage{tikz}
\usetikzlibrary{intersections} %% named intersections
\usetikzlibrary{calc}

\makeatletter
% http://tex.stackexchange.com/questions/33703/extract-x-y-
\newcommand{\gettikzxy}[3]{%
  \tikz@scan@one@point\pgfutil@firstofone#1\relax
  \edef#2{\the\pgf@x}%
  \edef#3{\the\pgf@y}%
}
\makeatother


\begin{document}

\def\xPoints{0.0,0.625,1.25,1.875,2.5,3.125,3.75,4.375}

\begin{tikzpicture}
\begin{axis}[ymin = 0, ymax = 2]

  \addplot[blue,domain=0:3.1] {sin(deg(x))}; % must have

  \foreach [count=\i] \x in \xPoints {
    \edef\temp{
      \noexpand\node [draw,blue] (tnode\i) at ({axis cs:\x,1.0}) {} ;
    }
    \temp
  }


  \pgfplotsextra{ % must have, else Package pgf Error: "No shape named" txnode1 "is known" for gettikzxy

    \newlength{\tl}
    \foreach [count=\i] \x in \xPoints {
      \gettikzxy{(tnode\i)}{\tix}{\tiy}
      \pgfmathsetmacro{\newy}{\tiy+\i*2.0}
      \setlength{\tl}{\newy pt}
      \edef\temp{
        \noexpand\node [draw,red] (txnode\i) at ({axis cs:\x,0}|-{0,\tl}) {} ;
      }
      \temp
    } % \foreach

    \foreach [count=\i] \x
        [evaluate=\x as \upx using (\x+0.1)]
    in \xPoints {
      \gettikzxy{(txnode\i)}{\tix}{\tiy}
      \pgfmathsetmacro{\newy}{\tiy+0.7}
      \setlength{\tl}{\newy pt}
      \edef\temp{
        \noexpand\addplot[color=blue!50,restrict x to domain=\x:\upx,domain=\x:\upx]
        plot[fill] {sin(deg(x))} |- ({axis cs:\x,0}|-{0,\tl}) -- cycle;
      }
      %\temp % the problem line - generates:
      %! Package PGF Math Error: Sorry, an internal routine of the floating point unit
      % got an ill-formatted floating point number `97.191'. The unreadable part was n
      %ear '97.191'..
    } % \foreach

  } % \pgfplotsextra


  % seems to work here:
  \foreach [count=\i] \x
      [evaluate=\x as \upx using (\x+0.1)]
  in \xPoints {
    %\gettikzxy{(txnode\i)}{\tix}{\tiy} % No shape named txnode1 is known.
    %\pgfmathsetmacro{\newy}{\tiy+0.7}
    %\setlength{\tl}{\newy pt}
    %\edef\temp{
    %  \noexpand\addplot[color=blue!50,restrict x to domain=\x:\upx,domain=\x:\upx]
    %  plot[fill] {sin(deg(x))} |- ({axis cs:\x,0}|-{0,\tl}) -- cycle;
    %}
    % this works, though?
    \edef\temp{
      \noexpand\addplot[color=blue!50,restrict x to domain=\x:\upx,domain=\x:\upx]
      plot[fill] {sin(deg(x))} |- (txnode\i) -- cycle;
    }
    \temp
  } % \foreach

\end{axis}
\end{tikzpicture}

\end{document}
sdaau
  • 17,079
  • 2
    Mixing of \addplots, nodes, and calculations can quickly become quite complicated (as you have noticed). It's going to be hard to answer the question in your last paragraph in a general fashion, because it really depends on what you mean by "calculate some coordinates based on them" and "use those calculations in an \addplot". Could you edit your question to describe the concrete goal you're trying to achieve? That would make it possible to try and come up with different, potentially better suited approaches. – Jake Feb 17 '14 at 12:05
  • Thanks for that, @Jake - I tried to add an explanation of the workflow in the code, I hope that makes things clearer. Btw, I just thought of a possible solution - I can simply create the third set of points as invisible nodes, and then use those nodes in the snippet after \pfgplotsextra (given nodes can be addressed that way) - part of the problem may be, that I insisted on not creating nodes for those points, as I didn't want them to be shown... – sdaau Feb 17 '14 at 12:35

0 Answers0