反向剪辑时如何确定路径的内部?

反向剪辑时如何确定路径的内部?

我一直在玩[reverseclip]如何在 TikZ 中反转“剪辑”选择?。效果很好。当您应用 [reverseclip] 时,它似乎会向您的路径添加另一部分——当前页面的顺时针遍历。但是,我无法理解如何确定多部分路径的内部。例如:

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[remember picture,overlay]
% A path that follows the edges of the current page, CW
\tikzstyle{reverseclip}=[insert path={(current page.north east) --
  (current page.south east) --
  (current page.south west) --
  (current page.north west) --
  (current page.north east)}
]
\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (1,1);
\begin{pgfinterruptboundingbox}
   \path [clip] (A) -- (B) -- (C) [reverseclip]; % good, CCW
%  \path [clip] (C) -- (B) -- (A) [reverseclip]; % bad, CW
\end{pgfinterruptboundingbox}
\fill[red!30] (A) circle (3cm);
%\fill[red!30,even odd rule] (A) circle (3cm); % does not make bad good
\end{tikzpicture}
\end{document}

因此,如果我的路径方向是逆时针,我只能获得所需的反向裁剪。当我将方向设为顺时针时,所有内容都会被不合需要地填充。

在文档第 15.4.2 节“图形参数:内部规则”中,我了解了非零和奇偶规则。我通过想象以 CW 方式绘制的圆圈来合理化这种行为。然后,第一个剪辑路径是 CCW,一切都应该正常工作。使用非零规则,CW 剪辑路径不会剪辑任何东西的原因就说得通了。但是,我尝试指定奇偶规则,期望这会使结果与剪辑路径的方向无关。我的期望错了。

看来内部规则并没有按照我理解的方式应用。

  1. 裁剪(反向)时,如何确定内部区域?
  2. 如何逆转通过 \pgfsyssoftpath@getcurrentpath{\mypath} 保存的路径?
  3. 除了定义 [reverseclipCW] 和 [reverseclipCCW] 之外,有没有办法使 reverseclip 概念对于路径的方向更加稳健?
  4. 基本形状(圆形、矩形等)的方向是什么?顺时针?

答案1

1- 如何使用nonzero ruleeven odd rule路径

当前规则(nonzero ruleeven odd rule)按操作逐个应用,并按路径逐个应用。

如下图所示:

  • 在左栏中,所有圆(内圆和外圆)都是逆时针(CCW=逆时针),
  • 在右栏中,外圆为逆时针内圈是 CW(CW=顺时针),
  • 在第一行,两条路用于绘制每对圆圈,
  • 在第二行和第三行,一条路径用于绘制每对圆圈,
  • 在第一行和第二行,填充使用nonzero rule(隐式)。
  • 在第三行,填充使用even odd rule

在此处输入图片描述

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[every node/.style={align=flush left,font=\bfseries}]
  \node at (0,3){Outer circle=CCW\\Inner circle=CCW};
  \node at (4.5,3){Outer circle=CCW\\Inner circle=CW};
  \begin{scope}[yshift=0mm,
    every path/.style={draw=black,fill=cyan}]

    \path (0,0) ++(0:2cm) arc (0:360:2cm);
    \path (0,0) ++(0:1.8cm) arc (0:360:1.4cm);

    \path (4.5,0) ++(0:2cm) arc (0:360:2cm);
    \path (4.5,0) ++(0:1.8cm) arc (360:0:1.4cm);

    \node[right] at (7,0) {Each circle=one path};
  \end{scope}
  \begin{scope}[yshift=-4.5cm,
    every path/.style={draw=black,fill=orange}]

    \path (0,0) ++(0:2cm) arc (0:360:2cm)
          (0,0) ++(0:1.8cm) arc (0:360:1.4cm);

    \path (4.5,0) ++(0:2cm) arc (0:360:2cm)
          (4.5,0) ++(0:1.8cm) arc (360:0:1.4cm);

    \node[right] at (7,0)
    {Outer and inner circles=single path\\nonzero rule};
  \end{scope}
  \begin{scope}[yshift=-9cm,
    even odd rule,every path/.style={draw=black,fill=lime}]

    \path (0,0) ++(0:2cm) arc (0:360:2cm)
          (0,0) ++(0:1.8cm) arc (0:360:1.4cm);


    \path (4.5,0) ++(0:2cm) arc (0:360:2cm)
          (4.5,0) ++(0:1.8cm) arc (360:0:1.4cm);

    \node[right] at (7,0)
    {Outer and inner circles=single path\\even odd rule};
  \end{scope}

\end{tikzpicture}
\end{document}

2-如何nonzero rule使用even odd rule剪裁路径

不能even odd rule直接应用于剪切路径(这是一个错误)。

在以下示例中,每行均显示一个填充的矩形。每个矩形均由单个路径中的四个圆圈剪切。第一行使用nonzero rule(隐式),第二行使用范围应用于even odd rule剪切路径,第三行使用 Andrew Stacey 建议的新选项clip even odd rule

\tikzset{clip even odd rule/.code={\pgfseteorule}} % Credit to Andrew Stacey

在此处输入图片描述

\documentclass{standalone}
\usepackage{tikz}
\tikzset{clip even odd rule/.code={\pgfseteorule}} % Credit to Andrew Stacey 
\begin{document}
\begin{tikzpicture}[every node/.style={align=flush left,font=\bfseries}]
  \node at (2.25,3) {All circles in a single clipping path};
  \node at (0,2){Outer circle=CCW\\Inner circle=CCW};
  \node at (4.5,2){Outer circle=CCW\\Inner circle=CW};
  \begin{scope}[yshift=0mm]
    \node[right] at (7,0) {clipping path with nonzero rule};

    \clip
    (0,0) circle (2cm)
    (0,0) ++(0:1.8cm) arc (0:360:1.4cm)
    (4.5,0) circle (2cm)
    (4.5,0) ++(0:1.8cm) arc (360:0:1.4cm);

    \draw[fill=red] (-2,-1) rectangle (7,1);
  \end{scope}

  \begin{scope}[yshift=-4.5cm,even odd rule]
    \node[right] at (7,0) {clipping path with even odd rule\\(via scope)};

    \clip
    (0,0) circle(2cm)
    (0,0) ++(0:1.8cm) arc (0:360:1.4cm)
    (4.5,0) circle(2cm)
    (4.5,0) ++(0:1.8cm) arc (360:0:1.4cm);

    \draw[fill=orange] (-2,-1) rectangle (7,1);
  \end{scope}

  \begin{scope}[yshift=-9cm]
    \node[right] at (7,0)
    {clipping path with even odd rule\\(via new \texttt{clip even odd rule} option)};

    \clip[clip even odd rule]
    (0,0) circle(2cm)
    (0,0) ++(0:1.8cm) arc (0:360:1.4cm)
    (4.5,0) circle(2cm)
    (4.5,0) ++(0:1.8cm) arc (360:0:1.4cm);

    \draw[fill=lime] (-2,-1) rectangle (7,1);
  \end{scope}
\end{tikzpicture}
\end{document}

关于 CCW 和 CW 的注释:

在路径中:

  • A circle(或ellipse)操作始终是 CCW。
  • rectangle根据提供的角,操作可以是 CCW 或 CW :

    (a) rectangle (b)相当于(a) -| (b) |- (a)

相关内容