级别样式

级别样式

我想绘制一棵树的“剪切”区域,并通过在图表的顶部和底部用虚线边缘来直观地强调这一点(以象征更上层和更下的层级)。

我尝试使用环境选项中定义的样式\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 基于 TiZ、主机包的功率也是可以用的。

例如,

\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}

相关内容