# TiKz Path Exclusion - Compound Shapes (pathfinder functionality)

On Adobe Illustrator, it is very easy to use Pathfinder to create compound shapes by (using the path exclude function with the shape to be retained in the back layer and all paths to be removed in above layers):

Clearly, we can use a basic application of clipping in an attempt to recreate this with Tikz, which works fine if we are not concerned with drawing borders:

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

%   \clip (0,0) circle (1);

\fill[red!20] (0,0) circle (1);

\begin{scope}[rotate=-60]
\fill[white] (0,-0.1) rectangle (1.5,0.1);
\end{scope}

\begin{scope}[rotate=-120]
\fill[white] (0,-0.1) rectangle (1.5,0.1);
\end{scope}

\fill[white] (-1.5,-0.1) rectangle (1.5,0.1);

\end{tikzpicture}
\end{document}


However, if we are concerned with draw borders, it then becomes a lot more interesting and cannot achieve the desired solution easily. Best attempt with a heap of issues (accounting for the line width on the clip (currently it cuts into the line) and overlapping lines from the excluded regions).

\documentclass[12pt,tikz, border = 1cm]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\clip (0,0) circle (1);

\filldraw[fill=red!10,draw=blue] (0,0) circle (1);

\begin{scope}[rotate=-60]
\filldraw[anchor=east,fill=white,draw=blue] (0,-0.1) rectangle (1.5,0.1);
\end{scope}

\begin{scope}[rotate=-120]
\filldraw[anchor=east,fill=white,draw=blue] (0,-0.1) rectangle (1.5,0.1);
\end{scope}

\filldraw[fill=white,draw=blue] (-1.5,-0.1) rectangle (1.5,0.1);

\end{tikzpicture}
\end{document}


Is there a way for us to achieve the desired result (first image, second circle with excluded regions but draw available) but with TikZ? Can we maybe do this by clipping a path, then filling that path, but also having that path available to draw?

• I guess a solution is to use TikZ to compute the coordinate of the intersection points, but that one isn't particularly easy to implement. Dec 21, 2021 at 5:11
• Agreed, very difficult to deploy at scale Dec 21, 2021 at 5:31
• Alternatively use whatever tool that can compute the coordinate and then export to TikZ. TeX is not meant to be a programming language that you can program in after all... Dec 21, 2021 at 5:32
• @user202729 wait, I'm using TeX wrong all the time! :D Dec 21, 2021 at 12:57

The spath3 library is very powerful and well suited to this question. But in this particular case, we can get a similar result by cheating with a double line like this:

\documentclass[tikz,border=7pt]{standalone}
\begin{document}
\begin{tikzpicture}
\clip[postaction={fill=red!20, draw=blue, thick}]
(0,0) circle (1cm)
;
\path[draw=blue, double, double distance=2mm]
(-2,0) -- (2,0)
(0,0) -- (-60:2)
(0,0) -- (-120:2)
;
\end{tikzpicture}
\end{document}


• Lovely solution! It's good to know about shortcuts for special cases since the general case can often be a bit time consuming. Dec 21, 2021 at 16:07
• What a lovely solution - well done Dec 29, 2021 at 0:51

Here is a possibility using the spath3 TikZ library and following the steps from Andrew Stacey's excellent answer here. The code is not so short but is repetitive and easy to understand (I hope). We need to create the paths (circle and rectangles), split them at the intersections and then use the appropriate components to draw the desired figure

Something like this:

\documentclass[tikz]{standalone}
\usetikzlibrary{intersections,spath3}

\begin{document}
\begin{tikzpicture}[line cap=round,line join=round]
\useasboundingbox (-1.2,-1.2) rectangle (1.2,1.2);
% original paths, not drawn
\path[spath/save=circle]            (0,0)    circle (1);
\path[rotate=240,spath/save=rect24] (0,-0.1) rectangle (1.5,0.1);
\path[rotate=300,spath/save=rect30] (0,-0.1) rectangle (1.5,0.1);
\path[spath/save=rect00]         (-1.5,-0.1) rectangle (1.5,0.1);
% spath3 operations
\tikzset
{% Circles have an "empty" component at the start which
% moves from the centre to the rim; it can be irritating
% when trying to count components later so this removes
% any empty components
spath/remove empty components={circle},
% Now split each path where it intersects with the lines
spath/split at intersections={circle}{rect00},
spath/split at intersections={circle}{rect24},
spath/split at intersections={circle}{rect30},
spath/split at intersections={rect00}{rect24},
spath/split at intersections={rect00}{rect30},
spath/split at intersections={rect24}{rect30},
% Each path is now a collection of components; to work
% with them individually we split them into a list of
% separate paths which is stored in a macro
spath/get components of={circle}\Ccpts,
spath/get components of={rect00}\Rcpts,
spath/get components of={rect24}\Scpts,
spath/get components of={rect30}\Tcpts,
}
\draw[fill=red!10,draw=blue,
spath/use=\getComponentOf\Ccpts{1},
spath/use={\getComponentOf\Rcpts{2},weld}
];
\draw[fill=red!10,draw=blue,
spath/use=\getComponentOf\Ccpts{3},
spath/use={\getComponentOf\Scpts{3},weld},
spath/use={\getComponentOf\Rcpts{8},weld},
];
\draw[fill=red!10,draw=blue,
spath/use=\getComponentOf\Ccpts{5},
spath/use={\getComponentOf\Tcpts{3},weld},
spath/use={\getComponentOf\Scpts{7},weld}
];
\draw[fill=red!10,draw=blue,
spath/use=\getComponentOf\Ccpts{7},
spath/use={\getComponentOf\Rcpts{4},weld},
spath/use={\getComponentOf\Tcpts{7},weld}
];
\end{tikzpicture}
\end{document}


Remark: the last (straight) line of each sector could be drawn with the cycle option, but I did it this way to see the spath3 library working.

• Fabulous! And some more characters to get over the minimum character limit. Dec 21, 2021 at 7:54
• @AndrewStacey, thanks!!! But the merit is all yours :-D Dec 21, 2021 at 7:59
• @AndrewStacey Being Fabulous...hence +1. :-) Dec 21, 2021 at 8:02
• @Sebastiano, thanks too!! Dec 21, 2021 at 8:09
• Wow, that is a beautiful solution. Well done and thank you! Dec 21, 2021 at 10:08