全球森林问题

全球森林问题

我想用 Latex 和森林绘制决策树。因此,我找到了以下相关问题,请参阅 如何绘制正确的决策树

所选答案基本满足了我的需求。但是,我无法重现输出。

\documentclass[margin=10pt]{standalone}
\usepackage{tikz,forest}
\usetikzlibrary{arrows.meta}

\forestset{
    .style={
        for tree={
            base=bottom,
            child anchor=north,
            align=center,
            s sep+=1cm,
    straight edge/.style={
        edge path={\noexpand\path[\forestoption{edge},thick,-{Latex}] 
        (!u.parent anchor) -- (.child anchor);}
        },
     if n children={0}
        {tier=word, draw, thick, rectangle}
        {draw, diamond, thick, aspect=2},
    if n=1{%
        edge path={\noexpand\path[\forestoption{edge},thick,-{Latex}] 
        (!u.parent anchor) -| (.child anchor) node[pos=.2, above] {Y};}
        }{
        edge path={\noexpand\path[\forestoption{edge},thick,-{Latex}] 
        (!u.parent anchor) -| (.child anchor) node[pos=.2, above] {N};}
        }
        }
     }
 }

\begin{document}
\begin{forest} 
 [$x_2$, tikz={\draw[{Latex}-, thick] (.north) --++ (0,1);}
    [$x_1$
        [1] 
        [0] 
    ]   
    [$x_3$
        [$x_1$
           [1] 
           [0] 
        ]   
        [0] 
     ]   
 ] 
\end{forest}
\end{document}

使用提供的源代码,结果是:

提供的源代码的输出

然而,将语句集成for tree到森林块中效果更好,但不会产生预期的输出。箭头与节点重叠。

自己的解决方案

有关所用版本的一些信息

  • 操作系统:Ubuntu 17.10

  • 森林:v2.1.5

  • Tikz:v3.0.1a

我已经查看了森林的当前文档,但没有发现森林当前版本发生变化的内容。

所以,我的主要问题是:

  • 我如何陈述森林树木的全球配置?
  • 为什么\forestset不能正常工作?

提前致谢。

答案1

.style从未得到支持,而且据我了解(来自 Forest 手册,其中详细记录了这一变化),它从未正常工作过。在 Forest 的当前版本中,它根本不起作用,但是default preamble,正如 Jasper Habicht 提到的,它可以工作。

如果您希望将此作为默认样式,我假设您会多次使用它。在这种情况下,我会简化代码并尝试使其尽可能灵活和自动化。特别是,我会尝试避免硬编码尺寸以避免冲突,而是通过以forest找出合理布局的方式来处理问题。

我认为,这可以通过利用一些提供的专用增长方向感知锚点来实现。(其中许多在软件包的 1 版中并不存在。)

例如,您可能会考虑以下内容。

\forestset{
  default preamble={
    before typesetting nodes={
      !r.replace by={[, coordinate, append]}

这将自动添加一个假根,这样上面的箭头就不需要手动绘制了。这有助于防止在编辑过程中出现线宽和距离等不一致的情况。

    },
    where n children=0{
      tier=word,
    }{
      diamond, aspect=2,
    },

这本质上是原始代码,经过精简,用于将终端节点与其他节点区别对待。

    where level=0{}{

不要对第一个节点(这是实际的、原始的根)做任何事情,因为我们不想在这里使用标签。

      if n=1{
        edge label={node[pos=.2, above] {Y}},
      }{
        edge label={node[pos=.2, above] {N}},
      }

这将设置标签。我不知道为什么您提供的代码没有使用,edge label因为这个功能根本不是新的,而且在版本 1 中肯定可用。

    },
    for tree={
      edge+={thick, -Latex},

一致的边缘。

      math content,

这都是数学,所以我们不必一直打字$...$

      s sep'+=1cm,

比原来快一点(在版本 1 中不可用)

      draw,
      thick,
      edge path'={ (!u) -| (.parent)},

这可以避免摆弄硬编码的节点微调以使事物分散。edge path'在版本 1 中不可用。它包装其参数以构造完整路径,包括edge label(由于某种原因,您的问题中的代码将其消除)。.parent此处指的是当前节点(即子节点)的锚点。它是其边界上朝向其父节点的一个点。(嗯,通常如此。)

通过使用!u而不是特定的锚点,我们得到 TiZ 来确定在菱形的边界上绘制的位置。这意味着我们不需要对左右分支进行不同的定义。这也意味着我们不必对指南针方向进行硬编码,因为这将根据树的生长方向等自动调整,就像这样.parent做一样。

    }
  }
}

我们就完成了。

半自动构建的决策树

完整代码:

\documentclass[border=10pt]{standalone}
\usepackage{forest}
\usetikzlibrary{arrows.meta}

\forestset{
  default preamble={
    before typesetting nodes={
      !r.replace by={[, coordinate, append]}
    },
    where n children=0{
      tier=word,
    }{
      diamond, aspect=2,
    },
    where level=0{}{
      if n=1{
        edge label={node[pos=.2, above] {Y}},
      }{
        edge label={node[pos=.2, above] {N}},
      }
    },
    for tree={
      edge+={thick, -Latex},
      math content,
      s sep'+=1cm,
      draw,
      thick,
      edge path'={ (!u) -| (.parent)},
    }
  }
}

\begin{document}
\begin{forest} 
    [x_2
        [x_1
            [1] 
            [0] 
        ]   
        [x_3
            [x_1
              [1] 
              [0] 
            ]   
            [0] 
        ]   
    ] 
\end{forest}
\end{document}

答案2

首先,根据软件包文档,森林的正确默认样式(至少在 2+ 版本中)是default preamble使用\forestset

(编辑:我刚刚读到您正在使用该forest软件包的 2+ 版本。默认设置确实已从 1 版更改,这可能是代码未产生所需输出的原因。)

其次,为了使箭头不与节点重叠,您要么必须改变菱形的外观以使节点稍微窄一些,要么必须增加最低级别节点的距离。

\documentclass[margin=10pt]{standalone}
\usepackage{tikz,forest}
\usetikzlibrary{arrows.meta}

\forestset{
    default preamble={
        for tree={
            base=bottom,
            child anchor=north,
            align=center,
            s sep+=1cm,                      % or use: s sep +=1.5 cm ...
    straight edge/.style={
        edge path={\noexpand\path[\forestoption{edge},thick,-{Latex}] 
        (!u.parent anchor) -- (.child anchor);}
        },
    if n children={0}
        {tier=word, draw, thick, rectangle}
        {draw, diamond, aspect=1.25, thick}, % ... and retain: aspect=2
    if n=1{%
        edge path={\noexpand\path[\forestoption{edge},thick,-{Latex}] 
        (!u.parent anchor) -| (.child anchor) node[pos=.2, above] {Y};}
        }{
        edge path={\noexpand\path[\forestoption{edge},thick,-{Latex}] 
        (!u.parent anchor) -| (.child anchor) node[pos=.2, above] {N};}
        }
        }
     }
 }

\begin{document}
\begin{forest}
 [$x_2$, tikz={\draw[{Latex}-, thick] (.north) --++ (0,1);}
    [$x_1$
        [1] 
        [0] 
    ]   
    [$x_3$
        [$x_1$
           [1] 
           [0] 
        ]   
        [0] 
     ]   
 ] 
\end{forest}
\end{document}

使用s sep+=1cmaspect=1.25

在此处输入图片描述

…或者与s sep+=1.5cmaspect=2

在此处输入图片描述

相关内容