我如何升级={Lu}{} 的 Forest 代码,以便我的图表可以与当前 Forest 一起编译?

我如何升级={Lu}{} 的 Forest 代码,以便我的图表可以与当前 Forest 一起编译?

我使用 Forest 版本 1 创建了下图:

v1

\documentclass[tikz,border=10pt]{standalone}
\usepackage{forest-1}% forest v.1

\begin{document}

\begin{forest}
  for tree={
    font=\sffamily\scriptsize,
    line width=1pt,
    draw,
    anchor=west,
    child anchor=west,
    parent anchor=east,
    grow'=east,
    align=center,
    edge path={
      \noexpand\path[line width=1pt, ->, \forestoption{edge}]
      (!u.parent anchor) -| +(5pt,0) -- +(5pt,0) |- (.child anchor) \forestoption{edge label};
    },
    for={Lu}{if={n_children==1}{l sep+=10pt}{}},
  },
  where level={1}{s+=-20pt}{},
  [Here\\Village, name=pc
    [There village\\your bird, name=arid
    ]
    [, phantom
      [Bananas, name=fb, xshift=-15pt, where n children=0{tier=sk}{}
        [Pineapple, name=sf
          [Middling\\villages?, name=solar
            [Current\\paper, name=cp, edge label={node [font=\sffamily\scriptsize, near end, auto, xshift=-1.5pt] {Imprudent}}
            ]
          ]
          [Creative\\endearments?, name=apple
            [Fantastic\\imaginations, name=su, edge label={node [font=\sffamily\scriptsize, near end, auto, xshift=-1.5pt] {Basic}}
            ]
          ]
          [Heathen\\hopscotch?, name=pear
            [Beneficent\\benevolence, name=cl, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Higher}}, edge={draw=none}
            ]
          ]
        ]
        [Zoological, name=gf
          [Orange\\kangaroos?, name=star
            [Strawberry\\seeker, name=rs, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Lower}}
            ]
          ]
          [Fragility of\\foundations?, name=hercules
            [Memorial\\cooks, name=ws, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Earthling}}
            ]
          ]
          [Best\\antelopes?, name=astro
            [Stellar\\horizons, name=ca, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Martian}}
            ]
          ]
        ]
      ]
    ]
    [Bad hollows\\spotty slugs, name=avid
    ]
  ]
  \begin{scope}[line width=1pt, ->]
    \draw (solar.east) -- (solar.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (su.west);
    \draw (apple.east) -| +(5pt,0) -- +(5pt,0) |- (cp.west);
    \draw (pear.east) -- (pear.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cp.west);
    \draw (pear.east) -- (pear.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (su.west);
    \draw (star.east) -- (star.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cl.west);
    \draw (star.east) -- (star.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ws.west);
    \draw (star.east) -- (star.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ca.west);
    \draw (astro.east) -- (astro.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cl.west);
    \draw (astro.east) -- (astro.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (rs.west);
    \draw (astro.east) -- (astro.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ws.west);
    \draw (hercules.east) -- (hercules.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cl.west);
    \draw (hercules.east) -- (hercules.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (rs.west);
    \draw (hercules.east) -- (hercules.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ca.west);
    \draw (avid.north) -- (avid.north |- fb.south);
    \draw (arid.south -| avid.north) -- (avid.north |- fb.north);
  \end{scope}
\end{forest}
\end{document}

该代码无法与 Forest v.2 或更新版本编译,因为

    for={Lu}{if={n_children==1}{l sep+=10pt}{}},

不再是有效代码:for已被升级删除。

手册告诉我该键已重命名为for group(第 85 页):

这些键已被重命名:

old     new           compat key (all but the last are in -most)
...
for     for group     1.0-for
...

我今天最终从幻灯片中删去了这张图表,因为我无法根据手册中的说明弄清楚如何更新当前森林的图表。

最初,我尝试过,

    for group={Lu}{if={n_children==1}{l sep+=10pt}{}},

然而,事情进展得并不顺利:

! Package pgfkeys Error: I do not know the key '/tikz/{Lu}{if={n_children==1}{l
 sep+=10pt}{}}' and I am going to ignore it. Perhaps you misspelled it.

See the pgfkeys package documentation for explanation.

我认为这意味着 Forest 解析for group=,然后尝试传递{Lu}{if ...}给 TiZ 作为单个键。我不知道为什么。我预计它会寻找一些东西,group因此如果没有其他的话,会从 Forest 中得到某种错误。

点击有关 的信息链接for group,我最终进入第 30 页,其中包含有关 的信息for <step>。因为这包括以下示例

for nodewalk={uu2}{blue}

for n=2{circle,draw}

我需要用 做什么不同的事情并不明显for group

group步骤记录在第 50-1 页。

group=<nodewalk>

将其<nodewalk>视为(外部)节点行走的单个步骤,即外部每一步键列表仅在嵌入节点行走结束时执行。嵌入<nodewalk>从外部节点行走继承历史。使用此键相当于编写

Nodewalk={every step=independent,history=inherited}<nodewalk>{}, current

→ 可以安全地修改的每一步键列表<nodewalk>

→ 对于组也进行了定义。

现在,我必须承认,嵌入式节点遍历对我来说仍然有点神秘,当我在手册的这一部分中找到我认为我需要的东西时,我的心就会沉下去。

但是,如果group以这种方式定义,我不确定如何for group有意义,因为for Nodewalk似乎没有意义。也就是说,似乎group只能是内部节点行走中的一步,而不是外部节点行走中的一步。

因此我尝试

    for nodewalk={group={Lu}}{if={n_children==1}{l sep+=10pt}{}},

这尝试用作group内部嵌入式节点行走中的一步。如果我理解正确的话,这将导致最后一步成为外部节点行走中的当前步骤,然后我的条件应该以与版本 1 中的原始代码相同的方式应用。

但是我收到另一个错误

! Package forest Error: nodewalk stepped to the invalid node
(forest)                nodewalk stack: ",root',tree,group,last leaf".

See the forest package documentation for explanation.

这是一个 Forest 错误,虽然比较好,但我不确定我是否理解了它。看起来好像L发生在外部 nodewalk 中,在之后group。但Lu应该是group,所以我不确定这是什么意思。

然而,这可能仅仅是由于 Forest 从 1 版到 2 版的另一个变化:即,现在不存在的步骤会导致错误,而以前不会这样。

我尝试

    for nodewalk={on invalid=fake,group={Lu}}{if={n_children==1}{l sep+=10pt}{}},

但是,我无法on invalid以这种方式在外部节点中使用。我不完全理解为什么,但我知道它不起作用。

因此我尝试

    for nodewalk={%
      Nodewalk={on invalid=fake}{group={Lu}}{if={n_children==1}{l sep+=10pt}{}}
    }{},

这让我

! Package forest Error: nodewalk stepped to the invalid node
(forest)                nodewalk stack: ",root',tree,Nodewalk,group,last leaf".

想到我可能需要on invalid小组内部,我尝试

    for nodewalk={%
      Nodewalk={on invalid=fake}{group={on invalid=fake,Lu}}{if={n_children==1}{l sep+=10pt}{}}
    }{},

这抱怨说这f不是on invalid再次有效的选择。

我放弃了,我把电话线改成了

\usepackage[compat=1.0-for]{forest}

并恢复

for={Lu}{if={n_children==1}{l sep+=10pt}{}},

这再次让我产生了关于无效性的抱怨:

! Package forest Error: nodewalk stepped to the invalid node
(forest)                nodewalk stack: ",root',tree,last leaf".

所以我尝试

\usepackage[compat=1.0-for,compat=1.0-forstep]{forest}

这给了我一个错误,我不知道该怎么办

! Undefined control sequence.
\forest@forstepwrapper ...dewalk@config@oninvalid 
                                                  }}\forest@marshal 

