Are boolean operations on TikZ shapes possible?

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.

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}


-
Use even odd rule. You can have a look at this question: tex.stackexchange.com/questions/9681/… –  Leo Liu Feb 19 '11 at 14:09
even odd rule appears to only pertain to fills, rather than outlines. –  Richard Terrett Feb 19 '11 at 14:21
Not an answer to your question, but might help you nevertheless: Have a look at the cloud node shape (see section 48.4 of the v2.10 manual or section 39.4 in the v2.00 manual). –  Caramdir Feb 19 '11 at 17:14
@Caramdir - I'm impressed by the level of detail of the manual and the cloud object itself - thanks for alerting me to its capabilities. Regrettably, I require a shape with puffs of equal radius, which appears to be only possible in the degenerate (circular) case of cloud. I may end up using the circular cloud anyhow as this is probably too much stuffing around for a simple schema. To give some background, this shape is representing a bounding volume in a chemistry calculation that has been capped with protruding hydrogen atoms. Accordingly, symmetry and equal puff radii are desired. –  Richard Terrett Feb 21 '11 at 3:35
Unfortunately TikZ always first fills a path and then strokes it. Even when giving the lowlevel commands the other way around. Theoretically, you draw the shape with some arc paths, but that would involve some calculations. –  Caramdir Feb 21 '11 at 4:42

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{http://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.

-
This seems to be the best way of doing it. Nice trick! –  Richard Terrett Feb 21 '11 at 10:43
Great idea! –  Caramdir Feb 21 '11 at 17:02

I just realized: There is a way to reuse paths: pre- and postactions.

\documentclass{minimal}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw[line width=0.8pt,postaction={gray!30,fill}]
( 0.0,  0.0) circle (1cm and 0.5cm)
( 0.4,  0.5) circle (0.3cm)
(-0.4, -0.5) circle (0.3cm)
(-0.4,  0.4) circle (0.3cm)
( 0.4, -0.4) circle (0.3cm);

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


As in Andrew's solution the line width needs to be twice the normal line width (the default line width if 0.4pt). Note also that by listing all the shapes in a single \draw statement, they are considered to belong to a single path.

-
That's also a great solution. –  Richard Terrett Feb 22 '11 at 5:42
Very neat. I feel that this is more "TikZ-y". –  Andrew Stacey Feb 22 '11 at 9:21