5

Found several questions here obviously related to what I want, TikZ outline stroke of a compound shape, How to outline the union of an annulus and a rectangle in TikZ?, TikZ: Drawing an arc from an intersection to an intersection and some others, but still could not figure out how to adapt them for my needs.

I have this:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc,intersections}

\begin{document}

\begin{tikzpicture}
\clip (-4,-1) rectangle (4,3);
\coordinate (a) at (-4,-3);
\coordinate (va) at (3,7.5);
\shadedraw[name path=higher,opacity=.3] (a) .. controls ($(a)+(va)$) .. ($(a)+(6,0)$);
\coordinate (b) at (4,-5);
\coordinate (vb) at (-3,7.5);
\shadedraw[name path=lower,opacity=.3] ($(b)-(6,0)$) .. controls ($(b)+(vb)$) .. (b);
\path [name intersections={of=higher and lower,by=x}];
\coordinate (xa) at (-1.65,3.45);
\coordinate (xb) at (1,.75);
\draw[thick] (a) .. controls ($(a)+.89*(va)$) and ($(x)+(xa)$) .. (x)
                 .. controls ($(x)+(xb)$) and ($(b)+.6*(vb)$) .. (b);
\end{tikzpicture}

\end{document} 

and the result is

enter image description here

but it took me quite some effort to find, by blind trial-and-error, the six decimals in the code, and, if you look attentively, the picture is still not entirely accurate.

Is there a better way to draw that thick line?

2 Answers 2

9

This can be achieved by use of the spath3 library (this ought to work with the current version on CTAN but if not the latest version is available from github - it's just waiting for me to upload it to CTAN).

After drawing and shading the original paths, it splits then at the point where they intersect. Individual components can then be rendered separately, and also welded together to form a nice joint at the intersection point.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/598243/86}

\usepackage{tikz}
\usetikzlibrary{
  calc,
  intersections,
  spath3
}

\begin{document}

\begin{tikzpicture}
\clip (-4,-1) rectangle (4,3);
\coordinate (a) at (-4,-3);
\coordinate (va) at (3,7.5);
\shadedraw[spath/save=higher,opacity=.3] (a) .. controls ($(a)+(va)$) .. ($(a)+(6,0)$);
\coordinate (b) at (4,-5);
\coordinate (vb) at (-3,7.5);
\shadedraw[spath/save=lower,opacity=.3] ($(b)-(6,0)$) .. controls ($(b)+(vb)$) .. (b);

\tikzset{
  spath/split at intersections={higher}{lower},
  spath/get components of={higher}\higherPath,
  spath/get components of={lower}\lowerPath,
}

\draw[
  thick,
  spath/use=\getComponentOf\higherPath{1},
  spath/use={\getComponentOf\lowerPath{2},weld},
];

\end{tikzpicture}

\end{document} 

End result:

Outlined shape

Detail of the intersection:

Detail of intersection point

7
  • Great work! I wish I could accept both answers - yours for universality and the other one for minimality... May 23, 2021 at 11:52
  • Version 2.4 (Feb 23 2021) from MiKTeX package repositories works perfectly with the latest system files (pgf 3.1.9a in particular) on Windows 10 May 23, 2021 at 13:16
  • 1
    I've always felt it a strength of the users of this site that although there can only be one accepted answer then the value of other contributions is acknowledged, so I wouldn't worry overmuch about which is marked as "accepted". May 23, 2021 at 16:32
  • 1
    weld is what produces the nice join. When an spath is used then there are a variety of options for how it combines with whatever is already there. Using the weld option makes it into a contiguous path. Without that it would be two separate components. It's the difference between \draw (0,0) -- (1,0) -- (1,1); and \draw (0,0) -- (1,0) (1,0) -- (1,1); May 23, 2021 at 16:34
  • 2
    @AndrewStacey spath3 is really powerful now, impressive.
    – Kpym
    May 24, 2021 at 13:19
7

One simple way of doing this is to clip out the portion below node (x). Store your two curves to be able to use them twice, one for the shading, and one for the line drawing. outline of two curves

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc,intersections}

\begin{document}

    \begin{tikzpicture}
        \clip (-4,-1) rectangle (4,3);
        \coordinate (a) at (-4,-3);
        \coordinate (va) at (3,7.5);
        \coordinate (b) at (4,-5);
        \coordinate (vb) at (-3,7.5);
        
        \def\higherpath{(a) .. controls ($(a)+(va)$) .. ($(a)+(6,0)$)}
        \def\lowerpath{($(b)-(6,0)$) .. controls ($(b)+(vb)$) .. (b)}
                
        \shadedraw[name path=higher,opacity=.3] \higherpath;
        \shadedraw[name path=lower,opacity=.3] \lowerpath;
        
        \path [name intersections={of=higher and lower,by=x}];
                
        \clip (-4,-1) -- (-2,-1) -- (x) -- (2,-1) -- (3,-1) -- (3,3) -| cycle;
        \draw \higherpath \lowerpath;
    \end{tikzpicture}

\end{document}
3
  • 1
    Very smart! Still needs to do something "by hand" but it is a joke compared to what I've been through. May 23, 2021 at 11:47
  • 2
    I am really sorry I had to accept another one, as more systematic and automated. I believe your solution would in one or other form work in 99% of the cases. I wish it would be possible to accept two different answers as useful in different situations. May 23, 2021 at 12:05
  • 3
    Don't worry about that. You have to accept the answer you find the best, and Andrew's one is better, since it provides a really continuous path instead of masking the part you don't want. I'm not that familiar with the spath3 library of his, and sure I'll have to dig in because it's wonderful.
    – SebGlav
    May 23, 2021 at 13:06

You must log in to answer this question.

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