4

Consider answer of Gonzalo Medina on question decision trees in TikZ. For my learning process proposes I slightly modified it:

\documentclass[tikz,multi,border=5pt]{standalone}
\usepackage{forest}

\tikzset{
EL/.style={%Edge Labels
  midway,
  #1,% <--- position: "EL=above" or "EL=below"
  font=\scriptsize\sffamily,
  text=teal,
  text width=1.5cm,
  align=center,
            }
}

\begin{document}
%%%% modified version
\begin{forest}
for tree={
  grow=east,
  draw=teal,
  circle,
  line width=0.4pt,
  parent anchor=east,
  child anchor=west,
  edge={draw=teal,very thin},
%  edge label={\Huge\color{black}}, % <-- this seems to haven't any influence on tree
  edge path={
    \noexpand\path[\forestoption{edge}]
      (!u.parent anchor) -- 
      ([xshift=-17mm].child anchor) -- % intermediate point
      (.child anchor)\forestoption{edge label};
  },
  l sep=19mm,            % <-- *l*: level distance
}
[,rectangle, 
  s sep=8mm,            % <-- *s*: sibling distance
  [,edge label={node[EL=below]{option1}}
    [,edge label={node[EL=below]{a longer text goes here}}
    ]
    [,edge label={node[EL=above]{text}}
    ]
  ]
  [B,edge label={node[EL=above]{option2}}
    [,edge label={node[EL=below]{a longer text goes here}}
    ]
    [,edge label={node[EL=above]{text}}
    ]
  ]
]
\end{forest}
    \end{document}

Why decision tree become asymmetric regarding to horizontal symmetry line through nodes, if I add some test in nodes? For example, at node B the next level upper branches have smaller distance from center horizontal line through node than lower one. I tested this with forest 2.0.

