编辑

编辑

我生成了一棵树,它由两棵子树组成,每棵子树都包含很多子树。默认情况下,森林会将它们并排呈现。但是,树的宽度会延伸页面,缩小后页面会变得难以阅读。

因此,我考虑将根节点的一棵子树放在另一棵子树的下方。如何在不改变所有子节点方向的情况下实现这一点?

简单示例:

而不是这样: 相反

我想要这样的东西: 在此处输入图片描述

第一棵树的 LaTeX 代码:

\documentclass{article}
\usepackage{forest}

\begin{document}    
\begin{forest}
[A 
    [B [B1] [B2]] 
    [C [C1] [C2]]
]
\end{forest}  
\end{document}

复杂示例: (注意:为了使示例正常运行,请将linguistics选项添加到森林包中)

[proc [body
    [decls
        [decl [decl\_tbl\_var
            [var\_name ['v1']]
            [tbl\_type\_def [col\_list\_def
                [col\_elem ['b1 INT', roof]]
                [col\_elem ['b2 DOUBLE', roof]]
                [col\_elem
                    [col\_name ['c1']]
                    [datatype ['INT']]
                ]
            ]]
        ]]
        [decl [decl\_tbl\_var
            [var\_name ['v2']]
            [tbl\_type\_def [col\_list\_def
                [col\_elem
                    [col\_name ['c1']]
                    [datatype ['INT']]
                ]
                [col\_elem ['c2 DOUBLE', roof]]
            ]]
        ]]
    ]
    [stmts 
        [stmt\_assign
            [var ['v1']]
            [expr [subquery 
                [select\_clause [attrs 
                    [attr ['a1 b1', roof]]
                    [attr ['SUM('a2 * a3') b2', roof]]
                    [attr ['a4'] [alias ['c1']]]
                ]]
                [from\_clause [tables ['t1']]]
                [group\_by\_clause [group\_by\_expr\_list 
                    [expr ['a1']]
                    [grouping\_set [grouping\_expr\_list 
                        [grouping\_expr [expr ['a1']]]
                        [grouping\_expr [expr ['a4']]]
                    ]]
                ]]
            ]]
        ]
        [stmt\_assign
            [var ['v2']]
            [expr [subquery 
                [select\_clause [attrs 
                    [attr ['a4'] [alias ['c1']]]
                    [attr ['SUM (a2 * a3) c2', roof]]
                ]]
                [from\_clause [tables ['t1']]]
                [group\_by\_clause [group\_by\_expr\_list [expr ['a4']]]]
            ]]
        ]
    ]
]]

在此处输入图片描述

在这个例子中,我想将stmts子树移动到子树下方decls

答案1

最简单的方法就是改变树的结构。例如,

