基于这个层次图在 tikz 中使用 forest 包,我想要一个修改后的版本。目前我有
\documentclass[tikz,border=10pt]{standalone}
\usepackage{verbatim}
\usepackage{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}
% colors
\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col6in}{blue!20}
\colorlet{col6out}{blue!30}
\colorlet{col7out}{orange}
\colorlet{col7in}{orange!50}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}
\begin{document}
\pgfkeys{/forest,
rect/.append style = {rectangle, rounded corners = 2pt,
inner color = col6in, outer color = col6out},
ellip/.append style = {ellipse, inner color = col5in,
outer color = col5out},
orect/.append style = {rect, font = \sffamily\bfseries\LARGE,
text width = 325pt, text centered,
minimum height = 10pt, outer color = col7out,
inner color=col7in},
oellip/.append style = {ellip, inner color = col8in, outer color = col8out,
font = \sffamily\bfseries\large, text centered}}
\begin{forest}
for tree={
font=\sffamily\bfseries,
line width=1pt,
draw=linecol,
ellip,
align=center,
child anchor=north,
parent anchor=south,
drop shadow,
l sep+=12.5pt,
edge path={
\noexpand\path[color=linecol, rounded corners=5pt,
>={Stealth[length=10pt]}, line width=1pt, ->, \forestoption{edge}]
(!u.parent anchor) -- +(0,-5pt) -|
(.child anchor)\forestoption{edge label};
},
where level={3}{tier=tier3}{},
where level={0}{l sep-=15pt}{},
where level={1}{
if n={1}{
edge path={
\noexpand\path[color=linecol, rounded corners=5pt,
>={Stealth[length=10pt]}, line width=1pt, ->,
\forestoption{edge}]
(!u.west) -| (.child anchor)\forestoption{edge label};
}
}{
edge path={
\noexpand\path[color=linecol, rounded corners=5pt,
>={Stealth[length=10pt]}, line width=1pt, ->,
\forestoption{edge}]
(!u.east) -| (.child anchor)\forestoption{edge label};
},
}
}{}
}
[Light Detection and Ranging\\LiDAR, inner color=col1in, outer color=col1out
[Scanning, inner color=col2in, outer color=col2out
[Spinning head\\with single-spot\\sensors, inner color=col4in, outer color=col4out]
[Moving mirrors/\\prisms, inner color=col4in, outer color=col4out
[Rotating/oscillating\\macro mirrors/prisms, inner color=col8in, outer color=col8out]
[Oscillating MEMS\\mirror, inner color=col8in, outer color=col8out]
]
[Optical phased-\\arrays, inner color=col4in, outer color=col4out]
]
[Non-scanning (staring), inner color=col2in, outer color=col2out
[Fixed (multi-)\\beam, inner color=col4in, outer color=col4out]
[Diffuse light cone\\ ``FLASH'' LiDAR, inner color=col4in, outer color=col4out]
]
]
\end{forest}
\end{document}
如您所见,第二级的连接并未针对三个子级进行优化。“移动镜子/棱镜”椭圆与其父级“扫描”的连接非常糟糕。
据我所知,森林文档对这个主题没有什么帮助。我该如何设置级别选项,以便所有内容都相同,但中间的椭圆直接与其父级“南”相连?
答案1
文档中可能很容易忽略这一点,但forest
有一个选项calign
(“子对齐”)可以解决您的问题。如果我理解正确的话,您希望将子节点定位到“扫描”节点,以便第二个节点居中。
这是通过calign=child, calign child=2
向父节点添加选项来实现的。(请参阅森林文档的 §3.7.2“节点位置”)。
如果您想自动设置,您可以使用语法if n children=3
。
\documentclass[tikz,border=10pt]{standalone}
\usepackage{verbatim}
\usepackage{forest}
\usetikzlibrary{arrows.meta, shapes.geometric, calc, shadows}
% colors
\colorlet{mygreen}{green!75!black}
\colorlet{col1in}{red!30}
\colorlet{col1out}{red!40}
\colorlet{col2in}{mygreen!40}
\colorlet{col2out}{mygreen!50}
\colorlet{col3in}{blue!30}
\colorlet{col3out}{blue!40}
\colorlet{col4in}{mygreen!20}
\colorlet{col4out}{mygreen!30}
\colorlet{col5in}{blue!10}
\colorlet{col5out}{blue!20}
\colorlet{col6in}{blue!20}
\colorlet{col6out}{blue!30}
\colorlet{col7out}{orange}
\colorlet{col7in}{orange!50}
\colorlet{col8out}{orange!40}
\colorlet{col8in}{orange!20}
\colorlet{linecol}{blue!60}
\begin{document}
\pgfkeys{/forest,
rect/.append style = {rectangle, rounded corners = 2pt,
inner color = col6in, outer color = col6out},
ellip/.append style = {ellipse, inner color = col5in,
outer color = col5out},
orect/.append style = {rect, font = \sffamily\bfseries\LARGE,
text width = 325pt, text centered,
minimum height = 10pt, outer color = col7out,
inner color=col7in},
oellip/.append style = {ellip, inner color = col8in, outer color = col8out,
font = \sffamily\bfseries\large, text centered}}
\begin{forest}
for tree={
font=\sffamily\bfseries,
line width=1pt,
draw=linecol,
ellip,
align=center,
child anchor=north,
parent anchor=south,
drop shadow,
l sep+=12.5pt,
edge path={
\noexpand\path[color=linecol, rounded corners=5pt,
>={Stealth[length=10pt]}, line width=1pt, ->, \forestoption{edge}]
(!u.parent anchor) -- +(0,-5pt) -|
(.child anchor)\forestoption{edge label};
},
where level={3}{tier=tier3}{},
where level={0}{l sep-=15pt}{},
where level={1}{
if n={1}{
edge path={
\noexpand\path[color=linecol, rounded corners=5pt,
>={Stealth[length=10pt]}, line width=1pt, ->,
\forestoption{edge}]
(!u.west) -| (.child anchor)\forestoption{edge label};
}
}{
edge path={
\noexpand\path[color=linecol, rounded corners=5pt,
>={Stealth[length=10pt]}, line width=1pt, ->,
\forestoption{edge}]
(!u.east) -| (.child anchor)\forestoption{edge label};
},
}
}{}
}
[Light Detection and Ranging\\LiDAR, inner color=col1in, outer color=col1out
[Scanning, inner color=col2in, outer color=col2out,calign=child, calign child=2
[Spinning head\\with single-spot\\sensors, inner color=col4in, outer color=col4out]
[Moving mirrors/\\prisms, inner color=col4in, outer color=col4out
[Rotating/oscillating\\macro mirrors/prisms, inner color=col8in, outer color=col8out]
[Oscillating MEMS\\mirror, inner color=col8in, outer color=col8out]
]
[Optical phased-\\arrays, inner color=col4in, outer color=col4out]
]
[Non-scanning (staring), inner color=col2in, outer color=col2out
[Fixed (multi-)\\beam, inner color=col4in, outer color=col4out]
[Diffuse light cone\\ ``FLASH'' LiDAR, inner color=col4in, outer color=col4out]
]
]
\end{forest}
\end{document}
答案2
另一种选择是before computing xy={s/.average={s}{siblings}}
在节点“移动镜子/\棱镜”处使用。通过一些努力使你的 MWE 更短(对我来说更美观),MWE 是:
\documentclass[tikz,border=10pt]{standalone}
\usepackage[edges]{forest}
\usetikzlibrary{arrows.meta, calc, shadows, shapes.geometric}
% colors
\colorlet{linecol}{blue!60}
\begin{document}
\begin{forest}
for tree={
E/.style = {ellipse, draw=linecol, line width=1pt,
inner color=#1!15, outer color=#1!45, % nodes color
inner xsep=-1pt, font=\sffamily\bfseries,
align=center, drop shadow}, % nodes style with parameter for color
child anchor = north,
parent anchor = south,
s sep = 4mm, % "sibling distance"
l sep = 8mm, % "level distance"
edge = {draw=linecol, line width=1pt, -{Stealth[length=7pt]}, % common style for all edges
rounded corners},
edge path = {\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- + (0,-4mm) -| (.child anchor);},
where level={2}{tier=tier2}{},% nodes on the level 2
% (from top) are vertically aligned
% on the top is level 0
where level={1}{
if n={1}{edge path={\noexpand\path[\forestoption{edge}]
(!u.west) -| (.child anchor);}
}{edge path={\noexpand\path[\forestoption{edge}]
(!u.east) -| (.child anchor);},
}
}{}% end of level 1
}% end for tree
[LiDAR\\ (Light Detection\\and Ranging), E=red
[Scanning, E=green
[Spinning head with\\single-spot sensors, E=teal]
[Moving mirrors/\\prisms, E=teal,
before computing xy={s/.average={s}{siblings}}
% or calign=child, calign child=2
[Rotating/oscillating\\macro mirrors/prisms, E=orange]
[Oscillating MEMS\\mirror, E=orange]
]
[Optical phased-\\arrays, E=teal]
]
[Non-scanning\\ (staring), E=green
[Fixed (multi-)\\beam, E=teal]
[Diffuse light cone\\ ``FLASH'' LiDAR, E=teal]
]
]
\end{forest}
\end{document}
您可以根据自己的意愿更改所用的节点颜色。