10

enter image description here

After looking up the PGF manual, I think the picture above might be drawn by using the \clip command and \usetikzlibrary{patterns}.

I have an easier example as follows:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{patterns}
\begin{document}
    \begin{figure}
        \begin{tikzpicture}
            \begin{scope}
                \clip[draw](0,0) circle(1);
                \fill[pattern=north east lines](1.5,0) circle(1);
            \end{scope}
            \draw (1.5,0) circle(1);  
        \end{tikzpicture}
    \end{figure}
\end{document}

And it generates the following picture: enter image description here However, to solve the original problem seems a little difficult for me because I have no idea how to use the \clip properly. Your tips will be appreciated. Thank you!

Stephen
  • 3,826

6 Answers6

17

The lower part (vertical lines) is tricky and I had to cheat a bit. The rest is pretty straightforward with \clip and even odd rule.

enter image description here

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{patterns,intersections}

\begin{document} \begin{tikzpicture}

    \def\A{(-.75,0) circle (2)}
    \def\B{(.75,0) circle (2)}
    \def\C{(0,0) to[out=-150,in=180,looseness=2] (0,-3.5) to[out=0,in=-30,looseness=2] (0,0) -- cycle}

    \path [name path=A] \A;
    \path [name path=B] \B;
    \path [name path=C] \C;
    \path [name intersections={of=A and B,by={p1,p2}}];
    \path [name intersections={of=A and C,by={q1,q2}}];
    \path [name intersections={of=B and C,by={r1,r2}}];

    \begin{scope}
        \clip (q1) -- (p2) -- (r2) --++ (.5,0) |-++ (-4.5,-2) |- (q1);
        \fill[even odd rule,pattern=vertical lines] \A \B \C  ;
    \end{scope}

    \begin{scope}
        \clip \A;
        \clip \B;
        \fill[pattern=horizontal lines] \C;
    \end{scope}

    \begin{scope}
        \clip \C;
        \fill[even odd rule,pattern=north east lines] \A \B;
    \end{scope}

    \draw \A \B \C;

\end{tikzpicture}

\end{document}

Someone would probably come with a better solution, and I'm looking forward to learning from it.

SebGlav
  • 19,186
10

While waiting for TikZ, or ...

Considering the following Asymptote code:

size(7cm);
import patterns;

// Two circles path c1=circle((-0.35,0),1); path c2=circle((0.35,0),1);

// Two arrows arrow("$E_1$",relpoint(c1,0.3),dir(135),align=0.3Relative(S),NoMargin); arrow("$E_2$",relpoint(c2,0.24),dir(40),align=0.3Relative(S),NoMargin);

// free path path g1=(0,0){dir(-145)}..tension 3 and 2 ..(-1,-1.25)..{dir(0)}(0,-1.6); path g2=reflect((0,0),(0,1))*g1; path combinedpaths=g1&reverse(g2)&cycle;

// patterns add("patternA",hatch(2mm,dir(0))); add("patternB",hatch(1mm,dir(45))); add("patternC",hatch(2mm,dir(90)));

// all needed paths picture pic1,pic2,pic3,pic4;

fill(pic1,c1,pattern("patternA")); clip(pic1,c2); clip(pic1,combinedpaths); add(pic1);

fill(pic2,c1,pattern("patternB")); unfill(pic2,c2); clip(pic2,combinedpaths); add(pic2);

fill(pic3,c2,pattern("patternB")); unfill(pic3,c1); clip(pic3,combinedpaths); add(pic3);

fill(pic4,combinedpaths,pattern("patternC")); unfill(pic4,c1); unfill(pic4,c2); add(pic4);

draw(c1^^c2); draw(combinedpaths);

enter image description here

10

Another TikZ approach. Not too different from SebGlav's method (+1), but changing the predefined paths. I don't use intersections or even odd rule but I have to admit that I use a trick with which I am not very happy: you can see that I draw the vertical lines and then I cover part of them. As SebGlav says, perhaps there is a better solution.

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{patterns}

