使用森林、pdflatex 并遇到重叠节点和填充较低分割节点的问题

使用森林、pdflatex 并遇到重叠节点和填充较低分割节点的问题

我的代码使用 forest 包并用 pdflatex 编译,对于窄文本和分割节点的上部运行良好。请提供您基于 forest 的输入

1.) 避免在具有较宽文本的节点中重叠。我认为

before computing xy={s/.average={s}{siblings}}

2.) 访问分裂节点的下半部分。当尝试

[narrow\\text 1\nodepart{lower}text, splitRec, draw, before computing xy={s/.average={s}{siblings}}]

pdflatex 生成错误:

! Missing \cr inserted.

代码:

\documentclass[tikz,border=10pt]{standalone}


\usepackage{verbatim}
\usepackage[edges]{forest}
\usepackage{flexisym}
\usetikzlibrary{svg.path}


\forestset{
    qtree/.style={for tree={fit=band, parent anchor=south, child anchor=north, align=center, inner sep=3pt}},
    splitRec/.style={rectangle, rectangle split, rectangle split parts=2, draw}
}


\begin{comment}
     :compile using pdflatex
\end{comment}


\begin{document}
    \begin{forest}, baseline, qtree, forked edges
        [start\\node, ellipse, draw
    [first\\diamond, diamond, draw
        [second\\diamond, diamond, draw, edge path'={ (!u) |- (.parent)} % 
            [, phantom] % phantom node left so that the subsequent child has a node leaving the parent on the west
            [third\\diamond, diamond, draw, s sep+=0.25cm, edge path'={ (!u) |- (.parent)}
                [, phantom]
                [narrow\\text 1, splitRec, draw, before computing xy={s/.average={s}{siblings}}]
                [forth\\diamond, diamond, draw, edge path'={ (!u) |- (.parent)}
                    [, phantom]
                    [narrow\\text 2, ellipse, draw, before computing xy={s/.average={s}{siblings}}]
                    [fifth\\diamond, diamond, draw, edge path'={ (!u) |- (.parent)}
                        [, phantom]
                        [wide text 3\\Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut\\labore et dolore magna aliqua ut enim ad minim veniam\\quis nostrud exercitation ullamco laboris nisi ut aliquip\\ex ea commodo consequat duis aute irure dolor in reprehenderit, rectangle, draw, before computing xy={s/.average={s}{siblings}}]
                        [sixth\\diamond, diamond, draw, edge path'={ (!u) |- (.parent)}
                            [, phantom]
                            [wide text 4\\Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut\\labore et dolore mag    na aliqua ut enim ad minim veniam\\quis nostrud exercitation ullamco laboris nisi ut aliquip\\ex ea commodo consequat duis aute irure dolor in reprehenderit, rectangle, draw, before computing xy={s/.average={s}{siblings}}]
                            [, phantom]
                        ]
                    ]
                ]
            ]
        ]
        [narrow\\text 0\\right below, rectangle, draw, before computing xy={s/.average={s}{siblings}}]
        [, phantom]
    ]
]
    \end{forest}
\end{document}

.pdf: 在此处输入图片描述

答案1

避免重叠最简单的方法是让forest完成避免重叠的任务。在本例中,这意味着省略fit=band。我们可以通过更大的 轻松获得所需的额外空间(例如,第一个菱形的子元素之间) 。(请参阅代码中的s sep注释。)increase/decrease the horizontal distance between children

在 OP 的代码中指定 nodeparts 不起作用,因为序言中定义的键align使用了该键。此键与同名键不同。它通过将内容插入到环境中来工作。在环境中,没有任何意义,因此出现错误。qtreetikztabular\nodepartMissing \cr

解决方案是在多部分节点上使用tikzalign键(或手动为每个文本部分创建表格环境),这是通过 实现的/tikz/align\nodepart内容中的命令然后按预期工作,请参阅narrow text 2节点。(顺便说一下, 的第二部分rectangle split称为two,而不是lower。)

