链上范围:节点距离不起作用

链上范围:节点距离不起作用

我定义了几个命令,每个命令都会输出一堆 TikZ 节点,这些节点组合起来,在概念上代表单个节点/对象。为了将生成的节点视为一个整体,我将它们包装在一个范围内。

  • \instruction{identifier base}{text L}{text R}{box style}{length style}{scope style}
  • \twoPInstruction{identifier base}{text L}{textR}{box style}{len1}{len3}{scope style}

通过这些命令,我​​想创建链式图这些色彩鲜艳的指令块彼此相邻放置。
我得到的只是这张重叠的图画:
enter image description here

但我希望它们相邻对齐:(类似这样)
enter image description here
(我的渲染图周围的灰色轮廓和黑色方框是由 texmaker 的预览造成的)

我曾尝试调整 TikZ 的node distance样式,但无论我选择多远的距离,我都无法将橙色框与蓝色框分离。

这是我的(超长)MWE。不过,大部分都是样式;有趣的事情发生在\newcommands 和末尾附近\begin{tikzpicture}

\documentclass{standalone}

\usepackage{tikz}

\usetikzlibrary{arrows,decorations.pathmorphing,positioning,calc,matrix,fit,shapes.miscs,scopes,chains}

\tikzstyle{base}=[
    font={\sffamily\bfseries},
]
\tikzstyle{box}=[
    base,
    rounded rectangle,
    draw=black,
    inner sep=0.5ex,
]
\tikzstyle{boxL}=[
    box,
    rounded rectangle right arc=none,
]
\tikzstyle{boxR}=[
    box,
    rounded rectangle left arc=none,
]
\tikzstyle{inner}=[
    base,
    inner sep=0,
    node distance=0,
    line width=0,
]
\tikzstyle{innerL}=[
    inner,
    font={\small\sffamily\bfseries\color{white}},
]
\tikzstyle{innerR}=[
    inner,
    font={\small\sffamily\bfseries\color{black}},
]
\tikzstyle{innerLine}=[
    ->,
    dashed,
    dash pattern=on 0.25ex off 0.125ex,
    decorate,
    decoration={
        snake,
        amplitude=0.18ex,
        segment length=1ex,
        post length=0.5ex
    },
]
\tikzstyle{hop}=[
    ->,
    out=45,
    in=135,
    dashed,
    dash pattern=on 0.25ex off 0.125ex,
]
\tikzstyle{sep}=[
    inner,
    minimum width=1ex,
]

\tikzstyle{blue}=[
    fill=cyan,
]
\tikzstyle{orange}=[
    fill=orange,
]
\tikzstyle{len1}=[
    inner,
    text width=6ex,
]
\tikzstyle{len2}=[
    inner,
    text width=13ex,
]
\tikzstyle{len3}=[
    inner,
    text width=19ex,
]
\tikzstyle{len4}=[
    inner,
    text width=25ex,
]

\pgfdeclarelayer{box}
\pgfdeclarelayer{text}
\pgfsetlayers{box,text,main}

