在森林图中节点之间的线上添加菱形

在森林图中节点之间的线上添加菱形

我希望能够在下图中添加一个可选的菱形和一个“弯曲箭头”。我曾考虑尝试将tikz命令放入forest环境中,但似乎行不通。例如: 在此处输入图片描述

    \begin{forest}
        for tree=draw,
        [Main(), [Level Setup],[Game], [Win_Game()]]
    \end{forest}

这就是我现在所拥有的,我记下了我用 找到的代码片段edge label={node[midway,left,font=\scriptsize]{text}},它会在我想要绘制的箭头上给出标签,但不会绘制箭头。

答案1

这是其中的一些样式,您可以根据需要进行修改或重复使用。我从MS-SPO 的代码因为它可以编译。

\documentclass[10pt,border=3mm,tikz]{standalone}
% ateb: https://tex.stackexchange.com/a/703039/ addaswyd o ateb MS-SPO: https://tex.stackexchange.com/a/703008/ i gwestiwn apathyy: https://tex.stackexchange.com/q/702992/
\usepackage{forest}
\usetikzlibrary{arrows.meta,shapes.geometric}    % to modify arrow tips, see ch. 16.5 pfgmanual
\forestset{%
  from diamond/.style={%
    before typesetting nodes={%
      replace by={%
        [,
          diamond, 
          inner sep=1.5pt, 
          no edge, 
          anchor=north, 
          draw, 
          append,
          before drawing tree={%
            y'=0pt,
            if={>Od>{x}{0pt}}{x'=10pt}{x'=-10pt},
          },
        ]%
      },
    },
  },
  branch arrows/.style args={from #1 to #2 with label #3 and from #4 to #5 with label #6}{%
    edge label+/.process={Ow{name}{coordinate [pos=#1] (##1-a) coordinate [pos=#2] (##1-b) coordinate [pos=#4] (##1-c) coordinate [pos=#5] (##1-d)}},
    tikz+/.process={Ow{name}{%
        \draw [{Circle[open]}-Stealth,very thin] (##1-c) ++(0pt,2.5pt) -- ([yshift=2.5pt]##1-d) node [above,my branch arrow label] {#3};
        \draw [{Circle[open]}-Stealth,very thin] (##1-b) ++(0pt,-2.5pt) -- ([yshift=-2.5pt]##1-a) node [below,my branch arrow label] {#6};
      }%
    },
  },
  trunk arrows/.style args={from #1 to #2 with label #3 and from #4 to #5 with label #6}{%
    edge label+/.process={Ow{name}{coordinate [pos=#1] (##1-a) coordinate [pos=#2] (##1-b) coordinate [pos=#4] (##1-c) coordinate [pos=#5] (##1-d)}},
    tikz+/.process={Ow{name}{%
        \draw [{Circle[open]}-Stealth,very thin] (##1-c) ++(2.5pt,0pt) -- ([xshift=2.5pt]##1-d) node [right,my arrow label] {#3};
        \draw [{Circle[open]}-Stealth,very thin] (##1-b) ++(-2.5pt,0pt) -- ([xshift=-2.5pt]##1-a) node [left,my arrow label] {#6};
      }%
    },
  },
  apathyy tree/.style={%
    for tree={%
      draw,
      fit=band,
      s sep'+=20pt,
      delay={content+=\strut},
      font=\sffamily,
    },
    for descendants={anchor=north,
      tier/.option=level,
    },
    anchor=south,
  },
  /tikz/my arrow label/.style={midway,font=\sffamily\tiny,inner sep=1pt,},
  /tikz/my branch arrow label/.style={/tikz/my arrow label,sloped},
}
\begin{document}
\begin{forest}
  apathyy tree,
  [Main()
    [Level Setup, 
      {fill=blue!20}, 
      from diamond,
      branch arrows=from 0.125 to 0.525 with label {text} and from 0.575 to 0.975 with label {other},
      [nested 1
        [nested 1.1]
        [nested 1.2
          [nested 1.2.1
            [nested 1.2.2]
          ]
        ]
      ]
    ]   % just put some color
    [Game,
      calign with current edge,
      trunk arrows=from 0.9 to 0.4 with label {label} and from 0.95 to 0.1 with label {extra},
      [nested 1]
      [nested 2]
    ]       % this tree only with ordinary lines
    [Win\_Game(), 
      from diamond,
      branch arrows=from 0.125 to 0.525 with label {more} and from 0.575 to 0.975 with label {another},
      [nested 1
        [nested 1.1]
      ]
    ]                   % you need to backslash the underscore
  ]
  \draw [-Stealth] (!r1.west) ..controls +(-25pt,-5pt) and +(-5pt,0pt).. ([yshift=-4pt]!r.center |- !r1.south) ..controls +(5pt,0pt) and +(25pt,-5pt).. (!r3.east);
\end{forest}
\end{document}

带箭头造型的冷漠树

编辑

这是一个更灵活的版本。它不会改变您添加钻石等的方式,但它应该可以更好地默认放置物品。

更多钻石和箭头

要添加钻石,你只需from diamond像以前一样将其添加到子项中。

弯曲的箭头只是普通的钛绘制树后添加的 Z 命令。我添加了另外两个示例。

  • 最简单的方法就是命名您想要的节点,就像我所做的那样wingame
  • 但是,对于菱形来说,这并不简单,所以我forest为它们使用了节点名。基本上,!表示“穿过”树到达节点。r是根。1是第一个子节点,2第二个子节点,依此类推。
  • (!r1.west)通向“级别设置”节点的分支顶部的菱形节点也是如此。
  • (!r21.west)是根的第二个孩子的第一个孩子的西锚点,即从“游戏”到“嵌套 1”的分支开头的菱形。

请注意,以下代码使用自定义参数处理器,因为我无法让标准处理器执行我想要的操作。据我所知,没有官方方法可以做到这一点,因此定义使用内部宏。这意味着forest如果软件包更新破坏了这一点,您不能责怪的作者。(您可能应该责怪我而不是forest的作者,但的定义q肯定是未经批准的。)

\documentclass[10pt,border=3mm,tikz]{standalone}
% ateb: https://tex.stackexchange.com/a/703039/ addaswyd o ateb MS-SPO: https://tex.stackexchange.com/a/703008/ i gwestiwn apathyy: https://tex.stackexchange.com/q/702992/
\usepackage{forest}
\usetikzlibrary{arrows.meta,shapes.geometric}    % to modify arrow tips, see ch. 16.5 pfgmanual
\makeatletter
\forest@def@processor{q}{}{}{%
  \forest@process@left@toppop\forest@temp
  \forest@process@left@toppop\forest@tempa
  \forest@process@left@toppop\forest@tempb
  \ifnum\forest@temp=0
    \forest@process@right@letprepend\forest@tempb
  \else
    \forest@process@right@letprepend\forest@tempa
  \fi
  \let\forestmathresulttype\forestmathtype@generic
}
\makeatother
\forestset{%
  declare dimen={parental width share}{-1000pt},
  declare boolean={is from diamond}{0},
  declare boolean={is diamond}{0},
  from diamond/.style={%
    is from diamond,
    before typesetting nodes={%
      replace by={%
        [,
          diamond, 
          is diamond,
          inner sep=1.5pt, 
          no edge, 
          anchor=north, 
          draw, 
          append,
          before drawing tree={%
            if={ >Od= {!u.parental width share}{-1000pt}}{
              !u.parental width share/.process={ OOOw3+P w+d d S2 l2 > q {!u.max x}{!u.min x}{!u.n children}{(##1-##2)/(##3-1)} {##1pt} {10pt} },
              for siblings={%
                if={>OO|{is diamond}{is from diamond}}{}{%
                  edge path'/.process={OOOw3+Pw {n}{!u.n children}{!u.parental width share}{(##1-((##2+1)/2))*##3} {(!u.south) ++(##1pt,0pt) -- (.child anchor)}},
                },
              },
            }{},
            y/.option=!u.y,
            y+/.option=!u.min y,
            x/.process={ OOOw3+P {n}{!u.n children}{!u.parental width share}{(##1-((##2+1)/2))*##3}},
          },
        ]%
      },
    },
  },
  branch arrows/.style args={from #1 to #2 with label #3 and from #4 to #5 with label #6}{%
    edge label+/.process={Ow{name}{coordinate [pos=#1] (##1-a) coordinate [pos=#2] (##1-b) coordinate [pos=#4] (##1-c) coordinate [pos=#5] (##1-d)}},
    tikz+/.process={Ow{name}{%
        \draw [{Circle[open]}-Stealth,very thin] (##1-c) ++(0pt,2.5pt) -- ([yshift=2.5pt]##1-d) node [above,my branch arrow label] {#3};
        \draw [{Circle[open]}-Stealth,very thin] (##1-b) ++(0pt,-2.5pt) -- ([yshift=-2.5pt]##1-a) node [below,my branch arrow label] {#6};
      }%
    },
  },
  trunk arrows/.style args={from #1 to #2 with label #3 and from #4 to #5 with label #6}{%
    edge label+/.process={Ow{name}{coordinate [pos=#1] (##1-a) coordinate [pos=#2] (##1-b) coordinate [pos=#4] (##1-c) coordinate [pos=#5] (##1-d)}},
    tikz+/.process={Ow{name}{%
        \draw [{Circle[open]}-Stealth,very thin] (##1-c) ++(2.5pt,0pt) -- ([xshift=2.5pt]##1-d) node [right,my arrow label] {#3};
        \draw [{Circle[open]}-Stealth,very thin] (##1-b) ++(-2.5pt,0pt) -- ([xshift=-2.5pt]##1-a) node [left,my arrow label] {#6};
      }%
    },
  },
  apathyy tree/.style={%
    for tree={%
      draw,
      fit=band,
      s sep'+=20pt,
      delay={content+=\strut},
      font=\sffamily,
    },
    for descendants={anchor=north,
      tier/.option=level,
    },
    anchor=south,
  },
  /tikz/my arrow label/.style={midway,font=\sffamily\tiny,inner sep=1pt,},
  /tikz/my branch arrow label/.style={/tikz/my arrow label,sloped},
}
\begin{document}
\begin{forest}
  apathyy tree,
  [Main()
    [Level Setup, 
      {fill=blue!20}, 
      from diamond,
      branch arrows=from 0.125 to 0.525 with label {text} and from 0.575 to 0.975 with label {other},
      [nested 1
        [nested 1.1]
        [nested 1.2
          [nested 1.2.1
            [nested 1.2.2]
          ]
        ]
      ]
    ]   % just put some color
    [Game,
      calign with current edge,
      trunk arrows=from 0.9 to 0.4 with label {label} and from 0.95 to 0.1 with label {extra},
      [nested 1, from diamond]
      [nested 2, from diamond]
      [nested 3, from diamond]
      [nested 4]
      [nested 5, from diamond]
    ]       % this tree only with ordinary lines
    [Win\_Game(), name=wingame,
      from diamond,
      branch arrows=from 0.125 to 0.525 with label {more} and from 0.575 to 0.975 with label {another},
      [nested 1
        [nested 1.1]
      ]
    ]                   % you need to backslash the underscore
  ]
  \draw [-Stealth] (!r1.west) ..controls +(-25pt,-5pt) and +(-5pt,0pt).. ([yshift=-4pt]!r.center |- !r1.south) ..controls +(5pt,0pt) and +(25pt,-5pt).. (!r3.east);
  \draw [-Stealth] (!r21.west) ..controls +(-25pt,-5pt) and +(-5pt,0pt).. ([yshift=-4pt]!r2.center |- !r21.south) ..controls +(5pt,0pt) and +(25pt,-5pt).. (!r25.east);
  \draw [-Stealth] (wingame.west) ..controls +(-35pt,-10pt) and +(-15pt,0pt).. ([yshift=-5pt]wingame.south) ..controls +(15pt,0pt) and +(35pt,-10pt).. (wingame.east);
\end{forest}
\end{document}

编辑2

您可以更改样式/tikz/my arrow label和/或/tikz/my branch arrow label使用任何标准 TiZ 键。这些不是 Forest 样式(实际上您不能在其中使用 Forest 键)。因此,align=center向这些样式中添加类似内容将允许您\\在标签中使用。或者textwidth=<dimension>将使标签换行到给定的宽度。如果您想要很多平行箭头,您可以创建专门的样式。或者您可以将它们添加到 Forest 环境的末尾。

例如,假设我们将 的定义my arrow label(这也会改变my branch arrow label)更改为

  /tikz/my arrow label/.style={midway,font=\sffamily\tiny,inner sep=1pt,align=center},

我们添加

  \draw [{Circle[open]}-Stealth,very thin] (wingame-a) ++(0pt,10pt) -- ([yshift=10pt]wingame-d) node [above,my branch arrow label] {parallel\\multiline};

之前\end{forest}。然后我们将得到一个双线标签,其中带有指向wingame节点的附加箭头。

带有多行标签的附加箭头到 wingame

这样画出的箭头是平行的,但它们的起点和终点不会对齐,因为我没有考虑到角度edge。我所做的只是将箭头向上移动。如果您愿意,您大概可以考虑这个角度,但希望在大多数情况下它不会太关键,因为您没有将箭头移动得太远。

答案2

以下是一种方法:

结果

\documentclass[10pt,border=3mm,tikz]{standalone}
\usepackage{forest}
\usetikzlibrary{arrows.meta}    % to modify arrow tips, see ch. 16.5 pfgmanual

\begin{document}
 \begin{forest}
    for tree={draw,edge={Turned Square[open]}-}% all start with a gem
    [Main()
        [Level Setup, {fill=blue!20}]   % just put some color
        [Game, for tree={edge=-}]       % this tree only with ordinary lines
        [Win\_Game()]                   % you need to backslash the underscore
    ]
 \end{forest}
\end{document}

相关内容