enter image description here

  • You are right about the edge label doing nothing, by the way. I'm slightly surprised it doesn't give an error, but it certainly shouldn't do anything else. – cfr Feb 16 '16 at 22:36
  • chat.stackexchange.com/rooms/34850/… (It is not really a discussion between me and crocket. The room has been hijacked and I've been discussing Forest 2 there with Sašo Živanović. It is a little one-sided today, but has been much more interesting over the weekend.) – cfr Feb 16 '16 at 23:03
2

This is a solution. The documentation is rather misleading since it isn't true the the value of anchor only matters when the node has a sibling.

[However, it is not saying what my earlier version of this answer claimed. So if you read that, I was being an idiot and you should ignore it.]

The default value of calign is center which aligns the parent's anchor with the midpoint between the children's anchors. And the default value of anchor is base.

Here's a picture:

default alignment demo

So the alignment we'd like requires either changing the anchor of the parent and children or using a non-default value for calign.

In the first case, we could do something like this, setting anchor=center for the tree:

anchor=center

or anchor=parent (i.e. west in this case):

anchor=parent

or anchor=children (i.e. east) here:

anchor=children

The anchor children always faces the children of the node (or where the children would be); parent faces the parent of the node (or where the parent would be).

Alternatively, we could alter calign. For example calign=edge midpoint. However, this doesn't work quite as I expected:

align midpoints of edges

I can't figure out exactly where the children's child anchors are in this case but they seem to be wherever-TikZ-would-take-a-path-to relative to wherever you are comping from or going to.

But even setting parent anchor=east and child anchor=west for the tree doesn't really help:

align midpoints of edges?

So I would change anchor for the tree, as I do below, regardless of what else seems desirable. This seems to give good results in this case.

(However, for non-circular nodes, something other than center does often make sense.)

I've also make a couple of other tiny modifications which you may (or may not) be interested in. In particular, I've changed the anchors so that they are not direction-dependent. So you can change the direction of growth and the parent and child anchors should still make sense. I've also had the package figure out whether the labels on the edges should go above or below the lines.

But only

    anchor=children,% work around alignment issue

is really making any difference to the result.

\documentclass[tikz,multi,border=5pt]{standalone}
\usepackage{forest}
\begin{document}
% Zarko's modification of Gonzalo Medina's answer: http://tex.stackexchange.com/a/177254/
\tikzset{%
  EL/.style={%
    midway,
    #1,
    font=\scriptsize\sffamily,
    text=teal,
    text width=1.5cm,
    align=center,
  }
}
\begin{forest}
  for tree={
    draw=teal,
    line width=0.4pt,
    edge={draw=teal,very thin},
    grow=east,
    circle,
    parent anchor=children,
    child anchor=parent,
    edge path'={
       (!u.parent anchor) -- ([xshift=-17mm].child anchor) -- (.child anchor)
    },
    l sep=19mm,
    anchor=children,% work around alignment issue
  },
  before typesetting nodes={%
    where n=1{%
      edge label/.wrap value={node[EL=below]{#1}}
    }{%
      edge label/.wrap value={node[EL=above]{#1}}
    }
  }
  [, rectangle, s sep=8mm,
    [, edge label={option1}
      [, edge label={a longer text goes here}
      ]
      [, edge label={text}
      ]
    ]
    [B, edge label={option2}
      [, edge label={a longer text goes here}
      ]
      [, edge label={text}
      ]
    ]
  ]
\end{forest}
\end{document}

workaround alignment issue

Code for demos:

\documentclass[tikz,multi,border=5pt]{standalone}
\usepackage{forest}
\usetikzlibrary{calc}
\begin{document}
\begin{forest}
  for tree={% default calign, anchor
    grow=east,
    draw
  }
  [
    [B, tikz={%
      \draw [densely dotted, blue] (!u.base) -- (.base);
      \draw [densely dotted, red] (.base) -- ($(!1.base)!1/2!(!l.base)$) edge (!1.base) -- (!l.base);
    }
      [][]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={% default calign, anchor=center
    grow=east,
    draw,
    anchor=center
  }
  [
    [B, tikz={%
      \draw [densely dotted, blue] (!u.center) -- (.center);
      \draw [densely dotted, red] (.center) -- ($(!1.center)!1/2!(!l.center)$) edge (!1.center) -- (!l.center);
    }
      [][]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={% default calign, anchor=parent
    grow=east,
    draw,
    anchor=parent
  }
  [
    [B, tikz={%
      \draw [densely dotted, blue] (!u.parent) -- (.parent);
      \draw [densely dotted, red] (.parent) -- ($(!1.parent)!1/2!(!l.parent)$) edge (!1.parent) -- (!l.parent);
    }
      [][]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={% default calign, anchor=children
    grow=east,
    draw,
    anchor=children
  }
  [
    [B, tikz={%
      \draw [densely dotted, blue] (!u.children) -- (.children);
      \draw [densely dotted, red] (.children) -- ($(!1.children)!1/2!(!l.children)$) edge (!1.children) -- (!l.children);
    }
      [][]
    ]
  ]
\end{forest}
\begin{forest}
  for tree={% calign=edge midpoint, default anchor
    grow=east,
    draw,
    calign=edge midpoint,
    parent anchor=east,
    child anchor=west,
  }
  [
    [B, tikz={%
      \draw [densely dotted, blue] (!u.parent anchor) -- (.child anchor);
      \draw [densely dotted, red] (.parent anchor)  -- ($(!1.child anchor)!1/2!(!l.child anchor)$) edge (!1.child anchor) -- (!l.child anchor);
    }
      [][]
    ]
  ]
\end{forest}
\end{document}
  • 1
    It's actually the documentation of anchor that is unclear. So setting anchor to center, west or children is not just a workaround, but the solution. – Sašo Živanović Feb 17 '16 at 1:37
  • Sorry I mixed up east and west above: in an east growing tree, east=children and west=parent. – Sašo Živanović Feb 17 '16 at 1:43
  • About s-alignment of children in an east growing tree: consider the following tree: \begin{forest}for tree={grow=east,draw}[[,anchor=west][,anchor=east]]\end{forest} – Sašo Živanović Feb 17 '16 at 1:45
  • 1
    Cleaned up a little ... – cfr Feb 17 '16 at 3:49
  • @cfr, thank you for your answer with exhaustive explanation. For understanding all I need to repeat all given examples. Hopefully I will do this during day :-) – Zarko Feb 17 '16 at 6:29

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.