6

Motivated by this recent question, I tried to cook up a tikz based solution using the code provided in the answer to this question. More precisely, I tried to cook up equivalents of the pstricks \rnode and \ncline commands in tikz. This is what I got:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\newsavebox{\tempbox}

\newcommand{\tikznode}[2]{\relax\ifmmode\savebox{\tempbox}{\ensuremath{#2}}
\makebox[\wd\tempbox]{\tikz[overlay,remember picture,baseline=-0.8ex]%
 \node[minimum width=\wd\tempbox] (#1) {\ensuremath{#2}};}
\else\savebox{\tempbox}{#2}
\makebox[0.5\wd\tempbox]{\tikz[overlay,remember picture,baseline=-0.8ex,minimum width=\wd\tempbox]%
 \node[minimum width=\wd\tempbox] (#1) {#2};}\fi}

\tikzset{
    ncbar angle/.initial=-90,
    ncbar/.style={
        to path=(\tikztostart)
        -- ($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)
        -- ($(\tikztotarget)!($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztostart)$)
        -- (\tikztotarget)
    },
    ncbar/.default=0.5cm
}

\begin{document}
blabla \tikznode{A}{A}\tikznode{B}{B}\tikznode{C}{C} blabla
\tikznode{X}{X}\tikznode{Y}{Y}\tikznode{Z}{Z} blabla
\tikz[overlay,remember picture]{\draw[->] (A) to [ncbar=0.4] (X);}%
\tikz[overlay,remember picture]{\draw[->] (B) to [ncbar=0.5] (Y);}%
\tikz[overlay,remember picture]{\draw[->] (C) to [ncbar=0.6] (Z);}%
\end{document}

It produces:

enter image description here

which looks not completely unreasonable. However, it seems unreasonably complicated and I assume that there is a much more elegant and stable solution. For instance, I need to shift the baseline by hand using baseline=-0.8ex. This doesn't seem right. I also need to compute the width of the text and multiply it by an arbitrary factor of 0.5, which again appears odd. Last but not least, I have to distinguish between math and text modes. (Yes, I know that in principle there is \mathchoice that may be used, but I feel that I've chosen an unnecessarily complicated approach, so I refrained from building this in.) My question is if someone knows how to make this more elegant and, in particular, stable.

  • Why do you have to distinguish between text and math mode? \tikz works in both, and the mode of the text in the node isn't affected by the mode in which the \tikz is placed. – Torbjørn T. Nov 21 '17 at 21:35
  • @TorbjørnT. because I'd also like to use it in math mode. More precisely, if I type $\tikz{\node(x){x};}$, the x is not in math mode, but with $\tikznode{x}{x}$ it is. – marmot Nov 21 '17 at 21:42
6

I would probably do

\newcommand{\tikznode}[2]{%
\ifmmode%
\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$#2$};%
\else
\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {#2};%
\fi}

By setting the baseline to the base anchor of the node, you don't have to use some specific value. With inner sep=0pt you wont get any extra space around the text in the node.

Note also that I removed the overlay option. That option means that you get a zero-size bounding box, which you don't want here.

output of code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\tikznode}[2]{%
\ifmmode%
\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$#2$};%
\else
\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {#2};%
\fi}

\tikzset{
    ncbar angle/.initial=-90,
    ncbar/.style={
        to path=(\tikztostart)
        -- ($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)
        -- ($(\tikztotarget)!($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztostart)$)
        -- (\tikztotarget)
    },
    ncbar/.default=0.5cm
}

\begin{document}
blabla \tikznode{A}{A}$\tikznode{B}{B}$\tikznode{C}{C} blabla
\tikznode{X}{X}\tikznode{Y}{Y}\tikznode{Z}{Z} blabla
\begin{tikzpicture}[overlay,remember picture]
\draw[->] (A) to [ncbar=0.4] (X);
\draw[->] (B) to [ncbar=0.5] (Y);
\draw[->] (C) to [ncbar=0.6] (Z);
\end{tikzpicture}
\end{document}

If you want to implement \mathchoice in this, you get problems, because all the four different choices are typeset. Hence, the naive implementation of

\newcommand{\tikznode}[2]{%
\ifmmode%
\mathchoice
  {\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$\displaystyle #2$};}%
  {\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$\textstyle #2$};}%
  {\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$\scriptstyle #2$};}%
  {\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$\scriptscriptstyle #2$};}%
\else
\tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {#2};%
\fi}

doesnt't work, because the node name will always refer to the scriptscript-version, which isn't used at all in the three other styles. So for the example above, where the B is in textstyle, you get an arrow pointing out of the page.

Perhaps unsurprisingly though, someone has wondered about that problem before, and Heiko Oberdiek provided a solution to it in mathchoice and tikz's remember picture. The refmathstyle package he made has not yet been published on CTAN though, and the link to it in that answer is dead, so here is the non-package version:

output of below code

\documentclass{article}
\usepackage{tikz}
\usepackage{refcount}
\usetikzlibrary{calc}

% from https://tex.stackexchange.com/questions/122415/mathchoice-and-tikzs-remember-picture
\makeatletter
\newcounter{tikznode}
\renewcommand*{\thetikznode}{tikznode@\the\value{tikznode}}
\newcommand*{\tikznodestyle}{%
  \refused{\thetikznode}%
  \ifcase\getrefbykeydefault{\thetikznode}{}{0} %
    \displaystyle
  \or\textstyle
  \or\scriptstyle
  \or\scriptscriptstyle
  \fi
}
\newcommand{\tikznode}[2]{%
\ifmmode%
  \stepcounter{tikznode}%
  \mathchoice
  {\def\@currentlabel{0}\label{\thetikznode}}%
  {\def\@currentlabel{1}\label{\thetikznode}}%
  {\def\@currentlabel{2}\label{\thetikznode}}%
  {\def\@currentlabel{3}\label{\thetikznode}}%
  \tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {$\tikznodestyle #2$};
\else
  \tikz[remember picture,baseline=(#1.base),inner sep=0pt] \node (#1) {#2};%
\fi}
\makeatother

% from https://tex.stackexchange.com/questions/55068/is-there-a-tikz-equivalent-to-the-pstricks-ncbar-command
\tikzset{
    ncbar angle/.initial=-90,
    ncbar/.style={
        to path=(\tikztostart)
        -- ($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)
        -- ($(\tikztotarget)!($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztostart)$)
        -- (\tikztotarget)
    },
    ncbar/.default=0.5cm
}

\begin{document}
blabla
$\displaystyle\tikznode{A}{A}\textstyle\tikznode{B}{B}_{\tikznode{C}{C}_{\tikznode{D}{D}}}$
blabla
\tikznode{X}{X}\tikznode{Y}{Y}\tikznode{Z}{Z}\tikznode{W}{W}
blabla
\begin{tikzpicture}[overlay,remember picture]
\draw[->] (A) to [ncbar=0.4] (X);
\draw[->] (B) to [ncbar=0.5] (Y);
\draw[->] (C) to [ncbar=0.6] (Z);
\draw[->] (D) to [ncbar=0.6] (W);
\end{tikzpicture}
\end{document}
  • I wouldn't be surprised if there are a number of caveats I haven't considered, so it this is useless let me know, I can always delete it. – Torbjørn T. Nov 21 '17 at 21:47
  • That's a great trick, so please don't delete it. Do you want to post it also as an answer to this question? (Since even you are a bit struggling with the math mode, perhaps it's really worthwhile to build in \mathchoice.) – marmot Nov 21 '17 at 21:51
  • @marmot (I rarely/never dig in to lower-level stuff, so there is a lot I don't know.) I've never used \mathchoice, but you get some problems because all four options are typeset, meaning that the node names get overwritten. I can give an impractical workaround for that, I don't know if there are any good ones. – Torbjørn T. Nov 21 '17 at 22:07
  • @marmot By the way, \mathchoice has nothing to with distinguishing between text and math mode, which it seems like you think. – Torbjørn T. Nov 21 '17 at 22:12
  • Hmmh, I thought it would discriminate the different math modes \displaystyle, normal, \scriptstyle and \scriptscriptstyle. Probably I misinterpreted this post. Anyway, you're right, I have a hard time implementing it. – marmot Nov 21 '17 at 22:18

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.