22

I want to draw an arc with a given radius from the point the arc intersects with a given circle to the point where the arc intersects with another circle. I have been reading through a lot of the TikZ manual, but to no avail. Can anyone help?

This PDF (http://www.mycroft.ch/tikztest.pdf) (MWE below) is intended to illustrate the problem. There are four circles, a part of each I want to use as path. The resulting curved wedge is then to be filled in black.

The green arc is no problem, I have start angle and end angle for it. For the two orange arcs I only have one angle (the one near the red circle is just an estimate). For the red arc I have nothing (both ends are estimates, thought to illustrate).

Interestingly, I can calculate the intersections (marked by the red circles), but I cannot fathom how to draw an arc there.

Hopefully I am overlooking something incredibly obvious! Thanks.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{intersections,scopes}
\tikzset{
  pics/carc/.style args={#1:#2:#3}{
    code={
      \draw[pic actions] (#1:#3) arc(#1:#2:#3);
    }
  }
}

\begin{document}
\begin{tikzpicture}

\draw [name path=three] (120:1.06) circle (1.9);
\draw [name path=four] (0:1.06) circle (2.12);
\draw [name path=five] (0:0.77) circle (2.41);
\draw [name path=two] (0:0) circle (1.06);

\draw[green, thick] (0:3.18) arc [radius=2.12, start angle=0, end angle=180]; 
\draw[orange, thick] (0:3.18) arc [radius=2.41, start angle=0, end angle=197]; 
\draw[orange, thick] (180:1.06) arc [radius=1.06, start angle=180, end angle=245]; 
\draw[red, thick, name intersections={of=five and three}] (intersection-2) circle (2pt) node {}; 
\draw[red, thick, name intersections={of=two and three}] (intersection-1) circle (2pt) node {}; 

{ [xshift=-0.53cm,yshift=0.918cm] \pic [red,thick] {carc=238:274:1.9}; }

\end{tikzpicture}

\end{document}
11
  • I'm sorry, I'm a little confused as to what's your question. Is it about how to fill a shape made of arcs, or is it about how to calculate the starting and ending angles of your arc?
    – LaX
    Apr 16, 2015 at 16:43
  • Sorry for being unclear. The filling is no problem. The problem is the arc in red, where do I get starting/ending angles from? What I am struggling with, in part, is that the circle in which the arc lies is not centered in (0,0) but in (120:1.06). Hope this helped!
    – Thorsten
    Apr 16, 2015 at 16:47
  • Oh OK, you mean how you could get a similar result while getting rid of the xshifts and yshifts options?
    – LaX
    Apr 16, 2015 at 16:50
  • No, the xshift and yshift I just introduced because that red arc was not correctly placed otherwise. Basically I want to do the following: - Draw an arc, whose underlying circle is centered in (120:1.06) and the radius is (1.9). - Starting point of that arc should be where this circle intersects with the other circle ("five). - Ending point of that arc should be where the arc's underlying circle intersects with yet another circle ("two").
    – Thorsten
    Apr 16, 2015 at 16:53
  • 1
    You could try this clip: \clip[draw] (center) -- ($(center)!2.5!(A)$) -- ($(center)!2.5!(B)$) -- cycle;. I added coordinates to your intersections: \draw[red, thick, name intersections={of=five and three}] (intersection-2) circle (2pt) node[below] {$A$} coordinate (A), did the same for (B) and defined (center) with \coordinate (center) at (120:1.06);. Wrap the clip in a scope env., along with \draw [red,thick] (120:1.06) circle (1.9); for the arc. This is just an example with a clip, but obviously this solution is not very nice as you have to adapt the clip to your draw every time.
    – LaX
    Apr 16, 2015 at 22:14

6 Answers 6

23

A solution which allows to draw intersection segments of any two intersections is available as tikz library fillbetween.

This library works as general purpose tikz library, but it is shipped with pgfplots and you need to load pgfplots in order to make it work:

\documentclass{standalone}

\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{fillbetween}

\begin{document}

\begin{tikzpicture}

\draw [name path=red,red] (120:1.06) circle (1.9);
%\draw [name path=yellow,yellow] (0:1.06) circle (2.12);
\draw [name path=green,green!50!black] (0:0.77) circle (2.41);
\draw [name path=blue,blue] (0:0) circle (1.06);

% substitute this temp path by `\path` to make it invisible:
\draw[name path=temp1, intersection segments={of=red and blue,sequence=L1}];
\draw[red,-stealth,ultra thick, intersection segments={of=temp1 and green,sequence=L3}];

\end{tikzpicture}

\end{document}

enter image description here

The key intersection segments is described in all detail in the pgfplots reference manual section "5.6.6 Intersection Segment Recombination"; the key idea in this case is to

  1. create a temporary path temp1 which is the first intersection segment of red and blue, more precisely, it is the first intersection segment in the Left argument in red and blue : red. This path is drawn as thin black path. Substitute its \draw statement by \path to make it invisible.

  2. Compute the desired intersection segment by intersecting temp1 and green and use the correct intersection segment. By trial and error I figured that it is the third segment of path temp1 which is written as L3 (L = left argument in temp1 and green and 3 means third segment of that path).

The argument involves some trial and error because fillbetween is unaware of the fact that end and startpoint are connected -- and we as end users do not see start and end point.

Note that you can connect these path segments with other paths. If such an intersection segment should be the continuation of another path, use -- as before the first argument in sequence. This allows to fill paths segments:

\documentclass{standalone}

\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{fillbetween}

\begin{document}

\begin{tikzpicture}

\draw [name path=red,red] (120:1.06) circle (1.9);
%\draw [name path=yellow,yellow] (0:1.06) circle (2.12);
\draw [name path=green,green!50!black] (0:0.77) circle (2.41);
\draw [name path=blue,blue] (0:0) circle (1.06);

% substitute this temp path by `\path` to make it invisible:
\draw[name path=temp1, intersection segments={of=red and blue,sequence=L1}];
\draw[red,fill=blue,-stealth,ultra thick, intersection segments={of=temp1 and green,sequence=L3}]  
    [intersection segments={of=temp1 and green, sequence={--R2}}]
;

\end{tikzpicture}

\end{document}

enter image description here

4
  • This looks as if it is the solution I have been searching for - but I get "Package pgf Error: The argument of 'sequence' has an unexp ected format near 'L1'. Please write something like A0 -- B1 -- A1. See the pgf package documentation for explanation." Any idea what's going wrong?
    – Thorsten
    Apr 20, 2015 at 15:22
  • Ah - I remember that I got feedback about 0-based indexing being inconsistent with the rest of the intersection libraries and I added L<1-based-index> as alias for A<0-based-index>. Apparently, your version of pgfplots does not have the L/R syntax. Please substitute L by A and decrease the following integer by 1. Apr 20, 2015 at 19:06
  • Ah, now it works. But while the arc is now constructed perfectly, I fail to put that into the entire path (of the four arcs) to create a to be filled structure. The point where it fails is that while now I have (more or less) coordinates for the start- and endpoints of "my" arc, I cannot connect it to the other arcs for which I cannot specifiy and endpoint, but only an angle. I tried to define the other segments in a similar way to what you did - but I seem to struggle with the syntax. Is it possible to read the polar coordinates from the arcs start- and endpoints and use the angle?
    – Thorsten
    Apr 22, 2015 at 10:34
  • I have edited the answer, in the hope that this helps to connect segments. Let me know if you encounter problems. Apr 22, 2015 at 15:53
10

This one is makes a nice example of using buildcycle with subpath in Metapost.

enter image description here

prologues := 3;
outputtemplate := "%j%c.eps";

beginfig(1);

path A, B, C, D, F;

A = fullcircle scaled 240;
B = fullcircle scaled 200 shifted 20 right;
C = fullcircle scaled 100 shifted 30 left;
D = fullcircle scaled 180 shifted 60 left shifted 40 up;

F = buildcycle(subpath (0,5) of A, 
               subpath (4,7) of D, 
               subpath (6,4) of C,
               subpath (4,0) of B);

fill F withcolor .8[blue,white];
draw A; draw B; draw C; draw D;
endfig;
end.

Each fullcircle has eight points numbered counter-clockwise from 3 o'clock. So subpath (0,5) of A is the an arc of the first 5/8 of A running counter-clockwise. If you reverse the order of the arguments to subpath you get a reversed path, so subpath (4,0) of B is the upper half of B running clockwise.

The buildcycle works best with a sequence of overlapping paths all running in the same direction.

7

I know that this is a very old question, but here's a solution using the new spath3 TikZ library that can work with splitting paths at intersection points. Using that, the various circles are split into sections which are then used to define the filled region and the coloured pieces around it.

(There's one extra path because TikZ wasn't picking up all the intersection points, especially where the circles are tangent.)

\documentclass{article}
%\url{https://tex.stackexchange.com/q/238967/86}
\usepackage{tikz}
\usetikzlibrary{intersections,scopes,spath3}

\begin{document}
\begin{tikzpicture}

% Draw and save the circles.
\draw [spath/save=three] (120:1.06) circle[radius=1.9];
\draw [spath/save=four] (0:1.06) circle[radius=2.12];
\draw [spath/save=five] (0:0.77) circle[radius=2.41];
\draw [spath/save=two] (0:0) circle[radius=1.06];
% This is useful for where the circles are meant to be tangent but don't actually quite intersect.
\path[overlay,spath/save=line] (-5,0) -- (5,0);

\tikzset{
  % Split various paths where they intersect with other paths:
  %
  % Split both three and two where they intersect
  spath/split at intersections={three}{two},
  % Split both three and five where they intersect
  spath/split at intersections={three}{five},
  % Split each of two, four, five where they intersect with line
  spath/split at intersections with={five}{line},
  spath/split at intersections with={four}{line},
  spath/split at intersections with={two}{line},
  % Get the components of each path as a list
  spath/get components of={three}\threeCpt,
  spath/get components of={five}\fiveCpt,
  spath/get components of={four}\fourCpt,
  spath/get components of={two}\twoCpt,
  % Join some of the components of path five together as it's been split into a lot of pieces
  spath/clone={five part}{\getComponentOf\fiveCpt{5}},
  spath/join with={five part}{\getComponentOf\fiveCpt{2},weld},
  spath/join with={five part}{\getComponentOf\fiveCpt{3},weld}
}

% Fill the region defined by the pieces
\fill[cyan,ultra thick,
  spath/use={\getComponentOf\fourCpt{2}},
  spath/use={\getComponentOf\twoCpt{5},weld},
  spath/use={\getComponentOf\threeCpt{5},weld,reverse},
  spath/use={five part,weld,reverse},
];

% Draw the pieces different colours
\draw[spath/use={\getComponentOf\threeCpt{5}},green,ultra thick];
\draw[spath/use={five part},red,ultra thick];
\draw[spath/use={\getComponentOf\fourCpt{2}},orange,ultra thick];
\draw[spath/use={\getComponentOf\twoCpt{5}},blue,ultra thick];

\end{tikzpicture}
\end{document}

Region formed by arcs split from circles

3
\documentclass{standalone} 
\usepackage{tkz-euclide}

\begin{document} 
\begin{tikzpicture}
\tkzDefPoints{0/0/O1,2/0/I,-1/2/O2,-2/0/J,1/0/O3,6/0/K}
\tkzDefPoints{-2/-2/M,1/-2/N}
\tkzDrawCircles(O1,I O2,I I,J O3,K)
\begin{scope}
  \tkzClipCircle(O2,I)
  \tkzClipCircle[out](O1,I)
  \tkzClipCircle[out](I,J)
\tkzFillCircle[teal!20](O3,K)
\end{scope}

\begin{scope}
  \tkzClipCircle(O2,I)
  \tkzClipCircle[out](O1,I)
  \tkzClipCircle(I,J)
  \tkzClipPolygon(M,N,I,J)
\tkzFillCircle[teal!20](O3,K)
\end{scope}

\begin{scope}
  \tkzClipCircle[out](O2,I)
  \tkzClipCircle[out](I,J)
  \clip   (current bounding box.west) --(current bounding box.east)
     --(current bounding box.north east) --  (current bounding box.north west)
     -- cycle;
  \tkzFillCircle[teal!20](O3,K)
\end{scope}

\tkzDrawCircles(O1,I O2,I I,J O3,K)
\tkzDrawCircle(I,J)
\end{tikzpicture}
\end{document}

enter image description here

1

I assume that I haven't been overlooking anything really obvious (because then someone would have pointed it out, probably), so I chose the less appealing, but more or less sufficient way to figure out the angles by hand:

\path [name path=A] (0:0.77) circle (2.41);
\path [name path=B, rotate=120] (0:1.06) circle (1.9);

\fill[black, name intersections={of=A and B}] (-1.06,0) arc [radius=2.12, start angle=180, end angle=0] arc [radius=2.41, start angle=0, end angle=196.75] arc [radius=1.9, start angle=238, end angle=273.8] arc [radius=1.06, start angle=247.54, end angle=180]  -- cycle; 

Thanks!

1
  • 3
    I think, this should be extended by an MWE and a screenshot
    – user31729
    Apr 20, 2015 at 17:03
1
  1. Circles with name path.
  2. Finding intersections with name intersections.
  3. Draw arcs between these points with arcto.

The points C2.0 = C3.0 and C2.180 = C4.180 are given explicitly because we know these points already (and I don't trust the intersections library with these touching points).

Code

\documentclass[tikz]{standalone}
\usetikzlibrary{
  intersections,
  through,        % → circle through
  ext.paths.arcto,% ← https://ctan.org/pkg/tikz-ext
}
\begin{document}
\begin{tikzpicture}[
  circle at/.style args={#1)#2radius#3}{
    at={#1)}, circle through={([shift={#1)}]0:#3)}, node contents=},
  declare function={x_radius=\pgfkeysvalueof{/tikz/x\space radius};},
  r1/.style={radius=1.9},  r2/.style={radius=2.12},
  r3/.style={radius=2.41}, r4/.style={radius=1.06},
  arc to/.search also=/tikz,
  %
  @/.code args={#1/#2}{
    \node(C#1)[draw,r#1,circle at={(#2) radius x_radius},name path=C#1];},
  @/.list={1/(120:1.06), 2/(0:1.06), 3/(0:0.77), 4/(0:0)},
  @/.style args={#1/#2}{name intersections={of=#1 and #2, name=#1/#2}},
  @/.list={C3/C1, C1/C4}
]
\fill[black]
  (C2.0) arcto[r3, large]     (C3/C1-2)
         arcto[r1]            (C1/C4-1)
         arcto[r4, clockwise] (C2.180)
         arcto[r2, clockwise] cycle;
\end{tikzpicture}
\end{document}

Output

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .