移除边缘标签并修复森林中的边缘

移除边缘标签并修复森林中的边缘

我正在尝试创建一个简单的层次结构,但无法让forest包完全按照我的要求执行。这是我目前所拥有的:

\documentclass[border=5pt]{standalone}
\usepackage{forest}
\begin{document}
\forestset{
  nolabel/.style={% abbreviation for Edge Label
             edge label={node[midway, font=\small, text=black,
                         fill=white, inner sep=2pt]{}},
             }
          }% end of forestset
          
\begin{forest}
  for tree={
    parent anchor=south,
    child anchor=north,
    anchor=north,
    calign=first,
    s sep = 0,
    edge path={
      \noexpand\path [draw, \forestoption{edge}]
      (!u.east) +(-2pt,-5pt) -| node[fill,circle,inner sep=1.25pt] {} (.child anchor)\forestoption{edge label};
    },
    before typesetting nodes={
      if n=1
        {insert before={[,phantom]}}
        {}
    },
    fit=band,
    before computing xy={l=20pt},
  }
[ $A$
  [$a_1$]
  [$\cdots$, nolabel]
  [$a_2$
    [$b_1^{(1)}$]
    [$b_2^{(1)}$
      [$c_1^{(2)}$]
      [$c_2^{(2)}$]
      [$c_3^{(2)}$]
    ]
    [$b_3^{(1)}$
      [$c_4^{(2)}$]
      [$c_5^{(2)}$]
      [$c_6^{(2)}$]    
    ]
  ]
  [$\cdots$, nolabel]
]
\end{forest}

\end{document}

产生 在此处输入图片描述

使用no label样式,我设法删除了省略号节点顶部的圆圈,但我仍然有边缘(红色圆圈)。我无法使用no edge找到的选项将其删除在这篇文章中。另外,我不明白为什么第一层和第二层的边的长度不同(红色矩形),所以我想知道是否有解决方法可以使这些长度相等。

答案1

如果我们加载库,Forest 已经有一个绘制直边树的选项edgesforked edges然后启用树的样式。但是,在我们的例子中,我们不需要 3 部分路径,而只需要 2 部分路径。要消除第一个“腿”,我们可以设置fork sep'=0pt。为了在不进行手动调整的情况下获得正确的对齐,我们可以设置parent anchor=south east

树有三种基本类型的节点:

  1. true phantom,自动插入;
  2. 节点\cdots只需要路径的第二个“腿”,而不需要第三个,并且没有圆圈;
  3. 其他节点需要第二条和第三条“腿”,以及圆圈。

Forest 已经将第一种类型与其他两种类型区分开来,因此我们只需创建一个选项来区分第二种和第三种。我这样称呼phantom edge并不完全准确。(也许partial edge会更好?)

  declare boolean={phantom edge}{0},

默认情况下为 false。我们将其添加phantom edge到需要此样式的节点。

处理圆/无圆的最直接的方法是利用选项,edge label而不是将圆直接硬编码到边缘规范中。

      edge label={node[midway,fill,circle,inner sep=1.25pt]{}},

我一开始是选择性地应用它,但最终决定普遍应用它并稍后选择性地覆盖该应用程序更有意义。

我们使用新的布尔值来调整edge path和,edge label同时插入真正的幻影。我们将其取出for tree以使代码更清晰,并使用whereif覆盖整个树。

    before typesetting nodes={%
      where n=1{%
        insert before={[,phantom]}
      }{%
        +content=\strut,

添加\strut所有地方(除了真实的幻影)会让我们得到统一的节点高度。

        if phantom edge={%
          edge path'={(!u.parent anchor)   -- (.child anchor -| !u.parent anchor)},

请注意使用edge path'而不是 来edge path简化代码并避免重复标准包装器。还请注意,使用child anchorparent anchor会使代码更灵活一些,以防我们以后需要进行调整。

          edge label={},

这将删除edge label我们的第二种节点类型(即圆形节点)。

        }{%

对于第三种类型,无需执行任何操作,因为它们只是使用我们已经设置的默认值。

        },
      },
    },

