Lost in the Forest -- Merging after Branching?
Here's my take on the diagram. Rather than use matrix of nodes
I've used nodes multipart
.
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,arrows,shapes.multipart,shapes.geometric,arrows.meta}
\tikzset{multi/.style={
rectangle split,rectangle split horizontal, rectangle split parts=6,align=center,
text width=2cm,
draw=black!15!yellow,
fill=yellow!20}
}
\begin{document}
\begin{tikzpicture}[rounded corners,very thick,-Stealth]
\node(A) [draw=black!15!green,very thick,fill=green!30,minimum height=1cm,rounded corners] {Full Data Set};
\node(B) [multi,below=1cm of A]{%
Middle
\nodepart{two}
Bottom\\Support
\nodepart{three}
Bottom\\Carry
\nodepart{four}
Bottom\\Other
\nodepart{five}
Top
\nodepart{six}
Jungle
};
\node(C)[circle,draw=purple!70!blue,below=1 cm of B,fill=purple!30] {EFA};
\node(D)[multi,below=1cm of C]{%
Middle
\nodepart{two}
Bottom\\Support
\nodepart{three}
Bottom\\Carry
\nodepart{four}
Bottom\\Other
\nodepart{five}
Top
\nodepart{six}
Jungle
};
\node(E)[diamond,draw=purple!70!blue,below=of D,fill=purple!30,sharp corners={}] {L/R};
\foreach \x in {one,two,three,four,five,six}{
\draw(A.south) -- ++(0,-1.5ex) -| (B.\x\space north);
\draw(B.\x\space south) -- ++(0,-4.ex) -| (C.north);
\draw(C.south) -- ++(0,-1.5ex) -| (D.\x\space north);
\draw(D.\x\space south) -- ++(0,-4.ex) -| (E.north);
}
\end{tikzpicture}
\end{document}
This is not a tree. Hence, it is not necessarily wise to choose forest
as the means to draw it. Where only slight deviations from a tree are involved, forest
can make good sense. But this diagram involves more deviance than non-deviance, so forest
isn't the best option.
Nonetheless, if you do wish to use the package to draw a non-tree for some reason, I would certainly try to do it using forest
's facilities within a single picture.
I present two solutions. The first uses a matrix of nodes
. The second uses forest
.
Matrix
The idea is to draw the yellow boxes using a matrix and then to use the names those nodes get automatically to place the remaining three nodes. Because the matrix's nodes are automatically named in a systematic way, it is then easy to loop through and draw the arrows.
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, positioning, matrix, shapes.geometric}
\begin{document}
\begin{tikzpicture}[thick, >/.tip=Stealth, my node/.style={font=\sffamily, draw, fill=#1!15, thick}]
\matrix (m) [matrix of nodes, every node/.append style={my node=yellow, minimum height=7ex, anchor=center, text centered, text width=15mm}]
{
Middle & Bottom support & Bottom carry & Bottom other & Top & Jungle \\[15ex]
Middle & Bottom support & Bottom carry & Bottom other & Top & Jungle \\
} ;
\node (r) [above=7.5ex of m-1-3.north east, anchor=center, my node=green] {Full data set};
\node (e) [above= 7.5ex of m-2-3.north east, anchor=center, my node=red, circle] {EPA};
\node (t) [below= 7.5ex of m-2-3.south east, anchor=center, my node=red, diamond] {LR};
\begin{scope}[rounded corners, ->]
\foreach \i in {1,...,6} {
\draw (r.south) -- ++(0,-1.5ex) -| (m-1-\i.north);
\draw (e.south) -- ++(0,-1.5ex) -| (m-2-\i.north);
\draw (m-1-\i.south) -- ++(0,-1.5ex) -| (e.north);
\draw (m-2-\i.south) -- ++(0,-1.5ex) -| (t.north);
}
\end{scope}
\end{tikzpicture}
\end{document}
Forest
In this case, the yellow layer is repeated, so it seems a shame not to use forest
's facility for copying bits of trees from one place to another. repeat aunts
is a style which repeats all of a node's aunts as children of that node. join aunts
joins a node to all of its aunts. not a tree
just sets the style of the tree: colouring by level and so on. I just didn't know what to call it, so not a tree
did.
The upshot is that
\begin{forest}
not a tree,
[Full data set
[Middle]
[Bottom\\support]
[Bottom\\carry]
[
[EPA, repeat aunts, join aunts [ [LR, join aunts]]]
]
[Bottom\\other]
[Top]
[Jungle]
]
\end{forest}
produces the following non-tree result
Complete code:
\documentclass[border=10pt]{standalone}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta}
\forestset{
declare keylist={copy list a}{},
declare keylist={copy list b}{},
declare keylist={join list}{},
not a tree/.style={
forked edges,
for tree={
edge+={thick, rounded corners, -Stealth},
thick,
draw,
font=\sffamily,
align=c,
parent anchor=children,
child anchor=parent,
anchor=parent,
l sep'+=10pt,
fork sep'+=5pt,
},
where level=0{fill=green}{ if={> O_= {!u.n children}{1}} {fill=pink, circle}{fill=yellow}, },
delay={ where content={}{phantom, before computing xy={tempdima/.min={>O{min y}}{siblings}, l-/.register=tempdima }}{} },
},
repeat aunts/.style={
before typesetting nodes={tempkeylista'=, tempkeylistb'=, for nodewalk={fake=u,siblings}{%append={[, phantom]},
if={ > OOw+n< {n}{!u.n children}{(##1+1)/2}}{ tempkeylista/.option=name }{ tempkeylistb/.option=name }
}, copy list a/.register=tempkeylista, copy list b/.register=tempkeylistb, split option={copy list a}{,}{prepend'}, split option={copy list b}{,}{append'} }
},
join aunts/.style={
before drawing tree={
tempkeylista'=,
for nodewalk={fake=u, siblings}{tempkeylista/.option=name},
join list/.register=tempkeylista,
tikz+/.process={ OOw2 {join list} {fork sep} { \draw [thick, rounded corners, Stealth-]\foreach \i in {##1} { (.child anchor) -- ++(0,##2) -| (\i.parent anchor) }; } },
}
}
}
\begin{document}
\begin{forest}
not a tree,
[Full data set
[Middle]
[Bottom\\support]
[Bottom\\carry]
[
[EPA, repeat aunts, join aunts [, phantom[LR, join aunts]]]
]
[Bottom\\other]
[Top]
[Jungle]
]
\end{forest}
\end{document}
EDIT: I leave my original answer only to show how much better @cfr's answer is. This is clearly the winner.
ORIGINAL FOREST ANSWER (DON'T USE IT!!!): It is possible to do that using Ulrike Fischer's trick, yet it requires some adjustments since tikzmark
's \subnode
command is not really designed for that application.
\documentclass{article}
\usepackage{forest}
\usetikzlibrary{shadows.blur,arrows.meta,positioning}
\usetikzlibrary{tikzmark} % subnode trick from https://tex.stackexchange.com/a/393656/121799
\tikzset{yellowbox/.style={fill=yellow},
greenbox/.style={fill=green,rounded corners=3pt},
purplecirc/.style={fill=purple!30,circle}}
\begin{document}
\begin{center}
\begin{forest}
for tree={
font=\sffamily\bfseries,
line width=2pt,
draw=black, % adds the border to all nodes
align=center,
child anchor=north,
parent anchor=south,
blur shadow,
l sep+=12.5pt,
s sep=0.1cm,
edge={rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt},
edge path={
\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- +(0,-10pt) -|
(.child anchor)\forestoption{edge label};
},
where level={1}{minimum width=2cm,yellowbox,text width=1.3cm,align=center}{},
}
[Full data set,greenbox
[\subnode{t1}{Middle\vphantom{p}}]
[Bottom\\ \subnode{t2}{support}]
[Bottom\\ \subnode{t3}{carry}]
[Bottom\\ \subnode{t4}{other\vphantom{p}}]
[\subnode{t5}{Top}]
[\subnode{t6}{Jungle}]]
\end{forest}\\[1.5cm]
\begin{forest}
for tree={
font=\sffamily\bfseries,
line width=2pt,
draw=black, % adds the border to all nodes
align=center,
child anchor=north,
parent anchor=south,
blur shadow,
l sep+=12.5pt,
s sep=0.1cm,
edge={rounded corners=5pt, -{Stealth[length=10pt]}, line width=1pt},
edge path={
\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- +(0,-10pt) -|
(.child anchor)\forestoption{edge label};
},
where level={1}{minimum width=2cm,yellowbox}{},
}
[\subnode{EPA}{EPA},purplecirc
[\subnode{b1}{Middle\vphantom{p}}]
[Bottom\\ \subnode{b2}{support}]
[Bottom\\ \subnode{b3}{carry}]
[Bottom\\ \subnode{b4}{other\vphantom{p}}]
[\subnode{b5}{Top}]
[\subnode{b6}{Jungle}]]
\end{forest}\\[2cm]
\end{center}
\begin{tikzpicture}[overlay,remember picture]
\node[below=3.2cm of EPA,fill=purple!30,diamond,draw,line width=2pt,blur
shadow](LR){LR};
\foreach \X in {1,...,6}
{
\draw[{Stealth[length=10pt]}-,line width=1.2pt,rounded corners] ([yshift=6pt]EPA.north) -- ++(0,18pt) -| (t\X.south);
\draw[{Stealth[length=10pt]}-,line width=1.2pt,rounded corners] (LR.north) -- ++(0,18pt) -| (b\X.south);
}
\end{tikzpicture}
\end{document}
EDIT: Since all the experts are saying that it might be advantageous not to use forest here, I add a plain TikZ solution. It is certainly less fragile than the forest solution.
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{shapes.geometric,shadows.blur,positioning,arrows.meta}
\tikzset{yellowbox/.style={fill=yellow,minimum height=0.8cm},
greenbox/.style={fill=green,rounded corners=3pt,minimum height=18pt},
purplecirc/.style={fill=purple!30,circle}}
\begin{document}
\begin{tikzpicture}[
sibling distance=2cm,
level distance=2.2cm,
every node/.style = {
align=center,blur shadow,draw,line width=1pt,rounded corners=3pt,
},edge from parent path=
{(\tikzparentnode.south) -- ++(0,-14pt) -| (\tikzchildnode.north)},
edge from parent/.style={draw,-{Stealth[length=10pt]},line width=1.2pt,rounded corners}]
%
\node[greenbox] (fds) {Full data set}
child {
node[yellowbox] {Middle}
}
child {
node[yellowbox] {Bottom\\ support}
}
child {
node[yellowbox] {Bottom\\ carry}
}
child {
node[yellowbox] {Bottom\\ other}
}
child {
node[yellowbox] {Top}
}
child {
node[yellowbox] {Jungle}
};
%
\node[below=3.6cm of fds,purplecirc] (EPA) {EPA}
child {
node[yellowbox] {Middle}
}
child {
node[yellowbox] {Bottom\\ support}
}
child {
node[yellowbox] {Bottom\\ carry}
}
child {
node[yellowbox] {Bottom\\ other}
}
child {
node[yellowbox] {Top}
}
child {
node[yellowbox] {Jungle}
};
%
\node[below=3.6cm of EPA,fill=purple!30,diamond](LR){LR};
%
\foreach \X in {1,...,6}
{
\draw[{Stealth[length=10pt]}-,line width=1.2pt,rounded corners] (EPA.north) --
++(0,16pt) -| (fds-\X.south);
\draw[{Stealth[length=10pt]}-,line width=1.2pt,rounded corners] (LR.north) --
++(0,16pt) -| (EPA-\X.south);
}
\end{tikzpicture}
\end{document}