为什么 \begin{scope} 内的节点名称在外部仍然可见?

为什么 \begin{scope} 内的节点名称在外部仍然可见?

以下示例绘制了三个矩形,每个矩形分为两部分(它们是 Lisp cons 单元)。它工作正常,但似乎有些不对劲:我在宏\begin{scope}内部使用了\cons,并且在该宏内部我有两个名为a和 的节点b。但是,如果我在宏外部使用名称 和 ,事情就会变得混乱。这两个名称和 不应该a对文档的其余部分不可见吗?bab\begin{scope}

该示例运行良好,但更改aaa等则会暴露问题。

有没有更好或更简单的方法来完成我想做的事情?

更新:所以,名称无论如何都是全局定义的……我想\cons在同一张图片中多次使用宏——如果节点名称是全局的,这似乎行不通。那我该怎么办?我应该只使用相对定位而不给节点任何名称吗?这是唯一的方法吗?

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes,positioning}

\begin{document}

\newcommand{\cons}{%
\begin{tikzpicture}[cell/.style={draw,shape=rectangle,minimum size=0.4cm}]
\begin{scope}
\node[cell](a)[anchor=west]{};
\node[cell](b)[right=0mm of a.east,anchor=west]{};
\end{scope}
\end{tikzpicture}
}

\begin{tikzpicture}
\node(aa){\cons};
\node(bb)[below left=of aa]{\cons};
\node(cc)[below right=of aa]{\cons};
\draw[->,red]  (aa.west) -| (bb.north);
\draw[->,blue] (aa.east) -| (cc.north);
\end{tikzpicture}

\end{document}

答案1

您可以使用现成的多部分节点形状。

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart,positioning}

\begin{document}


\begin{tikzpicture}[twocell/.style={draw,
                                    rectangle split, 
                                    rectangle split horizontal,
                                    rectangle split parts=2
                                   }
]
\node[twocell](aa){};
\node[twocell](bb)[below left=of aa]{};
\node[twocell](cc)[below right=of aa]{};
\draw[->,red]  (aa.west) -| (bb.north);
\draw[->,blue] (aa.east) -| (cc.north);
\end{tikzpicture}

\end{document}

在此处输入图片描述

答案2

杰伊,我不会回答你最初的问题,因为 Percusse 已经回答了,但是你在评论中提出了一个问题:如何让 cons 变圆角。

(我不确定是否应该在那里提出“关注”问题并回答。让我们看看版主怎么看)

正如 Percusse 所建议的,解决方案很棘手。您可以使用未绘制的多部分矩形,并使用append after command选项在每个部分上绘制圆角矩形。在这里,您将找到使用此选项的几个答案。特别是,我从中获取了代码向简单的 TikZ 图表添加新符号“命令后附加”和“插入路径”的问题。我不明白为什么命令\pgfextra是必要的,但它确实有效。

下面是:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes.multipart,positioning}

\begin{document}
\begin{tikzpicture}[%
cons/.style={%
    rectangle split,%
    rectangle split horizontal,%
    rectangle split parts=2,%
   outer sep=0pt,%
    append after command={%
    \pgfextra{%
     \draw[rounded corners=3pt] (\tikzlastnode.south west)      
          rectangle (\tikzlastnode.one split north);%
     \draw[rounded corners=3pt] (\tikzlastnode.north east)   
          rectangle (\tikzlastnode.one split south);}}}]
\node[cons](aa){};
\node[cons](bb)[below left=of aa]{};
\node[cons](cc)[below right=of aa]{};
\draw[->,red]  (aa.west) -| (bb.north);
\draw[->,blue] (aa.east) -| (cc.north);
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

append after command由于使用without ,因此可以简化代码pgfextra

您需要使用path选项创建一个draw,然后使用选项将节点添加到路径中cons。使用此方法,您可以避免使用\draw内部“在命令后附加” 。

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart,positioning}

\begin{document}
\begin{tikzpicture}[%
cons/.style={%
    rectangle split,%
    rectangle split horizontal,%
    rectangle split parts=2,%
    outer sep=0pt,%
    append after command={%
     [rounded corners=3pt] (\tikzlastnode.south west)  rectangle (\tikzlastnode.one split north)
                           (\tikzlastnode.north east)  rectangle (\tikzlastnode.one split south)  
          }}]
\path [draw] node[cons](aa){};
\path [draw] node[cons](bb)[below left=of aa]{};
\path [draw] node[cons](cc)[below right=of aa]{};

\draw[->,red]  (aa.west) -| (bb.north);
\draw[->,blue] (aa.east) -| (cc.north);  
\end{tikzpicture}
\end{document}  

