# How can I invert a 'clip' selection within TikZ?

I wish to draw an arc for a reflex angle on the outside of a triangle with coordinates (A), (B) and (C).

If I wanted to draw the arc inside the triangle I could use something like

\begin{scope}
\path[clip] (A) -- (B) -- (C) -- cycle;
\draw (B) circle (2mm);    % this is the little angle marker
\end{scope}


Is there a straightforward way to exclude the part of the circle that's in the triangle, as in the pseudo-code below?

\begin{scope}
\path[magicalinverseclipcommand] (A) -- (B) -- (C) -- cycle;
\draw (B) circle (2mm);    % this is the little angle marker
\end{scope}


EDIT: Although I included the code above as a motivating example of what an inverse clip would do, I would prefer a general solution that works systematically with any closed path, and not just in the particular example of a triangle with a circle clipped out of it. Looking at my question, I realise this isn't clear, and I will be happy with the best solution to my particular problem, but wonder if there is a less ad hoc solution than those listed so far.

-
Good question! I was trying to do something like this to construct an answer to tex.stackexchange.com/q/3528/86 (a question about cutting out a circle from an ellipse) but haven't found anything yet. –  Loop Space Feb 25 '11 at 8:55
Thanks! I'm having to do messy things like creating new closed paths to clip against, but I'd prefer to have a systematic solution so I can use it in \newcommands easily. –  bryn Feb 25 '11 at 9:03
Maybe you could edit your question to explain in a little more detail what you are looking for that is not provided by the answers already given? The bounty you set out is likely to attract people to the question, but when they see three posts that seem to answer your question, they are less likely to provide answers of their own. –  Jake Mar 5 '11 at 12:57
Bryn, I still don't see what isn't answered by Jake's answer. His method provides a way to invert an arbitrary clip, so anything you previously wanted to clip against can be inverted. Do you have an example where it fails? Or a more complicated example where you can't see how to implement it? –  Loop Space Mar 9 '11 at 9:41
@Jake: Thanks -- I think this looks like a good solution now, and hopefully will be stored for posterity (until Till Tantau implements it natively maybe!). –  bryn Mar 12 '11 at 3:21

What you can do is add a rectangle to your clipping path that's larger than the current bounding box, and clip with that. Andrew Stacey suggested using the current page as the clipping rectangle, because that will catch all elements that follow. By using the pgfinterruptboundingbox environment when defining the clipping rectangle, the actual size of the tikzpicture will not be influenced.

Note that, in order to use the current page, the remember picture,overlay options need to be passed to the tikzpicture, and you need two compile runs to get the positioning of all the elements right. Furthermore, this doesn't work with the minimal documentclass.

\documentclass{article} % Has to be a proper class, not minimal
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[remember picture,overlay]

% A path that follows the edges of the current page
\tikzstyle{reverseclip}=[insert path={(current page.north east) --
(current page.south east) --
(current page.south west) --
(current page.north west) --
(current page.north east)}
]

\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (1,1);

\begin{pgfinterruptboundingbox} % To make sure our clipping path does not mess up the placement of the picture
\path [clip] (A) -- (B) -- (C) -- cycle [reverseclip];
\end{pgfinterruptboundingbox}

\draw[thick] (A) circle (2mm);
\draw[thick] (B) circle (2mm);
\draw[thick] (C) circle (2mm);

\end{tikzpicture}
\end{document}


And just to show that it works for the general case:

\documentclass{article}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[remember picture,overlay]

% A path that follows the edges of the current page
\tikzstyle{reverseclip}=[insert path={(current page.north east) --
(current page.south east) --
(current page.south west) --
(current page.north west) --
(current page.north east)}
]

\draw [step=0.1,red] (0,0) grid  (2,2);

\begin{pgfinterruptboundingbox} % To make sure our clipping path does not mess up the placement of the picture
\path [clip,rounded corners] (0,0) -- (.75,0) -- (1.2,.8) -- (2,1) -- (1.4,1) -- (1.2,2) -- (.3,.75) -- cycle [reverseclip];
\end{pgfinterruptboundingbox}