\newcommand{\circlesint}{(270:{0.5sqrt(3)}) arc (-60:60:1) arc (120: 240:1)} \newcommand{\circlesext}{(270:{0.5sqrt(3)}) arc (300:60:1) arc (120:-120:1)} \newcommand{\guitarpick}{rounded corners to[out=-40,in=120] (-50:1.5) to[out=270,in=270] (230:1.5) to[out=60,in=220] (0,0)}

\begin{document} \begin{tikzpicture}[line cap=round,line join=round,scale=2] % vertical lines \path[pattern=vertical lines] \guitarpick; \fill[white] \circlesext; % covered part (a trick) % horizontal lines \begin{scope} \clip\circlesint -- cycle; \fill[pattern=horizontal lines] \guitarpick; \end{scope} % north east lines \begin{scope} \clip \guitarpick; \fill[pattern=north east lines] \circlesint \circlesext; \end{scope} % cricles and guitar pick \draw \circlesext \circlesint \guitarpick; % labels \foreach\i in{1,2} \draw[-latex] (2*\i-3,1.25) node[above] {$E_\i$} -- (\i-1.5,1); \end{tikzpicture} \end{document}

enter image description here

Juan Castaño
  • 28,426
  • 1
    That \fill[white] was exactly what I tried to avoid, in order to let this picture being displayed on whatever background. But it's always nice to have many different approaches. – SebGlav Sep 04 '21 at 17:36
10

No extra libraries - just \clip. Shapes copied from @SebGlav.

\documentclass[tikz, border=1 cm]{standalone}
\usetikzlibrary{patterns}
\begin{document}
\begin{tikzpicture}
\newcommand{\A}{(-.75,0) circle (2)}
\newcommand{\B}{(.75,0) circle (2)}
\newcommand{\C}{(0,0) to[out=-150,in=180,looseness=2] (0,-3.5) to[out=0,in=-30,looseness=2] (0,0) -- cycle}
\newcommand{\bgd}{(-2.75,-3.5) rectangle (2.75,2)}

\draw \bgd;

%red \begin{scope} \clip \A; \clip \B; \fill[red] \C; \end{scope}

%green \begin{scope} \clip \A \bgd; \clip \B \bgd; \fill[green] \C; \end{scope}

%blue \begin{scope} \clip \C; \clip \B \bgd; \fill[blue] \A; \end{scope}

%orange \begin{scope} \clip \C; \clip \A \bgd; \fill[orange] \B; \end{scope}

\draw \A; \draw \B; \draw \C; \end{tikzpicture} \end{document}

Filled shapes with colors

Result:

\documentclass[tikz, border=1 cm]{standalone}
\usetikzlibrary{patterns}
\begin{document}
\begin{tikzpicture}
\newcommand{\A}{(-.75,0) circle (2)}
\newcommand{\B}{(.75,0) circle (2)}
\newcommand{\C}{(0,0) to[out=-150,in=180,looseness=2] (0,-3.5) to[out=0,in=-30,looseness=2] (0,0) -- cycle}
\newcommand{\bgd}{(-2.75,-3.5) rectangle (2.75,2)}
\begin{scope}
\clip \A;
\clip \B;
\fill[pattern=horizontal lines] \C;
\end{scope}
\begin{scope}
\clip \A \bgd;
\clip \B \bgd;
\fill[pattern=vertical lines] \C;
\end{scope}
\begin{scope}
\clip \C;
\clip \B \bgd;
\fill[pattern=north east lines] \A;
\end{scope}
\begin{scope}
\clip \C;
\clip \A \bgd;
\fill[pattern=north east lines] \B;
\end{scope}
\draw \A;
\draw \B;
\draw \C;
\end{tikzpicture}
\end{document}

Shapes filled with patterns

To make the inverse clip, I just used a rectangle big enough. For a more universal method, see: https://tex.stackexchange.com/a/12033/8650

5

Another solution with TikZ ...

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc, patterns}

