4

I am working on a tree using tikz. Is there a way to define the node size globally? If I delete the text in my tree nodes they become really small. I want to define a different size for blue, orange and red nodes. And is there a way for automatic node alignment?

\documentclass{article}
\usepackage[a4paper,margin=1cm,landscape]{geometry}
\usepackage{tikz}

%%%<
\usepackage{verbatim}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{5pt}%
%%%>

\usetikzlibrary{positioning,shadows,arrows}

\begin{document}


\begin{center}
\begin{tikzpicture}[
    fact/.style={circle, draw=none, rounded corners=1mm, fill=gray, drop shadow,
        text centered, anchor=north, text=white},
    state/.style={circle, draw=none, fill=orange, circular drop shadow,
        text centered, anchor=north, text=white},
    empty/.style={circle, draw=none, fill=blue, circular drop shadow,
        text centered, anchor=north, text=white},
    leaf/.style={circle, draw=none, fill=red, circular drop shadow,
        text centered, anchor=north, text=white},
    level distance=0.5cm, growth parent anchor=south
]
\node (Fact00) [fact] {$root$}
[sibling distance=5cm]
child{ [sibling distance=1.2cm]
node (State00) [state] {$pp$}
    child{
    node (State09) [empty] {$$}
    }
    child{
    node (State09) [leaf] {$leaf$}
    }
    child{
    node (State09) [empty] {$$}
    }
    child{ [sibling distance=3cm]
    node (State09) [state] {$pp$}
        child{ [sibling distance=1cm]
        node (State10) [state] {$pp$}
            child{
            node (Leaf1) [leaf] {$leaf$}
            }
            child{
            node (Leaf1) [leaf] {$leaf$}
            }
        }
        child{ [sibling distance=1cm]
        node (State10) [state] {$pp$}
            child{
            node (Leaf1) [leaf] {$leaf$}
            }
            child{
            node (Leaf1) [leaf] {$leaf$}
            }
        }
    }
}
child{ [sibling distance=1.2cm]
node (State00) [state] {$pp$}
    child{
    node (State09) [leaf] {$leaf$}
    }
    child{
    node (State09) [leaf] {$leaf$}
    }
}
child{ [sibling distance=1.2cm]
node (State00) [state] {$pp$}
    child{
    node (State09) [leaf] {$leaf$}
    }
    child{
    node (State09) [leaf] {$leaf$}
    }
    child{
    node (State09) [leaf] {$leaf$}
    }
}
child{ [sibling distance=1.2cm]
    node (State01) [state] {$pp$}
    child{
    node (State11) [leaf] {$leaf$}
    }
    child{
    node (State09) [leaf] {$leaf$}
    }
}
;  
\end{tikzpicture}
\end{center}


\end{document}

enter image description here

2
  • Add minimum size to your styles or for all nodes, as applicable. Automatic alignment etc.: either Forest or you can use the algorithmic layouts in the TikZ graph drawing libraries, which requires LuaTeX for the computations.
    – cfr
    Dec 28, 2016 at 21:37
  • Please don't use minimal for examples as it is not suitable.
    – cfr
    Dec 28, 2016 at 21:38

2 Answers 2

2

You can add minimum size to the style definitions to enforce minimum sizes. You can't get things laid out automatically using this method, although you can use styles such as level <n> with keys such as sibling distance for tree/level-wide control.

For automatic layouts, try Forest or the algorithmic graph-drawing which are part of TikZ itself. The latter requires LuaTeX and is not specific to trees, but includes a library of tree-based layout algorithms.

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

\begin{document}
\begin{tikzpicture}[
  fact/.style={circle, draw=none, rounded corners=1mm, fill=gray, drop shadow, text centered, anchor=north, text=white},
  state/.style={circle, draw=none, fill=orange, circular drop shadow, text centered, anchor=north, text=white, minimum size=7mm},
  empty/.style={circle, draw=none, fill=blue, circular drop shadow, text centered, anchor=north, text=white, minimum size=9mm},
  leaf/.style={circle, draw=none, fill=red, circular drop shadow, text centered, anchor=north, text=white, minimum size=5mm},
  level distance=0.5cm,
  growth parent anchor=south,
  ]
    \node (Fact00) [fact] {$root$}
    [sibling distance=5cm]
    child{ [sibling distance=1.2cm]
      node (State00) [state] {$pp$}
      child{
        node (State09) [empty] {$$}
      }
      child{
        node (State09) [leaf] {$leaf$}
      }
      child{
        node (State09) [empty] {$$}
      }
      child{ [sibling distance=3cm]
        node (State09) [state] {$pp$}
        child{ [sibling distance=1cm]
          node (State10) [state] {$pp$}
          child{
            node (Leaf1) [leaf] {$leaf$}
          }
          child{
            node (Leaf1) [leaf] {$leaf$}
          }
        }
        child{ [sibling distance=1cm]
          node (State10) [state] {$pp$}
          child{
            node (Leaf1) [leaf] {$leaf$}
          }
          child{
            node (Leaf1) [leaf] {$leaf$}
          }
        }
      }
    }
    child{ [sibling distance=1.2cm]
      node (State00) [state] {$pp$}
      child{
        node (State09) [leaf] {$leaf$}
      }
      child{
        node (State09) [leaf] {$leaf$}
      }
    }
    child{ [sibling distance=1.2cm]
      node (State00) [state] {$pp$}
      child{
        node (State09) [leaf] {$leaf$}
      }
      child{
        node (State09) [leaf] {$leaf$}
      }
      child{
        node (State09) [leaf] {$leaf$}
      }
    }
    child{ [sibling distance=1.2cm]
      node (State01) [state] {$pp$}
      child{
        node (State11) [leaf] {$leaf$}
      }
      child{
        node (State09) [leaf] {$leaf$}
      }
    }
    ;