在此处输入图片描述

答案4

针对 Ignasi 所说的他不知道\pgfextra是什么,它会暂停路径解析或跟踪,以便可以执行任意代码。否则,这是有风险的或不可能的。我在下面演示了任意代码的使用。

经过长时间的跟踪,我发现使用时\pgfextra必须避免使用虚假空格,例如 后面的空格\pgfextra{。这些空格不会在内部被删除。Ignasi 在他的解决方案中正确地做到了这一点,但很容易被忽视。我希望 PGF 开发人员稍后会在内部处理这个问题。与此同时,当\pgfextra的参数出现时at end node,可以使用以下解决方案。

编辑:我在下面提供完整的代码以回应 Altermundus 的评论。

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.multipart,positioning}
\makeatletter
% If we load pgfkeyx.sty, we can normalize the list before parsing.
% Well, let's ignore difficult lists here.
% Using the delimiter \pgfeov for the callback of \pgfkeyscommaloop allows it 
% to be multi-parametered.
\def\pgfkeyscommaloop#1#2{\pgfkeys@commaloop{#1}#2,\pgfkeyscommaloop,}
\def\pgfkeys@commaloop#1#2,{%
  \expandafter\ifx\@car#2x\@nil\pgfkeyscommaloop
    \expandafter\@gobble\else\expandafter\@iden\fi
  {#1#2\pgfeov\pgfkeys@commaloop{#1}}%
}
\def\ifpgfkeydef#1{%
  \ifcsname pgfk@#1/.@cmd\endcsname
    % OK, the command is already in the hash table; no safeguard needed
    % against filling the hash.
    \expandafter\ifx\csname pgfk@#1/.@cmd\endcsname\relax
      \expandafter\expandafter\expandafter\@secondoftwo
    \else
      \expandafter\expandafter\expandafter\@firstoftwo
    \fi
  \else
    \expandafter\@secondoftwo
  \fi
}
\def\pgfkey@def@do#1\pgfeov{\ifpgfkeydef{#1}{-1}{+0}}
\def\pgfkey@undef@do#1\pgfeov{\ifpgfkeydef{#1}{+0}{-1}}
% Given a list of keys, I want to know if at least one of them is defined:
\def\ifonepgfkeydef#1{%
  \ifnum\numexpr\z@\pgfkeyscommaloop\pgfkey@def@do{#1}<\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
% Given a list of keys, I want to know if at least one of them is undefined:
\def\ifonepgfkeyundef#1{%
  \ifnum\numexpr\z@\pgfkeyscommaloop\pgfkey@undef@do{#1}<\z@
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi
}
\ifonepgfkeydef{/tikz/at end of node,/tikz/at end node}{%
  \@latexerr{Key(s) '/tikz/at end of node' and/or
    '/tikz/at end node' already exist}\@ehd
}{}

% The following acrobatics is just an academic exercise: Altermundus's approach
% is simpler and better:
\tikzset{at end of node/.code=
  \begingroup
  \def\pgf@@relax{\relax}%
  \pgfkeys@spdef\reserveda{#1}%
  \def\reservedb##1\pgfextra##2##3\pgf@nil{%
    \ifx\pgf@@relax##2\else
      \pgfkeys@spdef\reservedb{##2}%
      \def\reservedc##1\pgfextra\pgf@@relax{##1}%
      \edef\reserveda{\unexpanded{##1}\noexpand\pgfextra{\unexpanded
      \expandafter{\reservedb}}\unexpanded\expandafter{\reservedc##3}}%
    \fi
  }%
  \expandafter\reservedb\reserveda\pgfextra\pgf@@relax\pgf@nil
  \edef\reserveda{\endgroup
    \noexpand\pgfkeysalso{append after command=%
    {\unexpanded\expandafter{\reserveda}}}%
  }\reserveda
  ,
  at end node/.style={at end of node={#1}}
}
\def\minorrect#1#2#3{%
  \draw[rounded corners=#1] (\tikzlastnode.#2)
    rectangle (\tikzlastnode.one split #3);
}
\makeatother

\begin{document}
\begin{tikzpicture}[cons/.style={%
  rectangle split,
  rectangle split horizontal,
  rectangle split parts=2,
  outer sep=0pt,
  at end of node={
    \pgfextra{
      \minorrect{3pt}{south west}{north}%
      \minorrect{10pt}{north east}{south}%
    }%
  }%
}%
]
\node[cons](aa){};
\node[cons](bb)[below left=of aa]{};
\node[cons](cc)[below right=of aa]{};
\draw[->,red]  (aa.west) -| (bb.north);
\draw[->,blue] (aa.east) -| (cc.north);
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容