4

I would like to generate the following Venn diagram:

enter image description here

which can be generated by the following

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

However, I wish to use use path rather than directly specify the shapes, i.e., I wish to replace the line \clip (0.8cm,0) circle (1.5cm) (-2.3cm,-1.5cm) rectangle (2.3,1.5); by something like \clip [use path=YCircle, use path=WholeSet];. However, the line I wrote above will generate the wrong output:

enter image description here

My question is: How can I get even odd clipping and use path= to work together?

  • Seems to me like use path can't be used multiple times in one path: \draw[red,use path=YCircle, use path=WholeSet]; ony draws the last given path. – wrtlprnft Mar 29 '16 at 9:22
4

The code use path overwrites the current path with the named path. So the second use path replaces the first and the first is effectively ignored. To achieve the end you need, you need an append version of the use path key. With a few \expandafters (probably a few too many) you can do this.

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

(I wouldn't \draw the path inside the clip, it will draw something a bit odd. Although it's overdrawn by the later \draw commands, it's better style not to draw something unnecessary.)

Venn diagram

| improve this answer | |
3

I just want to point out that it may not be necessary to mess this deeply with PGF's system layer, which has the following to say about \pgfsyssoftpath@:

On the other hand, as a user you will never use these commands directly, they are described as part of the low-level interface.

Of course, messing with it is fun, but here is how it could be done with just the basic LaTeX \newcommand macro:

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

There are some fine differences with this approach (for example, in my version, the path is parsed every time it's used, so it will be affected by coordinate system transformations and the like), but at least it's easy to see what's going on.

| improve this answer | |
  • Notice that this assumes very basic paths and very basic intersection patterns. – percusse Mar 29 '16 at 12:41
  • I did use this trick before I turned to intersections library. Very often I need to clip shapes that are rotated and distorted in arbitrary way, and I find name path very useful. – wdg Mar 30 '16 at 3:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.