我正在绘制某种图形TikZ
,并且我在一个循环中有几个连接的节点,我想为这些节点之间的路径所包围的区域着色。我的问题是阴影与节点之间的弧不一致(我分别绘制了节点之间的弧)。我的代码如下所示:
\documentclass{article}
\usepackage{tikz}
\tikzset{state/.style={circle,draw=black, very thick,inner sep=3pt}}
\begin{document}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\draw (a) to [bend right=30] (b);
\draw (a) to [bend left=30] (d);
\draw (b) to [bend right=30] (c);
\draw (c) to [bend right=30] (d);
\path[fill=gray!50,opacity=.5] (a) to [bend right=30] (b) to [bend right=30] (c) to [bend right=30] (d) to [bend right=30] (a);
\end{tikzpicture}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\draw (a) to [bend right=30] (b);
\draw (a) to [bend left=30] (d);
\draw (b) to [bend right=30] (c);
\draw (c) to [bend right=30] (d);
\path[fill=gray!50,opacity=.5] (0,0) to [bend right=30] (2,0) to [bend right=30] (2,-1.5) to [bend right=30] (0,-1.4) to [bend right=30] (0,0);
\end{tikzpicture}
\end{document}
我尝试了两种方法。第一种,我使用节点名称作为阴影的锚点,但这并不能覆盖曲线所包围的所有区域。阴影似乎使用节点的外边缘作为锚点,而不是中心。第二种,我使用节点的坐标作为锚点,但这覆盖了太多。据我所知,这是由于 (a) 节点之间绘制的弧的距离较短,弯曲量也较短,以及 (b) 由于字符大小不同,节点的半径并不都相等。结果是这样的:
我想保持节点之间绘制的弧线原样(即使它们不是关于中心轴对称的),并且想遮蔽由这些路径和节点的外边界所包围的区域,效果如下:
任何与此相关的建议都将受到赞赏!
答案1
你应该尝试从节点的中心画弧和线。这可以借助positioning
tikz 库来完成。
代码
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\tikzset{state/.style={circle,draw=black, very thick,inner sep=3pt,fill=white}}
\begin{document}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\draw (a.center) to [bend right=30] (b.center);
\draw (a.center) to [bend left=30] (d.center);
\draw (b.center) to [bend right=30] (c.center);
\draw (c.center) to [bend right=30] (d.center);
\path[fill=gray!50,opacity=.5] (a.center) to [bend right=30] (b.center) to [bend right=30] (c.center) to [bend right=30] (d.center) to [bend right=30] (a.center);
\end{tikzpicture}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\draw (a.center) to [bend right=30] (b.center);
\draw (a.center) to [bend left=30] (d.center);
\draw (b.center) to [bend right=30] (c.center);
\draw (c.center) to [bend right=30] (d.center);
\path[fill=gray!50,opacity=.5] (0,0) to [bend right=30] (2,0) to [bend right=30] (2,-1.5) to [bend right=30] (0,-1.5) to [bend right=30] (0,0);
\end{tikzpicture}
\end{document}
这产生了
这里的问题是曲线出现在节点上方。这是由于绘制顺序造成的。这表明您应该稍后绘制节点。但如果我们这样做,tikz 将不知道点(a.center)
等,因此会抛出错误。补救措施是绘制节点两次(绘制曲线之前和之后,并用white
颜色填充节点),如下所示:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\tikzset{state/.style={circle,draw=black, very thick,inner sep=3pt,fill=white}}
\begin{document}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\draw (a.center) to [bend right=30] (b.center);
\draw (a.center) to [bend left=30] (d.center);
\draw (b.center) to [bend right=30] (c.center);
\draw (c.center) to [bend right=30] (d.center);
\path[fill=gray!50,opacity=.5] (0,0) to [bend right=30] (2,0) to [bend right=30] (2,-1.5) to [bend right=30] (0,-1.5) to [bend right=30] (0,0);
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\end{tikzpicture}
\end{document}
看起来不当!
根据建议克劳迪奥·菲安德里诺该backgrounds
库可用于将一些对象推送到后台。
代码:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning,backgrounds}
\tikzset{state/.style={circle,draw=black, very thick,inner sep=3pt,fill=white,minimum size=4ex}}
\begin{document}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\begin{pgfonlayer}{background}
\draw (a.center) to [bend right=30] (b.center);
\draw (a.center) to [bend left=30] (d.center);
\draw (b.center) to [bend right=30] (c.center);
\draw (c.center) to [bend right=30] (d.center);
\path[fill=gray!50,opacity=.5] (a.center) to [bend right=30] (b.center) to [bend right=30] (c.center) to [bend right=30] (d.center) to [bend right=30] (a.center);
\end{pgfonlayer}
\end{tikzpicture}
\begin{tikzpicture}
\node[state] (a) at (0,0) {$a$};
\node[state] (b) at (2,0) {$b$};
\node[state] (c) at (2,-1.5) {$c$};
\node[state] (d) at (0,-1.5) {$d$};
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\begin{pgfonlayer}{background}
\draw (a.center) to [bend right=30] (b.center);
\draw (a.center) to [bend left=30] (d.center);
\draw (b.center) to [bend right=30] (c.center);
\draw (c.center) to [bend right=30] (d.center);
\path[fill=gray!50,opacity=.5] (0,0) to [bend right=30] (2,0) to [bend right=30] (2,-1.5) to [bend right=30] (0,-1.5) to [bend right=30] (0,0);
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
由此我们得到
我建议的另一种方法是使用coordinates
它们并按照要叠加对象的正确顺序绘制所有内容。此外,字母a
和的大小b
并不相同。因此,您的圆圈的半径会有所不同。可以通过添加phantom
空间或 minimum size
为节点定义来解决此问题。代码将是:
\documentclass{article}
\usepackage{tikz}
\tikzset{state/.style={circle,draw=black,fill=white, very thick,inner sep=3pt,minimum size=4ex}}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (2,0);
\coordinate (c) at (2,-1.5);
\coordinate (d) at (0,-1.5);
\draw (a) to [bend right=30] (b);
\draw (a) to [bend left=30] (d);
\draw (b) to [bend right=30] (c);
\draw (c) to [bend right=30] (d);
\path[draw,fill=gray!50,opacity=.5] (a) to [bend right=30] (b) to [bend right=30] (c) to [bend right=30] (d) to [bend right=30] (0,0);
\draw (a) to (b);
\draw (a) to (d);
\draw (b) to (c);
\draw (c) to (d);
\node[state] at (a) {$a$};
\node[state] at (b) {$b$};
\node[state] at (c) {$c$};
\node[state] at (d) {$d$};
\end{tikzpicture}
\end{document}
答案2
更加紧凑一些。
\documentclass[tikz]{standalone}
\tikzset{state/.append style={circle,draw=black,fill=white,
minimum size=4ex,very thick,inner sep=3pt}}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (2,0);
\coordinate (c) at (2,-1.5);
\coordinate (d) at (0,-1.5);
\draw (a) rectangle (c);
\draw[bend right=30,fill=gray!50,opacity=.5] (a) to (b) to (c) to (d) to (a);
\foreach \x in {a,...,d}{\node[state] at (\x) {$\x$};}
\end{tikzpicture}
\end{document}
如果我没记错的话,最好避免覆盖(实际上使用另一个名称)state
在库中使用的样式automata
,或者至少附加您的样式。
答案3
- 声明坐标。
- 借助这些坐标绘制阴影区域。
- 弯曲的线条与阴影的路径相同
fill opacity
确保线条也没有被阴影覆盖。
- 绘制节点。
fill=white
用于隐藏阴影区域的部分。\mathmakebox[\widthof{d}][c]{\vphantom{d}\c}
用于获取所有节点的相同大小(并且需要包mathtools
)。您还可以使用和
的组合,但不一定能获得真正的最小尺寸。如果指定的小于最大节点的大小,则仍会得到不同大小的节点。如果将其设置为大于最大节点的大小,则不会获得最紧密的尺寸(这不一定会有坏处)。 此外,来自位于同一垂直位置的节点的节点测试使用相同的基线,我发现这比ing 更令人满意。(当然,可以将解决方案与此结合起来,请参见下文。该解决方案也使用而不是。)minimum size
inner sep
minimum size
.center
.center
\strut
\vphantom
- 连接节点
代码
\documentclass[border=2pt]{standalone}
\usepackage{mathtools}
\usepackage{tikz}
\tikzset{state/.style={circle,draw=black, very thick,inner sep=3pt}}
\begin{document}
\begin{tikzpicture}
\coordinate (a) at (0,0);
\coordinate (b) at (2,0);
\coordinate (c) at (2,-1.5);
\coordinate (d) at (0,-1.5);
\path[draw,fill=gray!50,fill opacity=.5,bend right=30] (a) to (b)
to (c)
to (d)
to (a);
\foreach \c in {a,b,c,d} {
\node [state,fill=white] at (\c) (n\c) {$\mathmakebox[\widthof{b}][c]{\vphantom{d}\c}$};
}
\draw (na) edge (nb)
(na) edge (nd)
(nb) edge (nc)
(nc) edge (nd);
\end{tikzpicture}
\end{document}
输出
.center
使用和进行编码\strut
\documentclass[border=2pt]{standalone}
\usepackage{mathtools}
\usepackage{tikz}
\usetikzlibrary{backgrounds}
\tikzset{state/.style={circle,draw=black, very thick,inner sep=3pt}}
\begin{document}
\begin{tikzpicture}
\foreach \c/\cx/\cy in {a/0/0,
b/2/0,
c/2/-1.5,
d/0/-1.5
} {
\node [state,fill=white] at (\cx,\cy) (\c) {$\mathmakebox[\widthof{d}][c]{\strut \c}$};
}
\draw (a) edge (b)
(a) edge (d)
(b) edge (c)
(c) edge (d);
\begin{scope}[on background layer]
\draw[fill=gray!50,fill opacity=.5,bend right=30] (a.center) to (b.center)
to (c.center)
to (d.center)
to (a.center);
\end{scope}
\end{tikzpicture}
\end{document}