\draw [step=0.1,thick] (0,0) grid  (2,2);

\end{tikzpicture}
\end{document}


-
If you're doing it in one action (as you are here, unlike my answer) why not use the page itself as the "infinitely large" box? Although 1m seems pretty big, I have some pictures that are on canvas bigger than that! Or maybe it's a big picture scaled down a lot. Would that work? (PS I like the answer - much better than mine) –  Loop Space Feb 25 '11 at 13:13
@Andrew: I tried using the current page originally, but somehow couldn't get it to work and so settled for the pretty big rectangle. But you're right, there's always going to be something that's a bit bigger than that. So following your comment, I revisited my answer and found out that the current page node does not work with the minimal class, but otherwise it's fine. I've added the approach to my answer. –  Jake Feb 25 '11 at 13:36
Great! I'd vote again but I'm not allowed. Now I'm wondering whether the choice of "even odd rule" or the other one leads to strange behaviour ... but I can experiment with that myself! –  Loop Space Feb 25 '11 at 14:01
Oh, and you have 10 minutes to adapt this to an answer to tex.stackexchange.com/q/3528/86 before I steal your idea and do so myself. –  Loop Space Feb 25 '11 at 14:01
@Andrew: I think the OP of the question you linked to wants the resulting shape to have an outline, and I don't see how that can be achieved. I've bookmarked the question, however, and am looking forward to seeing your solution! –  Jake Feb 25 '11 at 14:17

To avoid remember picture and overlay, I mix Jack's solution and Altermundus's solution using the bigger rectangle that TikZ/PGF (TeX?) can used (Edit: as suggested by Qrrbrbirlbel, I add [reset cm] to get a solution independent from any scale transformations).

First tikzpicture shows two (inv)clipping triangles.

Second tikzpicture shows the effect of nonzero rule (even odd rule can't be used to clip).

\documentclass{standalone}
\usepackage{tikz}
\begin{document}

\tikzset{invclip/.style={clip,insert path={{[reset cm]
(-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)
}}}}

\begin{tikzpicture}[outer sep=0mm]
\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (.5,1);
\coordinate (Ap) at (0,1);
\coordinate (Bp) at (1,1);
\coordinate (Cp) at (.5,0);
\begin{scope}
\begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
\path[invclip]
(A) -- (B) -- (C) -- (A)
(Ap) -- (Cp) -- (Bp) -- (Ap);
\end{pgfinterruptboundingbox}

\fill[orange!50] (-1,-1) rectangle (2,2);

\draw (A) circle (2mm);    % this is the little angle marker
\draw (B) circle (2mm);    % this is the little angle marker
\draw (C) circle (2mm);    % this is the little angle marker

\draw (Ap) circle (2mm);    % this is the little angle marker
\draw (Bp) circle (2mm);    % this is the little angle marker
\draw (Cp) circle (2mm);    % this is the little angle marker

\end{scope}

\draw[red] (current bounding box.south west)
rectangle (current bounding box.north east);
\end{tikzpicture}

\begin{tikzpicture}[outer sep=0mm]
\coordinate (A) at (0,0);
\coordinate (B) at (1,0);
\coordinate (C) at (.5,1);
\coordinate (Ap) at (0,1);
\coordinate (Bp) at (1,1);
\coordinate (Cp) at (.5,0);
\begin{scope}
\begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
\path[invclip]
(A) -- (B) -- (C) -- (A)
(Ap) -- (Bp) -- (Cp) -- (Ap);
\end{pgfinterruptboundingbox}

\fill[orange!50] (-1,-1) rectangle (2,2);

\draw (A) circle (2mm);    % this is the little angle marker
\draw (B) circle (2mm);    % this is the little angle marker
\draw (C) circle (2mm);    % this is the little angle marker

\draw (Ap) circle (2mm);    % this is the little angle marker
\draw (Bp) circle (2mm);    % this is the little angle marker
\draw (Cp) circle (2mm);    % this is the little angle marker

\end{scope}

\draw[red] (current bounding box.south west)
rectangle (current bounding box.north east);
\end{tikzpicture}
\end{document}


-
Using insert path={{[reset cm] (-16383.99999pt,-16383.99999pt) rectangle (16383.99999pt,16383.99999pt)}} makes this solution independent from any [x|y] scale options. –  Qrrbrbirlbel Jun 18 '13 at 21:55
@Qrrbrbirlbel This is a very good suggestion! –  Paul Gaborit Jun 19 '13 at 22:28
I really like this answer, but I don't fully understand how it works. In the PGF manual it says the following about pgfinterruptboundingbox: "This environment temporarily interrupts the computation of the bounding box and sets up a new bounding box. At the beginning of the environment the old bounding box is saved and an empty bounding box is installed. After the environment the original bounding box is reinstalled as if nothing has happened." What does this last part mean? It cannot be that it completely undoes whatever it is that you did within the pgfinterruptboundingbox, right? –  gablin Oct 10 '14 at 11:53

The solution to draw an arc outside the triangle is to use my new package tkz-euclide and with this way, you don' need to invert a clip selection

\documentclass{minimal}
\usepackage{tkz-euclide}
\usetkzobj{all}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}