\end{tikzpicture}
\end{document}

enforced minimum sizes

Forest tries hard to place nodes automatically and generally succeeds in avoiding overlaps for the majority of trees. It is also designed to construct trees as compactly as possible (although this can be altered if spacier trees are desired).

Here's an example:

\documentclass[border=10pt,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{shadows}
\begin{document}
\begin{forest}
  colour me/.style={
    fill=#1,
    draw=#1,
  },
  for tree={
    circle,
    circular drop shadow,
    text=white,
    math content,
    edge+={draw=gray, thick},
  },
  where n children=0{% for the leaves
    colour me=red,
    minimum size=5mm,
  }{
    if level=0{% for the root
      colour me=gray,
      minimum size=6mm,
    }{
      colour me=orange,
      minimum size=2mm,
    },
  },
  delay={
    where content={}{% just the empty nodes
      colour me=blue,
      minimum size=12mm,
    }{},
  },
  [root
    [pp
      [][leaf][]
      [pp
        [pp
          [leaf][leaf]
        ]
        [pp
          [leaf][leaf]
        ]
      ]
    ]
    [pp
      [leaf][leaf]
    ]
    [pp
      [leaf][leaf][leaf]
    ]
    [pp
      [leaf][leaf]
    ]
  ]
\end{forest}
\end{document}

Forest tree

Note that the larger blue nodes are automatically accommodated by spreading out the relevant parts of the tree to make room.

The colouring here utilises a base style, colour me, which is configured depending on place in the tree and node content according to the following rules:

  • root node? -> gray + size specification;
  • leaf node? -> red + size specification;
  • empty node? -> blue + size specification;
  • otherwise -> orange + size specification.

More fine-grained control can be achieved by applying styles to individual nodes, but this course-grained classification suffices for the tree in the question.

4
  • How can I decrease the size of the blue nodes? Is there something like maximum size=5mm?
    – Gilfoyle
    Dec 29, 2016 at 16:52
  • @Samuel Just make the minimum size smaller e.g. 5mm rather than 12mm.
    – cfr
    Dec 29, 2016 at 16:53
  • What if the tree gets to big? I like your second example and work with it now. Is there a way to decrease the overall size of a given tree. Something like size=\textwidth?
    – Gilfoyle
    Dec 29, 2016 at 17:05
  • @Samuel Scaling the tree (as any diagram) should be a last resort. The best method depends on the details of the tree - there really isn't a general one-size-fits-all answer. Not even if you want all-one-size.
    – cfr
    Dec 29, 2016 at 17:11
4

I suggest the following changes:

  • Use minimum size to set a minimal size of the nodes, e.g. minimum size=7mm.

  • Use inner sep to reduce the empty space in the nodes, e.g. inner sep=1pt.

  • Factor out the style elements common to all nodes, e.g.

    common/.style={circle, draw=none, text centered, anchor=north,
      minimum size=7mm, inner sep=1pt, text=white, circular drop shadow}
    

    and use it as in state/.style={common, fill=orange}.

  • Don't use math mode to typeset text in italics, use \textit instead; e.g. \textit{leaf} instead of $leaf$.

  • Use a command to format the node contents consistently; I call it \nc below. E.g., define

    \newcommand\nc[1]{\textit{#1}}
    

    and use \nc{leaf}.

enter image description here

\documentclass[border=1mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,shadows,arrows}
\begin{document}
\newcommand\nc[1]{\textit{#1}}
\begin{tikzpicture}[
    common/.style={circle, draw=none, text centered, anchor=north,
      minimum size=7mm, inner sep=1pt, text=white, circular drop shadow},
    fact/.style={common, fill=gray},
    state/.style={common, fill=orange},
    empty/.style={common, fill=blue},
    leaf/.style={common, fill=red},
    level distance=0.5cm, growth parent anchor=south
]
\node (Fact00) [fact] {\nc{root}}
[sibling distance=5cm]
child{ [sibling distance=1.2cm]
node (State00) [state] {\nc{pp}}
    child{
    node (State09) [empty] {}
    }
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
    child{
    node (State09) [empty] {}
    }
    child{ [sibling distance=3cm]
    node (State09) [state] {\nc{pp}}
        child{ [sibling distance=1cm]
        node (State10) [state] {\nc{pp}}
            child{
            node (Leaf1) [leaf] {\nc{leaf}}
            }
            child{
            node (Leaf1) [leaf] {\nc{leaf}}
            }
        }
        child{ [sibling distance=1cm]
        node (State10) [state] {\nc{pp}}
            child{
            node (Leaf1) [leaf] {\nc{leaf}}
            }
            child{
            node (Leaf1) [leaf] {\nc{leaf}}
            }
        }
    }
}
child{ [sibling distance=1.2cm]
node (State00) [state] {\nc{pp}}
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
}
child{ [sibling distance=1.2cm]
node (State00) [state] {\nc{pp}}
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
}
child{ [sibling distance=1.2cm]
    node (State01) [state] {\nc{pp}}
    child{
    node (State11) [leaf] {\nc{leaf}}
    }
    child{
    node (State09) [leaf] {\nc{leaf}}
    }
}
;  
\end{tikzpicture}
\end{document}

You must log in to answer this question.

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