如何让 TikZ 在左子节点之前绘制右子节点

如何让 TikZ 在左子节点之前绘制右子节点

我正在尝试制作一棵树,其边缘有两种不同的颜色,黑色和灰色。这是我的代码:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata}
\definecolor{light-gray}{gray}{0.6}
\begin{document}
\begin{tikzpicture}[line width=.1cm,shorten >=0pt,auto,on grid=false, every state/.style={minimum size=0pt}, level distance=2.0cm, level 1/.style={sibling distance=2cm}, level 2/.style={sibling distance=1cm}, level 3/.style={sibling distance=.5cm}]
\tikzstyle{every node}=[font=\tiny , circle, outer sep=0pt, inner sep=0pt]
\node[] (S) {}
  child {node[state] (S1) {}
     child {node[state] (S11) {} edge from parent[light-gray] }
     child {node[state] (S12) {}}}
  child {node[state] (S2) {}
     child {node[state] (S21) {}}
     child {node[state] (S22) {} edge from parent[light-gray] }};
\end{tikzpicture}
\end{document}

您可以看到以下输出:

具有重叠边缘的 TikZ 树

问题是,我希望黑线位于灰线之上。这发生在左子树中,因为左边缘在右边缘之前绘制。然而,这并没有发生在右子树中。我希望右子树是左子树的镜像。它应该是这样的:

所需的 TikZ 树

我尝试改变灰色和黑色节点的顺序并尝试指定子节点的方向,如下所示:

     child[right] {node[state] (S22) {} edge from parent[light-gray] }
     child[left] {node[state] (S21) {}}};

和这个:

     child {node[state, right] (S22) {} edge from parent[light-gray] }
     child {node[state, left] (S21) {}}};

但它不起作用!

任何帮助,将不胜感激!

答案1

以下是两个快速解决方法:

代码 A 为路径运算符引入了一个修复程序edge to parent,该修复程序用作background edge开关将路径封闭在pgfonlayer环境中。

代码 B 使用\tikz@swap@growthgrow'交换方向。正如您的想法,您也需要交换子代(如果您在一行中有交替的黑/灰线,则此方法不起作用,它们仍然会一个接一个地绘制)。

代码A

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata,backgrounds}
\definecolor{light-gray}{gray}{0.6}
\makeatletter
\def\tikz@@edgetoparent[#1]{%
  \let\tikz@edge@to@parent@needed=\pgfutil@empty%
  \tikz@node@is@a@labeltrue%
  \begingroup
    \tikzset{edge from parent,#1}%
    \ifpgf@edge@background
      \edef\pgf@next{\noexpand\edef\noexpand\pgf@linewidth{\the\pgflinewidth}\noexpand\pgfutil@firstoftwo}
    \else
      \def\pgf@next{\pgfutil@secondoftwo}
    \fi
    \pgfmath@smuggleone\pgf@next
  \endgroup
  \pgf@next{\pgfonlayer{background}\path[style=edge from parent,line width/.expanded=\pgf@linewidth,#1] \tikz@edge@to@parent@path;\endpgfonlayer\tikz@scan@next@command}%
  {\tikz@scan@next@command [style=edge from parent,#1] \tikz@edge@to@parent@path}%
}
\newif\ifpgf@edge@background
\tikzset{background edge/.is if=pgf@edge@background}
\makeatother

\begin{document}
\begin{tikzpicture}[line width=.1cm,shorten >=0pt,auto,on grid=false, every state/.style={minimum size=0pt}, level distance=2.0cm, level 1/.style={sibling distance=2cm}, level 2/.style={sibling distance=1cm}, level 3/.style={sibling distance=.5cm}]
\tikzstyle{every node}=[font=\tiny , circle, outer sep=0pt, inner sep=0pt]
\node[] (S) {} 
  child {node[state] (S1) {}
     child {node[state] (S11) {} edge from parent[background edge,light-gray] }
     child {node[state] (S12) {}}
  }
  child {node[state] (S2) {}
     child {node[state] (S21) {}}
     child {node[state] (S22) {} edge from parent[background edge,light-gray] }
  };
\end{tikzpicture}
\end{document}

代码 B

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata}
\definecolor{light-gray}{gray}{0.6}
\makeatletter
\tikzset{swap grow direction/.style={every child/.append code=\tikz@swap@growth}}
\makeatother
\begin{document}
\begin{tikzpicture}[line width=.1cm,shorten >=0pt,auto,on grid=false, every state/.style={minimum size=0pt}, level distance=2.0cm, level 1/.style={sibling distance=2cm}, level 2/.style={sibling distance=1cm}, level 3/.style={sibling distance=.5cm}]
\tikzstyle{every node}=[font=\tiny , circle, outer sep=0pt, inner sep=0pt]
\node[] (S) {}
  child {node[state] (S1) {}
     child {node[state] (S11) {} edge from parent[light-gray] }
     child {node[state] (S12) {}}}
  child[swap grow direction] {node[state] (S2) {}
     child {node[state] (S22) {} edge from parent[light-gray] }
     child {node[state] (S21) {}}};
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案2

在我看来,改变 TikZ 路径读取和处理的顺序是徒劳的。因此,快速修复方法是将内容发送到背景层。这需要暂停当前路径,并引入父节点路径(我不确定这一点,一定有更简洁的方法,但我现在想不通)。无论如何,要传递图形参数,您可以在样式键中保留自定义设置的副本,并在需要时应用。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,automata,backgrounds}
\definecolor{light-gray}{gray}{0.6}
\begin{document}
\begin{tikzpicture}[
my style/.style={line width=.1cm,shorten >=0pt,auto,on grid=false},
my style, 
every state/.style={minimum size=0pt}, 
level distance=2.0cm, 
level 1/.style={sibling distance=2cm}, 
level 2/.style={sibling distance=1cm}, 
level 3/.style={sibling distance=.5cm},
every node/.style={font=\tiny , circle, outer sep=0pt, inner sep=0pt},
my edge/.style={edge from parent path={
    \pgfextra{%
    \begin{pgfonlayer}{background}
    \draw[my style,#1] (\tikzparentnode\tikzparentanchor) -- (\tikzchildnode\tikzchildanchor);
    \end{pgfonlayer}
  }
}
}]
\node[] (S) {}
  child {node[state] (S1) {}
     child {node[state] (S11) {} edge from parent[light-gray] }
     child {node[state] (S12) {}}
     child {node[state] (S11) {} edge from parent[my edge=light-gray] }}
  child {node[state] (S2) {}
     child {node[state] (S21) {}}
     child {node[state] (S22) {} edge from parent[my edge=light-gray] }
     child {node[state] (23) {}}};
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容