I don't recommend this. For me, it produces an overfull box and, even if it doesn't in this case, it very likely will in others. Moreover, the tree will not look centred if it is asymmetrical.
But you can, if you so wish do it:
The dashed blue line is just to show the centre of the page.
The centring is achieved using an empty, undrawn node as the root of width \linewidth
. The visible root is then aligned with the real root, which puts it dead centre.
\documentclass{article}
\usepackage{forest}
\begin{document}
\begin{tikzpicture}[overlay, remember picture]% this is just to show the centre of the page
\draw [dashed, draw=blue!50!white] (current page.north) -- (current page.south);
\end{tikzpicture}
\begin{center}
\begin{forest}
for tree={
if level=0{
text height=0pt,
text width=\linewidth,
inner sep=0pt,
outer sep=0pt,
parent anchor=north
}{
parent anchor=south,
child anchor=north,
align=center,
if level=1{
l=0pt,
no edge,
}{
l=2cm
},
},
},
[
[{[?,?,?,?]}
[{[Intel,?,?,?]}
[{[i7,?,?,?]}
]
]
[{[?,Radeon,?,?]}
]
[{[?,?,4GB,?]}
[{[Intel,?,4GB,?]}
]
[{[?,Radeon,4GB,?]}
]
[{[?,?,8GB,?]}
]
[{[?,?,4GB,Asus]}
]
]
]
]
\end{forest}
\end{center}
\end{document}
EDIT
In this particular case, because the node anchors are centred, as Sašo Živanović points out, a simpler version is possible using minimum width
rather than text width
and applying to the existing root node. The will make vertical alignment with other document elements simpler but will fail if parent anchor
is not centred.
\begin{center}
\begin{forest}% simplified with Sašo Živanović's suggestion (https://tex.stackexchange.com/questions/278708/center-root-of-forest-tree/278793?noredirect=1#comment671409_278793)
for tree={
parent anchor=south,
child anchor=north,
align=center,
l=2cm,
if level=0{
minimum width=\linewidth,
inner xsep=0pt,
outer xsep=0pt,
}{},
},
[{[?,?,?,?]}
[{[Intel,?,?,?]}
[{[i7,?,?,?]}
]
]
[{[?,Radeon,?,?]}
]
[{[?,?,4GB,?]}
[{[Intel,?,4GB,?]}
]
[{[?,Radeon,4GB,?]}
]
[{[?,?,8GB,?]}
]
[{[?,?,4GB,Asus]}
]
]
]
\end{forest}
\end{center}
This is a hack. It is provided as is. There are no guarantees. I don't even guarantee that it has anything to do with forest, multiline nodes or TeX. At this point, in case it is not clear, I should state that I guarantee nothing whatsoever. If the code dials the CIA, MI5 and the KGB and offers them your cat in exchange for a tube of Smarties, don't say I didn't warn you.
Caveat emptor...
Here's the idea:
If we put a tabular
into a node in a tree which does not use align
to create multiline nodes, we get just the same results as we do using align
. However, tabular
itself doesn't add vertical space, so we can't set that space to 0 as it is already zero.
If we put a minipage
into a node in the same tree, the spacing is the same as putting the contents of the minipage
in the node alone. (Assuming the node has only one line.)
So, if we could create multiline nodes as minipage
s rather than tabular
s, then it would work as desired. (Whether what is desired is desirable is left for you to determine, gentle reader.)
This is not as straightforward as it sounds because a minipage
, unlike a tabular
requires a width and we don't want to have to set a width for all nodes in the tree.
Surely, there are easier ways to do this and doubtless there are far more efficient ones. Especially a TeX guru would likely do this far better.
At this point, the gentle reader is urged to review again the statement above concerning guarantees and the danger to the cats of all readers, however gentle.
We start by creating a new style squat multiline
for trees of this kind:
\forestset{
squat multiline/.style={
We need a couple of custom forest options:
declare dimen={thiswidth}{0pt},
declare autowrapped toks={thiscontent}{},
Now we start manipulating the nodes. We do this in cycles to ensure that each set of keys are processed for each node before the next set of keys is processed for each node.
for tree={
delay={
This is round one:
thiscontent/.wrap pgfmath arg={##1}{content()},
In effect, this saves the content of the node. It copies it, basically. We delay this else the content won't be set when we try to copy it.
},
Now for the next round:
delay+={
content/.wrap value={\begin{tabular}{@{}c@{}}##1\\\end{tabular}},
This wraps the content in a tabular
environment like that used by align=center
. We are going to use this to get the width for the minipage
.
typeset node,
We typeset the node now, earlier than usual, because we need to get the width next.
},
The final round:
before typesetting nodes={
We set thiswidth
using the width of the node as it currently is.
thiswidth/.wrap pgfmath arg={##1}{int(abs(max_x()-min_x()))},
Now we reset the content of the node in a minipage
of width thiswidth
. We use the copy of the contents from thiscontent
because otherwise we'll get the tabular
wrapper as well.
content/.wrap pgfmath arg={\begin{minipage}[t]{\dimexpr\forestove{thiswidth}}\centering ##1\end{minipage}}{thiscontent()},
We've already got one lot of inner xsep
because it was included when we typeset the node originally. So we set it to 0 to avoid getting double the usual amount:
inner xsep=0pt,
We need to tell forest to typeset the node again:
typeset node,
},
Just the usual anchors from the original example:
parent anchor=south,
child anchor=north,
},
}
}
Now we can use the new style. The first example compares the default spacing with that used by squat multiline
when the content of the nodes are identical:
\begin{forest}
for tree={draw}
[, phantom
[A, for tree={parent anchor=south, child anchor=north}
[B]
[C
[D]
[E]
]
]
[A, squat multiline
[B]
[C
[D]
[E]
]
]
]
\end{forest}
Then the example with larger nodes and a roof:
\begin{forest}
for tree={draw},
squat multiline
[A,
[B\\long node]
[C
[D\\long multiline, triangle]
]
]
\end{forest}
The style does not appear be responsible for the slight misalignment of the roof here as I get the same issue when I compare the default style with drawn nodes.
Comparison:
In any case, I assume that the combination of a roof and draw
is unlikely to be desirable, and the misalignment is only noticeable because the nodes are drawn for purposes of illustration.
Complete code:
\documentclass[multi,tikz,border=10pt]{standalone}
\usepackage{forest}
\begin{document}
\forestset{
squat multiline/.style={
declare dimen={thiswidth}{0pt},
declare autowrapped toks={thiscontent}{},
for tree={
delay={
thiscontent/.wrap pgfmath arg={##1}{content()},
},
delay+={
content/.wrap value={\begin{tabular}{@{}c@{}}##1\\\end{tabular}},
typeset node,
},
before typesetting nodes={
thiswidth/.wrap pgfmath arg={##1}{int(abs(max_x()-min_x()))},
content/.wrap pgfmath arg={\begin{minipage}[t]{\dimexpr\forestove{thiswidth}}\centering ##1\end{minipage}}{thiscontent()},
inner xsep=0pt,
typeset node,
},
parent anchor=south,
child anchor=north,
},
}
}
\begin{forest}
for tree={draw}
[, phantom
[A, for tree={parent anchor=south, child anchor=north}
[B]
[C
[D]
[E]
]
]
[A, squat multiline
[B]
[C
[D]
[E]
]
]
]
\end{forest}
\begin{forest}
for tree={draw},
squat multiline
[A,
[B\\long node]
[C
[D\\long multiline, triangle]
]
]
\end{forest}
\end{document}
Best Answer
That's because you're setting the caption as a node, which is also not the standard way of doing this. Captions are added to figures in a Latex document externally to the picture, i.e. they are not part of it.
Also, you're manually assigning a number to your figure and this makes the use of Latex a bit pointless, because one of the great advantages of using Latex is that captions are automatically numbered.
You can customize them, but they are automatic, so if you add another figure, they are all automatically fixed, while in your case, you'd have to fix each one manually. And that is not good in a long document.
You can add
\renewcommand{\thefigure}{\Roman{figure}}
to your preamble to make figure numbering with uppercase Roman numerals, and\usepackage[labelfont=bf]{caption}
to make it bold.Output
Code