一点forest糖果。

  • nodepart序言中定义的样式让您可以编写nodepart={nodepart name}{text},请参阅narrow text 1节点。
  • 可以轻松定义特定节点部分的样式,请参阅的定义part two及其用法wide text 3
  • nodepartsstyle 使用任意分隔符将内容解析为多个部分。即使\\有效,请参阅narrow text 0。用逗号分隔需要将内容放在括号中,请参阅wide text 4。对我来说,分号通常是分隔符的最佳候选。style 如何nodeparts工作?
    • 首先,它为特定节点部分定义样式,并构造一个临时键列表,以 开头,content'后跟所有已定义的节点部分样式。这是通过split对给定的节点部分名称列表进行调整来实现的。在narrow text 0其中,它定义了节点部分样式nodepart@twonodepart@three;临时键列表为content',nodepart@two,nodepart@three。(更好的实现可能是预先计算临时键列表(这取决于节点的形状)。)
    • 临时键列表用作 的第三个参数split option,它实际上会拆分内容。临时键列表的键和内容部分被“压缩”:content'获取主要部分并简单地截断content其选项;nodepart@two获取第二部分并调用nodepart={two}{second part of content}它,有效地用 ; 替换第一个分隔符\nodepart{two}等。

代码:

\documentclass[tikz,border=10pt]{standalone}

\usepackage{verbatim}
\usepackage[edges]{forest}
\usepackage{flexisym}
\usetikzlibrary{svg.path}
\usetikzlibrary{shapes.multipart}

