# Drawing discs with circular holes with TikZ

I am using the TikZ package to show a set of complex numbers where those I want are in the outer part of a circle with a radius 2, and where the circle with radius 1 is not in the set:

I want to let the inner circle be white, with the axes showing completely, but I am not able to find out how. I am using two circles with semi-transparent fillings. Is there any way to make only the outer part filled? Relevant code below.

(This is where I got most of the code: Drawing a circle in the complex plane.)

\begin{tikzpicture}
\begin{scope}[thick,font=\scriptsize][set layers]
\draw [->] (-4,0) -- (4,0) node [above left]  {$\Re\{z\}$};
\draw [->] (0,-4) -- (0,4) node [below right] {$\Im\{z\}$};
\iffalse% Single
\draw (1,-3pt) -- (1,3pt)   node [above] {$1$};
\draw (-1,-3pt) -- (-1,3pt) node [above] {$-1$};
\draw (-3pt,1) -- (3pt,1)   node [right] {$i$};
\draw (-3pt,-1) -- (3pt,-1) node [right] {$-i$};
\else% Multiple
\foreach \n in {-3,...,-1,1,2,...,3}{%
\draw (\n,-3pt) -- (\n,3pt)   node [above] {$\n$};
\draw (-3pt,\n) -- (3pt,\n)   node [right] {$\n i$};
}
\fi
\end{scope}
\draw[solid] (0,-1) circle (1);
\draw[solid] (0,-1) circle (2);
\path [draw=none,fill=gray, fill opacity = 0.1] (0,-1) circle (2);
\path [draw=none,fill=white, fill opacity = 0.7] (0,-1) circle (1);
\node [below right,black] at (1.2,1.2) {$A=\{z\in\mathbb{C}:1\leq|z-(-i)|\leq2\}$};
\end{tikzpicture}


You can use a different fill rule which is called even odd rule that fills every even numbered closed region.

So if you use the following line instead of two distinct circles you get a donut fill;

\path [draw=none,fill=gray, fill opacity = 0.1,even odd rule] (0,-1) circle (2) (0,-1) circle (1);


In this particular case, you can simply change the drawing order i.e., draw the circles first:

\documentclass[tikz]{standalone}
\usepackage{amsfonts}
\begin{document}
\begin{tikzpicture}
\path [draw=none,fill=gray, fill opacity = 0.1] (0,-1) circle (2);
\path [draw=none,fill=white] (0,-1) circle (1);
\begin{scope}[thick,font=\scriptsize][set layers]
\draw [->] (-4,0) -- (4,0) node [above left]  {$\Re\{z\}$};
\draw [->] (0,-4) -- (0,4) node [below right] {$\Im\{z\}$};
\iffalse% Single
\draw (1,-3pt) -- (1,3pt)   node [above] {$1$};
\draw (-1,-3pt) -- (-1,3pt) node [above] {$-1$};
\draw (-3pt,1) -- (3pt,1)   node [right] {$i$};
\draw (-3pt,-1) -- (3pt,-1) node [right] {$-i$};
\else% Multiple
\foreach \n in {-3,...,-1,1,2,...,3}{%
\draw (\n,-3pt) -- (\n,3pt)   node [above] {$\n$};
\draw (-3pt,\n) -- (3pt,\n)   node [right] {$\n i$};
}
\fi
\end{scope}
\draw[solid] (0,-1) circle (1);
\draw[solid] (0,-1) circle (2);
%    \path [draw=none,fill=gray, fill opacity = 0.1] (0,-1) circle (2);
%    \path [draw=none,fill=white, fill opacity = 0.7] (0,-1) circle (1);
\node [below right,black] at (1.2,1.2) {$A=\{z\in\mathbb{C}:1\leq|z-(-i)|\leq2\}$};
\end{tikzpicture}
\end{document}


Use the 'even odd rule':

\documentclass[tikz]{standalone}
\usepackage{amsfonts}
\begin{document}
\begin{tikzpicture}
\begin{scope}[thick,font=\scriptsize][set layers]
\draw [->] (-4,0) -- (4,0) node [above left]  {$\Re\{z\}$};
\draw [->] (0,-4) -- (0,4) node [below right] {$\Im\{z\}$};
\iffalse% Single
\draw (1,-3pt) -- (1,3pt)   node [above] {$1$};
\draw (-1,-3pt) -- (-1,3pt) node [above] {$-1$};
\draw (-3pt,1) -- (3pt,1)   node [right] {$i$};
\draw (-3pt,-1) -- (3pt,-1) node [right] {$-i$};
\else% Multiple
\foreach \n in {-3,...,-1,1,2,...,3}{%
\draw (\n,-3pt) -- (\n,3pt)   node [above] {$\n$};
\draw (-3pt,\n) -- (3pt,\n)   node [right] {$\n i$};
}
\fi
\end{scope}
\draw[solid] (0,-1) circle (1);
\draw[solid] (0,-1) circle (2);
\path [draw=none, fill=gray, even odd rule, fill opacity = 0.1] (0,-1) circle (2) (0,-1) circle (1);
\node [below right,black] at (1.2,1.2) {$A=\{z\in\mathbb{C}:1\leq|z-(-i)|\leq2\}$};
\end{tikzpicture}
\end{document}


# EDIT

Since percusse was faster with the even-odd rule solution (but did not, I note, provide a complete MWE), here's a solution you can use if you want the inner circle filled but you still want the axes on top. This solution uses the backgrounds library to fill the inner circle behind the rest of the picture, so that the axes remain on top.

