3

How can I accomplish the following things?

  • Nodes need to be same size.
  • Get rid of thicker lines caused by overlapping.
  • Get the finished state below state (aligned).

enter image description here

\documentclass[11pt]{article}
\usepackage{lscape}
\usepackage{pdflscape}
\usepackage{tikz}
\usepackage{tikz-qtree}

\begin{document}
\begin{landscape}
\begin{tikzpicture}
\tikzset{edge from parent/.style=
{draw,
edge from parent path={(\tikzparentnode.south)
-- +(0,-8pt)
-| (\tikzchildnode)}}}
\Tree 
[.\node[draw]{State}; 
    [.\node[draw]{StandingUp};]
    [.\node[draw]{Searching}; 
        [.\node[draw, text width=25mm, align=center, text height=3mm]{SearchRotate};] 
        [.\node[draw, text width=25mm, align=center, text height=3mm]{Detecting};] 
    ]
    [.\node[draw]{Finished};]
    [.\node[draw]{Approaching}; 
        [.\node[draw]{Walking};]
        [.\node[draw]{ApproachRotate};]
    ]
    [.\node[draw]{Fallen};]
]
\end{tikzpicture}
\end{landscape}
\end{document}
3
  • Welcome! Are you joined at the hip to tikz-qtree? It would be easy in Forest, for example. For the sizing, you need to apply a standard text width, text depth and text height to all nodes if they should all have the same size. – cfr Jun 1 '16 at 2:30
  • @cfr I'm free to use any other packages ;) Can you provide an example? It might help other people as well. – user1534664 Jun 1 '16 at 2:31
  • Sure. Forest can also calculate the correct values for the width, depth and height which makes the structure of the tree more compact/efficient. (And Forest can do very compact trees, if that's what you want.) See below for a very compact and a spacier version. – cfr Jun 1 '16 at 3:03
3

This first solution requires Forest v.2 or later. If you have an earlier version and cannot update, see below for an alternative which works with v.1.

Here's a Forest solution. The code parses the tree to determine the maximum depth, width and height of the nodes' contents. These values are then used to set the text width, text depth and text height for all nodes in the tree. The edges Forest library is used for the forked edges option.

Once the sizes are standardised, the middle child automatically aligns with its parent.

\documentclass[tikz,multi,border=10pt]{standalone}
\usepackage[edges]{forest}
\begin{document}
\begin{forest}
  forked edges,
  for tree={
    draw,
    text centered,
  },
  before typesetting nodes={
    tempdima/.max={width(content())}{root,tree},
    tempdimb/.max={height(content())}{root,tree},
    tempdimc/.max={depth(content())}{root,tree},
    for tree={
      text width/.register=tempdima,
      text height/.register=tempdimb,
      text depth/.register=tempdimc,
    }
  }
  [State
      [StandingUp]
      [Searching
          [SearchRotate]
          [Detecting]
      ]
      [Finished]
      [Approaching
          [Walking]
          [ApproachRotate]
      ]
      [Fallen]
  ]
\end{forest}
\end{document}

Forest tree solution

If a less compact tree is desired, add fit=rectangle or fit=band to the options for the tree. For example,

\begin{forest}
  forked edges,
  for tree={
    draw,
    text centered,
    fit=band,
  },
  before typesetting nodes={
    tempdima/.max={width(content())}{root,tree},
    tempdimb/.max={height(content())}{root,tree},
    tempdimc/.max={depth(content())}{root,tree},
    for tree={
      text width/.register=tempdima,
      text height/.register=tempdimb,
      text depth/.register=tempdimc,
    }
  }
  [State
      [StandingUp]
      [Searching
          [SearchRotate]
          [Detecting]
      ]
      [Finished]
      [Approaching
          [Walking]
          [ApproachRotate]
      ]
      [Fallen]
  ]
\end{forest}

produces a tree which is spread out further

spacier tree

EDIT (for Forest v.1)

It is a bit more work to do this with earlier versions of Forest and the way I've done it requires a few TeX dimensions, but similar results are certainly possible:

trees with Forest v.1

The main problem is not the lack of the edges library - this can easily be emulated - but the complications caused by the lack of registers, introduced in v.2, and the need to substitute for the .max handler.

Code:

\documentclass[tikz,multi,border=10pt]{standalone}
\usepackage{forest}
\newdimen\statenodeswidth
\newdimen\statenodesheight
\newdimen\statenodesdepth
\forestset{%
  declare dimen={node width}{0pt},
  declare dimen={node height}{0pt},
  declare dimen={node depth}{0pt},
  declare dimen={nodes width}{0pt},
  declare dimen={nodes height}{0pt},
  declare dimen={nodes depth}{0pt},
  my forked edges/.style={
    for tree={
      edge path={
        \noexpand\path [\forestoption{edge}] (!u.parent anchor) -- ++(0,-5pt) -| (.child anchor)\forestoption{edge label};
      },
      parent anchor=south,
      child anchor=north,
    },
  },
  state tree/.style={
    my forked edges,
    for tree={
      draw,
      text centered,
    },
    before typesetting nodes={
      for tree={
        node width/.pgfmath={width(content())},
        node height/.pgfmath={height(content())},
        node depth/.pgfmath={depth(content())},
        if={node_width()>\statenodeswidth}{
          TeX/.wrap pgfmath arg={\statenodeswidth=##1pt}{node_width()}
        }{},
        if={node_height()>\statenodesheight}{
          TeX/.wrap pgfmath arg={\statenodesheight=##1pt}{node_height()}
        }{},
        if={node_depth()>\statenodesdepth}{
          TeX/.wrap pgfmath arg={\statenodesdepth=##1pt}{node_depth()}
        }{},
      },
      delay={
        for tree={
          text width=\statenodeswidth,
          text height=\statenodesheight,
          text depth=\statenodesdepth,
        }
      }
    }
  }
}
\begin{document}
\begin{forest}
  state tree,
  for tree={
    fit=band,
  }
  [State
      [StandingUp]
      [Searching
          [SearchRotate]
          [Detecting]
      ]
      [Finished]
      [Approaching
          [Walking]
          [ApproachRotate]
      ]
      [Fallen]
  ]
\end{forest}
\begin{forest}
  state tree,
  [State
      [StandingUp]
      [Searching
          [SearchRotate]
          [Detecting]
      ]
      [Finished]
      [Approaching
          [Walking]
          [ApproachRotate]
      ]
      [Fallen]
  ]
\end{forest}
\end{document}
8
  • Thanks, it looks great! am I supposed to modify tempdima, tempdimb and tempdimc? I'm currently getting errors when compiling it: sharelatex.com/project/574e44b00c338a4e540774e1 – user1534664 Jun 1 '16 at 3:26
  • Possibly ShareLaTeX only has version 1 of Forest, whereas this code needs version 2. Do you know which version of TeX Live they're using? I'd know for sure if this is the problem if you say which error you get. (The first one is usually what matters.) – cfr Jun 1 '16 at 13:07
  • @user1534664 Yes, ShareLaTeX has an old version of Forest: (/usr/local/texlive/2015/texmf-dist/tex/latex/forest/forest.sty Package: forest 2015/07/15 v1.0.10 Drawing (linguistic) trees. – cfr Jun 1 '16 at 13:16
  • I'm using sharelatex cause I'm working in a group, so I can't really go with texmaker for example. But I'll just use your diagram as an image. Perhaps less ideal but it's okay ;) Thanks a lot for your help. – user1534664 Jun 1 '16 at 13:31
  • 1
    @user1534664 Please see edit above for a version which works with Forest v.1. Hopefully, this should work with ShareLaTeX. – cfr Jun 1 '16 at 20:44

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.