如何有条件地将标签节点插入 TikZ 路径?

如何有条件地将标签节点插入 TikZ 路径?

梅威瑟:

\documentclass[border = 10pt]{standalone}

\usepackage{ifthen}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}[every node/.style = {align = center}]
    \newcounter {lfpnode}
    \coordinate (LFP) at (0,0);
    \newcommand {\drawaline} [3] {
        \ifthenelse{\equal{#2}{}}
            {\def\tdsdabovespec{}}
            {\def\tdsdabovespec{node[above] \unexpanded{{#2}}}}

        \coordinate (LFPS) at ($(LFP) - (0,{#1})$);
        \ifthenelse{\equal{#3}{}} {
            \def\tdsdnewLFP{LFPS}
            \def\tdsdbelowspec{}
        }{
            \edef\tdsdlfpnode{LFPN\arabic{lfpnode}}
            \def\tdsdnewLFP{0,0 |- \tdsdlfpnode.south}
            \def\tdsdbelowspec{node[below] (\tdsdlfpnode) \unexpanded{{#3}}}
        }

            % this doesn't work
            \def\tdsddataflowspec{[blue] (0,0 |- LFPS) -> \tdsdabovespec \tdsdbelowspec (5,0 |- LFPS)}
            \expandafter\draw\tdsddataflowspec;

            % neither does this, although I didn't expect it to
            \draw [blue] (0,0 |- LFPS) -> \tdsdabovespec \tdsdbelowspec (5,0 |- LFPS);

        \coordinate (LFP) at (\tdsdnewLFP);
        \stepcounter{lfpnode}
    }

    \newcommand {\drawalineone} [1] {
        \def\tdsdnewLFP{LFPS}
        \coordinate (LFPS) at ($(LFP) - (0,{#1})$);

            \draw [blue] (0,0 |- LFPS) -> node[above] {ABOVE1-1\\ABOVE1-2} (5,0 |- LFPS);

        \coordinate (LFP) at (\tdsdnewLFP);
        \stepcounter{lfpnode}
    }

    \newcommand {\drawalinetwo} [1] {
        \coordinate (LFPS) at ($(LFP) - (0,{#1})$);
        \edef\tdsdlfpnode{LFPN\arabic{lfpnode}}
        \def\tdsdnewLFP{0,0 |- \tdsdlfpnode.south}

            \draw [blue] (0,0 |- LFPS) -> node[above] {ABOVE2-1} node[below]
                (\tdsdlfpnode) {BELOW2-1} (5,0 |- LFPS);

        \coordinate (LFP) at (\tdsdnewLFP);
        \stepcounter{lfpnode}
    }

    \newcommand {\drawalinethree} [1] {
        \coordinate (LFPS) at ($(LFP) - (0,{#1})$);
        \edef\tdsdlfpnode{LFPN\arabic{lfpnode}}
        \def\tdsdnewLFP{0,0 |- \tdsdlfpnode.south}

            \draw [blue] (0,0 |- LFPS) -> node[below] (\tdsdlfpnode) {BELOW3-1\\BELOW3-2} (5,0 |- LFPS);

        \coordinate (LFP) at (\tdsdnewLFP);
        \stepcounter{lfpnode}
    }

    % The following causes errors aplenty:
    %    "Cannot parse this coordinate."
    %    "A node must have a (possibly empty) label text."
    %    "Giving up on this path. Did you forget a semicolon?"
    % \drawaline{0}     {ABOVE1-1\\ABOVE1-2} {}
    % \drawaline{1.3cm} {ABOVE2-1} {BELOW2-1}
    % \drawaline{1cm}   {} {BELOW3-1\\BELOW3-2}

    % Works!
    \drawalineone{0}
    \drawalinetwo{1.3cm}
    \drawalinethree{1cm}
\end{tikzpicture}
\end{document}

总体思路很简单:\drawaline画一条线并接受三个参数。如果第二个参数非空,则在线上方出现一个标签。如果第三个参数非空,则在线下方出现一个标签。

线条的垂直间距使得当前正在渲染的线条与之前渲染的线条的最低点(包括标签,如果存在)之间出现由第一个参数定义的空间。这对于 MWE 来说并不重要,但我还是将其包括在内,因为它是代码在原始上下文中的使用方式,并且它可能会影响哪些修复是可能的。

、和宏是 的硬编码版本。它们按预期运行。实际的宏没有。请注意,当(以及)被或 替换时,中使用的任何\drawalineone一种方法都不起作用。简而言之,我不知道如何让 TikZ 将后面的内容识别为可解析的 TikZ 路径规范。\drawalinetwo\drawalinethree\drawaline\drawaline\drawaline\unexpanded{{#2}}#3{#2}\begingroup #2\endgroup\draw

最后,请注意\drawaline必须接受多行标签。

任何帮助,将不胜感激。

答案1

我不确定是否理解了您的目的---但如果我正确理解了您的描述,我会尝试简化它。

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usepackage{ifthen}
\newcommand\drawline[3]{
    % the position of the line is #1 below the previous line
    % it is not accounting for the (not typeset yet) above box
    \path (lastline) ++(0,{-(#1)}) coordinate(thisline);
    % draw the line and mark midway
    \draw (thisline) -- ++(5,0) coordinate[pos=0.5](midline);
    % if we have the box above, draw it
    \ifthenelse{\equal{#2}{}}{}{\node[above, align=center] at (midline) {#2};}
    % if we have the box below, type it. Either case, re-set
    % the (lastline) position accordingly
    \ifthenelse{\equal{#3}{}}
        {\coordinate(lastline) at (thisline);}
        {\node[below, align=center](tmp) at (midline) {#3};
        \coordinate(lastline) at (thisline|-tmp.south);}
}

\begin{document}
\begin{tikzpicture}[]
    \coordinate (lastline) at (0,0);
    \drawline{0}{Only \\ above}{}
    \drawline{2}{Either \\ above}{Or \\ below}
    \drawline{1}{}{Only \\ below}
\end{tikzpicture}
\end{document}

在此处输入图片描述

考虑到上面文本块的大小,为了指定文本之间的距离而不是线条之间的距离,会稍微复杂一些,但并非不可能......

答案2

也许不是完整的解决方案,但也许是一个方向。我尝试使用您的一个代码示例并对其进行了一点增强:

    \newcommand {\drawalinetwo} [3] {
    \coordinate (LFPS) at ($(LFP) - (0,{#1})$);
    \edef\tdsdlfpnode{LFPN\arabic{lfpnode}}
    \def\tdsdnewLFP{0,0 |- \tdsdlfpnode.south}

        \draw [blue] (0,0 |- LFPS) -- node[above] {#2} node[below]
            (\tdsdlfpnode) {#3} (5,0 |- LFPS);

    \coordinate (LFP) at (\tdsdnewLFP);
    \stepcounter{lfpnode}
}

使用命令

\drawalinetwo{1cm}{}{BELOW2-1}
\drawalinetwo{1cm}{ABOVE2-1}{}
\drawalinetwo{1cm}{ABOVE2-1}{BELOW2-1}

我明白了:

在此处输入图片描述

相关内容