![在森林图中节点之间的线上添加菱形](https://linux22.com/image/471661/%E5%9C%A8%E6%A3%AE%E6%9E%97%E5%9B%BE%E4%B8%AD%E8%8A%82%E7%82%B9%E4%B9%8B%E9%97%B4%E7%9A%84%E7%BA%BF%E4%B8%8A%E6%B7%BB%E5%8A%A0%E8%8F%B1%E5%BD%A2.png)
答案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
使用任何标准 Ti钾Z 键。这些不是 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
节点的附加箭头。
这样画出的箭头是平行的,但它们的起点和终点不会对齐,因为我没有考虑到角度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}