对节点之间弯曲路径所包围的区域进行着色

对节点之间弯曲路径所包围的区域进行着色

我正在绘制某种图形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

你应该尝试从节点的中心画弧和线。这可以借助positioningtikz 库来完成。

代码

\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

  1. 声明坐标。
  2. 借助这些坐标绘制阴影区域。
    • 弯曲的线条与阴影的路径相同
    • fill opacity确保线条也没有被阴影覆盖。
  3. 绘制节点。
    • fill=white用于隐藏阴影区域的部分。
    • \mathmakebox[\widthof{d}][c]{\vphantom{d}\c}用于获取所有节点的相同大小(并且需要包mathtools)。您还可以使用和
      的组合,但不一定能获得真正的最小尺寸。如果指定的小于最大节点的大小,则仍会得到不同大小的节点。如果将其设置为大于最大节点的大小,则不会获得最紧密的尺寸(这不一定会有坏处)。 此外,来自位于同一垂直位置的节点的节点测试使用相同的基线,我发现这比ing 更令人满意。(当然,可以将解决方案与此结合起来,请参见下文。该解决方案也使用而不是。)minimum sizeinner sepminimum size
      .center.center\strut\vphantom
  4. 连接节点

代码

\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}

输出.center\strut

使用 .center 和 \strut 输出

相关内容