Tikz 相当于 PSTricks 命令 ncbar 和 rnode

Tikz 相当于 PSTricks 命令 ncbar 和 rnode

动机这个最近问题tikz,我尝试使用答案中提供的代码来编写一个基于解决方案这个问题。更准确地说,我尝试编写与 中的pstricks \rnode\ncline命令等效的命令tikz。这是我得到的:

\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}

它产生:

在此处输入图片描述

这看起来并非完全不合理。但是,它似乎过于复杂,我认为存在更优雅、更稳定的解决方案。例如,我需要使用 手动移动基线baseline=-0.8ex。这似乎不对。我还需要计算文本的宽度并将其乘以任意因子 0.5,这再次显得很奇怪。最后但并非最不重要的一点是,我必须区分数学和文本模式。(是的,我知道原则上可以\mathchoice使用,但我觉得我选择了一种不必要的复杂方法,所以我没有将其内置。)我的问题是是否有人知道如何使其更优雅,特别是更稳定。

答案1

我可能会这么做

\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}

通过将基线设置为base节点的锚点,您不必使用某些特定值。这样inner sep=0pt您就不会在节点中的文本周围获得任何额外的空间。

还请注意,我删除了该overlay选项。该选项意味着您将获得一个零大小的边界框,而这并非您想要的。

代码输出

\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}

如果你想实现\mathchoice这个,你会遇到问题,因为所有四个不同的选择都是排版的。因此,简单的实现

\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}

不起作用,因为节点名称将始终引用脚本版本,而在其他三种样式中根本不使用。因此,对于上面的示例,当B在 textstyle 中时,您将获得一个指向页面外的箭头。

不过,也许并不令人意外的是,之前有人曾想过这个问题,Heiko Oberdiek 在mathchoice 和 tikz 的记忆图片refmathstyle不过,他制作的软件包尚未在 CTAN 上发布,并且该答案中的链接已失效,因此这里是非软件包版本:

下面的代码输出

\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}

答案2

由于它被埋在 Torbjørn 的答案的评论中,因此这只是为了指出这现在是tikzmark包,并正确处理不同的数学模式。以下是演示:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/402462/86}
\usepackage{tikz}
\usetikzlibrary{tikzmark,calc}

\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 \tikzmarknode{A}{A}\(\tikzmarknode{B}{B}^{\tikzmarknode{C}{C}}\) blabla
\tikzmarknode{X}{X}\tikzmarknode{Y}{Y}\tikzmarknode{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}

tikzmarknode 不同数学模式的演示

C从到 的线条Z是有角度的,因为节点的底部处于不同的水平。我不知道原始 PSTricksncline在这种情况下会做什么,所以我保留了 Torbjørn 答案中的代码。

相关内容