TikZ Boolean Operations – Are Boolean Operations on TikZ Shapes Possible?

tikz-pgf

The Situation

Many vector graphics editors (for instance, Inkscape, Adobe Illustrator and Microsoft Visio) permit the synthesis of new shapes by union, difference or intersection operators. A collection of Venn diagrams on TeXample demonstrates the use of clipping to fill unions and differences of shapes, however I have not yet seen any examples of construction of new shape outlines through boolean operations. Does this functionality exist in TikZ at all?

A Workaround

I have devised a workaround for the little diagram that I'm working on that takes advantage of Z-ordering to give the impression of a composite outline (i.e. the union of several shapes) by drawing a shape, drawing intersecting shapes and then redrawing the original shape without a line style. It is necessary to slightly shrink the redrawn shape to get constant apparent line weight all the way around:

\begin{tikzpicture}[scale=1]

% Draw all of the necessary shapes.
    \draw[fill=gray!30] ( 0.0,  0.0) circle (1cm and 0.5cm);
    \draw[fill=gray!30] ( 0.4,  0.5) circle (0.3cm);
    \draw[fill=gray!30] (-0.4, -0.5) circle (0.3cm);
    \draw[fill=gray!30] (-0.4,  0.4) circle (0.3cm);
    \draw[fill=gray!30] ( 0.4, -0.4) circle (0.3cm);

% Now draw a grey circle over the top with no outline.
    \draw[fill=gray!30,draw=none] (0,0) circle (0.99cm and 0.49cm);
    \draw[] (0,0) node {Q.M.};
\end{tikzpicture}

Needless to say this is probably the wrong way to go about this problem. Any better ways?

Example Output

at 200% zoom, as viewed in Evince.

A hacky composite shape in TikZ

Further Explorations

In my dabbling I have determined that fairly interesting effects can be had by judicious z-ordering of shapes with and without borders, for instance, giving the appearance of an ellipsoid with protrusions in front and behind. Shared in the hope it might be useful to someone.

\begin{tikzpicture}[scale=1]
% Draw lobes behind.
    \draw[fill=gray!30] ( 0.4,  0.4) circle (0.3cm);
    \draw[fill=gray!30] (-0.4, -0.4) circle (0.3cm);
% Draw ellipsoid.
    \draw[fill=gray!30] ( 0.0,  0.0) circle (1cm and 0.5cm);
% Draw lobes in front.
    \draw[fill=gray!30] (-0.4,  0.4) circle (0.3cm);
    \draw[fill=gray!30] ( 0.4, -0.4) circle (0.3cm);
% Now draw a grey circle over the top with no outline,
% shrunken to only clip a section of the lobes in front.
    \draw[fill=gray!30,draw=none] (0,0) circle (0.80cm and 0.35cm);
    \draw[] (0,0) node {Q.M.};
\end{tikzpicture}

Shape with vaguely 3D appearance.

Best Answer

It does seem, as Caramdir says in the comments, that the ideal way to do this would be to separate the drawing from the filling and do all of the drawing first and then the filling afterwards. I don't think that this is doable as a single preexisting command, but where there's a TeX there's a TikZ, as the saying goes. Here's a way that works by using layers.

Edit: Using the technique in "Z-level" in TikZ it is now possible to collapse the commands a little so that there's no need to introduce a new high-level command. (Original solution left in for comparison.) Caramdir's solution is probably the simplest when it is possible to give all the paths in a single command. If that is not (for some reason) possible, the following is more adaptable.

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


\pgfdeclarelayer{back}
\pgfsetlayers{back,main}

\def\drawfill#1;{
  \fill[gray!30] #1;
\begin{pgfonlayer}{back}
  \draw[line width=2pt] #1;
\end{pgfonlayer}}

\tikzset{%
  on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  },%
  draw on back/.style={
    preaction={
      draw,
      on layer=back,
      line width=2pt
    },
    gray!30
  }
}


\begin{document}
\begin{tikzpicture}

\drawfill ( 0.0,  0.0) circle (1cm and 0.5cm);
\drawfill ( 0.4,  0.5) circle (0.3cm);
\drawfill (-0.4, -0.5) circle (0.3cm);
\drawfill (-0.4,  0.4) circle (0.3cm);
\drawfill ( 0.4, -0.4) circle (0.3cm);

    \draw[] (0,0) node {Q.M.};

\begin{scope}[yshift=-2cm]

\fill[draw on back] ( 0.0,  0.0) circle (1cm and 0.5cm);
\fill[draw on back] ( 0.4,  0.5) circle (0.3cm);
\fill[draw on back] (-0.4, -0.5) circle (0.3cm);
\fill[draw on back] (-0.4,  0.4) circle (0.3cm);
\fill[draw on back] ( 0.4, -0.4) circle (0.3cm);

    \draw[] (0,0) node {Q.M.};

\end{scope}
\end{tikzpicture}
\end{document}

Notice the extra large line width since half of the line width gets covered by the fills.

union of shapes

Related Question