答案1
这里尝试使用 forest
包和angles
库来绘制边缘之间的角度
\documentclass{article}
\usepackage[landscape]{geometry}
\usepackage{forest}
\usetikzlibrary{angles}
\begin{document}
\null
\vfill
\centering
\begin{forest}%
for tree={parent anchor=south,
child anchor=north,
l+=1cm,
fill=blue!30,
delay={content={\strut #1}},
},
blackcircle/.style={tikz={\node[fill=black!60,inner sep=3pt,circle]at(.north){};}},
whitecircle/.style={tikz={\node[draw,fill=white,inner sep=3pt,circle]at(.north){};}},
%
[Emergency Response System,fill=blue!10
[User interface,blackcircle]
[Inform emergency,blackcircle
[Inform Earthquake]
[Inform flood]
]
[Display neighborhood,blackcircle
[Map
[Display danger zone]
[Display safe zone]
[Display path to safe zone]
]
[Textual direction]
]
[Shortcut calls,whitecircle
[Cops]
[Ambulance]
[Fireman]
]
]
% fill angles
\foreach \i/\j/\k in {!21/!2/!22,!31/!3/!32,!41/!4/!43,!311/!31/!313}
{
\coordinate (A)at (\i.north);
\coordinate (O)at (\j.south);
\coordinate (B)at (\k.north);
\path (A)--(O)--(B)
pic [fill=black!60, angle radius=4mm] {angle = A--O--B};
}
\end{forest}
\par
\vfill
\end{document}
答案2
我认为,我不应该回答那些需要我亲自回答的问题。即使别人先回答了。
这厚颜无耻地改编Salim Bou 的回答因为这已经完成了所有需要输入内容等无聊的工作。
它改编了我之前回答 3 个类似问题时使用的一些代码,目前我还没有参考资料。(不过,我想无论如何,不引用我写的代码也是可以的。)
基本上,所有花哨的步法都是通过创造 Ti钾Z 和 Forest 样式位于文档的序言中。指定树只是应用样式和指定一些参数的问题。大部分操作都在树的序言中完成,即在环境forest
启动之后但在根节点之前。
\begin{forest}
主要风格:
disjunction tree,
我们希望1
当节点具有(多个)子节点时,将从级别开始的所有节点都标记为分离。
disjuncts from'=1,
我们希望从级别1
开始的所有节点都被标记为具体的,而不是抽象的。
concrete from'=1,
指定具体和抽象节点的颜色以及绘制、勾勒和填充角度和圆圈的颜色。
concrete colour=blue!85!cyan!40,
abstract colour=blue!85!cyan!15,
draw colour=darkgray,
就是这样。现在是 Salim Bou 对树的规范。这稍微简化了一点,因为我们会自动设置大部分样式。我们确实需要说明何时需要使用强制和可选标记。我们对适当的节点使用mandatory
和来执行此操作。optional
[Emergency Response System
这里有 2 个强制性分离词。
[User interface, mandatory]
[Inform emergency, mandatory
[Inform Earthquake]
[Inform flood]
]
还有第三个。
[Display neighbourhood, mandatory
[Map
[Display danger zone]
[Display safe zone]
[Display path to safe zone]
]
[Textual direction]
]
这个是可选的。
[Shortcut calls, optional
[Cops]
[Ambulance]
[Fireman]
]
]
大功告成。我们不需要手动标记角度等,因为样式disjunction tree
会帮我们完成这些,并创建图例。
\end{forest}
完整代码:
\documentclass[border=10pt,tikz,multi]{standalone}
\usetikzlibrary{angles,shadows.blur,positioning,backgrounds}
\usepackage{forest}
\forestset{
declare count register=disjuncts from,
disjuncts from'=0,
declare count register=concrete from,
concrete from'=2,
concrete colour/.code={\colorlet{concretecol}{#1}},
abstract colour/.code={\colorlet{abstractcol}{#1}},
draw colour/.code={\colorlet{drawcol}{#1}},
concrete colour=gray,
abstract colour=white,
draw colour=black,
/tikz/mandatory/.style={circle, fill=drawcol, draw=drawcol},
/tikz/optional/.style={circle, draw=drawcol, fill=white},
/tikz/concrete/.style={fill=concretecol, draw=drawcol},
/tikz/abstract/.style={fill=abstractcol, draw=drawcol},
/tikz/or/.style={},
mandatory/.style={edge label={node [mandatory] {}}},
optional/.style={edge label={node [optional] {}}},
or/.style={for first={disjunct}},
disjunct/.style={
tikz+={\path (.parent) coordinate (A) -- (!u.children) coordinate (B) -- (!ul.parent) coordinate (C) pic [fill=drawcol] {angle};}
},
disjunction tree/.style={
where={isodd(n_children())}{
for n={int((n_children()+1)/2)}{calign with current},
}{
calign=midpoint,
},
before typesetting nodes={
for nodewalk={
filter/.wrap pgfmath arg={{level>=##1}{n_children()>1}}{(disjuncts_from)}
}{
or,
},
where={level()>=(concrete_from)}{
concrete,
}{
abstract,
},
tikz+={
[font=\sffamily]
\node (l) [anchor=north west, xshift=10pt] at (current bounding box.north east) {Legend};
\foreach \i/\j [remember=\i as \k (initially l)] in {mandatory/Mandatory,optional/Optional,or/Or,abstract/Abstract,concrete/Concrete}
{
\node (\i) [below=20pt of \k.north, anchor=north, text centered, \i, minimum width=5pt,] {};
\node (\j) [right=15pt of \i.center -| mandatory.west, anchor=west] {\j};
};
\draw [drawcol] (or.south west) coordinate (A) -- (or.north) coordinate (B) -- (or.south east) coordinate (C) pic [fill=drawcol, angle radius=5pt] {angle};
\foreach \i in {mandatory,optional} \draw [darkgray] (\i.north east) -- +(45:5pt);
\node (c) [below=0pt of Concrete.south] {};
\scoped[on background layer]{\node [draw, fill=white, blur shadow, fit=(l) (Mandatory) (Optional) (Or) (Abstract) (Concrete) (c), rounded corners] {};}
},
},
for tree={
parent anchor=children,
child anchor=parent,
l'+=10mm,
blur shadow,
rounded corners,
text height=2ex,
text depth=.5ex,
font=\sffamily,
},
},
}
\begin{document}
\begin{forest}% addaswyd o gôd Salim Bou: https://tex.stackexchange.com/a/335782/
disjunction tree,
disjuncts from'=1,
concrete from'=1,
concrete colour=blue!85!cyan!40,
abstract colour=blue!85!cyan!15,
draw colour=darkgray,
[Emergency Response System
[User interface, mandatory]
[Inform emergency, mandatory
[Inform Earthquake]
[Inform flood]
]
[Display neighbourhood, mandatory
[Map
[Display danger zone]
[Display safe zone]
[Display path to safe zone]
]
[Textual direction]
]
[Shortcut calls, optional
[Cops]
[Ambulance]
[Fireman]
]
]
\end{forest}
\end{document}