如何填充以边缘[向右弯曲]为界的形状?

如何填充以边缘[向右弯曲]为界的形状?

我有

\node (A) at (0,2) {$A$};
\node (B) at (0,0) {$B$}
  edge [<-] (A)
  edge [<-, bend right=90] (A); 

我该如何填充这个 D 形?显然,我必须使用\filldraw,但我不知道如何进行弯曲。

答案1

很难给出答案,因为你没有准确解释什么是 D 形。如果你想从 A.center 和 B.center 填充,答案是不一样的。现在重要的是要了解你为什么会遇到问题。

所有的解释都在 pgfmanual 中,但我会添加一些完整的示例。

边缘操作的效果是在主路径之后在图片中添加以下路径:

  \path[every edge,⟨options⟩] (\tikztostart) ⟨path⟩;

这里,⟨path⟩ 是 to 路径。请注意,与 to 操作添加的路径不同,(\tikztostart) 被添加到 ⟨path⟩ 之前(对于 to 操作来说,这是不必要的,因为这个坐标已经是主路径的一部分)。\tikztostart 是路径上紧接在边缘操作之前的最后一个坐标,就像节点或 to 操作一样。但是,这条规则有一个例外:如果边缘操作直接位于节点操作之前,那么这个刚刚声明的节点就是起始坐标(而不是像通常那样,放置这个刚刚声明的节点的坐标 - 这是一个很小但微妙的区别)。在这方面,edge 与 node 和 to 都不同。如果连续有多个边缘操作,那么它们的起始坐标对于所有操作都是相同的,因为它们的目标坐标毕竟不是主路径的一部分。因此,起始坐标是第一个边缘操作之前的坐标。这与节点类似,因为边缘操作根本不会修改当前路径。具体来说,它不会改变最后访问的坐标,请参见以下示例:

   \tikzstyle{every edge}=              [draw]  

边操作的工作方式类似于在绘制主路径后添加的 to 操作,就像在绘制主路径后添加节点一样。这允许每条边具有不同的外观。作为节点操作,边会暂时中止当前路径的构建,并构建一条新路径 p。这条新路径 p 将在绘制主路径后绘制。请注意,p 的选项可能与主路径完全不同。还请注意,如果主路径中有多个 to 和/或节点操作,则每个操作都会创建自己的路径,并按照在路径上遇到的顺序绘制它们。

 \path ... edge[⟨options⟩] ⟨nodes⟩ (⟨coordinate⟩) ...;

您的代码

\node (A) at (0,2) {$A$};
\node (B) at (0,0) {$B$}
  edge [<-] (A)
  edge [<-, bend right=90] (A); 

首先,我认为将节点的创建、边的创建和区域的填充混合在一起并不是一个好主意。我建议

\begin{tikzpicture}
  \node (A) at (0,2) {$A$};
  \node (B) at (0,0) {$B$};
  \path[<-] (B) edge  (A)
                edge [bend right=90] (A); 
 \end{tikzpicture} 

但更自然的是

\begin{tikzpicture}
    \node (A) at (0,2) {$A$};
    \node (B) at (0,0) {$B$};
    \path[->] (A) edge  (B)
                  edge [bend left=90] (B);  
\end{tikzpicture}  

但我们可以注意到尽管使用了\path曲线,但每条曲线都有一个箭头。

边缘操作的效果是在主路径之后在图片中添加以下路径:

 \path[every edge,⟨options⟩] (\tikztostart) ⟨path⟩; 

  \tikzstyle{every edge}=              [draw]  

