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!

2

6 Answers 6

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.

0
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

1
  • Thanks a lot. And waiting for a TikZ method at the same time.
    – Stephen
    Sep 4, 2021 at 10:22
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.5*sqrt(3)}) arc (-60:60:1) arc (120: 240:1)}
\newcommand{\circlesext}{(270:{0.5*sqrt(3)}) arc (300:60:1) arc (120:-120:1)}
\newcommand{\guitarpick}{[rounded corners](0,0) 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

1
  • 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 4, 2021 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

2
  • 2
    Very good!! (+1) And useful, I didn't know about the inverse clip. Sep 4, 2021 at 14:02
  • 1
    Great! That is exactly what I tried to do. You did it very simply. +1
    – SebGlav
    Sep 4, 2021 at 17:38
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

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

5
  • 2
    Very nice!! (+1). And thanks for the complete explanation :-) Sep 5, 2021 at 18:41
  • @Andrew Stacey How can I use spath3 to question tex.stackexchange.com/questions/614030/…? Sep 6, 2021 at 1: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? Sep 18, 2021 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. Sep 18, 2021 at 17:18
  • Thanks!!! I'll try it. Sep 18, 2021 at 17:56

You must log in to answer this question.

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