\newcommand{\cirin}{($(0.5,0)+(120:1)$) arc[start angle=120, end angle=240, radius=1] arc[start angle=-60, end angle=60, radius=1] -- cycle;} \newcommand{\cirout}{($(0.5,0)+(-120:1)$) arc[start angle=-120, end angle=120, radius=1] arc[start angle=60, end angle=-60, radius=1] arc[start angle=300, end angle=60, radius=1] arc[start angle=120, end angle=240, radius=1] -- cycle;} \newcommand{\cirbottom}{(1.5,0) arc[start angle=0, end angle=-120, radius=1] arc[start angle=300, end angle=180, radius=1] -- ++(0,-2) -- ++(3,0) -- cycle;} \newcommand{\curv}{(0,0) .. controls +(220:0.5) and +(180:2) .. (0,-1.6) .. controls +(0:2) and +(320:0.5) .. (0,0) -- cycle;}

\begin{document} \begin{tikzpicture} \begin{scope} \clip\cirin \path[pattern=horizontal lines] \curv \end{scope} \begin{scope} \clip[draw]\cirout \path[pattern=north east lines] \curv \end{scope} \begin{scope} \clip[draw]\curv \path[pattern=vertical lines] \cirbottom \end{scope} \end{tikzpicture} \end{document}

enter image description here

Update

New answer with clip and intersection segment recombination.

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\usepgfplotslibrary{fillbetween}
\usetikzlibrary{patterns}