\coordinate (A) at (0,0);
\coordinate (B) at (2,0);
\coordinate (C) at (2,2);

\draw (A) -- (B) -- (C) -- cycle;
\draw (B) circle (2mm);    % this is the little angle marker
\tkzDrawArc[R with nodes,color=red](B,1cm)(A,C)
\tkzDrawArc[R with nodes,color=blue](B,1cm)(C,A)
\end{tikzpicture}
\end{document}


Now if you want, I can extract the code from my package. You need to use an internal macro of pgf named \pgfmathanglebetweenpoints; in my package I use \tkzmathanglebetweenpoints because I want a good precision so I work with fp and not with pgfmath from some parts of the code. Then the problem it's to use angles with + or - because I want to draw from (B,A) towards (B,C) or from (B,C) towards (B,A). If you want all the details, I give you in some hours because now, I need to work with my students

I complete my answer without tkz-euclide

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}

\makeatletter
\def\drawarc{\pgfutil@ifnextchar[{\draw@arc}{\draw@arc[]}}
\def\draw@arc[#1](#2,#3)(#4,#5){%
\begingroup
\pgfmathanglebetweenpoints{\pgfpointanchor{#2}{center}}{%
\pgfpointanchor{#4}{center}}
\global\let\FirstAngle\pgfmathresult
\pgfmathanglebetweenpoints{\pgfpointanchor{#2}{center}}{%
\pgfpointanchor{#5}{center}}
\global\let\SecondAngle\pgfmathresult
\pgfmathgreaterthan{\FirstAngle}{0}
\ifdim\pgfmathresult pt=1 pt\relax%
\pgfmathgreaterthan{\FirstAngle}{\SecondAngle}
\ifdim\pgfmathresult pt=1 pt\relax%
\pgfmathsubtract{\FirstAngle}{360}
\edef\FirstAngle{\pgfmathresult}%
\fi
\else
\pgfmathgreaterthan{\FirstAngle}{\SecondAngle}
\ifdim\pgfmathresult pt=1 pt\relax%
\edef\SecondAngle{\pgfmathresult}%
\fi
\fi
\draw[#1,shift = {(#2)}](\FirstAngle:#3) arc (\FirstAngle:\SecondAngle:#3);
\endgroup
}
\makeatother

\begin{document}
\begin{tikzpicture}

\coordinate (A) at (2,2);
\coordinate (B) at (1,0);
\coordinate (C) at (3,1);
\draw (A) -- (B) -- (C) -- cycle;
\drawarc[red](B,1cm)(A,C)
\drawarc[blue](B,1cm)(C,A)
\end{tikzpicture}
\end{document}


-
It's not the answer at "How to invert a clip selection" but at the subquestion " how to draw an arc outside a triangle" and you don't need to use an invert clip. The Jake'answer is very interesting. –  Alain Matthes Mar 4 '11 at 8:29

To get the ball rolling on this one, here's a method that uses fadings. What I don't like about it is that to make this work, one has to specify a large rectangle in the fading that one hopes (!) is large enough - I don't know how to automate this. The issue is that when specifying a fading, everything outside the fading is assumed to be transparent, whereas for this one wants everything outside to be visible.

\documentclass{minimal}
\usepackage{tikz}
\begin{document}

\fill[white] (-10,-10) rectangle (10,10);
\path (0,0) coordinate (A) +(0:2) coordinate (B) +(50:2) coordinate (C);
\fill[black] (B) -- (A) -- (C) -- cycle;

\begin{tikzpicture}
\end{tikzpicture}
\end{document}


It's also not so great because one has to split the definition of the cutout from the picture (I wonder if it's possible to fix this using remember picture ...).

-

this all can be done very easily using the even odd rule, see http://www.texample.net/tikz/examples/venn-diagram/

-
Welcome to TeX.sx! Having thought about this quite a bit when it was first posted, I'd really want to see an example before I was convinced that this could be done easily using the even-odd rule. The assumption with a clip is that the outside will be thrown away and that's true for any clipping rule as far as I'm aware, and certainly is true of the venn diagram example. –  Loop Space Nov 12 '11 at 21:35

I search how to avoid the use of remember picture with the Jake's solution. I find this :

\documentclass{article}
\usepackage{tikz}

\begin{document}
\fbox{\begin{tikzpicture}[invclip/.style={insert path={(-1,-1) rectangle (2,2)}}]
% a rectangle is necessary

\path coordinate (A) at (0,0)
coordinate (B) at (1,0)
coordinate (C) at (1,1);

\begin{pgfinterruptboundingbox} % useful to avoid the rectangle in the bounding box
\path[clip] (A) -- (B) -- (C) -- cycle [invclip];
\end{pgfinterruptboundingbox}

\draw[thick] (A) circle (2mm)
(B) circle (2mm)
(C) circle (2mm);
\end{tikzpicture}}
\end{document}


( I added fbox to verify the bounding box)

-
I had this in the first version of my solution (it's still in the edit history), but I think the general consensus was that the drawback of having to decide on a rectangle size (how do you know if it's big enough?) is serious enough to warrant the use of remember picture –  Jake Mar 29 '11 at 16:48
@Jake No problem you can write : invclip/.style={insert path={(-10,-10) rectangle (20,20)}}or bigger if necessary. Another possibility, is to use the fit' library. –  Alain Matthes Mar 29 '11 at 17:12
See Andrew Stacey's first comment on my answer regarding the size of the box (even 1 metre might not be big enough for some things). I'd be interested to see a solution with the fit library, however! –  Jake Mar 29 '11 at 17:16
@Jake The fit idea does not work. It was to get the rectangle size but I can't place the rectangle correctly. I think the rectangle size is not a good argument. When you draw something, generally you have an idea of the final size. Why do you need overlay in your solution? Without it the bounding box is correct within no. Another suggestion is insert path={ (current page.south west) rectangle (current page.north east)}. –  Alain Matthes Mar 29 '11 at 21:38
Sorry, my previous (now deleted) comment was not correct: You need the remember picture, overlay to make sure the current page node is positioned correctly. In reply to your previous comment: I agree, in the vast majority of cases specifying a large clipping rectangle will work just fine, but I wanted a solution that will work for the general case. Using the current page` node ensures that the clipping rectangle is always large enough and you don't need to make adjustments to the clipping path for different pictures. –  Jake Mar 29 '11 at 21:55