3

I'm trying to draw the chart below, but I haven't found any solution to get the connection from "Option 1" and "Option 2" to a common child node "C".

enter image description here

I've tried my best using forest package, which resulted in the following MWE:

\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}

\begin{document}
\begin{forest}
    warn/.append style = {
        % rectangle,
        font = \sffamily\footnotesize\bfseries,
        % rounded corners = 2pt,
        % inner color = hsoorange, 
        % outer color = hsoorange
    },
    box/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = green,
        outer color   = green,
    },
    special/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = orange,
        outer color   = orange,
    },
    for tree = {
        font = \sffamily\footnotesize,
        l sep           = 0.6em,
        s sep           = 0.3em,
        minimum width   = 4.0em,
        line width    = 1pt,
        child anchor  = north,
        parent anchor = south,
        edge path={
            \noexpand\path[color=black, 
                % rounded corners=5pt,
                >={Stealth[length=10pt]}, 
                line width = 1pt, 
                -, 
                \forestoption{edge}
            ]
                (!u.parent anchor) -- +(0,-9pt) -| (.child anchor)\forestoption{edge label};
        },
    },
    forked edges,
    [Title, box
        [Option 1, box
            [A, box
                [, edge=dotted,
                    [cool, warn, edge=dotted]]
            ]
            [B, box
                [, edge=dotted
                    [not cool, warn, edge=dotted]]
            ]
            [C, special]
        ]
        [Option 2, box
            [X, box
                [, edge=dotted
                    [ok!, warn, edge=dotted]]
            ]
            [Y, box
                [1, box]
                [2, box]
                [3, box]
                [4, box]
            ]
            [Z, box]
        ]
    ]
\end{forest}
\end{document}

However, I was not able to have a common child node "C", and the edges leading to the comments on the last level are interrupted and not continous, which does not look so nice.

enter image description here

Please, could anyone provide me with a solution using forest, tree or native tikz?

Kind Regards

3

3 Answers 3

3

This is a modification of Alan Munn's answer, which aims to correct a slight misalignment of the fake edges and takes a slightly different approach to dealing with the three nodes at the bottom.

Here's a close-up of the misalignment. Notice the lines don't quite align and there is something odd about the arrow where it contacts C's neighbours.

misaligned somewhere?

Rather than increasing l, I use coordinates to take the three nodes to a lower level. I did this because I think it improves the spacing around the line to OK!. This node is created differently. Rather than creating it as a child of X, we create its parent as a child of Y and omit the edge.

We use conditional styling to format the tree, adding coordinate, dotted, edge=line, special and box on the basis of a series of tests. We also use a boolean to make this a bit easier for C. This boolean option has to be declared outside the forest environment - it can't be declared inside that environment. That is, declaring it is fine, but it doesn't work properly, so there's not much point.

I've also increased the distance between levels slightly to avoid the squashed look of the arrow heads. Obviously, you can adjust this as required.

