5

I'm trying to make a tree with two different colors of edges, black and gray. This is my code:

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

You can see the output below:

TikZ Tree with overlapping edges

The problem is, I want the black lines to be on top of the gray lines. This is happening in the left subtree, because the left edge is drawn before the right one. However, this is not happening in the right subtree. I want the right subtree to be a mirror image of the left subtree. This is what it should look like:

Desired TikZ Tree

I tried changing the order of the gray and black nodes and trying to specify the direction of the children, like this:

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

and this:

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

but it doesn't work!

Any help would be appreciated!

3

Here are two quick fixes:

Code A introduces a fix for the edge to parent path operator that uses background edge as a switch to enclose the path in a pgfonlayer environment.

Code B uses \tikz@swap@growth which is used by grow' to swap the directions. As in your idea, you need to switch the children, too (this won’t work if you have alternating black/gray lines in a row, they are still drawn after each other).

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

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

Output

enter image description here

3

Changing the order of TikZ path reading and handling is, in my opinion a lost cause. So a quick fix can be sending things to the background layer. That requires the current path to be paused and a parent to node path should be introduced (I'm not sure about this, there must be a cleaner way but I can't think straight now). Anyway to pass the graphical parameters you can keep a copy of your custom settings in a style key and apply whereever needed.

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

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.