\documentclass[tikz]{standalone}
\usepackage{amsfonts}
\usetikzlibrary{backgrounds}
\begin{document}
\begin{tikzpicture}
\begin{scope}[thick,font=\scriptsize][set layers]
\draw [->] (-4,0) -- (4,0) node [above left]  {$\Re\{z\}$};
\draw [->] (0,-4) -- (0,4) node [below right] {$\Im\{z\}$};
\iffalse % Single
\draw (1,-3pt) -- (1,3pt)   node [above] {$1$};
\draw (-1,-3pt) -- (-1,3pt) node [above] {$-1$};
\draw (-3pt,1) -- (3pt,1)   node [right] {$i$};
\draw (-3pt,-1) -- (3pt,-1) node [right] {$-i$};
\else% Multiple
\foreach \n in {-3,...,-1,1,2,...,3}{%
\draw (\n,-3pt) -- (\n,3pt)   node [above] {$\n$};
\draw (-3pt,\n) -- (3pt,\n)   node [right] {$\n i$};
}
\fi
\end{scope}
\draw[solid] (0,-1) circle (1);
\draw[solid] (0,-1) circle (2);
\path [fill=gray, fill opacity = 0.1] (0,-1) circle (2);
\begin{scope}[on background layer]
\path [fill=white, fill opacity=.7] (0,-1) circle (1);
\end{scope}
\node [below right,black] at (1.2,1.2) {$A=\{z\in\mathbb{C}:1\leq|z-(-i)|\leq2\}$};
\end{tikzpicture}
\end{document}


A PSTricks solution:

\documentclass{article}

\usepackage{amssymb,mathtools}

\DeclarePairedDelimiter{\abs}{\lvert}{\rvert}
\DeclarePairedDelimiter{\set}{\lbrace}{\rbrace}

\newcommand*\mathsetfont{\mathbb}
\newcommand*\DeclareMathSet[1]{%
\expandafter\newcommand\csname set#1\endcsname{\mathsetfont{#1}}
}
\DeclareMathSet{C}

\begin{document}

\begin{pspicture}(-3.9,-3.9)(6.5,4.55)
\psaxes[
xlabelPos = t,
ylabelPos = r,
ylabelFactor = {i}
]{->}(0,0)(-3.9,-3.9)(4,4)[$\Re\{z\}$,0][$\Im\{z\}$,90]
\psRing*[
opacity = 0.3
](0,-1){1}{2}
\rput(4,2){$A = \set*{z \in \setC : 1 \leq \abs*{z - (-i)} \leq 2}$}
\end{pspicture}

\end{document}


Notice that it may be rather cumbersome to write the set of complex numbers as I've done but with this approach you get a clear code syntax and it's both easy to change and add new sets.

P.S. With the option ylabelPos = r, you get an

overfull \hbox

warning but I'm not sure why.

Done with MetaPost (via LuaLaTeX), for whom it may interest.

With the help of the Metafun format for the transparent filling:

fill ring withcolor transparent(1, 0.1, \mpcolor{gray});


The ring itself is created by appending one of the circles to the reversed other circle:

ring = circle1 -- reverse circle2 -- cycle;


(Of course a simpler and quicker method would have been to fill the biggest circle and unfill the smallest one, but I found it interesting to create this ring path and directly fill it.)

The full code:

\documentclass[12pt]{standalone}
\usepackage{amssymb, xcolor}
\usepackage{luamplib}
\mplibsetformat{metafun}
\mplibtextextlabel{enable}
\begin{document}
\begin{mplibcode}
u = 1.5cm; xmax = 3.9 = ymax = -ymin = -xmin; len = 6bp;
path circle[], ring;
circle1 = fullcircle scaled 2u shifted (0, -u);
circle2 = fullcircle scaled 4u shifted (0, -u);
ring = circle1 -- reverse circle2 -- cycle;
labeloffset := 6bp;
beginfig(1);
for i = ceiling(xmin) upto floor(xmax):
draw (i*u, -0.5len) -- (i*u, 0.5len);
if i <> 0: label.top("$" & decimal i & "$", (i*u, 0)); fi
endfor
for j = ceiling(ymin) upto floor(ymax):
draw (-0.5len, j*u) -- (0.5len, j*u);
if j <> 0: label.rt("$" & decimal j & "i$", (0, j*u)); fi
endfor
drawarrow (xmin*u, 0) -- (xmax*u, 0); label.top("$\Re\{ z \}$", (xmax*u, 0));
drawarrow (0, ymin*u) -- (0, ymax*u); label.rt("$\Im\{ z \}$", (0, ymax*u));
fill ring withcolor transparent(1, 0.1, \mpcolor{gray});
for i = 1,2: draw circle[i]; endfor
label.urt("$A = \{z \in \mathbb{C}: 1 \leqslant |z-(-i)| \leqslant2 \}$",
point 1.5 of circle2);
endfig;
\end{mplibcode}
\end{document}


The even odd rule works to not fill inside the smaller circle as shown in the answer of @percusse.

But if you want to decorate your path with arrows, it could be useful to revers the orientation of the circle. This can be done with the following style :

\tikzset{
}
}


You can use it like this

\draw[preaction={fill,opacity=.1}, with arrows]


to obtain something like this :

where the style with arrows is defined as

\tikzset{
with arrows/.style={
decoration={ markings,
mark=between positions #1 and .999 step #1 with {\arrow{stealth}}
}, postaction={decorate}
}, with arrows/.default=25mm,
}