\newcommand{\baseInstruction}[7]{% id-base, text L, text R, color style, box style, length style, scope style
{[#7]
    \begin{pgfonlayer}{text}%box contents
        \node[#6] (#1 Skel) {};
        \node[innerL, right=of #1 Skel.base west, anchor=base west] (#1 SkelL) {#2};
        \node[innerR, left=of #1 Skel.base east, anchor=base east] (#1 SkelR) {#3};
        \node[inner, fit=(#1 SkelL.north east)(#1 SkelR.south west)] (#1 Between1) {};
        \node[inner, fit=(#1 SkelL.south east)(#1 SkelR.north west)] (#1 Between2) {};
        \node[inner, fit=(#1 Between1)(#1 Between2)] (#1 Between) {};
        \node[inner, fit=(#1 SkelL)(#1 SkelR)] (#1 Contents) {}; %needed for attaching arrows to
        \draw[innerLine] ($(#1 Between.west) + (0.2ex,0)$) -- ($(#1 Between.east) - (0.2ex,0)$);
    \end{pgfonlayer}
    \begin{pgfonlayer}{box}%box outlines
        \node[#5, #4, fit=(#1 SkelL)(#1 SkelR)] (#1) {};
    \end{pgfonlayer}
}
}

\newcommand{\instruction}[6]{% id-base, text L, text R, color style, length style, scope style
    \baseInstruction{#1}{#2}{#3}{#4}{box}{#5}{#6}
}

\newcommand{\instructionL}[6]{% id-base, text L, text R, color style, length style, scope style
    \baseInstruction{#1L}{#2}{#3}{#4}{boxL}{#5}{#6}
}

\newcommand{\instructionR}[6]{% id-base, text L, text R, color style, length style, scope style
    \baseInstruction{#1R}{#2}{#3}{#4}{boxR}{#5}{#6}
}

\newcommand{\twoPInstruction}[7]{% id-base, text L, text R, color style, length style L, length style R, scope style
{[#7]
    \instructionL{#1}{#2}{\vphantom{#3}}{#4}{#5}{}
    \begin{pgfonlayer}{text}%box contents   
        \node[sep, right=of #1L Skel.base east] (#1 Sep) {};
    \end{pgfonlayer}    
    \instructionR{#1}{\vphantom{#2}}{#3}{#4}{#6, right=of #1 Sep}{}
    \begin{pgfonlayer}{text}
        \draw ($(#1L Between.east) + (0,0.3ex)$) edge[hop] ($(#1R Between.west) + (0,0.3ex)$);
    \end{pgfonlayer}
}
}


\begin{document}


\begin{tikzpicture}[
    start chain,
    node distance=10cm,
    every child node/.style={on chain,join},
    every join/.style={->}
]
\instruction{a}{a}{X}{blue}{len2}{}
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{}
\end{tikzpicture}

\end{document}

答案1

首先,您需要包含scopes库以使范围简写正常工作。

其次,node distance仅适用于使用positioning等键放置的节点,right=of a您在此处不使用它们来将两个主节点相对于彼此定位。

因此,对代码最快的修复(包括之后scopes)是手动移动第二个节点:

\begin{tikzpicture}
  \instruction{a}{a}{X}{blue}{len2}{}
  \twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{xshift=2cm}
\end{tikzpicture}

此外,您可以考虑使用多部分节点,而不是手动绘制形状。

另一种选择是使用嵌套的tikzpicture,只有两个节点\node (a) {\tikz{...}};\node[right=of a] (b) {\tikz{...}};这样您就可以将两个“逻辑”节点用作“模块”,从而fit无需使用。

答案2

根据建议@Bordaigorl回答评论\instruction,我已经将和的主体包裹\twoPInstruction在节点和 tikzpictures 中。

\newcommand{\baseInstruction}[7]{% id-base, text L, text R, color style, box style, length style, scope style
{
    \begin{pgfonlayer}{text}%box contents
        \node[#6] (#1 Skel) {};
        \node[innerL, right=of #1 Skel.base west, anchor=base west] (#1 SkelL) {#2};
        \node[innerR, left=of #1 Skel.base east, anchor=base east] (#1 SkelR) {#3};
        \node[inner, fit=(#1 SkelL.north east)(#1 SkelR.south west)] (#1 Between1) {};
        \node[inner, fit=(#1 SkelL.south east)(#1 SkelR.north west)] (#1 Between2) {};
        \node[inner, fit=(#1 Between1)(#1 Between2)] (#1 Between) {};
        \node[inner, fit=(#1 SkelL)(#1 SkelR)] (#1 Contents) {}; %needed for attaching arrows to
        \draw[innerLine] ($(#1 Between.west) + (0.2ex,0)$) -- ($(#1 Between.east) - (0.2ex,0)$);
    \end{pgfonlayer}
    \begin{pgfonlayer}{box}%box outlines
        \node[#5, #4, fit=(#1 SkelL)(#1 SkelR)] (#1 Box) {};
    \end{pgfonlayer}
}}

\newcommand{\instruction}[6]{% id-base, text L, text R, color style, length style, scope style
\node [#6] (#1) {\tikz{
    \baseInstruction{#1}{#2}{#3}{#4}{box}{#5}{}
}};
}

\newcommand{\instructionL}[6]{% id-base, text L, text R, color style, length style, scope style
    \baseInstruction{#1L}{#2}{#3}{#4}{boxL}{#5}{#6}
}

\newcommand{\instructionR}[6]{% id-base, text L, text R, color style, length style, scope style
    \baseInstruction{#1R}{#2}{#3}{#4}{boxR}{#5}{#6}
}

\newcommand{\twoPInstruction}[7]{% id-base, text L, text R, color style, length style L, length style R, scope style
\node [#7] (#1) {\tikz{
    \instructionL{#1}{#2}{\vphantom{#3}}{#4}{#5}{}
    \begin{pgfonlayer}{text}%box contents   
        \node[sep, right=of #1L Skel.base east] (#1 Sep) {};
    \end{pgfonlayer}    
    \instructionR{#1}{\vphantom{#2}}{#3}{#4}{#6, right=of #1 Sep}{}
    \begin{pgfonlayer}{text}
        \draw[hop] ($(#1L Between.east) + (0,0.3ex)$) to[hop] ($(#1R Between.west) + (0,0.3ex)$);
    \end{pgfonlayer}
}};
}

reverse order

\begin{tikzpicture}[start chain, node distance=5ex, every join/.style={->},]
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{on chain, join}
\instruction{a}{a}{X}{blue}{len2}{on chain, join}
\end{tikzpicture}

但是反转ab最初在行上给了我一个错误\twoPInstruction:“!包 pgf 错误:没有已知的名为 chain-2 的形状。” ...“l.139 ...b}{Y}{orange}{len1}{len3}{on chain, join}”
为了解决这个问题,我不得不摆脱 in edgetwoPInstruction因为这会干扰链库。相反,我现在使用to[hop]。NB,我在一行中使用了hop两次样式(因为我很懒);一半的样式键应用于\draw行的一部分,而另一半应用于\to部分。

normal order

\begin{tikzpicture}[start chain, node distance=5ex, every join/.style={->},]
\instruction{a}{a}{X}{blue}{len2}{on chain, join}
\twoPInstruction{b}{b}{Y}{orange}{len1}{len3}{on chain, join}
\end{tikzpicture}

PS:我还从中删除了组样式([#7]),以\baseInstruction避免日志中出现警告。

相关内容