\newcommand{\curv}[1]{\path[#1] (0,0) .. controls +(220:0.5) and +(180:2) .. (0,-1.6) .. controls +(0:2) and +(320:0.5) .. (0,0) -- cycle;}

\begin{document}

\begin{tikzpicture} \path[name path=A] (-1.5,0) arc[start angle=-180, end angle=0, radius=1]; \path[name path=B] (-0.5,0) arc[start angle=-180, end angle=0, radius=1]; \begin{scope} \clip[intersection segments={of=A and B, sequence={R1 -- L2}}]; \curv{pattern=horizontal lines} \end{scope} \begin{scope} \clip[intersection segments={of=A and B, sequence={L1 -- R1[reverse]}}]; \curv{pattern=north west lines} \end{scope} \begin{scope} \clip[intersection segments={of=A and B, sequence={L2[reverse] -- R2}}]; \curv{pattern=north east lines} \end{scope} \begin{scope} \clip[intersection segments={of=A and B, sequence={L1 -- R2}}] |- ++(-3,-2) -- cycle; \curv{pattern=vertical lines} \end{scope} \draw (-0.5,0) circle[radius=1] (0.5,0) circle[radius=1]; \curv{draw} \end{tikzpicture}

\end{document}

enter image description here

polyn
  • 5,614
4

Here are two methods that use my spath3 library to simplify the path use/reuse. The first uses the clipping method used in hpekristiansen's answer so the benefit of the spath3 library here is simply a way to refer to a path multiple times. The second creates each region by defining a path that circumscribes it. This involves cutting up the paths and reassembling the pieces in a suitable order and this uses the deeper functionality of the spath3 library.

First method:

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

\begin{document} \begin{tikzpicture}

% Define the paths and save them, but don't draw them \path[spath/save=A] (-.75,0) circle[radius=2]; \path[spath/save=B] (.75,0) circle[radius=2]; \path[spath/save=C] (0,0) to[out=-150,in=180,looseness=2] (0,-3.5) to[out=0,in=-30,looseness=2] (0,0) -- cycle; % Get the current bounding box for the inverse clipping \path[spath/save=bb] (current bounding box.south west) rectangle (current bounding box.north east);

% Define an inverse clip style \tikzset{ inverse clip/.style={ clip, spath/use=bb }, }

% Each region is defined by all three paths % If the region is inside the path we use clip % if outside we use inverse clip \begin{scope}[even odd rule] \path[spath/use=A, clip, ]; \path[spath/use=B, clip, ]; \path[spath/use=C, clip, ]; \fill[ pattern=horizontal lines, spath/use=bb ]; \end{scope}

\begin{scope}[even odd rule] \path[spath/use=A, inverse clip, ]; \path[spath/use=B, inverse clip, ]; \path[spath/use=C, clip, ]; \fill[ pattern=vertical lines, spath/use=bb ]; \end{scope}

\begin{scope}[even odd rule] \path[spath/use=A, clip, ]; \path[spath/use=B, inverse clip, ]; \path[spath/use=C, clip, ]; \fill[ pattern=north west lines, spath/use=bb ]; \end{scope}

\begin{scope}[even odd rule] \path[spath/use=A, inverse clip, ]; \path[spath/use=B, clip, ]; \path[spath/use=C, clip, ]; \fill[ pattern=north east lines, spath/use=bb ]; \end{scope}

\draw[ spath/use=A, spath/use=B, spath/use=C, ];

\end{tikzpicture} \end{document}

Second method:

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

\begin{document} \begin{tikzpicture}

% Define the paths and save them, but don't draw them \path[spath/save=A] (-.75,0) circle[radius=2]; \path[spath/save=B] (.75,0) circle[radius=2]; \path[spath/save=C] (0,0) to[out=-150,in=180,looseness=2] (0,-3.5) to[out=0,in=-30,looseness=2] (0,0) -- cycle; \tikzset{ % We'll use the original paths later for the drawing so % we clone them for the surgery spath/clone={split A}{A}, spath/clone={split B}{B}, spath/clone={split C}{C}, % 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={split A}, spath/remove empty components={split B}, spath/remove empty components={split C}, % Now split each path where it intersects with the others spath/split at intersections={split A}{split B}, spath/split at intersections={split B}{split C}, spath/split at intersections={split C}{split A}, % 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={split A}\Acpts, spath/get components of={split B}\Bcpts, spath/get components of={split C}\Ccpts, }

% The lower part \fill[pattern=vertical lines, %\draw[red,ultra thick, % useful for testing spath/use=\getComponentOf\Acpts{2}, spath/use={\getComponentOf\Bcpts{3},weld}, spath/use={\getComponentOf\Ccpts{2},weld,reverse}, ];

\fill[pattern=north east lines, %\draw[red,ultra thick, % useful for testing spath/use=\getComponentOf\Acpts{3}, spath/use={\getComponentOf\Ccpts{3},weld,reverse}, spath/use={\getComponentOf\Bcpts{3},weld,reverse}, ];

\fill[pattern=north west lines, %\draw[red,ultra thick, % useful for testing spath/use=\getComponentOf\Acpts{2}, spath/use={\getComponentOf\Bcpts{2},weld,reverse}, spath/use={\getComponentOf\Ccpts{1},weld}, ];

\fill[pattern=horizontal lines, %\draw[red,ultra thick, % useful for testing spath/use=\getComponentOf\Acpts{3}, spath/use={\getComponentOf\Ccpts{4},weld}, spath/use={\getComponentOf\Bcpts{2},weld}, ];

\draw[ spath/use=A, spath/use=B, spath/use=C, ];

% Useful for figuring out the path components \begin{scope}[ every node/.style={ pos=.5, fill=white, circle, inner sep=0pt, opacity=.75 } ] \foreach \cpts/\clr in {\Acpts/red,\Bcpts/green,\Ccpts/blue} { \expandafter\let\expandafter\cpts\expandafter=\cpts \foreach[count=\k] \cpt in \cpts { \path[spath/use=\cpt] node[text=\clr] {\k}; } } \end{scope} \end{tikzpicture} \end{document}

The result of both is essentially the same, though the second has a labelling of the components which is useful for figuring out what's going on and would be removed in the final code. That's what's in the picture below.

Decorated regions

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • 2
    Very nice!! (+1). And thanks for the complete explanation :-) – Juan Castaño Sep 05 '21 at 18:41
  • @Andrew Stacey How can I use spath3 to question https://tex.stackexchange.com/questions/614030/how-to-draw-circle-passing-through-three-points-in-3d? – minhthien_2016 Sep 06 '21 at 01:55
  • I was trying your second example to learn about spath3, but it doesn't compile in my system (TL2020). I copy-pasted it and I get the error: Package pgfkeys Error: I do not know the key '/tikz/spath/use'. Do I need a more recent version? – Juan Castaño Sep 18 '21 at 17:14
  • @JuanCastaño Yes, you'll need a version from 2021. The latest on ctan should work, or you could get the development version from github. Both should be fine with tl2020. – Andrew Stacey Sep 18 '21 at 17:18
  • Thanks!!! I'll try it. – Juan Castaño Sep 18 '21 at 17:56