4

Based on this hierarchical diagram in tikz using the forest package, i wanted a modified version of it. Currently i have

\documentclass[tikz,border=10pt]{standalone}
\usepackage{verbatim}
\usepackage{forest}

\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}

% colors
\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col6in}{blue!20}
\colorlet{col6out}{blue!30}
\colorlet{col7out}{orange}
\colorlet{col7in}{orange!50}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}

\begin{document}
\pgfkeys{/forest,
  rect/.append style   = {rectangle, rounded corners = 2pt,
                         inner color = col6in, outer color = col6out},
  ellip/.append style  = {ellipse, inner color = col5in,
                          outer color = col5out},
  orect/.append style  = {rect, font = \sffamily\bfseries\LARGE,
                         text width = 325pt, text centered,
                         minimum height = 10pt, outer color = col7out,
                         inner color=col7in},
  oellip/.append style = {ellip, inner color = col8in, outer color = col8out,
                          font = \sffamily\bfseries\large, text centered}}

\begin{forest}
    for tree={
        font=\sffamily\bfseries,
      line width=1pt,
      draw=linecol,
      ellip,
      align=center,
            child anchor=north,
      parent anchor=south,
            drop shadow,
            l sep+=12.5pt,
            edge path={
        \noexpand\path[color=linecol, rounded corners=5pt,
          >={Stealth[length=10pt]}, line width=1pt, ->, \forestoption{edge}]
          (!u.parent anchor) -- +(0,-5pt) -|
          (.child anchor)\forestoption{edge label};
        },
            where level={3}{tier=tier3}{},
            where level={0}{l sep-=15pt}{},
            where level={1}{
        if n={1}{
          edge path={
            \noexpand\path[color=linecol, rounded corners=5pt,
              >={Stealth[length=10pt]}, line width=1pt, ->,
              \forestoption{edge}]
              (!u.west) -| (.child anchor)\forestoption{edge label};
            }
                }{
          edge path={
            \noexpand\path[color=linecol, rounded corners=5pt,
              >={Stealth[length=10pt]}, line width=1pt, ->,
              \forestoption{edge}]
              (!u.east) -| (.child anchor)\forestoption{edge label};
            },
        }
            }{}
    }
    [Light Detection and Ranging\\LiDAR, inner color=col1in, outer color=col1out
    [Scanning, inner color=col2in, outer color=col2out
      [Spinning head\\with single-spot\\sensors, inner color=col4in, outer color=col4out]
      [Moving mirrors/\\prisms, inner color=col4in, outer color=col4out
                [Rotating/oscillating\\macro mirrors/prisms, inner color=col8in, outer color=col8out]
                [Oscillating MEMS\\mirror, inner color=col8in, outer color=col8out]
            ]
      [Optical phased-\\arrays, inner color=col4in, outer color=col4out]
    ]
    [Non-scanning (staring), inner color=col2in, outer color=col2out
      [Fixed (multi-)\\beam, inner color=col4in, outer color=col4out]
      [Diffuse light cone\\ ``FLASH'' LiDAR, inner color=col4in, outer color=col4out]
        ]
    ]
\end{forest}

\end{document}

what produces enter image description here

As you can see the connection at second level is not optimized for three children. The "moving mirrors/prisms" ellipse is really bad connected to its parent "Scanning".

The forest documentation is not really helpful on this topic, as far as i can see. How can i set level options, so that everything is the same, but the ellipse in middle is directly connected "south" to its parent?

2 Answers 2

4

It may be easily overlooked in the docs, but forest has the option calign ('child alignment') that solves your issue. When I understand you correctly, you want to position the children to the 'Scanning' node such that the second node is centered.

This is done by adding options calign=child, calign child=2 to the parent node. (See §3.7.2, "Node position", of the forest documentation).

If you wanted to set this automatically, you could use the if n children=3 syntax.

with calign

\documentclass[tikz,border=10pt]{standalone}
\usepackage{verbatim}
\usepackage{forest}

\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}

% colors
\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col6in}{blue!20}
\colorlet{col6out}{blue!30}
\colorlet{col7out}{orange}
\colorlet{col7in}{orange!50}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}

\begin{document}
\pgfkeys{/forest,
  rect/.append style   = {rectangle, rounded corners = 2pt,
                         inner color = col6in, outer color = col6out},
  ellip/.append style  = {ellipse, inner color = col5in,
                          outer color = col5out},
  orect/.append style  = {rect, font = \sffamily\bfseries\LARGE,
                         text width = 325pt, text centered,
                         minimum height = 10pt, outer color = col7out,
                         inner color=col7in},
  oellip/.append style = {ellip, inner color = col8in, outer color = col8out,
                          font = \sffamily\bfseries\large, text centered}}