我放弃了,并从课堂演示文稿中剪掉了该图表。

如果我使用

\usepackage[compat=1.0-all]{forest}

那么我的代码确实可以用版本 2 进行编译,但是它看起来与使用版本 1 获得的结果完全不同:

版本 2 兼容

这几乎不是人们希望兼容密钥能够实现的功能!

另一方面,使用compat=1.0-most仍然会产生无效错误。

在这种情况下应如何应用升级说明,以及如何从手册中的更改列表或其他修订中确定这一点?

为什么兼容性密钥在这里会失败,并且为什么在这种情况下会如此引人注目compat=1.0-all

答案1

首先快速回答一下,只是为了让示例编译。分析如下。

使用以下方式加载包

\makeatletter
\def\forest@nodewalk@config@oninvalid{fake}
\makeatother
\usepackage[compat={1.0-for,1.0-forstep}]{forest}

并替换for={Lu}{...}for={last leaf',u}。结果将不会是确切地相同,但足够接近。

快速编辑 1,固定l右侧叶子的距离。for={Lu}{if={n_children==1}{l sep+=10pt}{}}用替换for last leaf={for parent={if={n_children==1}{l sep+=10pt}{}}}。(这仍然需要compat=1.0-forstep。)

快速编辑 2,修复s根子节点的距离。替换where level={1}{s+=-20pt}{}s sep+=20pt

完整的 v2 代码产生的结果与 v1 完全相同:

\documentclass[tikz,border=10pt]{standalone}
\makeatletter
\def\forest@nodewalk@config@oninvalid{fake}
\makeatother
\usepackage[compat=1.0-forstep]{forest}

\begin{document}

\begin{forest}
  for tree={
    font=\sffamily\scriptsize,
    line width=1pt,
    draw,
    anchor=west,
    child anchor=west,
    parent anchor=east,
    grow'=east,
    align=center,
    edge path={
      \noexpand\path[line width=1pt, ->, \forestoption{edge}]
      (!u.parent anchor) -| +(5pt,0) -- +(5pt,0) |- (.child anchor) \forestoption{edge label};
    },
    % for={last leaf',u}{if={n_children==1}{l sep+=10pt}{}},
    for last leaf={for parent={if={n_children==1}{l sep+=10pt}{}}},
  },
  % where level={1}{s+=-20pt}{}
  s sep+=20pt,
  [Here\\Village, name=pc
    [There village\\your bird, name=arid
    ]
    [, phantom
      [Bananas, name=fb, xshift=-15pt, where n children=0{tier=sk}{}
        [Pineapple, name=sf
          [Middling\\villages?, name=solar
            [Current\\paper, name=cp, edge label={node [font=\sffamily\scriptsize, near end, auto, xshift=-1.5pt] {Imprudent}}
            ]
          ]
          [Creative\\endearments?, name=apple
            [Fantastic\\imaginations, name=su, edge label={node [font=\sffamily\scriptsize, near end, auto, xshift=-1.5pt] {Basic}}
            ]
          ]
          [Heathen\\hopscotch?, name=pear
            [Beneficent\\benevolence, name=cl, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Higher}}, edge={draw=none}
            ]
          ]
        ]
        [Zoological, name=gf
          [Orange\\kangaroos?, name=star
            [Strawberry\\seeker, name=rs, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Lower}}
            ]
          ]
          [Fragility of\\foundations?, name=hercules
            [Memorial\\cooks, name=ws, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Earthling}}
            ]
          ]
          [Best\\antelopes?, name=astro
            [Stellar\\horizons, name=ca, edge label={node [font=\sffamily\scriptsize, near end, xshift=-1.5pt, below] {Martian}}
            ]
          ]
        ]
      ]
    ]
    [Bad hollows\\spotty slugs, name=avid
    ]
  ]
  \begin{scope}[line width=1pt, ->]
    \draw (solar.east) -- (solar.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (su.west);
    \draw (apple.east) -| +(5pt,0) -- +(5pt,0) |- (cp.west);
    \draw (pear.east) -- (pear.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cp.west);
    \draw (pear.east) -- (pear.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (su.west);
    \draw (star.east) -- (star.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cl.west);
    \draw (star.east) -- (star.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ws.west);
    \draw (star.east) -- (star.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ca.west);
    \draw (astro.east) -- (astro.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cl.west);
    \draw (astro.east) -- (astro.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (rs.west);
    \draw (astro.east) -- (astro.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ws.west);
    \draw (hercules.east) -- (hercules.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (cl.west);
    \draw (hercules.east) -- (hercules.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (rs.west);
    \draw (hercules.east) -- (hercules.east -| apple.east) -| +(5pt,0) -- +(5pt,0) |- (ca.west);
    \draw (avid.north) -- (avid.north |- fb.south);
    \draw (arid.south -| avid.north) -- (avid.north |- fb.north);
  \end{scope}
\end{forest}
\end{document}

分析

OP 勇敢地试图抵抗我的包裹,但却被至少四个错误所挫败。

  • 中的一个错误compat=1.0-forstep。兼容模式应该保存和恢复的内部宏\forest@nodewalk@config@oninvalid在程序包加载期间未初始化。解决方法是在加载程序包之前定义此宏,如本答案顶部所示。

  • 的实施不完整compat=1.0-forstep。虽然此兼容键使森林默默地忽略了步骤(上文,L)到无效节点,但进一步的步骤(上文,u)会导致错误,这与 v1 不同。上面的快速编辑 1 中给出了解决方法。

  • 中的一个错误for group。虽然groupnodewalk 中需要一个参数,但实际上for group不需要。这个错误还会影响next on tierprevious on tier(我发现它实际上还包含两个错误......)

  • compat=1.0-stages(包含在 中),在 v2.0.2 中引入了一个错误compat=1.0-all:给定的选项根本无法处理。

OP 在战斗中犯了一个错误:试图on invalid错误地使用。这个键接受的参数不止一个,而是两个:模式和在此模式下要执行的键。(但这里的文档也有部分错误!)

最后细节:where level={1}{s+=-20pt}{}由于 v1 中的一个错误,它只能工作。增加兄弟节点之间的 s 距离的正确方法是增加s sep其父节点的 s 距离,如上面的快速编辑 2 所示。

为了使代码在 v2 中工作compat,请将原始代码替换for={Lu}{...}

if n children={0}{for parent={if={n_children==1}{l sep+=30pt}{}}}{}

相关内容