5

there is a family tree from the BBC Website and I'm wondering if it is possible to use tikz decorations to create such "blood lines".

Does anybody have an idea?

enter image description here

schmendrich
  • 3,908

2 Answers2

7

This is not much like the target image but it does have a certain edge to it.

[The pun here is fully intended.]

The decoration is blatantly appropriated from renard's answer. I used that answer because it claimed to be compatible with circles and I planned to use some. However, the code below is, it turns out, entirely circle-free. I have modified the decoration code slightly, despite having no clue what it means, though only really to avoid an additional dependency.

The results are, however, entirely my fault and should not be blamed on the decoration's author who clearly never intended it to be abused in this way.

I am, as usual, entirely and obviously to blame for the tree.

Caveat emptor...

\documentclass[border=0pt,tikz]{standalone}
\usepackage{forest}
\usepackage[sf={lining},rm={lining},tt={lining}]{cfr-lm}
\usetikzlibrary{decorations,backgrounds}
% ref.: decoration is from renard's answer at https://tex.stackexchange.com/a/218483/ but avoid depending on ifthen package
\makeatletter
\pgfdeclaredecoration{penciline}{initial}{
  \state{initial}[width=+\pgfdecoratedinputsegmentremainingdistance,
    auto corner on length=1pt,
  ]{
    \pgfmathparse{equal(\penciline@jagratio,0) ? "0" : "1"}
    \ifnum\pgfmathresult=0
          \pgfpathcurveto%
              {% 1st control point
                \pgfpoint
                    {\pgfdecoratedinputsegmentremainingdistance/2}
                    {2*rnd*\pgfdecorationsegmentamplitude}
              }
              {%% 2nd control point
                \pgfpoint
                %% Make sure random number is always between origin and target points
                    {\pgfdecoratedinputsegmentremainingdistance/2}
                    {2*rnd*\pgfdecorationsegmentamplitude}
              }
              {% 2nd point (1st one is implicit)
                \pgfpointadd
                    {\pgfpointdecoratedinputsegmentlast}
                    {\pgfpoint{0*rand*1pt}{0*rand*1pt}}
              }
        \else
          \pgfpathcurveto%
              {% 1st control point
                \pgfpoint
                    {\pgfdecoratedinputsegmentremainingdistance*rnd*1pt}
                    {\penciline@jagratio*
                      rand*\pgfdecorationsegmentamplitude}
              }
              {%% 2nd control point
                \pgfpoint
                %% Make sure random number is always between origin and target points
                    {(.5+0.25*rand)*\pgfdecoratedinputsegmentremainingdistance}
                    {\penciline@jagratio*
                      rand*\pgfdecorationsegmentamplitude}
              }
              {% 2nd point (1st one is implicit)
                \pgfpointadd
                    {\pgfpointdecoratedinputsegmentlast}
                    {\pgfpoint{rand*1pt}{rand*1pt}}
              }
       \fi
  }
  \state{final}{}
}
\tikzset{
  penciline/.code = {
    \tikzset{
      penciline/.cd,
      #1,
    },
  },
  penciline/.cd,
  jag ratio/.store in=\penciline@jagratio,
  jag ratio=5,
}
\makeatother
\begin{document}
\begin{forest}
  bloody node/.style={
    text=#1,
    text opacity=1,
    ball color=white,
    fill opacity=.15,
    rounded corners=5pt,
  },
  for tree={
    align=center,
    parent anchor=south,
    child anchor=north,
    if={isodd(n_children())}{
      for children={
        if={n()==int((n_children("!u")+1)/2)}{
          calign with current
        }{}
      }
    }{},
    font=\tistyle\bfseries\scshape,
    edge={decorate, decoration=penciline, penciline={jag ratio=4}, ultra thin, inner color=red, outer color=red!25!black, draw=red!15!black, rounded corners=1mm},
    l sep+=5mm,
    s sep+=5mm,
  },
  where level=0{}{
    if={n()>int((n_children("!u")+1)/2)}{
      edge path={
        \noexpand\path [\forestoption{edge}] (!u.parent anchor) -- ++(0,-2.5mm) coordinate (!u second parent) [bend left=10] to (!u second parent -| .child anchor) [bend left] to (.child anchor)\forestoption{edge label} [bend right] to (!u second parent -| .child anchor) [bend right=10] to (!u second parent) -- cycle;
      },
    }{
      edge path={
        \noexpand\path [\forestoption{edge}] (!u.parent anchor) -- ++(0,-2.5mm) coordinate (!u second parent) [bend right=10] to (!u second parent -| .child anchor) [bend right] to (.child anchor)\forestoption{edge label} [bend left] to (!u second parent -| .child anchor) [bend left=10] to (!u second parent) -- cycle;
      },
    },
  }
  [Mandy\\Evans, bloody node=blue, tikz+={\scoped[on background layer]\fill (current bounding box.south west) rectangle (current bounding box.north east);}
    [Gerald\\Evans, for tree={bloody node=blue}]
    [Catherine\\Evans, for tree={bloody node=red}
      [Arnold\\Evans]
      [Donald\\Evans]
      [Amy\\Akrington
        [Basil\\Pasilicous]
        [Divula\\Akrington
          [Livia\\Arlington-Likrinton]
        ]
      ]
    ]
    [Lima\\Peterson, for tree={bloody node=green}
      [Esmeralda\\Bobbington]
      [Tivulus\\Kadaverula]
    ]
  ]
\end{forest}
\end{document}

bloody nodes

cfr
  • 198,882
3

Here is an attempt with metapost. First I'll show the result (just for the lines, not the text).

enter image description here

The main idea is to split each path into small segments and draw each segment by a slightly randomized pen. Then add a bit of randomization to the entire path as well.

\startMPdefinitions
  pen randompen;

  randompen_n := 100;
  randompen_a := 0.75;
  randompen_s := 3bp;
  sketch_amount := 0.5bp;

  def basicpen =
    ((-0.5,0.5) -- (0.5,0.5) --
    (0.5,-0.5) .. (0, -0.5 randomized randompen_a) 
    .. (-0.5, 0.5) -- cycle) rotated 45

  enddef;

  def bloodydraw expr p =
      for i = 0 step 1/randompen_n until length p:
        randompen := makepen (basicpen) scaled randompen_s;
        draw subpath (i, i + 1/randompen_n) of p randomized sketch_amount withpen randompen _op_;
      endfor
  enddef;
\stopMPdefinitions

\starttext

\startMPpage[offset=2mm]
  u := 1cm ;

  z[0]  = (0u,0u);
  z[-1] = (-1u,-1u);  z[1] = (1u,-1u);
  z[-2] = (-2u,-1u);  z[2] = (2u,-1u);

  z[-20] = (-2u,-2u); z[20] = (2u,-2u);
  z[-10] = (-1u,-2u); z[10] = (1u,-2u);

  drawoptions(withcolor 0.7red);

  bloodydraw z[0] -- 0.5[z[-1],z[1]];
  bloodydraw z[-2] -- z[2];

  for i = -2,-1,1,2 :
    bloodydraw z[i] -- z[i*10];
  endfor;

\stopMPpage

\stoptext

Drawing the complete image using this technique is left as an exercise to the reader :-)

Aditya
  • 62,301