如何使用 tikz 绘制由节点形成圆形的路径?
我曾尝试使用
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning}
\begin{document}
\begin{tikzpicture}[->,node distance=2cm, auto, thick,main node/.style={circle,fill=blue!20,draw}]
\node[main node] (1) {A};
\node[main node] (2) [above left=of 1] {B};
\node[main node] (3) [above right=of 1] {C};
\node[main node] (4) [above=of 2] {D};
\node[main node] (5) [above=of 3] {E};
\path[draw, every node/.style={font=\sffamily\small}] (1) -- (2) -- (4) -- (5) -- (3) -- cycle;
\end{tikzpicture}
\end{document}
但要正确地组织它们非常困难。我认为只用 4 个节点就很容易做到,但我需要 5 个节点。我想知道我是否可以用路径绘制节点。
编辑
抱歉,我忘了说我需要节点之间的箭头,并且我希望每个节点都有不同的文本。
我还能使用 foreach 吗?也许我可以列出文本,然后让 foreach 确定要绘制列表中的哪个元素?
答案1
正多边形上的节点
可以将各种大小的圆形节点放置在一个圆上以及一个正多边形的角上,并在它们之间画箭头,箭头也位于圆上。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{bending}
\begin{document}
\begin{tikzpicture}[
->,
thick,
main node/.style={circle, fill=blue!20, draw},
]
\newcommand*{\MainNum}{5}
\newcommand*{\MainRadius}{1.5cm}
\newcommand*{\MainStartAngle}{90}
% Print main nodes, node names: p1, p2, ...
\path
(0, 0) coordinate (M)
\foreach \t [count=\i] in {A, Hello\\World, 3, foobar, $\cdot$} {
+({\i-1)*360/\MainNum + \MainStartAngle}:\MainRadius)
node[main node, align=center] (p\i) {\t}
}
;
% Calculate the angle between the equal sides of the triangle
% with side length \MainRadius, \MainRadius and radius of circle node
% Result is stored in \p1-angle, \p2-angle, ...
\foreach \i in {1, ..., \MainNum} {
\pgfextracty{\dimen0 }{\pgfpointanchor{p\i}{north}}
\pgfextracty{\dimen2 }{\pgfpointanchor{p\i}{center}}
\dimen0=\dimexpr\dimen2 - \dimen0\relax
\ifdim\dimen0<0pt \dimen0 = -\dimen0 \fi
\pgfmathparse{2*asin(\the\dimen0/\MainRadius/2)}
\global\expandafter\let\csname p\i-angle\endcsname\pgfmathresult
}
% Draw the arrow arcs
\foreach \i [evaluate=\i as \nexti using {int(mod(\i, \MainNum)+1}]
in {1, ..., \MainNum} {
\pgfmathsetmacro\StartAngle{
(\i-1)*360/\MainNum + \MainStartAngle
+ \csname p\i-angle\endcsname
}
\pgfmathsetmacro\EndAngle{
(\nexti-1)*360/\MainNum + \MainStartAngle
- \csname p\nexti-angle\endcsname
}
\ifdim\EndAngle pt < \StartAngle pt
\pgfmathsetmacro\EndAngle{\EndAngle + 360}
\fi
\draw
(M) ++(\StartAngle:\MainRadius)
arc[start angle=\StartAngle, end angle=\EndAngle, radius=\MainRadius]
;
}
\end{tikzpicture}
\end{document}
等距节点
可以将节点放置在圆上,而不是放置在正多边形的角上,这样箭头的长度相等。这样做的好处是,主半径可以更小,从而呈现更紧凑的效果。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{bending}
\begin{document}
\begin{tikzpicture}[
->,
thick,
main node/.style={circle, fill=blue!20, draw, align=center},
]
\newcommand*{\MainRadius}{1.2cm}
\newcommand*{\MainStartAngle}{90}
\coordinate (M) at (0, 0);
\newcommand*{\MainAngleSum}{0}
\begin{scope}
% First the nodes are only set, but clipped to get their size.
% The final location is not yet known.
\clip (M);
\foreach \t [count=\i] in {A, Hello\\World, 3, foobar, $\cdot$} {
\global\expandafter\let\csname p\i-text\endcsname\t
\node[main node] (p\i) at (M) {\t};
%
\global\let\MainNum\i % the last assignment is number of nodes
% Calculate the angle between the equal sides of the triangle
% with side length \MainRadius, \MainRadius and radius of circle node
% Result is stored in \p1-angle, \p2-angle, ...
\pgfextracty{\dimen0 }{\pgfpointanchor{p\i}{north}}
\pgfextracty{\dimen2 }{\pgfpointanchor{p\i}{center}}
\dimen0=\dimexpr\dimen2 - \dimen0\relax
\ifdim\dimen0<0pt \dimen0 = -\dimen0 \fi
\pgfmathparse{2*asin(\the\dimen0/\MainRadius/2)}
\global\expandafter\let\csname p\i-angle\endcsname\pgfmathresult
\pgfmathparse{\MainAngleSum + 2*\csname p\i-angle\endcsname}
\global\let\MainAngleSum\pgfmathresult
}
\end{scope}
\pgfmathsetmacro\MainAngleStep{(360 - \MainAngleSum)/\MainNum}
% Draw the nodes and arrow arcs
\global\let\CurrentAngle\MainStartAngle
\foreach \i in {1, ..., \MainNum} {
\pgfmathsetmacro\AngleA{\CurrentAngle + \csname p\i-angle\endcsname}
\pgfmathsetmacro\AngleB{\AngleA + \MainAngleStep}
\draw
(M) +(\CurrentAngle:\MainRadius)
node[main node] {\csname p\i-text\endcsname}
+(\AngleA:\MainRadius)
arc[
start angle=\AngleA,
end angle=\AngleB,
radius=\MainRadius,
]
;
\ifnum\i<\MainNum
\pgfmathparse{
\AngleB
+ \csname p\the\numexpr\i+1\relax-angle\endcsname
}
\global\let\CurrentAngle\pgfmathresult
\fi
}
\end{tikzpicture}
\end{document}
答案2
我会使用极坐标:
\documentclass[border=5mm,tikz]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \ang/\lab in {0/A,72/B,144/C,216/D,288/E} {
\node[circle,fill=blue!20,draw] (\ang) at (\ang:2){\lab};
}
\draw(0)--(72)--(144)--(216)--(288)--(0);
\end{tikzpicture}
\end{document}
答案3
您可以使用极坐标和\foreach
循环:
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning}
\begin{document}
\begin{tikzpicture}[
->,
thick,
main node/.style={circle,fill=blue!20,draw}
]
\foreach \Rotulo [count=\ci] in {C,E,D,B,A}
\node[main node] (\ci) at (-90+\ci*360/5:2cm) {\Rotulo};
\path[draw, every node/.style={font=\sffamily\small}]
(1) -- (2) -- (3) -- (4) -- (5) -- (1);
\end{tikzpicture}
\end{document}
结果:
另一种选择是使用regular polygon
形状(需要shapes.geometric
库):
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning,shapes.geometric}
\begin{document}
\begin{tikzpicture}[
->,
thick,
main node/.style={circle,fill=blue!20,draw}
]
\node[
regular polygon,
regular polygon sides=5,
draw,
inner sep=1cm
]
(pentagon) at (0,0) {};
\foreach \Rotulo [count=\ci] in {C,E,D,B,A}
\node[main node] (\ci) at (pentagon.corner \ci) {\Rotulo};
\end{tikzpicture}
\end{document}
更新:
\documentclass[tikz]{standalone}
\usetikzlibrary{arrows,positioning}
\begin{document}
\begin{tikzpicture}[
->,
thick,
main node/.style={circle,fill=blue!20,draw}
]
\foreach \Rotulo [count=\ci] in {C,E,D,B,A}
\node[main node] (\ci) at (-90+\ci*360/5:2cm) {\Rotulo};
\draw
(1) to[out=85,in=-40] (2);
\draw
(2) to[out=155,in=25] (3);
\draw
(3) to[out=225,in=95] (4);
\draw
(4) to[out=295,in=175] (5);
\draw
(5) to[out=5,in=245] (1);
\end{tikzpicture}
\end{document}
有关在节点之间获取圆形箭头阵列的其他方法,请参阅连接看起来像圆圈的节点。
答案4
您还可以使用smartdiagram
\documentclass{standalone}
\usepackage{smartdiagram}
\begin{document}
\smartdiagramset{module shape=circle}
\smartdiagram[circular diagram]{A, B, C, D, E}
\end{document}