我用forest
它来构造树。我有一个(小问题但持续存在)问题:有时我想将节点放置在(例如)叶子的适当部分的某个点上,特别是这样我就可以绘制针对节点适当部分的移动箭头。以下是我想要的示例:
一个低技术选项是简单地命名整个节点(此处为John see x
),然后逐个调整箭头的原点(这就是我制作上述树的方式)。但在单个文档中多次执行此操作非常烦人,或者(喘息)如果树的布局需要进行大幅更改。
用户 cfr 定义了一个很好的解决方法这里。但是,我不清楚如何将其转化为通用解决方案:
例如,此解决方案仅允许针对一个这样的子部分。修改 cfr 的代码以处理例如存在以下情况是相当简单的:两个相邻的子部分,但一般情况下,感兴趣的区域可能不相邻,或者可能有两个以上。
此外,链接解决方案使用了“全局”长度
\sourcetextaddwidth
,这可以防止在单个文档中多次重复使用代码,而无需重复手动调整。最后(对我来说最重要的是),人们可能希望以某种方式塑造箭头,但链接方法将箭头绘图定位在样式
move
/“宏”内,这不允许这样做。同样,要实现所需的效果需要反复进行手动调整。
我认为可重复使用的宏/forest
样式,这样可以创建一个 tikz 节点在树节点的子部分forest
。然后,人们可以简单地使用这些节点以通常的方式绘制移动箭头(或其他任何东西)。我不确定这是否可行,但如果可行,那肯定超出了我的能力范围。
编辑后添加了一个带有简单树的 MWE,供大家玩弄(根据问题的性质,没有箭头)。希望有一个箭头将 的两次出现联系起来B
:
\documentclass{article}
\usepackage{forest}
\begin{document}
\begin{forest}
[A
[B]
[C
[D]
[E B F]
]
]
\end{forest}
\end{document}
答案1
您可以使用tikzmark
库。使用\subnode{<name>}{<content>}
您可以在指定元素周围放置一些标记,然后使用这些标记和节点锚点轻松放置箭头:
\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}
更新
先前的解决方案不适用于当前版本的 xetex;驱动程序似乎有问题?这个问题已在tikzmark 和 xelatex在那里,a comment
,用户角斗明建议一个似乎有效的解决方法:
\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}
结果,使用xelatex
:
我对 xelatex 了解不多,所以使用时请谨慎。由于涉及内部计算,代码需要运行两到三次才能让箭头落到最终位置。