TikZ:使用按交叉点命名路径库进行奇数剪切

TikZ:使用按交叉点命名路径库进行奇数剪切

我想生成以下维恩图:

在此处输入图片描述

可以通过以下方式生成

\documentclass[tikz,margin=0pt]{standalone}

\usepackage{tikz}
\usetikzlibrary{shapes,intersections}
\begin{document}
\pagestyle{empty}

\makeatletter
\tikzset{
  use path for main/.code={%
    \tikz@addmode{%
      \expandafter\pgfsyssoftpath@setcurrentpath\csname tikz@intersect@path@name@#1\endcsname
    }%
  },
  use path for actions/.code={%
    \expandafter\def\expandafter\tikz@preactions\expandafter{\tikz@preactions\expandafter\let\expandafter\tikz@actions@path\csname tikz@intersect@path@name@#1\endcsname}%
  },
  use path/.style={%
    use path for main=#1,
    use path for actions=#1,
  }
}
\makeatother


\begin{tikzpicture}
    \path[name path=XCircle] (-0.8cm,0) circle (1.5cm);
    \path[name path=YCircle] (0.8cm,0) circle (1.5cm);
    \path[name path=WholeSet] (-2.3cm,-1.5cm) rectangle (2.3,1.5);

    \begin{scope} [even odd rule]
            \clip (0.8cm,0) circle (1.5cm) (-2.3cm,-1.5cm) rectangle (2.3,1.5);
                \draw [use path=XCircle, fill=gray!70];
    \end{scope}


    \draw [use path=XCircle];
    \draw [use path=YCircle];
\end{tikzpicture}
\end{document}

但是,我希望使用use path而不是直接指定形状,即我希望用\clip (0.8cm,0) circle (1.5cm) (-2.3cm,-1.5cm) rectangle (2.3,1.5);类似的东西替换线条\clip [use path=YCircle, use path=WholeSet];。但是,我上面写的行将生成错误的输出:

在此处输入图片描述

我的问题是:我怎样才能获得奇偶剪辑并use path=一起工作?

答案1

代码use path 覆写当前路径与命名路径。因此,第二个use path替换第一个,第一个实际上被忽略。要实现所需的目的,您需要一个附加版本的密钥use path。使用几个\expandafters(可能太多了)您可以做到这一点。

\documentclass[tikz,margin=3pt]{standalone}
%\url{http://tex.stackexchange.com/q/301335/86}

\usepackage{tikz}
\usetikzlibrary{shapes,intersections}
\begin{document}
\pagestyle{empty}

\makeatletter


\def\@appendnamedsoftpath#1{%
  \pgfsyssoftpath@getcurrentpath\@temppatha
  \expandafter\let\expandafter\@temppathb\csname tikz@intersect@path@name@#1\endcsname
  \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\@temppatha\expandafter\expandafter\expandafter{\expandafter\@temppatha\@temppathb}%
  \pgfsyssoftpath@setcurrentpath\@temppatha
}

\def\@appendnamedpathforactions#1{%
  \pgfsyssoftpath@getcurrentpath\@temppatha
  \expandafter\let\expandafter\@temppathb\csname tikz@intersect@path@name@#1\endcsname
  \expandafter\def\expandafter\@temppatha\expandafter{\csname @temppatha\expandafter\endcsname\@temppathb}%
  \let\tikz@actions@path\@temppatha
}

\tikzset{
  use path for main/.code={%
    \tikz@addmode{%
      \expandafter\pgfsyssoftpath@setcurrentpath\csname tikz@intersect@path@name@#1\endcsname
    }%
  },
  append path for main/.code={%
    \tikz@addmode{%
      \@appendnamedsoftpath{#1}%
    }%
  },
  use path for actions/.code={%
    \expandafter\def\expandafter\tikz@preactions\expandafter{\tikz@preactions\expandafter\let\expandafter\tikz@actions@path\csname tikz@intersect@path@name@#1\endcsname}%
  },
  append path for actions/.code={%
\expandafter\def\expandafter\tikz@preactions\expandafter{\tikz@preactions
    \@appendnamedpathforactions{#1}}%
  },
  use path/.style={%
    use path for main=#1,
    use path for actions=#1,
  },
  append path/.style={%
    append path for main=#1,
    append path for actions=#1
  }
}
\makeatother


\begin{tikzpicture}
    \path[name path=XCircle] (-0.8cm,0) circle (1.5cm);
    \path[name path=YCircle] (0.8cm,0) circle (1.5cm);
    \path[name path=WholeSet] (-2.3cm,-1.5cm) rectangle (2.3,1.5);

\begin{scope} [even odd rule]
\clip [use path=YCircle, append path=WholeSet];
\fill [use path=XCircle, gray!70];
\end{scope}


    \draw [use path=XCircle];
    \draw [use path=YCircle];
\end{tikzpicture}
\end{document}

(我不会\draw在剪辑里面添加路径,它会画出一些奇怪的东西。虽然它被后面的\draw命令透支了,但最好不要画一些不必要的东西。)

维恩图

答案2

我只是想指出,可能没有必要对 PGF 的系统层进行如此深入的研究,该系统层有以下几点需要说明\pgfsyssoftpath@

另一方面,作为用户您永远不会直接使用这些命令,它们被描述为低级界面的一部分。

当然,摆弄它是很有趣的,但是这里介绍如何使用基本的 LaTeX 宏来完成它\newcommand

\documentclass[tikz]{standalone}

\begin{document}
    \begin{tikzpicture}
        \newcommand\XCircle {(-0.8cm,0) circle (1.5cm)}
        \newcommand\YCircle {(0.8cm,0) circle (1.5cm)}
        \newcommand\WholeSet{(-2.3cm,-1.5cm) rectangle (2.3,1.5)}

        \begin{scope}[even odd rule]
            \clip          \YCircle \WholeSet;
            \fill[gray!70] \XCircle;
        \end{scope}

        \draw \XCircle;
        \draw \YCircle;
    \end{tikzpicture}
\end{document}

这种方法存在一些细微的差别(例如,在我的版本中,每次使用路径时都会对其进行解析,因此它会受到坐标系变换等的影响),但至少很容易看出发生了什么。

相关内容