![使用 foreach 和 \newcommand 宏在 tikZ 中创建树](https://linux22.com/image/303238/%E4%BD%BF%E7%94%A8%20foreach%20%E5%92%8C%20%5Cnewcommand%20%E5%AE%8F%E5%9C%A8%20tikZ%20%E4%B8%AD%E5%88%9B%E5%BB%BA%E6%A0%91.png)
在下面的两个例子中,我以两种不同的方式使用了相同的代码。为什么 TikZ 在使用宏时会对父节点感到困惑
\department{name dept}{list of subdepts}
代替
child[option]{name dept}
\subdepartment{list of subdepts}
用于创建分支?
我已经尝试扩展命令但没有成功。
\documentclass[border=2pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{trees, calc}
\begin{document}
\begin{tikzpicture}[
%style every node
every node/.style={
draw=black
},
%style management node
management/.style={
anchor=south,
text centered,
text width=5cm
},
%style department node
department/.style={
anchor=north,
text width=2.5cm
},
%style subdepartment node
subdepartment/.style={
grow=down,
anchor=west,
xshift=-1cm,
text width=1.75cm,
edge from parent path={(\tikzparentnode.191) |- (\tikzchildnode.west)}
},
%sibling distances
level 1/.style={sibling distance=3.5cm}
%level distances subdepartment node
%via macro
]
%macros
%level distances subdepartment node
\newcommand{\subdepartmentleveldistance}{0.75cm}
%
\newcommand{\department}[2]{
child{node [department] {#1}
%\subdepartment{#2}
child[subdepartment, level distance=\number * \subdepartmentleveldistance] foreach [count=\number from 1] \name in {#2} {node {\name}}
}
}
%
\newcommand{\subdepartment}[1]{
child[subdepartment, level distance=\number * \subdepartmentleveldistance] foreach [count=\number from 1] \name in {#1} {node {\name}}
}
%=====graphic
%works as intendet
\node[draw] at (0,1.5) {works as intended};
%management
\node[management] at (0,0) {Geschäftsführung}[edge from parent fork down]
%
%department and subdepartment via macro
%
child{node [department] {Einkauf}
\subdepartment{EK I, EK II}
}
%
child{node [department] {Konstruktion}
\subdepartment{KuE I, KuE II}
}
child{node [department] {Produktion}
\subdepartment{P I, P II, P III, P IV}
}
child{node [department] {Vertrieb}
\subdepartment{VK I, VK II}
}
;
%works not as intendet
\node[draw] at (10,1.5) {works not as intended seems to get confused about who the parent node is};
%management
\node[management] at (10,0) {Geschäftsführung}[edge from parent fork down]
%
%department and subdepartment via macro
\department{Einkauf}{EK I, EK II}
%
\department{Konstruktion}{KuE I, KuE II}
%
\department{Produktion}{P I, P II, P III, P IV}
%
\department{Vertrieb}{VK I, VK II}
;
\end{tikzpicture}
\end{document}
答案1
\department
我用一种样式替换了你的宏ins dep
。不要问我为什么一个不起作用而另一个起作用……我不知道!对不起。
\documentclass[border=7mm]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{trees, calc}
\begin{document}
\begin{tikzpicture}[
%style every node
every node/.style={
draw=black
},
%style management node
management/.style={
anchor=south,
text centered,
text width=5cm
},
%style department node
department/.style={
anchor=north,
text width=2.5cm
},
%style subdepartment node
subdepartment/.style={
grow=down,
anchor=west,
xshift=-1cm,
text width=1.75cm,
edge from parent path={(\tikzparentnode.191) |- (\tikzchildnode.west)}
},
%sibling distances
level 1/.style={sibling distance=3.5cm},
%level distances subdepartment node
%via macro
ins dep/.style 2 args={insert path={
node [department] {Einkauf}
child[subdepartment, level distance=\number * \subdepartmentleveldistance] foreach [count=\number from 1] \name in {#2} {node {\name}}
}}
]
%macros
%level distances subdepartment node
\newcommand{\subdepartmentleveldistance}{0.75cm}
%=====graphic
%works now as intendet
\node[draw] at (10,1.5) {works now as intendet};
%management
\node[management] at (10,0) {Geschäftsführung}[edge from parent fork down]
%
%department and subdepartment via macro
child{[ins dep={Einkauf}{EK I, EK II}]}
%
child{[ins dep={Konstruktion}{KuE I, KuE II}]}
%
child{[ins dep={Produktion}{P I, P II, P III, P IV}]}
%
child{[ins dep={Vertrieb}{VK I, VK II}]}
;
\end{tikzpicture}
\end{document}
答案2
我不知道你的问题的答案,但是如果你对使用有点类似的解决方案感兴趣forest
,这里有一种绘制树的方法,可以让你这样说,例如,
[, dept={some department}{some sub-department, some other sub-deparment, yet another sub-department}]
使用绘制树时使用的标准括号语法来绘制节点。设置有点复杂,但好处是可以简单地指定树。
\documentclass[border=5pt]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{forest}
\standaloneenv{forest}
\begin{document}
\forestset{
sub dept/.style={
append={
[#1,
draw,
child anchor=west,
anchor=west,
edge path={
\noexpand\path [draw, \forestoption{edge}] (!u.parent anchor) |- (.child anchor)\forestoption{edge label};
},
before computing xy={
l=10pt,
},
]
},
},
dept/.style n args={2}{
content/.wrap value={#1},
append={
[,
inner sep=0pt,
outer sep=0pt,
child anchor=center,
parent anchor=center,
grow'=0,
sub dept/.list={#2},
]
},
},
}
\begin{forest}
for tree={
draw,
if level=0{
align=center,
}{
align=left,
if level=1{
edge path={
\noexpand\path [draw, \forestoption{edge}] (!u.parent anchor) -- +(0,-15pt) -| (.child anchor)\forestoption{edge label};
},
}{
parent anchor=west,
child anchor=west,
},
},
}
[Geschäftsführung
[, dept={Einkauf}{EK I, EK II}
]
[, dept={Konstruktion}{KuE I, KuE II}
]
[, dept={Produktion}{P I, P II, P III, P IV}
]
[, dept={Vertrieb}{VK I, VK II}
]
]
\end{forest}
\end{document}
请注意,我不确定这是否充分利用了forest
的功能。我想知道是否有更优雅的解决方案,但至少目前我找不到。