7

I am using forest to construct trees. I have one (minor but persistent) issue: sometimes I would like to place a node at a point that is a proper part of (e.g.) a leaf, in particular so that I can draw movement arrows targeting proper parts of nodes. Here is an example of what I'm after:

movement from inside a node

One low-tech option is to simply name the entire node (here, John see x) and then tweak the arrow's origin on a case-by-case basis (which is how I made the tree above). But that's pretty annoying to do multiple times in a single document, or (gasp) if the tree's layout ever needs to change substantially.

User cfr defined a nice workaround here. However, it is not obvious to me how to turn this into a general solution:

  • For example, this solution only allows for one such sub-part to be targeted. It's straightforward enough to modify cfr's code to handle e.g. the case where there are two adjacent sub-parts, but in the general case, the regions of interest may be non-adjacent, or there may be more than two.

  • In addition, the linked solution makes use of a "global" length \sourcetextaddwidth, which prevents one from reusing the code multiple times in a single document without repeated manual adjustments.

  • Finally (most importantly for me), one may wish to shape the arrow in certain ways, but the linked approach locates the arrow drawing inside the move style/"macro", which doesn't allow for this. Again, achieving the desired effect requires repeated manual adjustments.

What I think would be preferable is a reusable macro/forest style that allows one to create a tikz node at a sub-part of a forest tree node. Then, one can simply use those nodes to draw movement arrows (or whatever) in the usual way. I am not sure whether this is possible, but if it is, it's certainly beyond my pay grade.

Edited to add a MWE with a simple tree for folks to play around with (no arrows, per the nature of the question). The hope is to have an arrow relating the two occurrences of B:

\documentclass{article}
\usepackage{forest}
\begin{document}
\begin{forest}
  [A
    [B]
    [C
      [D]
      [E B F]
    ]
  ]
\end{forest}
\end{document}
8

You could use the tikzmark library. Using \subnode{<name>}{<content>} you can place some marks around designated elements and then use those marks and the node anchors to easily place the arrows:

\documentclass{article}
\usepackage{forest}
\usetikzlibrary{tikzmark}

\begin{document}

\begin{forest}
for tree={s sep=20pt}
[A t\subnode{endc}{e}st text
  [B
    [\subnode{enda}{C},
    ]
  ]
  [D
    [\subnode{endb}{E}
    ]
    [\subnode{startc}{F}
      [G
      ]
      [H
        [\subnode{startb}{Johh} see \subnode{starta}{x}
        ]
      ]
    ]
  ]
]
\end{forest}

\begin{tikzpicture}[
  remember picture,
  overlay,
  >=latex
]
\draw[cyan,thick,->]
  (starta.south) --
  ++(0pt,-10pt) -| 
  (enda.south);
\draw[red!80!black,thick,->]
  (startb.south) --
  ++(0pt,-5pt) -| 
  (endb.south);
\draw[green!80!black,thick,->]
  (startc) to[out=60,in=90,looseness=1.4]
  (endc.north);
\end{tikzpicture}

\end{document}

enter image description here

Update

The previous solution won't work with current version of xetex; there seems to be a problem with the drivers? This problem has been noticed in tikzmark and xelatex and there, in a comment, user Akira Kakuto suggested a workaround that seems to work here:

\documentclass{article}
\newcount\pdftexversion 
\pdftexversion140 \def\pgfsysdriver{pgfsys-dvipdfm.def}
\usepackage{forest}
\usetikzlibrary{tikzmark}

\begin{document}

\begin{forest}
for tree={s sep=20pt}
[A t\subnode{endc}{e}st text
  [B
    [\subnode{enda}{C},
    ]
  ]
  [D
    [\subnode{endb}{E}
    ]
    [\subnode{startc}{F}
      [G
      ]
      [H
        [\subnode{startb}{Johh} see \subnode{starta}{x}
        ]
      ]
    ]
  ]
]
\end{forest}

\begin{tikzpicture}[
  remember picture,
  overlay,
  >=latex
]
\draw[cyan,thick,->]
  (starta.south) --
  ++(0pt,-10pt) -| 
  (enda.south);
\draw[red!80!black,thick,->]
  (startb.south) --
  ++(0pt,-5pt) -| 
  (endb.south);
\draw[green!80!black,thick,->]
  (startc) to[out=60,in=90,looseness=1.4]
  (endc.north);
\end{tikzpicture}

\end{document}

The result, using xelatex:

enter image description here

I have no advanced knowledge of xelatex, so use this with precaution. Since internal calculations are involved, the code needs two or three runs for the arrows to land on their final places.

  • 1
    Unfortunately, compiling with xetex is enough to break this (image of result here). This has been discussed here, but I am not able to find a solution anywhere (I'm running MacTeX 2015, everything up-to-date on TeX Live). – Simon C Jul 15 '15 at 15:09
  • @SimonC Hmmm. True. Let me think of an alternative for xetex. I'll let you know what I find. – Gonzalo Medina Jul 15 '15 at 15:50
  • Much obliged. I'll leave your current answer accepted, since it's helpful for the pdflatexers in our midst. – Simon C Jul 15 '15 at 16:35
  • @SimonC I've found that the workaround presented in the thread you linked to also works here. I'll consult in chat with xelatex experts to see if this workaround might have some potential drawbacks. – Gonzalo Medina Jul 15 '15 at 18:00
  • Let us continue this discussion in chat. – Simon C Jul 15 '15 at 19:32

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.