我想在我的文档中包含如下图形。由于这只是一个示例,并且会有不同的模型,因此我不能只包含它,而是需要能够自己构建它。我认为 TikZ 是一种方便的方法。
我在这个网站的其他地方找到了一个很有前途的基础,但到目前为止,我还没有能够根据自己的具体需求采用它。基本上,我没有包括多行项目,也可能出现错误,因为有时没有“家庭”或类似的东西,就像这个例子中的荷兰的情况一样。
实现此目的的最佳方法是什么?我绝对会喜欢矩形结构,并希望始终将其缩放到 \textwidth 或类似值。这可能吗?谢谢
\documentclass{article}
\usepackage{tikz-qtree}
\begin{document}
\tikzset{edge from parent/.style=
{draw, edge from parent path={(\tikzparentnode.south)
-- +(0,-8pt)
-| (\tikzchildnode)}},
blank/.style={draw=none}}
\begin{tikzpicture}
\matrix
{
\node{\Tree
[.Class \edge[blank];
[.Order \edge[blank];
[.Family \edge[blank];
[.Genus ]]]]};
&
\node{\Tree
[.{$\gamma$-proteobacteria}
[.Alteromonadales
[.Alteromonadaceae {Glaciecola} Alteromonas Agarivorans ] ]
[.Vibrionales [.Vibrionacae Vibrio ]]]};\\
};
\end{tikzpicture}
\end{document}
答案1
如果您不介意的话,您可以切换到forest
使构建树更加整洁的包,只使用方括号来编写树。
这些级别实际上是树的一个分支,但边缘并未绘制(使用命令no edge
)。树的实际显示方式如下:
输出
代码
\documentclass[margin=10pt]{standalone}
\usepackage{tikz}
\usepackage{forest}
\usetikzlibrary{positioning}
\forestset{%
my forest/.style={%
for tree={%
node options={text width=5cm, align=center},
l sep=1cm,
parent anchor=south,
child anchor=north,
if n children=0{tier=word}{},
edge path={%
\noexpand\path [\forestoption{edge}] (!u.parent anchor) -- +(0,-15pt) -| (.child anchor)\forestoption{edge label};
},
}
}
}
\begin{document}
\begin{forest} my forest,
[, for tree={s sep=-5mm} % levels are a bit closer, fix depending on nodes
[, no edge,
[Classes\textsuperscript{$b$}, no edge
[Sub-classes\textsuperscript{$b$}, no edge
[Families\textsuperscript{$b$}, no edge]
]
]
]% levels above here <--o--> tree below here
[$\gamma$-proteobacteria, no edge
[Alteromonadales, name=lvl1
[Alteromonadaceae Glaciecola Alteromonas Agarivorans, name=lvl2
[another node]
]
]
[Vibrionales
[Vibrionacae Vibrio]
]
]
]
\end{forest}
\end{document}
答案2
该解决方案还使用森林但它通过包提供的包装器使用它正义树。这个软件包是实验性的,但我很乐意根据要求提供副本。(我需要实验鼠!)
要点正义树是为了便于在树的左侧和/或右侧提供水平对齐的标签。特别是,它会为您完成所有计算和对齐。您所要做的就是为您想要的级别指定您想要的标签,作为树的主要规范的一部分。
它提供了一个新的环境justtree
,该环境接受一个强制参数。(参数可以为空,但必须存在。环境的内容包括实际的树规范。
\begin{justtree}
{
<tree preamble, options - may be empty>
}
<tree specification>
\end{justtree}
由于你计划做很多类似的树,因此定义一个森林样式,以适应您想要的方形外观。下面设置此样式。(它并不特定于正义树- 你可以用它来做普通的森林树。)
\forestset{
squared just tree/.style={
for tree={
edge path={% set up the squared look
\noexpand\path [\forestoption{edge}] (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
},
由于您还需要多线节点,我们将为样式添加允许这样做的对齐方式。center
将使每行多线节点居中。
align=center,
下一位是可选的。在许多树中,这看起来会更好。基本上,如果子节点数为奇数且大于 2,则中间子节点将与其父节点对齐。因此,如果有 3 个子节点,则第二个子节点将对齐。这确保了从父节点到中间子节点的直线。
if={(isodd(n_children))&&(n_children>2)}
{
for children={
if={equal(n,((n_children("!u"))+1)/2)}
{
calign with current
}{},
}
}{},
从问题来看我不太确定您是否想要这样做,但以下内容可确保每个分支中的最后一个子项水平对齐,即使某些分支中的级别比其他分支多。
if n children=0
{
before packing={tier=terminus}
}{},
},
}
}
这样做的好处是,一旦你找到了自己喜欢的样式,就可以将它应用于所有想要应用的树。在我们的例子中,这意味着我们可以像这样指定树。
\begin{justtree}
回想一下,这个环境采用一个强制参数,其中包含树的序言。
{%
默认情况下,水平标签(根据包的来源,称为“对齐”)将显示在右侧。您可以为单个标签覆盖此设置,但如果您只希望标签显示在左侧,则将默认设置为左侧是合理的。
left justifications,
现在我们只需添加为树木设置的样式。
squared just tree,
序言已经讲完了。
}
现在来看看树规范本身。我写了一篇介绍森林的语法和它的一些选项在第二部分这个答案回答之前的一个问题。
这是根。just=<whatever>
将此级别的标签设置为<whatever>
。绘制树时,标签将自动放置和对齐。
[$\gamma$-proteobacteria, just=Class
这是下一级别的另一个标签。
[Alteromonadales, just=Order
[Alteromonadaceae
[Alteromonas
]
[Glaciecola
]
这是下一级别的标签。请注意,使用级别上的哪个节点来指定标签并不重要。just
始终会将其放在树的最左侧。
[Agarivorans, just=Genus
]
]
]
[Vibrionales
如果标签被指定为不同分支的一部分,则也没有关系。标签仍将位于最左侧分支的左侧。
[Vibrionacae, just=Family
[Vibrio
]
]
]
只是为了好玩:一个多线节点和一个比其他节点具有更少级别的分支。
[A longer text\\ split over 2 lines
[Last]
]
]
\end{justtree}
这将生成以下树:
完整代码:
\documentclass[border=5pt, multi, tikz]{standalone}
\usepackage{justtrees}% version 0.05 : available for experimental use on request (just ask!)
\forestset{
squared just tree/.style={
for tree={
edge path={
\noexpand\path [\forestoption{edge}] (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
},
align=center,
if={(isodd(n_children))&&(n_children>2)}
{
for children={
if={equal(n,((n_children("!u"))+1)/2)}
{
calign with current
}{},
}
}{},
if n children=0
{
before packing={tier=terminus}
}{},
},
}
}
\begin{document}
\begin{justtree}
{%
left justifications,
squared just tree,
}
[$\gamma$-proteobacteria, just=Class
[Alteromonadales, just=Order
[Alteromonadaceae
[Alteromonas
]
[Glaciecola
]
[Agarivorans, just=Genus
]
]
]
[Vibrionales
[Vibrionacae, just=Family
[Vibrio
]
]
]
[A longer text\\ split over 2 lines
[Last]
]
]
\end{justtree}
\end{document}
如果你想尝试正义树, 请告诉我。
我很乐意提供一份该软件包的副本。这里有副本。但它们不是最新版本,因此如果您想尝试,请询问。
编辑和更新
请注意,无需just=
确保级别对齐。只需指定树中该级别的标签内容。如果特定级别不需要标签,则无需指定标签。
为了响应 OP 关于将标签左对齐到树左侧的请求,我修改了包的代码以启用此功能。我忘记了,在简化创建时的代码时justtrees.sty
,prooftrees.sty
我完全放弃了使用标签的分支,而只使用选项tikz+
。这在某些方面使改变标签中文本的对齐方式变得更简单,但在其他方面则更复杂。(秋千和旋转木马。旋转木马和秋千。)
主要问题是需要跟踪节点内容的宽度,以便所有标签都可以放置在相同宽度的节点中。现在的工作方式基本上是,代码检查左侧(右侧)每个标签的内容,看其宽度是否超过宏中存储的宽度。如果是,则更新宏以存储较大的宽度。如果不是,则保持不变。然后,将此宏存储的宽度馈送到左侧(右侧)的标签节点,此外text width
,还适当设置对齐方式。
这些变化在代码的 0.06 版本中有效。
设置标签在左侧的对齐方式
left just align=<alignment>
合理的值是right
(默认),left
或center
。
设置标签在右侧的对齐方式
right just align=<alignment>
合理的值是left
(默认),right
或center
。
因此,为了对齐左上方树中的标签,我们只需按如下方式更改序言:
\begin{justtree}
{%
left justifications,
squared just tree,
left just align=left,
}
以下看起来有点奇怪的示例将左标签设置为左,将右标签设置为右,并且包含一些特别长的标签只是为了检查它是否仍然有效:
\begin{justtree}
{%
left justifications,
squared just tree,
left just align=left,
right just align=right,
}
[$\gamma$-proteobacteria, left just=Class Membership
[Alteromonadales, left just=Order
[Alteromonadaceae
[Alteromonas
]
[Glaciecola
]
[Agarivorans, right just={Genus, Kingdom \& Sovereignty}
]
]
]
[Vibrionales, right just={$E=mc^2$}
[Vibrionacae, left just=Family
[Vibrio
]
]
]
[A longer text\\ split over 2 lines
[Last]
]
]
\end{justtree}
完整代码:
\documentclass[border=5pt, multi, tikz]{standalone}
\usepackage{justtrees}% version 0.06 : available for experimental use on request (just ask!)
\forestset{
squared just tree/.style={
for tree={
edge path={
\noexpand\path [\forestoption{edge}] (!u.parent anchor) -- +(0,-5pt) -| (.child anchor)\forestoption{edge label};
},
align=center,
if={(isodd(n_children))&&(n_children>2)}
{
for children={
if={equal(n,((n_children("!u"))+1)/2)}
{
calign with current
}{},
}
}{},
if n children=0
{
before packing={tier=terminus}
}{},
},
}
}
\begin{document}
\begin{justtree}
{%
left justifications,
squared just tree,
left just align=left,
}
[$\gamma$-proteobacteria, just=Class
[Alteromonadales, just=Order
[Alteromonadaceae
[Alteromonas
]
[Glaciecola
]
[Agarivorans, just=Genus
]
]
]
[Vibrionales
[Vibrionacae, just=Family
[Vibrio
]
]
]
[A longer text\\ split over 2 lines
[Last]
]
]
\end{justtree}
\begin{justtree}
{%
left justifications,
squared just tree,
left just align=left,
right just align=right,
}
[$\gamma$-proteobacteria, left just=Class Membership
[Alteromonadales, left just=Order
[Alteromonadaceae
[Alteromonas
]
[Glaciecola
]
[Agarivorans, right just={Genus, Kingdom \& Sovereignty}
]
]
]
[Vibrionales, right just={$E=mc^2$}
[Vibrionacae, left just=Family
[Vibrio
]
]
]
[A longer text\\ split over 2 lines
[Last]
]
]
\end{justtree}
\end{document}
请注意,目前,如果标签的字体大小与主树中的节点不同,则对齐将不起作用。我认为这是个错误,我想修复它,但无法立即看到如何修复,所以现在还没有修复。
答案3
这是我目前想到的。我尝试用一些内容来填充它,s sep
尽管有些内容可能还有改进的空间。
从我的角度来看,这仍然不是完全完美无缺的,但一开始应该还可以。
- 关于标签,文本应该左对齐,而不是实际的文本框(或这里的正确概念)
“分支”并不完美。它取决于父节点的行数,甚至取决于是否包含小写字母(如 q 或 g)。一般来说,如果“分支”发生在相同的高度并且更靠近子节点而不是父节点,那么它会更整洁。(顺便说一句,这就是我在某些节点中添加一些空白行的原因,这也不是一个理想的解决方案。)
\begin{spacing}{1} \footnotesize \begin{forest} my forest, [, name=1, for tree={s sep=-20mm+(1-level)*2mm}, s sep=-14mm [, no edge, [\textbf{Classes}\textsuperscript{$b$}, no edge, tier=class [\textbf{Sub-classes}\textsuperscript{$b$}, no edge, tier=sclass [\textbf{Families}\textsuperscript{$b$}, no edge, tier=family] ] ] ] [Accounting~systems, no edge, for tree={s sep=-23mm+(0-level)*2mm}, s sep=-23mm [Micro-fair-judgmental\\Commercially-driven, tier=class, s sep=-25mm [Business~economics\\Extreme~judgmental, tier=sclass [Netherlands, tier=country] ] [Business~practice\\Professional rules\\British origin, tier=sclass [U.K.~influence\\Professional~regulation, tier=family, s sep=-32mm [Australia, tier=country] [N.Z., tier=country] [U.K., tier=country] [Ireland, tier=country] ] [U.S.~influence\\SEC~enforcement, tier=family [Canada, tier=country] [U.S.A., tier=country] ] ] ] [Macro-uniform\\Government-driven\\Tax~dominated, tier=class, s sep=-31mm [Code-based\\international\\influences, tier=family, [Italy, tier=country] ] [Plan-based\\~, tier=family, s sep=-30mm [France, tier=country] [Belgium, tier=country] [Spain, tier=country] ] [Statute-based\\~, tier=family [Germany, tier=country] [Japan, tier=country] ] [Economic\\control, tier=family [Sweden, tier=country] ] ] ] ] % \end{forest} \end{spacing}
编辑
在添加edge path={% \noexpand\path [\forestoption{edge}] (!u.parent anchor) -- +(0,-30pt) -| (.child anchor)\forestoption{edge label}; }
或类似一些节点后,我得到了以下树:
就是这样了!