\forestset{
  qtree/.style={for tree={
      parent anchor=south,
      child anchor=north,
      /tikz/align=center,
      inner sep=3pt,
      s sep=5em,
    }},
  splitRec/.style={rectangle, rectangle split, rectangle split parts=2, draw},
  right below/.style={
    calign with current,
  },
  my diamond/.style={
    diamond,
    draw,
    edge path'={ (!u) |- (.parent)},
  },
  nodepart/.style 2 args={% generic nodepart
    content+=\nodepart{#1}#2,
  },
  part two/.style={nodepart={two}{#1}}, % specific nodepart
  % parse the content into nodeparts:
  nodeparts/.style 2 args={% #1 = part names, #2 = content separator
    tempkeylista'={content'},
    split={#1}{,}{define@nodepart},
    split option/.process=Rw1{tempkeylista}{{content}{#2}{##1}},
  },
  define@nodepart/.style={
    nodepart@#1/.style={nodepart={#1}{##1}},
    tempkeylista=nodepart@#1,
  },
}


\begin{comment}
  :compile using pdflatex
\end{comment}

\begin{document}
\begin{forest}, baseline, qtree, forked edges
  [start\\node, ellipse, draw
    [first\\diamond, diamond, draw,
      s sep=30em, % increase the horizontal distance between children
      [second\\diamond, my diamond, 
        [,right below, phantom]
        [third\\diamond, my diamond, 
          [narrow\\text 1, nodepart={two}{text}, splitRec, draw, right below]
          [forth\\diamond, my diamond, 
            [narrow\\text 2\nodepart{lower}text, ellipse split, draw, right below]
            [fifth\\diamond, my diamond,
              s sep=2em, % decrease the horizontal distance between children
              [wide text 3, splitRec, part two={Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut\\labore et dolore magna aliqua ut enim ad minim veniam\\quis nostrud exercitation ullamco laboris nisi ut aliquip\\ex ea commodo consequat duis aute irure dolor in reprehenderit}, right below]
              [sixth\\diamond, my diamond, 
                [{wide text 4,Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut\\labore et dolore mag    na aliqua ut enim ad minim veniam\\quis nostrud exercitation ullamco laboris nisi ut aliquip\\ex ea commodo consequat duis aute irure dolor in reprehenderit},
                  rectangle split, rectangle split parts=2, nodeparts={two}{,},
                  draw, right below]
              ]
            ]
          ]
        ]
      ]
      [narrow\\text 0\\right below,
        rectangle split, rectangle split parts=3, nodeparts={two,three}{\\},
        draw, right below]
    ]
  ]
\end{forest}
\end{document}

答案2

通常情况下,我会使用 Sašo 的代码,因为它肯定比我能想到的任何东西都要好。但是,我真的不喜欢多部分节点,所以我可能会做这样的事情。

[翻译:在萨索回答之前我已经做完了大部分工作,所以我想我最好完成它。]

  • 在解决此类问题时,我几乎总是从删除所有手动调整开始,理由是它们几乎肯定弊大于利。

  • 我认为几乎没有理由使用多部分节点,因为即使在普通tikzpicture节点中它们也会出现错误,而任何 Forest 节点都可以是tabular具有您喜欢的任何规范的节点。

  • 相反,我会调整设置inner xsep为零,并在居中列的每一侧放置补偿空间,以便\hline可以使用普通空间来分隔节点“部分”。我将其设置为3pt并将设置inner ysep3pt,以便间距与原始意图一致。

  • 我使用 Forest 锚点和一些条件来使边缘与菱形等完美配合。

\documentclass[border=10pt]{standalone}
\usepackage{forest,array}
\newcolumntype{C}{@{\hspace{3pt}}c@{\hspace{3pt}}}

\begin{document}
  \begin{forest}, baseline,  for tree={draw, inner xsep=0pt, inner ysep=3pt, fit=rectangle, align=C},
  where n children=0{calign with current edge, for siblings={if n=1{edge path'={(!u.first)-|(.parent)}}{edge path'={(!u.last)-|(.parent)}}}}{}
    [start\\node, ellipse, 
    [first\\diamond, diamond, 
        [second\\diamond, diamond, 
            [third\\diamond, diamond, 
                [narrow\\text 1\\\hline lower part\\of node ]
                [forth\\diamond, diamond, 
                    [narrow\\text 2, ellipse,  ]
                    [fifth\\diamond, diamond,  
                        [wide text 3\\Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut\\labore et dolore magna aliqua ut enim ad minim veniam\\quis nostrud exercitation ullamco laboris nisi ut aliquip\\ex ea commodo consequat duis aute irure dolor in reprehenderit ]
                        [sixth\\diamond, diamond,  
                            [wide text 4\\Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut\\labore et dolore mag    na aliqua ut enim ad minim veniam\\quis nostrud exercitation ullamco laboris nisi ut aliquip\\ex ea commodo consequat duis aute irure dolor in reprehenderit,  ]
                        ]
                    ]
                ]
            ]
        ]
        [narrow\\text 0\\right below, ]
    ]
]
\end{forest}
\end{document}

输出“树”

答案3

在我看来,你的图表绘制成纯tikz图片更简单:

\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{positioning,
                shapes}

\begin{document}
    \begin{tikzpicture}[
    node distance=3mm and 4mm,
    box/.style = {draw, text width=#1, align=center,inner sep=2pt},
    box/.default = 24em,
    dia/.style = {diamond, aspect=1.5, draw, align=center, inner xsep=0pt},
    elp/.style = {ellipse, aspect=1.5, draw, align=center, inner xsep=0pt}
    mpv/.style = {rectangle split, rectangle split parts=2, 
                  rectangle split empty part height=2ex, draw,
                  text width=#1, align=center},
    mpv/.default = 4em
                        ]
% from bottom to top
\node[box]  (n1) {wide text 4\\Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore mag na aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit, rectangle, draw, before computing};
\node (n2) [dia, above=of n1]           {sixth\\diamond};
\node (n3) [box, left=of n2 -| n1.west] {wide text 3\\Lorem ipsum dolor sit amet consectetur adipiscing\\elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit};
\node (n4) [dia, above=of n3]           {fifth\\diamond};
\node (n5) [elp,right=of n3.west |- n4] {narrow\\text 2};
\node (n6) [dia, above=of n5]           {forth\\diamond};
\node (n7) [mpv, left=of n6]            {narrow\\text 1};     
\node (n8) [dia, above=of n7]           {third\\diamond};
\node (n9) [dia,above left=of n8]       {second\\diamond};
\node (n10) [dia,above right=of n9.north -| n4]     {first\\diamond};
\node (n11) [box=6em,below=of n10]      {narrow\\text 0\\right below};
\node (n12) [elp,above=of n10]          {start\\ node};
%
\draw   (n12) -- (n10) -- (n11)
        (n10) -| (n9)
        (n9)  -| (n8)
        (n8)  -- (n7)
        (n8)  -| (n6)
        (n6)  -- (n5)
        (n6)  -| (n4)
        (n4)  -- (n3)
        (n4)  -| (n2)
        (n2)  -- (n1)
        ;
   \end{tikzpicture}
\end{document}    

编辑:我添加了一个具有多部分形状的节点,我在答案的第一个版本中忘记了它。

在此处输入图片描述

相关内容