4

I use the forest package to draw ancestry trees. I would like to add papyrus scroll-like backgrounds to the nodes. This is the basic example:

\documentclass[]{standalone}
\usepackage{pgfplots}
\usepackage{forest}
\begin{document}
\begin{forest}
        child anchor=south,
        parent anchor=north,
        grow'=north,
[Child
    [Father]
    [Mother]
]
\end{forest}
\end{document}

I have been able to add an image, but it always ended up before the text, while I would like to achieve something like the following:

Forest tree example with a background image

I wonder if there is a way to add the image behind the text, ideally scaled to the text size.

4 Answers 4

3

Here's an adaptation of SandyG's answer which doesn't require labels:

\documentclass{article}
\usepackage{forest}

\forestset{scroll/.style 2 args={
    content={\includegraphics[width=4cm]{5FHPu.png}},
    tikz={\node[align=center,yshift=-2.5mm] at () {#1\\*\ #2};},
    edge path={\noexpand\path[\forestoption{edge}] ([yshift=-3mm]!u.parent anchor)--(.child anchor)\forestoption{edge label};}
}}

\begin{document}
\begin{forest}
for tree={
    child anchor=south,
    parent anchor=north,
    grow'=north,
}
[, scroll={Child}{1722}
    [, scroll={Father}{1702}]
    [, scroll={Mother}{1701}]
]
\end{forest}
\end{document}

output of code

1
  • As long as the names aren't too long ....
    – cfr
    Feb 29 at 5:10
6

You can place the scroll image using content= and place the text as a label. I suggest keeping all scrolls the same size.

enter image description here

\documentclass{article}
\usepackage{forest}

\forestset{scroll/.style={
    content={\includegraphics[width=2cm]{5FHPu.png}}, 
    label={[label distance=-6mm]below:#1},
    edge path={\noexpand\path[\forestoption{edge}] ([yshift=-3mm]!u.parent anchor)--(.child anchor)\forestoption{edge label};}
}}

\begin{document}
\begin{forest}
for tree={
    child anchor=south,
    parent anchor=north,
    grow'=north
}
[, scroll=Child
    [, scroll=Father]
    [, scroll=Mother]
]
\end{forest}
\end{document}
1
  • Thank you for the suggestion. Unfortunately, my labels are more complex, structured entries and I was simply unable to get them working as labels. See my eventual, not so elegant solution below.
    – lak20
    Feb 25 at 22:00
3

Here's an adaption of Alan Munn's answer which deals automatically with long names (or dates). It provides a style family tree for use in the preamble. Node content should be provided in the format

<name or first line>:<date or second line>

The code then has Forest calculate the widest node and compare it with a standardised width. If the widest node is too wide to fit the standard width, an adjustment is made to all scrolls in the tree. We don't really want the image in the background to simply scale, however, as this will create unnecessarily deep nodes. So we just scale the middle part of the scroll image and only horizontally.

To avoid duplicating code, the image is split into three trimmed and clipped parts. These are saved to dedicated boxes and scaled. The three boxes provide the three parts of the scroll: one for the left, one for the middle and one for the right. In the 'standard' case, where the name and date fit into the middle of this standardised scroll, we just use the boxes. If the content is too wide, however, the middle part of the scroll is stretched first to accommodate the additional width.

The result looks like this:

family trees with standard and stretched scrolls behind content

The input for these trees is

\begin{forest}
  family tree
  [Child:1722
    [Father:1702]
    [Mother:1701]
  ]
\end{forest}

for the 'standard' case and

\begin{forest}
  family tree,
  [Child:1722
    [Father:1702
      [Paternal Grandfather:1680]
      [Paternal Grandmother:1682]
    ]
    [Mother:1701
      [Maternal Grandfather:1680]
      [Maternal Grandmother:1682]
    ]
  ]
\end{forest}

for the 'stretched'.

The placement is not quite perfect because the content of the node is placed at the horizontal centre, whereas the scroll image is slightly lopsided. (The right end is a bit wider than the left.) However, in practice, this seems to look about right (and is what other answers have done). If you want more or less allowance for the 'standard' case, you can alter min scroll wd for one or all trees. The default value is 61pt. For example,

\begin{forest}
  family tree,
  min scroll wd'=30pt
  [Child:1722
    [Father:1702]
    [Mother:1701]
  ]
\end{forest}
\begin{forest}
  family tree,
  min scroll wd'=100pt
  [Child:1722
    [Father:1702]
    [Mother:1701]
  ]
\end{forest}

decreasing or increasing space around content

Complete code:

\documentclass[11pt]{standalone}
% ateb: https://tex.stackexchange.com/a/711822/ addaswyd o ateb Alan Munn: https://tex.stackexchange.com/a/711581/ i gwestiwn lak20: https://tex.stackexchange.com/q/711483/
\usepackage[edges]{forest}
% width 2014.52136pt
\ExplSyntaxOn
\box_new:N \l_scroll_left_box
\box_new:N \l_scroll_right_box
\box_new:N \l_scroll_mid_box
\dim_new:N \l_scroll_mid_dim
\hbox_set:Nn \l_scroll_left_box { \includegraphics{5FHPu} }
\dim_set:Nn \l_tmpa_dim { \box_wd:N \l_scroll_left_box }
\box_set_eq:NN \l_scroll_right_box \l_scroll_left_box
\box_set_eq:NN \l_scroll_mid_box \l_scroll_left_box
\box_set_trim:Nnnnn \l_scroll_left_box {0pt} {0pt} {1565pt} {0pt}
\box_set_trim:Nnnnn \l_scroll_mid_box {450pt} {0pt} {475pt} {0pt}
\box_set_trim:Nnnnn \l_scroll_right_box {1540pt} {0pt} {0pt} {0pt}
\box_set_clipped:N \l_scroll_left_box
\box_set_clipped:N \l_scroll_mid_box
\box_set_clipped:N \l_scroll_right_box
\box_scale:Nnn \l_scroll_left_box {40mm/\l_tmpa_dim} {40mm/\l_tmpa_dim}
\box_scale:Nnn \l_scroll_right_box {40mm/\l_tmpa_dim} {40mm/\l_tmpa_dim}
\box_scale:Nnn \l_scroll_mid_box {40mm/\l_tmpa_dim} {40mm/\l_tmpa_dim}
\dim_set:Nn \l_scroll_mid_dim { \box_wd:N \l_scroll_mid_box }
\cs_new_protected:Nn \scroll_assemble:n
{
  \box_use:N \l_scroll_left_box
  \box_scale:Nnn \l_scroll_mid_box { #1 / \l_scroll_mid_dim } { 1 }
  \box_use:N \l_scroll_mid_box
  \box_use:N \l_scroll_right_box
}
\cs_new_eq:NN \doscroll \scroll_assemble:n
\ExplSyntaxOff
\forestset{%
  declare boolean={scroll}{0},
  declare dimen register={scroll wd},
  declare dimen register={min scroll wd},
  declare toks={person name}{},
  declare toks={person date}{},
  scroll wd'=0pt,
  min scroll wd'=61pt,
  family tree/.style={%
    forked edges,
    for tree={%
      scroll,
      child anchor=parent,
      parent anchor=children,
      grow'=north,
      align=center,
      edge+={shorten <=-15pt,rounded corners},
    },
    before typesetting nodes={
      for tree={
        split option={content}{:}{person name,person date},
        content/.process={ OOw2 {person name}{person date}{##1\\*~##2} },
      },
    },
    before packing={
      scroll wd/.max={>OOw2+d{max x}{min x}{##1-##2}}{tree},
      if={ > RR> {scroll wd}{min scroll wd} }{
      }{
         scroll wd/.register=min scroll wd,
      },
      where scroll={
        tikz+/.process={Ow{content}{\node [align=center,anchor=south] at (.base) {##1};}},
        content={%
          \doscroll {\foresteregister{scroll wd}}%
        },
        inner sep=0pt,
        typeset node,
      }{},
    },
  },
  do scroll/.style 2 args={
    content={\includegraphics[width=4cm]{5FHPu.png}},
    tikz={\node[align=center,yshift=-2.5mm] at () {#1\\*\ #2};},
    edge path'={%
      ([yshift=-3mm]!u.parent anchor)--(.child anchor)},
  },
}

\begin{document}
\begin{forest}
  family tree
  [Child:1722
    [Father:1702]
    [Mother:1701]
  ]
\end{forest}
\begin{forest}
  family tree,
  [Child:1722
    [Father:1702
      [Paternal Grandfather:1680]
      [Paternal Grandmother:1682]
    ]
    [Mother:1701
      [Maternal Grandfather:1680]
      [Maternal Grandmother:1682]
    ]
  ]
\end{forest}

\begin{forest}
  family tree,
  min scroll wd'=30pt
  [Child:1722
    [Father:1702]
    [Mother:1701]
  ]
\end{forest}
\begin{forest}
  family tree,
  min scroll wd'=100pt
  [Child:1722
    [Father:1702]
    [Mother:1701]
  ]
\end{forest}
\end{document}
2

I do not fully understand what goes on, but the following works:

\documentclass{article}
\usepackage{forest}

\makeatother
\newcommand{\Person}[2]{%
    \begin{center}%
        \vskip-38pt%
        {{#1}} \\%
        { *\  #2 }% 
    \end{center}%
}%
\begin{document}

\begin{forest}
    for tree={
            edge path={
                \noexpand\path[\forestoption{edge}]
                ([yshift=0.6pt]!u.parent anchor) --
                ([yshift=-0.9pt].child anchor)\forestoption{edge label};
            },
        text width=(4cm),
        child anchor=south,
        parent anchor=north,
        grow'=north,
        }
[{\makebox[\textwidth]{\centering\includegraphics[width=4cm]{5FHPu.png}}}\\%
\Person{Child}{1990}
    [{\makebox[\textwidth]{\centering\includegraphics[width=4cm]{5FHPu.png}}}\\%
    \Person{Father}{1950}
    ]
    [{\makebox[\textwidth]{\centering\includegraphics[width=4cm]{5FHPu.png}}}\\%
    \Person{Mother}{1960}
    ]
]
\end{forest} 
\end{document}

Family tree with names on papyrus

What I find especially puzzling is the effect of using a \vskip. It is required for the \'s to work within the Person environment; moreover, it seems useless in the node.

1
  • \vskip is only going to do something when LaTeX is able to add vertical stuff. Inside a node it can't do that. I'm not sure exactly how the pgf implementation goes, but think of something tabular-like. I don't know why the skip would be required in the Person environment for backslashes to work - that sounds pretty implausible?
    – cfr
    Feb 29 at 5:09

You must log in to answer this question.

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