我想绘制一棵树的“剪切”区域,并通过在图表的顶部和底部用虚线边缘来直观地强调这一点(以象征更上层和更下的层级)。
我尝试使用环境选项中定义的样式\tikzpicture
,但未能达到预期的结果,如下所示:
对我来说,“最外层”边缘(我希望是虚线)只是普通的线条。
\documentclass{beamer}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[
every node/.style={minimum size=4mm, inner sep=0.5mm},
normal/.style={circle,draw},
invis/.style={draw=none},
border/.style={ edge from parent/.style={dashed,draw} },
acc/.style={circle,thick,draw=green!50,fill=green!2},
rej/.style={circle,thick,draw=red!50,fill=red!20},
semithick]
node[invis] (root) {}
child[level distance=11mm] { node[border,normal] {x}
child {node[acc] {x1}
child {node[border,invis] {} }
child {node[border,invis] {} }
child {node[border,invis] {} }
}
child {node[rej] {x2} }
child {node[normal] {x3}
child {node[invis,border] {} }
child {node[invis,border] {} }
child {node[invis,border] {} }
}
};
\end{tikzpicture}
\end{document}
我的第一个想法是,也许一个节点的选项中只能定义一种样式,但即使将最后一个树节点的两种样式交换后,也没有任何区别。我还尝试在同一个 [] 块中应用样式并设置选项,并且成功了,所以这似乎不是问题所在。
我知道 TikZ 的作者在手册中指出“将节点选项放在正确的位置是一门神秘的艺术”,但是(仔细阅读后)我认为它基本上是这样的:
- 在 a 中定义的选项
node
是局部有效的。 - 命令中定义的选项
child
会被其所有子节点继承。
当尝试将border
样式传递给child
命令作为替代时,我做获取适用于底部的虚线边,但如果我将它传递给第一个可见子节点(x),则由于继承机制,树中的所有线都是虚线(甚至节点轮廓!)。
我做错了什么/我应该改变什么才能达到预期的结果?
答案1
只需使用 Forest 进行快速演示。Forest 的主要优势在于其强大、灵活性和简洁的语法。内容和样式的规律可以转化为自动配置规则,并且树本身可以非常简洁地指定。由于 Forest 基于 Ti钾Z、主机包的功率也是可以用的。
例如,
\begin{forest}
bordered tree,
[
[x, border
[x1, acc, for descendants=border
[][][]
]
[x2, rej]
[x3, for children=border
[][][]
]
]
]
\end{forest}
指定目标树:
下面部分解释了第一个技巧,并展示了一两个额外的技巧,
\begin{forest}
bordered tree,
[
[x, border, normal
[x1, acc, for descendants=border, label=left:\texttt{for descendants}
[][.,label=left:bordered children [][]][]
]
[x2, rej]
[x3, normal, for children=border, label=right:\texttt{for children}
[][.,label=right:unbordered children [][]][, for current and ancestors={edge+=blue}]
]
]
]
\end{forest}
生成结果:
完整代码:
\documentclass[border=10pt]{standalone}
\usepackage{forest}
\forestset{
declare boolean={border}{0},
bordered tree/.style={
for tree={
minimum size=4mm,
inner sep=0.5mm,
edge+={semithick},
semithick,
},
before typesetting nodes={
where border={
edge+={dashed, draw},
}{},
where={isodd(n_children)}{
tempcounta/.process={
Ow+n {n children}{(##1+1)/2}
},
for n={
> R {tempcounta} % doesn't work to plug the above in directly ??'
}{calign with current edge},
}{},
where content={}{}{normal},
},
},
/tikz/.cd,
normal/.style={circle,draw},
invis/.style={draw=none},
acc/.style={circle,thick,draw=green!50,fill=green!2},
rej/.style={circle,thick,draw=red!50,fill=red!20},
}
\begin{document}
\begin{forest}
bordered tree,
[
[x, border
[x1, acc, for descendants=border
[][][]
]
[x2, rej]
[x3, for children=border
[][][]
]
]
]
\end{forest}
\begin{forest}
bordered tree,
[
[x, border, normal
[x1, acc, for descendants=border, label=left:\texttt{for descendants}
[][.,label=left:bordered children [][]][]
]
[x2, rej]
[x3, normal, for children=border, label=right:\texttt{for children}
[][.,label=right:unbordered children [][]][, for current and ancestors={edge+=blue}]
]
]
]
\end{forest}
\end{document}
答案2
主要问题是,你为边缘设置的样式应该应用于命令,child
而不是命令node
本身。这是我在第二个解决方案中展示的。可能更好的方法是为级别设置样式。我先给出这个。
级别样式
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[
every node/.style={minimum size=4mm, inner sep=0.5mm},
level 1/.style={every child/.style={edge from parent/.style={draw,dashed}}},
level 2/.style={every child/.style={edge from parent/.style={draw,solid}}},
level 4/.style={every child/.style={edge from
parent/.style={draw,dashed}},sibling distance=5mm},
normal/.style={circle,draw,solid},
acc/.style={circle,thick,solid,draw=green!50,fill=green!2},
rej/.style={circle,thick,solid,draw=red!50,fill=red!20},
semithick]
\node (root) {}
child[level distance=11mm] { node[normal] {x}
child {node[acc] {x1}
child { node[normal] {} child child}
child { node[normal] {} child child}
}
child {node[rej] {x2} }
child {node[normal] {x3}
child {node[normal] {} child }
child {node[acc] {} child child }
child {node[normal] {} child child child}
}
};
\end{tikzpicture}
\end{document}
这假设截止深度均匀。第 2 级的样式由较低级别继承,因此您可以为第一级、第二级和最后一级指定样式。如果截止深度不均匀,您可以将最后一级的子级写为
child { edge from parent[dashed] }
产生一条下降的虚线。
儿童风格
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[
every node/.style={minimum size=4mm, inner sep=0.5mm},
normal/.style={circle,draw},
invis/.style={draw=none},
border/.style={ edge from parent/.style={dashed,draw} },
normaledge/.style={ edge from parent/.style={solid,draw}},
acc/.style={circle,thick,draw=green!50,fill=green!2},
rej/.style={circle,thick,draw=red!50,fill=red!20},
semithick]
\node[invis] (root) {}
child[level distance=11mm,border] { node[normal] {x}
child[normaledge] {node[acc] {x1}
child[border] {node {} }
child[border] {node {} }
child[border] {node {} }
}
child[normaledge] {node[rej] {x2} }
child[normaledge] {node[normal] {x3}
child[border] {node[invis] {} }
child[border] {node[invis] {} }
child[border] {node[invis] {} }
}
};
\end{tikzpicture}
\end{document}
我介绍了一种normaledge
非边界的边缘样式。
答案3
另一种解决方案是使用istgame
包。istgame
环境就像tikzpicture
环境一样,因此您可以使用任何在环境macros and options
中工作的东西tikzpicture
。
\documentclass{standalone}
\usepackage{istgame}
\begin{document}
\begin{istgame}[font=\footnotesize]
\setistEllipseNodeStyle{6mm}
\xtdistance{15mm}{15mm}
\istroot[north](0)
\istb[dashed] \endist
\istrooto(0){x}
\istb \istb \istb \endist
\xtdistance{15mm}{10mm}
\istrooto(1)(0-1){x1}
\istb[dashed] \istb[dashed] \istb[dashed] \endist
\istrooto(2)(0-2){x2}
\endist
\istrooto(3)(0-3){x3}
\istb[dashed] \istb[dashed] \istb[dashed] \endist
\end{istgame}
\end{document}