\documentclass{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
  [A 
    [B [B1] [, no edge, coordinate  [C, edge path'={(!uuu.parent anchor) -| (!uul.east |- .east) -- (.east)} [C1] [C2]]] [B2]] 
  ]
\end{forest}   
\end{document}

重组树

根据您需要的频率,您可以使其更加自动化,即不明确更改树的结构,而是让 Forest 为您完成。

在这种情况下,森林肯定会失去对事物的追踪,因此您需要注意确保事物不会相互交叉(例如,边与节点、节点与节点等)。

因此,这需要做更多的工作,但非常可行,尤其是在像这样的相对简单的情况下,您只需将一些子树移动到其兄弟子树下,并以相当一致(如此算法化)的方式更改边缘。因此,自动化需要明确森林应该做什么,但一旦您定义了例程,您就可以在任何需要的地方应用它。

但是,如果您只需要这样做几次,那么更容易的是自己重构树并定义一种样式来适应edge path不可见的父级的改变。

例如,手动方法可能如下所示:

\documentclass{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
  move me down/.style={
    edge path'={(!uuu.parent anchor) -| (!uul.east |- .east) -- (.east)},
    !u.no edge,
    !u.coordinate,
  }
  [A 
    [B [B1] [  [C, move me down  [C1] [C2]]] [B2]] 
  ]
\end{forest}  
\end{document}

这显然会产生与前面的代码相同的输出。

编辑

已编辑因为当提供代表性示例时,原始方法不起作用(叹气)。

基本上,你把movies树的前言放进去,告诉 Forest 你想要这种风格。然后你把选项添加move me down到你想要移动的子树的根节点。也就是说,在合理的范围内。例如,我不建议尝试将一个子树移动到另一棵移动的子树之下。我没有尝试过,但我想那不会成功。

然而,风格处理具有不同层数的相邻子树。当移动的子树向下移动时,它将移动到其相邻子树的下方,无论该子树有 2 个层还是(理论上)77 个层。

请注意,如果事情变得复杂,您不能指望 Forest 能够确定位置,因为事情已经非常棘手了。

例如,

\begin{forest}
  movies
  [A 
    [B [B1] [B2]] [C, move me down  [C1] [C2]]
    [B [B1] [q[x[y[z]]]B2]] [C, move me down  [C1v] [Cg2]]
 ]
\end{forest}  

生产

<code>电影</code> 树

以下是当前示例的代码:

\begin{forest}
  movies
  [proc [body
      [decls
          [decl [decl\_tbl\_var
              [var\_name ['v1']]
              [tbl\_type\_def [col\_list\_def
                  [col\_elem ['b1 INT', roof]]
                  [col\_elem ['b2 DOUBLE', roof]]
                  [col\_elem
                      [col\_name ['c1']]
                      [datatype ['INT']]
                  ]
              ]]
          ]]
          [decl [decl\_tbl\_var
              [var\_name ['v2']]
              [tbl\_type\_def [col\_list\_def
                  [col\_elem
                      [col\_name ['c1']]
                      [datatype ['INT']]
                  ]
                  [col\_elem ['c2 DOUBLE', roof]]
              ]]
          ]]
      ]
      [stmts, move me down
          [stmt\_assign
              [var ['v1']]
              [expr [subquery 
                  [select\_clause [attrs 
                      [attr ['a1 b1', roof]]
                      [attr ['SUM('a2 * a3') b2', roof]]
                      [attr ['a4'] [alias ['c1']]]
                  ]]
                  [from\_clause [tables ['t1']]]
                  [group\_by\_clause [group\_by\_expr\_list 
                      [expr ['a1']]
                      [grouping\_set [grouping\_expr\_list 
                          [grouping\_expr [expr ['a1']]]
                          [grouping\_expr [expr ['a4']]]
                      ]]
                  ]]
              ]]
          ]
          [stmt\_assign
              [var ['v2']]
              [expr [subquery 
                  [select\_clause [attrs 
                      [attr ['a4'] [alias ['c1']]]
                      [attr ['SUM (a2 * a3) c2', roof]]
                  ]]
                  [from\_clause [tables ['t1']]]
                  [group\_by\_clause [group\_by\_expr\_list [expr ['a4']]]]
              ]]
          ]
      ]
  ]]
\end{forest}

产生

OP 的代表性示例,采用 <code>movies</code> 风格

完整代码:

\documentclass[border=10pt]{standalone}
\usepackage[linguistics,edges]{forest}
\forestset{%
  declare toks={move me}{},
  declare toks={bio}{},
  declare toks={symud}{},
  movies/.style={
    forked edges,
  },
  move me down/.style={
    before typesetting nodes={
      if nodewalk valid={p2}{
        if={>O_={!u.n children}{2}}{!u.calign=first}{},
        temptoksa/.option=name,
        bio/.option=!u.name,
        for nodewalk={p,descendants}{
          if n children=0{
            append={[, phantom, tier/.register=temptoksa]},
          }{}
        },
        for nodewalk={
          group={p2}
        }{
          symud/.register=temptoksa, 
          insert before={[, move me/.option=!n.symud, tier/.option=!n.symud, no edge, before packing={
              append/.option=move me,
            }]}
        },
        replace by/.process={Ow{name}{[, no edge, coordinate, tier=##1, before computing xy={
              for nodewalk={
                p,
                tempdimc/.option=s,
                while nodewalk valid={l}{l,tempdimc+/.option=s, typeset node, if n children=0{tempdimc+/.option=max x}{}}
              }{},
              s/.register=tempdimc,
              s+/.option=s sep,
            }, name=##1-MT, append]}},
        edge path'/.process={
          OOw2 {bio}{name}
          {(##1.parent anchor) -- ++(\forestoption{fork sep},0) |- (##2-MT) -| (.east) }%
        },
      }{},
    },
  }
}
\begin{document}
\begin{forest}
  movies
  [proc [body
      [decls
          [decl [decl\_tbl\_var
              [var\_name ['v1']]
              [tbl\_type\_def [col\_list\_def
                  [col\_elem ['b1 INT', roof]]
                  [col\_elem ['b2 DOUBLE', roof]]
                  [col\_elem
                      [col\_name ['c1']]
                      [datatype ['INT']]
                  ]
              ]]
          ]]
          [decl [decl\_tbl\_var
              [var\_name ['v2']]
              [tbl\_type\_def [col\_list\_def
                  [col\_elem
                      [col\_name ['c1']]
                      [datatype ['INT']]
                  ]
                  [col\_elem ['c2 DOUBLE', roof]]
              ]]
          ]]
      ]
      [stmts, move me down
          [stmt\_assign
              [var ['v1']]
              [expr [subquery 
                  [select\_clause [attrs 
                      [attr ['a1 b1', roof]]
                      [attr ['SUM('a2 * a3') b2', roof]]
                      [attr ['a4'] [alias ['c1']]]
                  ]]
                  [from\_clause [tables ['t1']]]
                  [group\_by\_clause [group\_by\_expr\_list 
                      [expr ['a1']]
                      [grouping\_set [grouping\_expr\_list 
                          [grouping\_expr [expr ['a1']]]
                          [grouping\_expr [expr ['a4']]]
                      ]]
                  ]]
              ]]
          ]
          [stmt\_assign
              [var ['v2']]
              [expr [subquery 
                  [select\_clause [attrs 
                      [attr ['a4'] [alias ['c1']]]
                      [attr ['SUM (a2 * a3) c2', roof]]
                  ]]
                  [from\_clause [tables ['t1']]]
                  [group\_by\_clause [group\_by\_expr\_list [expr ['a4']]]]
              ]]
          ]
      ]
  ]]
\end{forest}

\end{document}

我不建议在没有的情况下尝试这一点,forked edges因为即使在最好的情况下,方线也肯定会切断其他东西。

相关内容