对于父节点和子节点之间的分离,我将 的更改l从 中移除for tree。这确保为所有节点(包括插入节点)设置该选项,而原始代码并未将其应用于插入节点。l sep也比 更接近我们在这里想要的l,但我们需要更早一点设置它才能使其生效。

    before packing={%
      for tree={l sep'=-5pt},
    },  

由于我不明白的原因,这些变化不足以规范路径第三“段”的长度。但是,添加text height=1em似乎for tree有效,即使我不确定它在做什么。

最后,我将所有内容包装成一种样式tree lines,以将树规范与用于排版的样式分开。

\forestset{%
  declare boolean={phantom edge}{0},
  tree lines/.style={%
    forked edges,
    for tree={%
      fork sep'=0pt,
      math content,
      parent anchor=south east,
      anchor=north,
      calign=first,
      s sep' = 0pt,
      text height=1em,
      fit=band,
      edge label={node[midway,fill,circle,inner sep=1.25pt]{}},
    },
    before typesetting nodes={%
      where n=1{%
        insert before={[,phantom]}
      }{%
        +content=\strut,
        if phantom edge={%
          edge path'={(!u.parent anchor)   -- (.child anchor -| !u.parent anchor)},
          edge label={},
        }{%
        },
      },
    },
    before packing={%
      for tree={l sep'=-5pt},
    },  
  },
}% end of forestset

树线

完整代码:

\documentclass[border=5pt]{standalone}
% ateb: https://tex.stackexchange.com/a/704927/ addaswyd o gwestiwn aaragon: https://tex.stackexchange.com/q/598942/
\usepackage[edges]{forest}
\forestset{%
  declare boolean={phantom edge}{0},
  tree lines/.style={%
    forked edges,
    for tree={%
      fork sep'=0pt,
      math content,
      parent anchor=south east,
      anchor=north,
      calign=first,
      s sep' = 0pt,
      text height=1em,
      fit=band,
      edge label={node[midway,fill,circle,inner sep=1.25pt]{}},
    },
    before typesetting nodes={%
      where n=1{%
        insert before={[,phantom]}
      }{%
        +content=\strut,
        if phantom edge={%
          edge path'={(!u.parent anchor)   -- (.child anchor -| !u.parent anchor)},
          edge label={},
        }{%
        },
      },
    },
    before packing={%
      for tree={l sep'=-5pt},
    },  
  },
}% end of forestset
\begin{document}
          
\begin{forest}
  tree lines,
  [ A
    [a_1]
    [\cdots, phantom edge]
    [a_2
      [b_1^{(1)}]
      [b_2^{(1)}
        [c_1^{(2)}]
        [c_2^{(2)}]
        [c_3^{(2)}]
      ]
      [b_3^{(1)}
        [c_4^{(2)}]
        [c_5^{(2)}]
        [c_6^{(2)}]    
      ]
    ]
    [\cdots, phantom edge]
  ]
\end{forest}

\end{document}

答案2

您的nolabel代码需要更改edge path而不是edge label。为起始坐标命名,例如ZZ,然后使用正交坐标(ZZ-|.child anchor)绘制水平部分但不绘制垂直部分。

为了使不同级别的垂直边缘保持一致,请添加minimum height=6mm, inner ysep=0pt

在此处输入图片描述

\documentclass{article}
\usepackage{forest}
\begin{document}
\forestset{
  nolabel/.style={
    edge path={
      \noexpand\path [draw, \forestoption{edge}]
      (!u.east) +(-2pt,-5pt) coordinate(ZZ) -- (ZZ-|.child anchor)\forestoption{edge label};
    }
  }
}% end of forestset
          
\begin{forest}
  for tree={
    anchor=north,
    calign=first,
    s sep = 0,
    edge path={
      \noexpand\path [draw, \forestoption{edge}]
      (!u.east) +(-2pt,-5pt) -| node[fill,circle,inner sep=1.25pt] {} (.child anchor)\forestoption{edge label};
    },
    before typesetting nodes={
      if n=1
        {insert before={[,phantom]}}
        {}
    },
    fit=band,
    before computing xy={l=20pt},
    minimum height=6mm, inner ysep=0pt
  }
[ $A$
  [$a_1$]
  [$\cdots$, nolabel]
  [$a_2$
    [$b_1^{(1)}$]
    [$b_2^{(1)}$
      [$c_1^{(2)}$]
      [$c_2^{(2)}$]
      [$c_3^{(2)}$]
    ]
    [$b_3^{(1)}$
      [$c_4^{(2)}$]
      [$c_5^{(2)}$]
      [$c_6^{(2)}$]    
    ]
  ]
  [$\cdots$, nolabel]
]
\end{forest}

\end{document}

相关内容