\begin{forest}
    for tree={
        font=\sffamily\bfseries,
      line width=1pt,
      draw=linecol,
      ellip,
      align=center,
            child anchor=north,
      parent anchor=south,
            drop shadow,
            l sep+=12.5pt,
            edge path={
        \noexpand\path[color=linecol, rounded corners=5pt,
          >={Stealth[length=10pt]}, line width=1pt, ->, \forestoption{edge}]
          (!u.parent anchor) -- +(0,-5pt) -|
          (.child anchor)\forestoption{edge label};
        },
            where level={3}{tier=tier3}{},
            where level={0}{l sep-=15pt}{},
            where level={1}{
        if n={1}{
          edge path={
            \noexpand\path[color=linecol, rounded corners=5pt,
              >={Stealth[length=10pt]}, line width=1pt, ->,
              \forestoption{edge}]
              (!u.west) -| (.child anchor)\forestoption{edge label};
            }
                }{
          edge path={
            \noexpand\path[color=linecol, rounded corners=5pt,
              >={Stealth[length=10pt]}, line width=1pt, ->,
              \forestoption{edge}]
              (!u.east) -| (.child anchor)\forestoption{edge label};
            },
        }
            }{}
    }
    [Light Detection and Ranging\\LiDAR, inner color=col1in, outer color=col1out
    [Scanning, inner color=col2in, outer color=col2out,calign=child, calign child=2
      [Spinning head\\with single-spot\\sensors, inner color=col4in, outer color=col4out]
      [Moving mirrors/\\prisms, inner color=col4in, outer color=col4out
                [Rotating/oscillating\\macro mirrors/prisms, inner color=col8in, outer color=col8out]
                [Oscillating MEMS\\mirror, inner color=col8in, outer color=col8out]
            ]
      [Optical phased-\\arrays, inner color=col4in, outer color=col4out]
    ]
    [Non-scanning (staring), inner color=col2in, outer color=col2out
      [Fixed (multi-)\\beam, inner color=col4in, outer color=col4out]
      [Diffuse light cone\\ ``FLASH'' LiDAR, inner color=col4in, outer color=col4out]
        ]
    ]
\end{forest}

\end{document}
3
  • Thanks a lot, that definitely helped me! Just to clarify calign=child, defines what the central aligned child should be, then calign child=2 sets the second child as primary child? So there are always both needed and calign=2 would not work? Jan 17, 2019 at 14:47
  • calign child=n defines the primary child node to be the n th one. Unfortunately I can't give you any details on the internal placement algorithm, but as I understand forest the primary node is the one that is placed directly under (or above, if that is your grow= value) the parent. And then calign=child says that the parent should be aligned to a specific child. Otherwise, if you set calign=midpoint, the parent will be horizontally placed not to a specific child, but to the mid distance between primary and secondary child. Jan 17, 2019 at 16:27
  • Oh i see, thanks for clarifying! The documentation is not that detailed on that points in my opinion. Jan 18, 2019 at 7:01
1

Another alternative is use before computing xy={s/.average={s}{siblings}} at node "Moving mirrors/\prisms". With some effort to make your MWE shorter and (to my taste nicer), the MWE is:

\documentclass[tikz,border=10pt]{standalone}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta, calc, shadows, shapes.geometric}
% colors
\colorlet{linecol}{blue!60}

\begin{document}

\begin{forest}
    for tree={
E/.style = {ellipse, draw=linecol, line width=1pt,
            inner color=#1!15, outer color=#1!45, % nodes color
            inner xsep=-1pt, font=\sffamily\bfseries,
            align=center, drop shadow}, % nodes style with parameter for color
 child anchor = north,
parent anchor = south,
        s sep = 4mm,    % "sibling distance"
        l sep = 8mm,    % "level distance"
         edge = {draw=linecol, line width=1pt, -{Stealth[length=7pt]}, % common style for all edges
                 rounded corners},
    edge path = {\noexpand\path[\forestoption{edge}]
          (!u.parent anchor) -- + (0,-4mm) -| (.child anchor);},
            where level={2}{tier=tier2}{},% nodes on the level 2
                                          % (from top) are vertically aligned
                                          % on the top is level 0
            where level={1}{
        if n={1}{edge path={\noexpand\path[\forestoption{edge}]
              (!u.west) -| (.child anchor);}
                }{edge path={\noexpand\path[\forestoption{edge}]
              (!u.east) -| (.child anchor);},
                    }
                            }{}% end of level 1
                }% end for tree
    [LiDAR\\ (Light Detection\\and Ranging), E=red
        [Scanning, E=green
            [Spinning head with\\single-spot sensors, E=teal]
            [Moving mirrors/\\prisms, E=teal,
             before computing xy={s/.average={s}{siblings}}
             % or calign=child, calign child=2
                [Rotating/oscillating\\macro mirrors/prisms, E=orange]
                [Oscillating MEMS\\mirror, E=orange]
          ]
            [Optical phased-\\arrays, E=teal]
        ]
        [Non-scanning\\ (staring), E=green
              [Fixed (multi-)\\beam, E=teal]
              [Diffuse light cone\\ ``FLASH'' LiDAR, E=teal]
        ]
    ]
\end{forest}

\end{document}

enter image description here

Used colors of nodes you can change according to your wishes.

3
  • Yeah im still new here, should've made my example a lot shorter, sorry. Thank you for the code, its much more structured and commented, i start to understand now whats going on in there. :D Jan 18, 2019 at 7:05
  • @ThomasNeubauer, you are welcome. however, you still stick with other solution :-)
    – Zarko
    Jan 18, 2019 at 11:00
  • @ThomasNeubauer, i add some more comments to used code in my answer.
    – Zarko
    Jan 18, 2019 at 11:31

You must log in to answer this question.

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