Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I think I need a way to flush the PGF commands as the reference to \LabelText uses the last value, and not value at the time of invocation. The macro LabelPoint is intended to replace the first \addplot command as shown and label the point with the coordinates, or a specified label if one is given. BUT, both points get labelled as top.

\documentclass{article}
\usepackage{pgfplots}
\usepackage{xparse}

\begin{document}
\newcommand{\LabelText}{}
\NewDocumentCommand{\LabelPoint}{o o m m g}{
    \IfNoValueTF{#5}{
        \renewcommand{\LabelText}{$(#3,#4)$} % Label with given coordinates
    }{
        \renewcommand{\LabelText}{#5} % Use given label
    }
    \addplot [#1] coordinates{(#3,#4)} node [#2] {\LabelText};

    %\pgfsyssoftpath@flushcurrentpath % -- Syntax error
    %\pgfusepath{fill}                % -- no effect
}

\NewDocumentCommand{\LabelPointX}{o o m m g}{
  \IfNoValueTF{#5}{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {$(#3,#4)$};
  }{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {#5};
  }
}

\begin{tikzpicture}
\begin{axis}
    \addplot [mark=*,color=red] coordinates{(0,0)} node [color=blue, below] {$(0,0)$};
    \LabelPoint[mark=*,color=red][color=blue, below]{0.5}{0.5}{middle}
    \LabelPoint[mark=*,color=red][color=blue, below]{1  }{1  }{top}
\end{axis}
\end{tikzpicture}
\end{document}

I thought the problem had to do with the PGF commands not being flushed, but I can't seem to get that to work -- Have commented out what I tried.

I also don't like having a global variable \LabelText as it only really has meaning within the scope of the macro so any help in moving that to be within the \NewDocumentCommand would be helpful as well.

The modified version \LabelTextX which uses two different \addplot commands works, but that just makes the code harder to read, and gets complicated when there are more conditions involved, so I really don't want to use that as a solution.

share|improve this question

2 Answers 2

up vote 1 down vote accepted

If I understand correctly \LabelPointX does what you want it to do, and \LabelPoint does the same thing. You want to refactor \LabelPoint so it's less repetitive.

Do you like this implementation?

\NewDocumentCommand{\LabelPointY}{o o m m g}{
  \addplot [#1] coordinates{(#3,#4)} node [#2] {\IfNoValueTF{#5}{$(#3,#4)$}{#5}};
}

This doesn't need any temporary variables and doesn't repeat anything.

share|improve this answer
    
Yes, LabelPointX does what I want, but I am trying to keep my code readable. Your solution is definitely better than LabelPointX, but I'd prefer to use some sort of intermediate variable for readability. There are a few other clauses in the actual code, and things very quickly become difficult to read without having intermediate variables. –  Peter Grill May 3 '11 at 3:48
    
I am trying to use this solution, and it works fine for the text label. However, I need similar \If conditions to be applied to where LabelPointY has #1 and #2 (i.e., I need to determine the the styles to be applied based on the given args). I tried the obvious (using similar \Ifs) and that resulted in errors. –  Peter Grill May 3 '11 at 23:31

This is an expansion question. The label text is passed as-is to the path generator and is stored without expansion. It is only expanded when the path is constructed which, since you are doing this several times on a single path, means that the label texts all expand to the same thing. You can see that this is the case by enclosing the contents of the \LabelPoint macro in a level of TeX grouping (say, by doubling the opening and closing parentheses). This causes the changes to \LabelText to be local to the definition and when the path is constructed, it uses the global version (which happens to be empty).

So the solution is to pass the label text macro to the path in a pre-expanded way. This can get a bit problematic when generalised, and there are a number of solutions to this. Which is best is something I'm not qualified to judge! Here's one method that uses an auxiliary macro and a single \expandafter.

\documentclass{article}
\usepackage{pgfplots}
\usepackage{xparse}

\begin{document}
\newcommand{\LabelText}{}
\NewDocumentCommand{\LabelPoint}{o o m m g}{
  \def\plotcmd{\addplot [#1] coordinates{(#3,#4)} node [#2]}
    \IfNoValueTF{#5}{
        \renewcommand{\LabelText}{ {$(#3,#4)$}} % Label with given coordinates
    }{
        \renewcommand{\LabelText}{ {#5}} % Use given label
    }

  \expandafter\plotcmd\LabelText;

    %\pgfsyssoftpath@flushcurrentpath % -- Syntax error
    %\pgfusepath{fill}                % -- no effect
}

\NewDocumentCommand{\LabelPointX}{o o m m g}{
  \IfNoValueTF{#5}{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {$(#3,#4)$};
  }{
    \addplot [#1] coordinates{(#3,#4)} node [#2] {#5};
  }
}

\begin{tikzpicture}
\begin{axis}
    \addplot [mark=*,color=red] coordinates{(0,0)} node [color=blue, below] {$(0,0)$};
    \LabelPoint[mark=*,color=red][color=blue, below]{0.5}{0.5}{middle}
    \LabelPoint[mark=*,color=red][color=blue, below]{1  }{1  }{top}
\end{axis}
\end{tikzpicture}
\end{document}

Notice that we put the braces in to the \LabelText macro. That just makes life a little easier with regard to assembling the final command. Using the auxiliary \plotcmd macro simply saves a lot of \expandafters. The whole purpose is that \LabelText should be expanded before the \addplot command is processed so that the value of \LabelText is seen, rather than \LabelText itself. Thus TeX merrily parses this line, sees the \expandafter and so expands \LabelText first. Then hops back to expand \plotcmd which expands to the \addplot ... stuff. Then it starts again at \addplot but now, due to our expansion magic, the input stream consists of:

\addplot [#1] coordinates {(#3,#4)} node [#2] {label};

which is what we wanted:

enter image description here

share|improve this answer
    
Yep, this solves it. I was hoping for some sort of ability to flush the path command so as to not deal with the \expandafters. –  Peter Grill May 3 '11 at 7:55
1  
@Peter: You could hide it a bit using some wizardry from pgfkeys. There's a method there to set a key having done a single expansion first. But however you dress it up, it boils down to expanding something before \addplot sees it. The principle behind it, I think, is that paths are quite "fluid" until they are finished so to enable complicated transformations and decorations, one wants to save the path as much "as is" as possible. You want to "half bake" it, which is possible but not via "high end" macros. –  Loop Space May 3 '11 at 9:12
    
Thanks. Interesting that the same problem does not happen when using just TikZ. I will look further into pgfkeys. –  Peter Grill May 3 '11 at 17:59
    
I am not sure I understand why this is considered "several times on a single path". How do I make them two separate paths? That was what I attempted to do with flushing the path, and would be my ideal solution. –  Peter Grill May 3 '11 at 23:42
    
@Peter: I don't know anything about pgfplots so don't know how it works. It might not be about the number of paths, maybe \addplot stores all its parameters and then executes them all in one go (the name, add plot suggests that it is adding something to a list). –  Loop Space May 4 '11 at 8:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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