5

I'm trying to make a tree of a corporate structure starting at some owner, and ending with a single company. This means that all lines start at a single node, and all ends at a single node.

This thread helped me to where I am: LaTeX: how to make a horizontal tree that is closed at the end (forest), but I end up with lines through my nodes. As I will be doing this repetitively (many different corporate structures) I'm looking for a structural solution.

\documentclass{standalone}
\usepackage{forest}
\forestset{
  default preamble={
    for tree={rectangle, draw, text width = 2cm, grow=0 }
  }
}
\begin{document}
\begin{forest} 
    [Company 4, name =E0
        [Company 3
            [Company 2, name = E1]
        ]
        [Company 5, name = E2]
        [Company 8
            [Company 7, name=E3]
            [Company 10, name = E4]
        ]
    ]
    \node[draw] (EndNode) at ($(E3.east) + (2,0)$){Company 1};
    \foreach \num in {0,1,2,3, 4}{
        \draw (E\num.east) -- (EndNode.west);
    }
\end{forest}
\end{document}

Tree at this stage

Minor other issue on the side : how to center the text within these boxes?

1
  • Welcome! Can you edit your code so we can copy-paste-compile it? That's a lot more helpful than a fragment (albeit a pretty hefty fragment). What you want is not strictly a tree but a generic graph and, out-of-the-box, Forest only does trees. So some hackery is necessary. What do you mean by a 'structural solution?
    – cfr
    Aug 23, 2017 at 16:10

2 Answers 2

6

This is a reasonably automatic solution. It changes the style of the edges, but I prefer squared edges here anyway. It is minimally tested, so let me know if it doesn't quite work as is. (I'm bound to have forgotten something.)

The tricky part is to connect the root node to the additional terminus. That takes a bit of trickery.

\documentclass[border=10pt]{standalone}
\usepackage[edges]{forest}
\tikzset{%
  company/.style={draw, text width = 2cm},
}
\forestset{%
  declare keylist register={terminus},
  terminus=,
  terminal/.style={
    tikz+={
      \node (terminal) [company, anchor=west] at ([xshift=2*\foresteoption{l sep}]current bounding box.east) {#1};
    },
    before drawing tree={
      split register={terminus}{,}{terminal connection},
    },
  },
  terminal connection/.style={
    tikz+={
      \draw (terminal.west) -- ++(-\foresteoption{fork sep},0pt) |- (#1.parent anchor)  ;
    },
  },
  default preamble={
    forked edges,
    for tree={
      company,
      grow=0,
      fit=band,
      parent anchor=children,
      child anchor=parent,
    },
    delay={
      if={>On>{!r.n children}{1}}{
        for n/.process={OSw+P?_lw2+n{n children}{isodd(#1)}{1}{0}{(#1+#2)/2}{insert after={[,coordinate, calign with current edge]}}},
      }{
        append={[, coordinate, calign with current]}
      },
    },
    before typesetting nodes={
      where n children=0{
        terminus/.option=name,
      }{},
    },
  },
}
\begin{document}
\begin{forest}
  terminal=Company 1,
  [Company 4
        [Company 3
            [Company 2]
        ]
        [Company 5]
        [Company 8
            [Company 7]
            [Company 10]
        ]
  ]
\end{forest}
\end{document}

closed Forest

The nice thing about separating the TikZ setting from the Forest configuration is that you can easily apply the same style to nodes in the tree and outside it, without needing to specify a special path for the key.

For example, to centre the text in nodes as desired, change the company style definition to

\tikzset{%
  company/.style={draw, text width = 2cm, text centered,
}

centred text

or, for something fancier, try

\usetikzlibrary{shadows.blur}
\tikzset{%
  company/.style={draw, text width = 2cm, text centered, rounded corners, font=\sffamily, top color=gray!5, bottom color=gray!15, blur shadow},
}

fancier style

1
  • bravo! (+1), i need more practice :-(
    – Zarko
    Aug 23, 2017 at 17:59
4

enter image description here

do you liked? mwe:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usepackage{forest}

\begin{document}
\forestset{
  default preamble={
    for tree={rectangle, draw, text width=22mm, inner sep=2mm,
              text centered,
              grow  = 0,
              s sep = 11mm,
              l sep = 7mm }
  }
}
\begin{forest}
    [Company 4, name =E0
        [Company 3
            [Company 2, name = E1]
        ]
        [Company 5, name = E2]
        [Company 8
            [Company 7, name=E3]
            [Company 10, name = E4]
        ]
    ]
    \node[draw, right=of E3.east |- E2] (EndNode) {Company 1};
    \foreach \num in {1,2,3, 4}{
        \draw (E\num.east) -- (EndNode.west);
                                }
    \draw (E0) edge [bend angle=20,bend right] (EndNode.west);
\end{forest}
\end{document}
2
  • Forest practise is paying off :-).
    – cfr
    Aug 23, 2017 at 17:30
  • Thanks to the both of you! Looks good and is exactly what I was looking for.
    – Gijs
    Aug 24, 2017 at 13:00

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.