1

I am trying to control filling different intersection areas in TikZ (including using patterns), utilizing the following code (I do not want to use \addplot, so that I can control the shape of the curves as needed), to get the top drawing.

But what I succeeded to do so far is only the bottom drawing.

I failed to fill areas between curveA and other paths, or to precisely control filling needed areas.

\documentclass{article}
\usepackage{tikz}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\usetikzlibrary{backgrounds,shadings,patterns}
\begin{document}
%begin curves definitions
\tikzset{pics/.cd,
curvef/.style n args={2}{code={
\node [red] at (#1,#2) (begin){}
([shift={(10.:.4cm)}]begin.center) node (beginr){}
([shift={(60:4.4cm)}]beginr.center) node (midtop){}
([shift={(-60:4.4cm)}]midtop.center) node (end){}
([shift={(-10.:.4cm)}]end.center) node (endr){}
;}}}
%end curves definitions
%
\tikzset{lw/.style={line width=.08cm}}
%
{
\begin{tikzpicture}[scale=.9, transform shape]
\pic at (0,0) {curvef={.8}{0}};
%
\draw[blue, lw, name path=curveA]([shift={(180.:.8cm)}]begin.center) --   (begin.center) to [out=6, in=-160, looseness=1.] (beginr.center) to [out=20, in=-125, looseness=.68] (midtop.center) coordinate (mda) to [out=55, in=160, looseness=.68] node[pos=.74] (r){} (end.center) to [out=-20, in=174, looseness=1.] (endr.center) --  ([shift={(0.:2.6cm)}]endr.center);
%
\pic at (2,0) {curvef={.8}{0}};
%
\draw[green!60!black, lw, name path=curveB] ([shift={(180.:2.8cm)}]begin.center) --  (begin.center) to [out=6, in=-160, looseness=1.] (beginr.center) to [out=20, in=-125, looseness=.68] (midtop.center) coordinate (mdb) to [out=55, in=160, looseness=.68] (end.center) to [out=-20, in=174, looseness=1.] (endr.center) --  ([shift={(0.:.8cm)}]endr.center);
\path[name intersections={of=curveA and curveB}] (intersection-2) node[circle, black, fill=black, scale=0.4] (ab2) {};
%
\path[name path=xaxis] (0,0)(8,0);
%
\draw [name path=red, red, lw, dotted](r.center|-0,0) -- ++(90:4);
\draw [violet, thin, name path=axis] (0,0) -- (9,0);
%
\begin{scope}[on background layer]
\path [fill=yellow, opacity=.5, intersection segments={of=curveB and axis, sequence={L2 -- R3}}];
%
\path [right color=cyan,left color=cyan!20, opacity=.5, intersection segments={of=red and axis, sequence={L* -- R*}}];
%
\path [fill=yellow, opacity=.5, intersection segments={of=curveB and axis, sequence={L2 -- R3}}];
%
\path [pattern=grid, pattern color=gray, opacity=.5, intersection segments={of=red and curveB, sequence={L1 -- R1[reverse]}}];
\fill [red] (ab2) -- ([shift={(40.:.3cm)}]mda) -- ([shift={(40.:.3cm)}]mdb) -- (ab2) -- cycle;
\end{scope}
\end{tikzpicture}
}
%
\end{document}

What I need to getWhat I need to get

What I managed to getWhat I managed to get

enter image description here

1 Answer 1

3

With your approach it is very difficult to find the maxima of the two curves, which is why the following example omits the gray section. It might be easier to draw the curves in a different way, so that there is actually a coordinate at the maximum already. By the way, I would rather use \coordinates instead of \nodes in this case.

I also would suggest that you modify the defintion of the \pic in order to draw the curves directly with it. Note that you can name a \pic and then refer to coordinates and nodes inside as shown in the below example. Also note that it might be a good idea to close paths when you want to fill them.

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{backgrounds, fillbetween}

\begin{document}

%begin curves definitions
\tikzset{
    pics/curvef/.style n args={3}{code={
        \coordinate (-begin) at #1;
        \coordinate (-beginr) at ([shift={(10:.4cm)}]-begin);
        \coordinate (-midtop) at ([shift={(60:4.4cm)}]-beginr);
        \coordinate (-end) at ([shift={(-60:4.4cm)}]-midtop);
        \coordinate (-endr) at ([shift={(-10:.4cm)}]-end);
        \coordinate (-start) at ([shift={#2}]-begin);
        \coordinate (-stop) at ([shift={#3}]-endr);
        \draw[pic actions] 
            (-start) --
            (-begin) to [out=6, in=-160, looseness=1] 
            (-beginr) to [out=20, in=-125, looseness=.68] 
            (-midtop) to [out=55, in=160, looseness=.68] 
            coordinate[pos=.74] (-r) 
            (-end) to [out=-20, in=174, looseness=1] 
            (-endr) -- 
            (-stop);
    }}
}
%end curves definitions

\tikzset{lw/.style={line width=.08cm}}

\begin{tikzpicture}[scale=.9, transform shape]

\pic[blue, lw, name path global=curveA] (curveA) 
    at (0,0) {curvef={(.8,0)}{(180:.8cm)}{(0:2.8cm)}};

\pic[green, lw, name path global=curveB] (curveB) 
    at (2,0) {curvef={(.8,0)}{(180:2.8cm)}{(0:.8cm)}};

\draw[name path=split, red, lw, dotted]
    (curveA-r |- 0,0) -- ++(90:4) coordinate (split top);
    
\draw[violet, thin, name path=axis] 
    (0,0) -- (8.8,0);

\begin{scope}[on background layer]
    \path[fill=magenta!50, 
        intersection segments={
            of=curveA and axis, sequence={L* -- R*}
        }] -- cycle;
        
    \path[fill=yellow, 
        intersection segments={
            of=curveB and axis, sequence={L* -- R*}
        }] -- cycle;

    \path[fill=green, 
        intersection segments={
            of=split and curveB, sequence={R1 -- L1[reverse]}
        }] -- cycle;

    \path[fill=cyan,
        name path=overlapAB,
        intersection segments={
            of=curveA and curveB, sequence={L3 -- R2}
        }] -- cycle;

    \path[fill=blue!50!cyan,
        intersection segments={
            of=split and overlapAB, sequence={R1 -- L1[reverse] -- R3}
        }] -- cycle;
\end{scope}

\end{tikzpicture}
\end{document}

enter image description here


As for filling the area between the maxima and the intersection of the two curves, things become a lot easier if you define the curves using a coordinate at their maximum (note that the curves are not exactly the same as in your original question):

\documentclass[border=10pt]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{backgrounds, fillbetween}

\begin{document}

%begin curves definitions
\tikzset{
    pics/curvef/.style n args={3}{code={
        \coordinate (-begin) at #1;
        \coordinate (-begin right) at ([shift={(1.75,0)}]-begin);
        \coordinate (-top) at ([shift={(2.5,4)}]-begin);
        \coordinate (-top left) at ([shift={(-0.75,0)}]-top);
        \coordinate (-top right) at ([shift={(0.75,0)}]-top);
        \coordinate (-end) at ([shift={(5,0)}]-begin);
        \coordinate (-end left) at ([shift={(-1.75,0)}]-end);
        \coordinate (-start) at ([shift={#2}]-begin);
        \coordinate (-stop) at ([shift={#3}]-end);
        \draw[pic actions] 
            (-start) --
            (-begin) .. controls (-begin right) and (-top left) ..
            (-top) .. controls (-top right) and (-end left) ..
            coordinate[pos=.74] (-r) 
            (-end) --
            (-stop);
    }}
}
%end curves definitions

\tikzset{lw/.style={line width=.8mm}}

\begin{tikzpicture}[scale=.9, transform shape]

\pic[blue, lw, name path global=curveA] (curveA) 
    at (0,0) {curvef={(.8,0)}{(-.8,0)}{(2.8,0)}};

\pic[green, lw, name path global=curveB] (curveB) 
    at (2,0) {curvef={(.8,0)}{(-2.8,0)}{(.8,0)}};

\draw[name path=split, red, lw, dotted]
    (curveA-r |- 0,0) -- (curveA-r |- curveA-top) 
    coordinate (split top);
    
\draw[violet, thin, name path=axis] 
    (0,0) -- (8.6,0);

\begin{scope}[on background layer]
    \path[name intersections={of=curveA and curveB}]
        coordinate (intersectionAB) at (intersection-2);
    
    \path[fill=red!50]
        (intersectionAB) -- (curveA-top) -- (curveB-top) -- cycle;
        
    \path[fill=magenta!50, 
        intersection segments={
            of=curveA and axis, sequence={L* -- R*}
        }] -- cycle;
        
    \path[fill=yellow, 
        intersection segments={
            of=curveB and axis, sequence={L* -- R*}
        }] -- cycle;

    \path[fill=green, 
        intersection segments={
            of=split and curveB, sequence={R1 -- L1[reverse]}
        }] -- cycle;

    \path[fill=cyan,
        name path=overlapAB,
        intersection segments={
            of=curveA and curveB, sequence={L3 -- R2}
        }] -- cycle;

    \path[fill=blue!50!cyan,
        intersection segments={
            of=split and overlapAB, sequence={R1 -- L1[reverse] -- R3}
        }] -- cycle;
\end{scope}

\end{tikzpicture}
\end{document}

enter image description here

9
  • @ Jasper Habicht Thank you very much for your time. I appreciate your solution very much. Just one explanation please; is there any special reason for naming the curves as global in [name path global=curveA]
    – Hany
    Commented Jun 2, 2023 at 4:59
  • @Hany This is needed because the path of the curve is constructed within a scope (the \pic), but you need to access is outside this scope. Commented Jun 2, 2023 at 7:38
  • @ Jasper Habicht Thank you for your answer and comments.
    – Hany
    Commented Jun 2, 2023 at 12:14
  • @ Jasper Habicht Just one final request please. I added coordinates mda,mdb,ab2 to draw a filled area between them in this modified code: \draw ... (midtop.center) coordinate (mda) ...; \draw... coordinate (mdb) ...; \path[name intersections={of=curveA and curveB}] (intersection-2) node[circle, black, fill=black, scale=0.4] (ab2) {}; \fill [red] (ab2) -- ([shift={(40.:.3cm)}]mda) -- ([shift={(40.:.3cm)}]mdb) -- (ab2) -- cycle; Is it possible to use soft clip to clip this filled area to match my gray area in my post? Thank you very much. i.sstatic.net/nsJx0.jpg
    – Hany
    Commented Jun 3, 2023 at 5:03
  • @Hany The problem is that in your original code, the midtop coordinates are not exactly at the top of the curves. Therefore, it is difficult to draw something there using these coordinates. Note that it is always better to leave the original code in your question after someone has posted an answer, because this answer relates to the original code. It is difficult for others to understand how the answer are related to the new code. You might want to ask a new question in such a case or add your modified code after some kind of notice that you edited the question. Commented Jun 3, 2023 at 15:27

You must log in to answer this question.

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