% addaswyd o ateb Alun Munn: https://tex.stackexchange.com/a/693202/ i MWE George: https://tex.stackexchange.com/q/693152/ 
\documentclass[border=10pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta}
\tikzset{line/.style={draw,-Stealth}}
\forestset{declare boolean={my special}{0}}% declare a custom boolean option and set it to false by default
\begin{document}
\begin{forest}
  warn/.append style = {
    font = \sffamily\footnotesize\bfseries,
  },
  box/.append style = {
    rectangle,
    font = \sffamily\footnotesize\bfseries,
    draw          = black,
    align         = center,
    inner color   = green,
    outer color   = green,
  },
  special/.append style = {
    rectangle,
    font = \sffamily\footnotesize\bfseries,
    draw          = black,
    align         = center,
    inner color   = orange,
    outer color   = orange,
    child anchor  = 140,% set the anchor specially so we get symmetric points for the two connections from Option 1 and Option 2
    tikz+={% add in a fake edge from the node named 2's parent anchor to this node's 40 anchor
      \draw [every edge, line] (2.parent anchor) -- ++(0pt,-\forestoption{fork sep}) -| (.40);
    }
  },
  for tree = {
    font = \sffamily\footnotesize,
    l sep'           = 0.6em,
    s sep'           = 0.3em,
    minimum width   = 4.0em,
    line width    = 1pt,
    child anchor  = north,
    parent anchor = south,
    tier/.option=level,
    l sep*=2,
  },
  forked edges,
  box,
  before typesetting nodes={%
    for descendants={%
      if={> O_= O_= | {content}{}{!u.content}{}}
      {% if either the node or its parent has no content
        edge=dotted,
        if n children=0 {% if the node is a terminus
          edge=line 
        } {% if it isn't a terminus
          coordinate 
        }
      }{% if both the node and its parent have some conent
        edge=line,
        if={> {O} {my special} }%
        {% if the option 'my special' is set for the node
          special 
        }{% if that option isn't set
          box 
        }
      }
    },
  }
    [Title
      [Option 1
          [A
            [
              [cool, warn]
            ]
          ]
          [B, calign with current edge
              [
                [not cool, warn]
              ]
          ]
          [C, my special
          ]
        ]
        [Option 2, name=2
            [X]
            [Y 
                [1]
                [
                  [ok!, warn]
                ]
                [2]
                [3]
                [4]
            ]
            [Z]
        ]
    ]
\end{forest}
\end{document}

result

2
  • I bow to your superior forest foo, or foorest.
    – Alan Munn
    Aug 11, 2023 at 2:06
  • @AlanMunn I'm just addicted to the argument processor.
    – cfr
    Aug 11, 2023 at 3:37
2

Since this is no longer a tree, some manual intervention is required. The basic idea is to make a node with no edge and then manually draw the branches. I've used the ext.paths.ortho library to draw equivalent forked paths. Your path code wasn't doing what you wanted, so I've added a different way to add the arrows adapted from here

\documentclass[border=10pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows,ext.paths.ortho}
\tikzset{line/.style={draw,-Stealth}}
\begin{document}
\begin{forest}
    warn/.append style = {
        % rectangle,
        font = \sffamily\footnotesize\bfseries,
        % rounded corners = 2pt,
        % inner color = hsoorange, 
        % outer color = hsoorange
    },
    box/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = green,
        outer color   = green,
    },
    special/.append style = {
        rectangle,
        font = \sffamily\footnotesize\bfseries,
        draw          = black,
        align         = center,
        inner color   = orange,
        outer color   = orange,
    },

    for tree = {
        font = \sffamily\footnotesize,
        l sep           = 0.6em,
        s sep           = 0.3em,
        minimum width   = 4.0em,
        line width    = 1pt,
        child anchor  = north,
        parent anchor = south,
        edge=line,
  },forked edges,
    [Title, box
        [Option 1, box
            [A, box,tier=A
                    [cool, warn, edge=dotted,l=.75in]
            ]
            [B, box,name=B
                    [not cool, warn, edge=dotted,l=.75in]
            ]
        ]
        [C,special,no edge,tier=A,name=C,
        ]
        [Option 2, box
            [X, box,name=X,
                [ok!, warn, no edge,l=.75in,name=OK]
            ]
            [Y, box
                [1, box]
                [2, box]
                [3, box]
                [4, box]
            ]
            [Z, box]
        ]
    ]
\draw[-Stealth] (B.north) r-ud[ud distance=5.6pt] (C.130);
\draw[-Stealth] (X.north) r-ud[ud distance=5.6pt] (C.50);
\draw[-Stealth,dotted] (X.south) -- (OK.north);
\end{forest}
\end{document}

output of code

