Boolean Diagrams in TikZ

If you’re like me, you like representing philosophical ideas with intersecting circles. Here’s how to draw them in TikZ.

Basics

Circles and rectangles with rounded corners are easy:

\draw[-] (0,0) circle (1cm);\draw[-,rounded corners,thick] (2,-1) rectangle (5,1);

In addition to specifying coordinates absolutely, as we have been doing so far, you can also do so via an angle (from 0 to 360, with 0 starting at x = 0) and distance from (0,0). So, for instance, if we have a 1cm circle centered on (0,0), \draw (0,0) — (90:1); will draw a line from the center of the circle straight up 1cm. And \draw (0,0) — (0:1); will draw a line from the center of the circle straight right 1cm, and so on. Here is an example dividing the circle into thirds and then adding nodes in the center of each part:

\draw[-] (0,0) circle (1cm);\draw (0,0) -- (90:1) (0,0) -- (210:1) (0,0) -- (330:1);\node at (30:1/2) {\bf B};\node at (150:1/2) {\bf A};\node at (270:1/2) {\bf C};

Clipping

We can now introduce a useful device: clipping. We use \clip to delimit a region of the tikzpicture which makes all following commands only drawn within this region. So, for example, suppose we clip our tikzpicture to a rectangle from (0,0) to (2,2). That means that every subsequent command will only draw what falls within this region. In the example below, that’s just the top half of the circle (I include the dotted rectangle to show you the clipped region):

\draw[dotted] (0,0) rectangle (2,2);\clip (0,0) rectangle (2,2);\draw (1,0) circle (1cm);

We can use clipping to selectively fill regions of our diagrams. In the example below, I draw and then clip a circle (this specifies that all following commands will only draw the part of their command that falls inside of the circle). Then, I use the \fill command to fill a rectangle that intersects the left half of the circle:

\draw (0,0) circle (1cm);\clip (0,0) circle (1cm);\fill[black] (0,1) rectangle (-1,-1);

In the next example, I draw two circles and then clip the region of their overlap; then I shade that region:

\draw (-.5,0) circle (1cm);\draw (.5,0) circle (1cm);\clip (-.5,0) circle (1cm);\clip (.5,0) circle (1cm);\fill[black!20!white] (-.5,-1) rectangle (.5,1);

Clipping is powerful, but it is also limited. Once you’ve clipped a region, you can only clip it down further. Suppose you wanted to label the intersection of the two circles with a circular node whose background color was white. Because later commands appear on higher layers than earlier commands, you could not do this with our current tools since, to be unclipped, the \node command would have to come before \clip, but then it would appear in a layer underneath \fill and would be covered up.

Luckily, TikZ has a solution! You can “unclip” by enclosing your clip commands within a scope delimiter: \begin{scope} … \end{scope}. Clips behave as normal within the scope delimiter but then after the scope delimiter ends the rest of your commands behave as if no clipping took place. This allows you to add the circular node labeling the intersection of our two circles as follows:

\begin{scope}\clip (-.5,0) circle (1cm);\clip (.5,0) circle (1cm);\fill[black!20!white] (-.5,-1) rectangle (.5,1);\end{scope}\draw (-.5,0) circle (1cm);\draw (.5,0) circle (1cm);\node at (0,0) {\bf A};

Here are a few more examples for good measure. These use the patterns library. Make sure to include \usetikzlibrary{patterns} in your preamble.

\fill[pattern=north west lines] (-0.5,0) circle (1cm);\fill[pattern=north west lines] (0.5,0) circle (1cm);\begin{scope}\clip (-.5,0) circle (1cm);\clip (.5,0) circle (1cm);\fill[white] (-.5,-1) rectangle (.5,1);\end{scope}\draw (-0.5,0) circle (1cm);\draw (0.5,0) circle (1cm);\node[fill=white,circle] at (-.9,0) {\small{\bf A}};\node[fill=white,circle] at (.9,0) {\small{\bf B}};

\draw (-0.5,0) circle (1cm);\draw (0.5,0) circle (1cm);\draw (0,1) circle (1cm);\begin{scope}\clip (-.5,0) circle (1cm);\clip (0,1) circle (1cm);\draw[ultra thick] (-0.5,0) circle (1cm);\draw[ultra thick] (0,1) circle (1cm);\clip (0.5,0) circle (1cm);\fill[pattern=grid] (-1,-1) rectangle (1,1);\end{scope}\begin{scope}\clip (.5,0) circle (1cm);\clip (0,1) circle (1cm);\draw[ultra thick] (0.5,0) circle (1cm);\draw[ultra thick] (0,1) circle (1cm);\end{scope}

\begin{scope}
\clip[rounded corners] (0,0) rectangle (3,2);\clip[rotate around={45:(0,1.5)}] (0,1.5) ellipse (1cm and 1.5cm);\clip (.5,2) ellipse (1cm and 1.5cm);\fill[red!30!white] (-2,-2) rectangle (3,2);\end{scope}\begin{scope}\clip[rounded corners] (0,0) rectangle (3,2);\clip[rotate around={45:(0,1.5)}] (0,1.5) ellipse (1cm and 1.5cm);\clip (-.5,1) ellipse (1.5cm and 1cm);\fill[red!30!white] (-2,-2) rectangle (3,2);\end{scope}\begin{scope}\clip[rounded corners] (0,0) rectangle (3,2);\clip[rotate around={45:(0,1.5)}] (0,1.5) ellipse (1cm and 1.5cm);\clip (-.5,1) ellipse (1.5cm and 1cm);\clip (.5,2) ellipse (1cm and 1.5cm);\fill[blue!30!white] (-2,-2) rectangle (3,2);\end{scope}\draw[thick, rounded corners] (0,0) rectangle (3,2);\draw[dotted] (-.5,1) ellipse (1.5cm and 1cm);\draw[rotate around={45:(0,1.5)}, dashed] (0,1.5) ellipse (1cm and 1.5cm);\draw (.5,2) ellipse (1cm and 1.5cm);