边缘操作会创建新路径。这就是绘制曲线的原因。绘制选项是继承的,如 ->、thick 等。使用 \tikzstyle{every edge}= [draw,fill=red]`,您可以填充边缘操作定义的所有区域。

一个示例来了解边缘如何工作

\documentclass{article}  
\usepackage{tikz}  
\usetikzlibrary{backgrounds} 
\begin{document} 
 \tikzstyle{every edge}=  [draw=red]     
  \begin{tikzpicture}[out=90,in=90,relative]
  \node [circle,draw] (a) at (0,0) {a};
  \node [circle,draw] (b) at (1,1) {b};
  \node [circle,draw] (c) at (2,2) {c};
  \draw[->] (a) -- (b) 
            (a) edge (b)
                edge (c)
            (b) -- (c); 
\end{tikzpicture}  

\end{document}

在此处输入图片描述

另一处充满

\documentclass{article}  
\usepackage{tikz}  
\usetikzlibrary{backgrounds} 
\begin{document} 
 \tikzstyle{every edge}=  [draw=red,fill=blue!20,opacity=.5]     
  \begin{tikzpicture}[out=90,in=90,relative]
  \node [circle,draw] (a) at (0,0) {a};
  \node [circle,draw] (b) at (1,1) {b};
  \node [circle,draw] (c) at (2,2) {c};
  \draw[->] (a) -- (b) 
            (a) edge (b)
                edge (c)
            (b) -- (c); 
\end{tikzpicture}  

\end{document} 

在此处输入图片描述

现在我将填充命令放在路径的开头。此命令仅用于主路径,但在您的情况下,主路径不是您想要的。我认为它是一个单点。您需要在边缘操作中添加一个选项,或者every edge如果您想填充使用边缘获得的额外路径,则需要进行修改。

现在有三个例子:第一个看看主路径的选项如何工作,第二个看看它是否可以用to,第三个填充整个图片。

\documentclass{article}
\usepackage{tikz}  
\usetikzlibrary{backgrounds} 
\begin{document} 



\begin{tikzpicture}
\node (A) at (0,2) {$A$};
\node (B) at (0,0) {$B$};
\draw[->,ultra thick] (A)    edge  (B)
                             edge[ bend left=90,fill=red] (B);
\end{tikzpicture}
\begin{tikzpicture}
\node (C) at (0,2) {$A$};
\node (D) at (0,0) {$B$};
\draw[->] (C)      to  (D);
\draw[->,fill=red] (C) to [ bend left=90] (D);
\end{tikzpicture} 
\begin{tikzpicture}
\node (C) at (0,2) {$A$};
\node (D) at (0,0) {$B$};
\draw[->] (C)      to  (D);
\draw[->] (C) to [ bend left=90] (D);
\begin{scope}[on background layer]
    \path [fill=red!30] (A) to [ bend left=90] (B) -- (B.center)--(A.center)--(A.east);
\end{scope}  
\end{tikzpicture} 
\end{document} 

在此处输入图片描述

答案2

您所要求的内容实际上相当复杂。以下是使其变得复杂的原因:

  1. 每个edge命令都定义一条全新的路径。因此,您要填充的区域不仅由物理上不相交的路径描述,还由编程上不相交的路径描述。
  2. 箭头只放在路径的末端,所以你确实希望这些路径在
  3. 您想要填充的区域没有精确定义。
  4. 填充路径时,将路径的每一段都通过直线连接起点和终点来独立填充。
  5. 至少有一条路径是这样的,用户不知道它到底在哪里。(在给定的代码中,可以看到弯曲的箭头最终到达了哪个锚点,但这可能并不总是正确的。)

所以你要做的是:指定一些路径,然后在两个不同的且不兼容方法。解决这个问题的一个复杂方法是​​存储这两条路径,然后通过“焊接”它们来生成一条新路径。然后,原来的两条路径可以用于箭头,焊接的路径用于填充。这样做完全可行(使用我的spath库),但是对于这种情况来说,这有点太复杂了(而且spath代码显然不稳定)。如果您准备再次指定这两条路径,那么有一个快速的破解方法可以得到您想要的。

指定路径时填充,我们使用tos 而不是edges。就创建的路径而言,它们是相同的(由于to更新当前位置但edge不更新,因此路径的指定方式有所不同)。不同之处在于生成的对象是单个路径,而不是多个路径。然后我们要做的是插入一个低级黑客,它会更改所有内部的movetos 到 linetos。这将创建一个封闭的填充路径。然后我们必须使用绘图命令重新指定它。

这样做的一个缺点是节点被绘制路径已填充(好吧,在示例中,A节点始终在路径填充之前绘制,但现在B也是如此),这意味着填充区域可能与节点文本重叠。在这种情况下,情况并非如此,但如果确实如此,则可以使用图层将填充区域放在节点下方(参见TikZ 中的“Z 级别”有一些偷偷摸摸的方法可以做到这一点)。

代码如下:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/55739/86}
\usepackage{tikz}

\makeatletter

\let\orig@pgfsyssoftpath@movetotoken=\pgfsyssoftpath@movetotoken
\def\new@pgfsyssoftpath@movetotoken{%
  \let\pgfsyssoftpath@movetotoken=\pgfsyssoftpath@linetotoken
  \orig@pgfsyssoftpath@movetotoken}


\tikzset{
  join with lines/.code={
    \let\pgfsyssoftpath@movetotoken=\new@pgfsyssoftpath@movetotoken
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node (A) at (0,2) {$A$};
\node (B) at (0,0) {$B$};
\fill[red,join with lines] (A) to (B) to[<-,bend right=90] (A);
\draw[black] (B) edge[<-] (A) edge[<-,bend right=90] (A);
\end{tikzpicture}
\end{document}

结果:

填充区域部分指定

答案3

只需使用fill

\documentclass{article}
\usepackage{tikz}
\begin{document}
  \begin{tikzpicture}
\node (A) at (0,2) {$A$};
\node (B) at (0,0) {$B$}
  edge [<-] (A)
  edge [<-, bend right=90,fill=red] (A);
\end{tikzpicture}
\end{document}

在此处输入图片描述

编辑一个小的修改(来自 Altermundus 答案的想法)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{backgrounds}
\begin{document}
\begin{tikzpicture}
\node[fill=white,inner sep=.5pt] (A) at (0,2) {$A$};
\node [fill=white,inner sep=.5pt] (B) at (0,0) {$B$};
\draw[->] (A)      to  (B);
\draw[->] (A) to [ bend left=90] (B);
\begin{scope}[on background layer]
    \path [fill=red!30] (A) to [ bend left=90] (B) -- (B.center)--(A.center)--(A.east);
\end{scope}
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容