4
  • Thanks for the cite ;). There's something not quite right about the fake edges' alignment and the arrow heads' contact with those nodes?
    – cfr
    Aug 11, 2023 at 0:36
  • Do you use arrow to in fact?
    – cfr
    Aug 11, 2023 at 0:46
  • @cfr You're right, it doesn't need that code. I've removed it but left the link. :) As for the fake edges, I don't see any real issues, even at very high magnification. Looking at your answer, clearly not high enough...
    – Alan Munn
    Aug 11, 2023 at 1:59
  • That's interesting. Difference in PDF viewers? Maybe Okular just doesn't appreciate your code! It looked funny to me even without zooming, which prompted the zooming. So I'm not sure it's a magnification issue per se. I suspect your viewer will show it differently regardless. (Not sure if that's a point in its favour or against, so take your pick.)
    – cfr
    Aug 11, 2023 at 3:36
1

I dont know forest package, so I propose one code plain tikz:

\documentclass[border=.5cm]{standalone}
\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}
    %   \draw[gray!20] (-10,-4) grid (10,4);
        \filldraw[draw=black,fill=green] (-2,3) rectangle (2,4) node[pos=.5] (t) {\large Title};
        \filldraw[draw=black,fill=green] (-8,1) rectangle (-5,2) node[pos=.5] (o1) {\large Option1};
        \filldraw[draw=black,fill=green] (5,1) rectangle (8,2) node[pos=.5] (o2) {\large Option2};
        \draw[-latex] (0,3)--(0,2.5)--(-6.5,2.5)--(-6.5,2);
        \draw[-latex] (0,3)--(0,2.5)--(6.5,2.5)--(6.5,2);
        \draw (-6.5,1)--(-6.5,.5);
        \draw (-10,.5)--(-2.25,.5);
        \draw (10,.5)--(-1.25,.5);
        \draw[-latex] (-1.25,.5)--(-1.25,0);
        \draw[-latex] (-2.25,.5)--(-2.25,0);
        \draw[-latex] (-6.5,.5)--(-6.5,0);
        \draw[-latex] (-10,.5)--(-10,0);
        \filldraw[draw=black,fill=orange] (-2.75,-1) rectangle (-.75,0) node[pos=.5] () {\large C};
        \filldraw[draw=black,fill=green] (-11,-1) rectangle (-9.,0) node[pos=.5] () {\large A};
        \filldraw[draw=black,fill=green] (-7.5,-1) rectangle (-5.5,0) node[pos=.5] () {\large B};
        \draw (6.5,1)--(6.5,.5);
        \draw[-latex] (10,.5)--(10,0);
        \filldraw[draw=black,fill=green] (2,-1) rectangle (4,0) node[pos=.5] () {\large X};
        \filldraw[draw=black,fill=green] (5.5,-1) rectangle (7.5,0) node[pos=.5] () {\large Y};
        \filldraw[draw=black,fill=green] (9,-1) rectangle (11,0) node[pos=.5] () {\large Z};
        \draw[-latex] (6.5,.5)--(6.5,0);
        \draw[-latex] (3,.5)--(3,0);
        \draw (2,-2)--(7.4,-2);
        \draw (6.5,-1)--(6.5,-2);
        \draw[-latex] (2,-2)--(2,-2.4);
        \filldraw[draw=black,fill=green] (1.4,-3.6) rectangle (2.6,-2.4) node[pos=.5] () {\large 1};
        \draw[-latex] (3.8,-2)--(3.8,-2.4);
        \filldraw[draw=black,fill=green] (3.2,-3.6) rectangle (4.4,-2.4) node[pos=.5] () {\large 2};
        \draw[-latex] (5.6,-2)--(5.6,-2.4);
        \filldraw[draw=black,fill=green] (5,-3.6) rectangle (6.2,-2.4) node[pos=.5] () {\large 3};
        \draw[-latex] (7.4,-2)--(7.4,-2.4);
        \filldraw[draw=black,fill=green] (6.8,-3.6) rectangle (8,-2.4) node[pos=.5] () {\large 4};
        \draw[dashed] (-10,-1)--(-10,-5);
        \draw[gray,line width=3pt] (-10.5,-5)--(-9.5,-5) node[pos=.5,below] () {\bfseries cool};
        \draw[dashed] (-6.5,-1)--(-6.5,-5);
        \draw[gray,line width=3pt] (-7,-5)--(-6,-5) node[pos=.5,below] () {\bfseries not cool};
        \draw[dashed] (3,-1)--(3,-5);
        \draw[gray,line width=3pt] (2.5,-5)--(3.5,-5) node[pos=.5,below] () {\bfseries OK!};
    \end{tikzpicture}
\end{document}

Output:

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .