[Tex/LaTex] How to set the TikZ label anchor explicitly

labelsnodespositioningtikz-pgf

I want to add a label to a node, but "inside" the node. Something like this:

desired output

The manual seems to indicate it might be possible, although no actual key is named.

The … anchor point for the label node … is determined in such a
way that the label node will “face away” from the border of the main
node. The anchor that is chosen depends on the position of the border
point that is chosen and its position relative to the center of the
main node and on whether the transform shape option is set. In
general, the choice should be what you would expect, but you may have
to set the anchor yourself in difficult situations.
(emph. added)

But when I try an example like this:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\tikz \node [circle,draw,label={[red,anchor=north]above:X}] {my circle};
\end{document}

I don't get any change in the position of the label node. It's still "outside."

actual output

Any ideas?

Best Answer

The problem here is that TikZ applies some automatication (namely the \tikz@auto@anchor macro) that will overwrite your set anchor.

We can either hijack a .code key that is applied very last in the node that is used internally for the label (yes, even after our own settings red, anchor=north) and which calls \tikz@auto@anchor:

\tikzset{label anchor/.style={tikz@label@post/.append style={anchor=#1}}}

or we let the macro that does the calculations relax a little bit (no additional key needed):

\tikzset{anchor/.append code=\let\tikz@auto@anchor\relax}

If the new and improved anchor key is now used more globally (say \tikz[anchor=<dir>]) it will also affects the nodes (and there is currently now way to get it back).

I also provide a key inside (you can even use it twice to reverse the effect).

Code

\documentclass[tikz]{standalone}
\usepackage{etoolbox}
\makeatletter
\tikzset{anchor/.append code=\let\tikz@auto@anchor\relax}
\tikzset{inside/.code=\preto\tikz@auto@anchor{\pgf@x-\pgf@x\pgf@y-\pgf@y}}
\makeatother
\begin{document}
\tikz\node [anchor=west, circle,draw,label={[red, anchor=north]above:X}] {my circle};
\tikz\node [anchor=west, circle,draw,label={[red, inside]below:X}] {my circle};
\end{document}

Output

enter image description here

enter image description here