![为(水平)tikz 树创建级别标签](https://linux22.com/image/252594/%E4%B8%BA%EF%BC%88%E6%B0%B4%E5%B9%B3%EF%BC%89tikz%20%E6%A0%91%E5%88%9B%E5%BB%BA%E7%BA%A7%E5%88%AB%E6%A0%87%E7%AD%BE.png)
我想创建标签和对应的线,穿过 (水平) tikz-qtree 的分支层。这是想法。
我尝试了很长时间并在网上搜索,但没有找到任何进一步的进展......
以下代码生成原始的 tikz 树。
\begin{figure}[bh!]
\centering
\begin{tikzpicture}[ level distance=1cm, growth parent anchor=east, grow=right,scale=0.78,
level distance=1cm,
]
\tikzstyle{every node}=[font=\footnotesize, text width=5mm,anchor=east]
\Tree[.{0} [.{1} [.{1} [.{1} [.{1} [.{2} [.{7} [.{9} [.{4} [.{33} ] [.{474} ] ] [.{478} ] ] [.{487} ] ] [.{494} ] ] [.{496} ] ] [.{497} ] ] [.{498} ] ] [.{499} ] ] [.{4} [.{13} [.{4} [.{4} [.{7} [.{25} [.{9} [.{120} [.{314} ] [.{314} ] ] [.{434} ] ] [.{443} ] ] [.{468} ] ] [.{475} ] ] [.{479} ] ] [.{483} ] ] [.{496} ] ] [.{1} [.{2} [.{18} [.{39} [.{2} [.{55} [.{56} [.{327} ] [.{327} ] ] [.{383} ] ] [.{438} ] ] [.{440} ] ] [.{479} ] ] [.{497} ] ] [.{499} ] ] [.{3} [.{10} [.{2} [.{3} [.{6} [.{8} [.{7} [.{16} [.{32} ] [.{445} ] ] [.{461} ] ] [.{468} ] ] [.{476} ] ] [.{482} ] ] [.{485} ] ] [.{487} ] ] [.{497} ] ] [.{6} [.{9} [.{7} [.{1} [.{3} [.{3} [.{9} [.{14} [.{24} ] [.{448} ] ] [.{462} ] ] [.{471} ] ] [.{474} ] ] [.{477} ] ] [.{478} ] ] [.{485} ] ] [.{494} ] ] [.{444} [.{56} ] [.{56} ] ] ]
\end{tikzpicture}
\end{figure}
答案1
这是一个可以重现您想要的图形的解决方案。该解决方案涉及手动“标记”一些节点以给它们命名,以便您稍后在注释树时可以引用它们,因此这是一个非常针对原始问题的解决方案。我不知道您是否想要一个更通用的解决方案。
我的解决方案如下。我手动查找最后一级的节点(我选择值为 448 的节点)并为其命名:\node(levelz){448};
。我对上一级的节点执行相同操作:\node(levelz-1){462}
。我还为根节点命名:\node(Root){0}
。
这些名称可以以不同的方式使用。我可以直接在任何 TikZ 绘图命令中使用它们,例如:\fill[red] (Root) circle(2pt);
这会在根节点上放置一个红点。但它也可以用作\subtreeof
命令的参数,在这种情况下,选定的节点不再是Root
,而是整个树。这使我能够获得整个树的边界框的坐标。例如\subtreeof{Root}.north
会给我顶部的坐标。
通过使用运算符将这些坐标组合起来-|
,我可以得到绘制所需线条的坐标,如下面的代码所示:
\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-qtree}
\begin{document}
\begin{tikzpicture}[ level distance=1cm, growth parent anchor=east, grow=right,scale=0.78,
level distance=1cm,
]
\tikzstyle{every node}=[font=\footnotesize, text width=5mm,anchor=east]
\Tree [.\node(Root){0}; [.{1} [.{1} [.{1} [.{1} [.{2} [.{7} [.{9} [.{4} [.{33} ] [.{474} ] ] [.{478} ] ] [.{487} ] ] [.{494} ] ] [.{496} ] ] [.{497} ] ] [.{498} ] ] [.{499} ] ] [.{4} [.{13} [.{4} [.{4} [.{7} [.{25} [.{9} [.{120} [.{314} ] [.{314} ] ] [.{434} ] ] [.{443} ] ] [.{468} ] ] [.{475} ] ] [.{479} ] ] [.{483} ] ] [.{496} ] ] [.{1} [.{2} [.{18} [.{39} [.{2} [.{55} [.{56} [.{327} ] [.{327} ] ] [.{383} ] ] [.{438} ] ] [.{440} ] ] [.{479} ] ] [.{497} ] ] [.{499} ] ] [.{3} [.{10} [.{2} [.{3} [.{6} [.{8} [.{7} [.{16} [.{32} ] [.{445} ] ] [.{461} ] ] [.{468} ] ] [.{476} ] ] [.{482} ] ] [.{485} ] ] [.{487} ] ] [.{497} ] ] [.{6} [.{9} [.{7} [.{1} [.{3} [.{3} [.{9} [.{14} [.{24} ] [.\node(levelz){448}; ] ] [.\node(levelz-1){462}; ] ] [.{471} ] ] [.{474} ] ] [.{477} ] ] [.{478} ] ] [.{485} ] ] [.{494} ] ] [.{444} [.{56} ] [.{56} ] ] ]
\draw[blue, dashed] (\subtreeof{Root}.south -| levelz.west) -- (\subtreeof{Root}.north -| levelz.west)
node[right, text width=] {Level $z$};
\draw[blue, dashed] (\subtreeof{Root}.south -| levelz-1.west) -- (\subtreeof{Root}.north -| levelz-1.west)
node[left, text width=] {Level $z-1$};
\end{tikzpicture}
\end{document}
其结果为:
更新
正如您在上一个示例中看到的,垂直虚线穿过边的末端。再次阅读您的问题,您说您希望它们“穿过分支”级别。这允许三种解释。第一种是我上面所做的。第二种是考虑边的左端(分叉发生的点)。第三种是考虑边的中点。
所有这些选项都很容易用相同的技术实现。对于第二个选项,您可以将级别为的节点命名z-1
为例如branchz
,将级别为的节点z-2
命名为branchz-1
。使用east
这些节点的锚点,您可以获得分叉发生的坐标。
对于第三个选项,您需要结合前两个选项并计算这些坐标的中点。
以下代码实现了所有选项,并用不同的颜色绘制线条(还用大点标记所选坐标)。我使用了两个嵌套循环。外层循环用于我们想要在树中标记的每个级别(假设中存在名称为levelz
、levelz-1
、branchz
等的适当节点)。内层循环用于为每个级别绘制三个选项。branchz-1
Tree
\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-qtree}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}[ level distance=1cm, growth parent anchor=east,
grow=right,scale=0.78, level distance=1cm,
]
\tikzstyle{every node}=[font=\footnotesize, text width=5mm,anchor=east]
\Tree [.\node(Root){0}; [.{1} [.{1} [.{1} [.{1} [.{2} [.{7} [.{9} [.{4} [.{33} ] [.{474} ] ] [.{478} ] ] [.{487} ] ] [.{494} ] ] [.{496} ] ] [.{497} ] ] [.{498} ] ] [.{499} ] ] [.{4} [.{13} [.{4} [.{4} [.{7} [.{25} [.{9} [.{120} [.{314} ] [.{314} ] ] [.{434} ] ] [.{443} ] ] [.{468} ] ] [.{475} ] ] [.{479} ] ] [.{483} ] ] [.{496} ] ] [.{1} [.{2} [.{18} [.{39} [.{2} [.{55} [.{56} [.{327} ] [.{327} ] ] [.{383} ] ] [.{438} ] ] [.{440} ] ] [.{479} ] ] [.{497} ] ] [.{499} ] ] [.{3} [.{10} [.{2} [.{3} [.{6} [.{8} [.{7} [.{16} [.{32} ] [.{445} ] ] [.{461} ] ] [.{468} ] ] [.{476} ] ] [.{482} ] ] [.{485} ] ] [.{487} ] ] [.{497} ] ] [.{6} [.{9} [.{7} [.{1} [.{3} [.{3} [.\node(branchz-1){9}; [.\node(branchz){14}; [.{24} ] [.\node(levelz){448}; ] ] [.\node(levelz-1){462}; ] ] [.{471} ] ] [.{474} ] ] [.{477} ] ] [.{478} ] ] [.{485} ] ] [.{494} ] ] [.{444} [.{56} ] [.{56} ] ] ]
\foreach \level in {z,z-1} {
\coordinate (option1) at (level\level.west) {};
\coordinate (option2) at (branch\level.east) {};
\coordinate (option3) at ($(branch\level.east)!.5!(level\level.west)$) {};
\foreach \i/\c in {1/red, 2/blue, 3/green} {
\fill[\c] (option\i) circle (2pt);
\draw[\c,dashed] (\subtreeof{Root}.south -| option\i)
-- (\subtreeof{Root}.north -| option\i);
}
}
\end{tikzpicture}
\end{document}
近距离观察有趣的部分: