# Filling a complex region with TikZ

I'm trying to fill a complex region which is defined by six intersections of 4 hyperbolas. As you can see here:

In particular I want to fill the region which is bounded and defined by the 6 points. I know the exact coordinates of the p_i's and the exact equations of each hyperbola. How can I concatenate them and fill the region?

For the sake of completeness, here's the code I have so far:

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\def\bndmax{5}
\def\bndmin{0.2}
\def\xS{1.5}
\def\gR{1.618034} % The golden ratio

\begin{tikzpicture}
\draw (-3,-3) grid (3,3);
\tikzset{func/.style={thick,color=orange!90}}
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{-1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{-1/\x});

\begin{scope}[shift={(\xS,1/\xS)}]
\tikzset{func/.style={thick,color=orange!60,dashed}}
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{-1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{-1/\x});
\end{scope}

\fill (\xS,1/\xS) circle (2pt);

\pgfmathsetmacro\x{-\gR*\xS}
\pgfmathsetmacro\y{1/(\gR*\xS)}
\coordinate (p1) at (\x,\y);

\pgfmathsetmacro\x{-(1/\gR)*\xS}
\pgfmathsetmacro\y{\gR*(1/\xS)}
\coordinate (p2) at (\x,\y);

\pgfmathsetmacro\x{1/(\gR*\gR)*\xS}
\pgfmathsetmacro\y{\gR*\gR/\xS)}
\coordinate (p3) at (\x,\y);

\pgfmathsetmacro\x{(1/\gR)*\xS}
\pgfmathsetmacro\y{-\gR*(1/\xS)}
\coordinate (p4) at (\x,\y);

\pgfmathsetmacro\x{\gR*\xS}
\pgfmathsetmacro\y{-1/(\gR*\xS)}
\coordinate (p5) at (\x,\y);

\pgfmathsetmacro\x{\gR*\gR*\xS}
\pgfmathsetmacro\y{1/(\gR*\gR*\xS)}
\coordinate (p6) at (\x,\y);

\foreach \i in {1,2,3,4,5,6}
\fill[red] (p\i) circle (2pt) node[right]{$p_{\i}$};

\end{tikzpicture}
\end{document}
-
What goes wrong if you use the lines to define clipped region and then fill it? –  Loop Space Aug 23 '12 at 15:46
@AndrewStacey: If You use the plots for clipping, then the region is the curve and the connection of start and and point, so you get kind of a diamond defined by p1 to p6, "eaten away" up to the functions. –  Tom Bombadil Aug 23 '12 at 17:00
@TomBombadil I know, but that's easy enough to correct. It's obvious which side of the line you want to clip, so you connect (for the clip) the end points with a big up-and-over. –  Loop Space Aug 23 '12 at 17:25
@AndrewStacey: If one knows what to do, indeed. I thought that \draw (<p>) plot (<f1>) plot (<f2>); would do waht I want, but is was really \draw (<p>) plot (<f1>) -- plot (<f2>); –  Tom Bombadil Aug 23 '12 at 17:33

Here's a not fully automatic solution. It doesn't work if I use \xs in the definition of the function in plot, so I had to put this in manually (and therefore, statically). For the respective domains, I renamed your reused help macros \x and \y to \xa and \ya up to \xa and \xf, thus they can be used later. Then it's only conacatenating a lot of plot and -- commands. The -- is important, otherwise each individual plot is closed, resulting in a weird diamond shape.

\documentclass{standalone}

\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\def\bndmax{5}
\def\bndmin{0.2}
\def\xS{1.5}
\def\gR{1.618034} % The golden ratio

\begin{tikzpicture}
\draw (-3,-3) grid (3,3);
\tikzset{func/.style={thick,color=orange!90}}
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{-1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{-1/\x});

\begin{scope}[shift={(\xS,1/\xS)}]
\tikzset{func/.style={thick,color=orange!60,dashed}}
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{-1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{-1/\x});
\end{scope}

\fill (\xS,1/\xS) circle (2pt);

\pgfmathsetmacro\xa{-\gR*\xS}
\pgfmathsetmacro\ya{1/(\gR*\xS)}
\coordinate (p1) at (\xa,\ya);

\pgfmathsetmacro\xb{-(1/\gR)*\xS}
\pgfmathsetmacro\yb{\gR*(1/\xS)}
\coordinate (p2) at (\xb,\yb);

\pgfmathsetmacro\xc{1/(\gR*\gR)*\xS}
\pgfmathsetmacro\yc{\gR*\gR/\xS)}
\coordinate (p3) at (\xc,\yc);

\pgfmathsetmacro\xd{(1/\gR)*\xS}
\pgfmathsetmacro\yd{-\gR*(1/\xS)}
\coordinate (p4) at (\xd,\yd);

\pgfmathsetmacro\xe{\gR*\xS}
\pgfmathsetmacro\ye{-1/(\gR*\xS)}
\coordinate (p5) at (\xe,\ye);

\pgfmathsetmacro\xf{\gR*\gR*\xS}
\pgfmathsetmacro\yf{1/(\gR*\gR*\xS)}
\coordinate (p6) at (\xf,\yf);

\foreach \i in {1,2,3,4,5,6}
\fill[red] (p\i) circle (2pt) node[right]{$p_{\i}$};

\clip (p1) plot[domain=\xa:\xb] (\x,{-1/\x}) -- plot[domain=\xb:\xc] (\x,{-1/(\x-1.5)+1/1.5}) -- plot[domain=\xc:\xf] (\x,{1/\x}) -- plot[domain=\xf:\xe] (\x,{-1/(\x-1.5)+1/1.5}) -- plot[domain=\xe:\xd] (\x,{-1/\x}) -- plot[domain=\xd:\xa] (\x,{1/(\x-1.5)+1/1.5}) --cycle;
\fill[opacity=0.3,blue!30!cyan] (\xa,\yd) rectangle (\xf,\yc);

\end{tikzpicture}
\end{document}

Edit 1: Just some minor improvements:

• expanded the grid to 10x10
• imprved the overall clipping
• fixed the boundaries such that all functions are drawn over the full domain
• put the blue filling on a background layer, so it does not patially overlap the functions or points

.

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}

\pgfdeclarelayer{background layer}
\pgfsetlayers{background layer,main}

\begin{document}

\def\bndmax{6.5}
\def\bndmin{0.15}
\def\xS{1.5}
\def\gR{1.618034} % The golden ratio

\begin{tikzpicture}
\clip (-5cm-0.2pt,-5cm-0.2pt) rectangle (5cm+0.pt,5cm+0.2pt);
\draw (-5,-5) grid (5,5);
\draw[thick] (-5,0) -- (5,0);
\draw[thick] (0,-5) -- (0,5);
\tikzset{func/.style={thick,color=orange!90}}
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{-1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{-1/\x});

\begin{scope}[shift={(\xS,1/\xS)}]
\tikzset{func/.style={thick,color=orange!60,dashed}}
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{-1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (\x,{1/\x});
\draw[func,domain=-\bndmax:-\bndmin] plot [samples=200] (-\x,{-1/\x});
\end{scope}

\fill (\xS,1/\xS) circle (2pt);

\pgfmathsetmacro\xa{-\gR*\xS}
\pgfmathsetmacro\ya{1/(\gR*\xS)}
\coordinate (p1) at (\xa,\ya);

\pgfmathsetmacro\xb{-(1/\gR)*\xS}
\pgfmathsetmacro\yb{\gR*(1/\xS)}
\coordinate (p2) at (\xb,\yb);

\pgfmathsetmacro\xc{1/(\gR*\gR)*\xS}
\pgfmathsetmacro\yc{\gR*\gR/\xS)}
\coordinate (p3) at (\xc,\yc);

\pgfmathsetmacro\xd{(1/\gR)*\xS}
\pgfmathsetmacro\yd{-\gR*(1/\xS)}
\coordinate (p4) at (\xd,\yd);

\pgfmathsetmacro\xe{\gR*\xS}
\pgfmathsetmacro\ye{-1/(\gR*\xS)}
\coordinate (p5) at (\xe,\ye);

\pgfmathsetmacro\xf{\gR*\gR*\xS}
\pgfmathsetmacro\yf{1/(\gR*\gR*\xS)}
\coordinate (p6) at (\xf,\yf);

\foreach \i in {1,2,3,4,5,6}
\fill[red] (p\i) circle (2pt) node[right]{$p_{\i}$};

\begin{pgfonlayer}{background layer}
\clip (p1) plot[domain=\xa:\xb] (\x,{-1/\x}) -- plot[domain=\xb:\xc] (\x,{-1/(\x-1.5)+1/1.5}) -- plot[domain=\xc:\xf] (\x,{1/\x}) -- plot[domain=\xf:\xe] (\x,{-1/(\x-1.5)+1/1.5}) -- plot[domain=\xe:\xd] (\x,{-1/\x}) -- plot[domain=\xd:\xa] (\x,{1/(\x-1.5)+1/1.5}) --cycle;
\fill[opacity=0.3,blue!30!cyan] (\xa,\yd) rectangle (\xf,\yc);
\end{pgfonlayer}

\end{tikzpicture}
\end{document}

-

While you have coordinates of each vertice of your complex region, you can draw it with a single path:

\documentclass{standalone}
\usepackage{tikz}
\def\xS{1.5}
\def\gR{1.618034} % The golden ratio
\begin{document}
\begin{tikzpicture}
\draw[samples=30,line join=round,fill=lime]
plot [domain=-\gR*\xS:-(1/\gR)*\xS] (\x,-{1/\x})
-- plot [domain=-\gR*\xS:-(1/\gR)*\xS] (\x+\xS,{-(1/\x)+(1/\xS)})
-- plot [domain=1/(\gR*\gR)*\xS:\gR*\gR*\xS] (\x,{1/\x})
-- plot [domain=\gR*\xS:{(1/\gR)*\xS}] (\x+\xS,{-1/\x+1/\xS})
-- plot [domain=\gR*\xS:{(1/\gR)*\xS}] (\x,{-1/\x})
-- plot [domain=-1/(\gR*\gR)*\xS:-\gR*\gR*\xS] (\x+\xS,{1/\x+1/\xS})
-- cycle;
\end{tikzpicture}
\end{document}

You can even vary the parameter `\xS':

\begin{tikzpicture}
\foreach \gray in {10,20,...,90}{
\pgfmathsetmacro{\xS}{.5+\gray/100*1.5}
\draw[samples=30,line join=round,draw=black!\gray!yellow]
plot [domain=-\gR*\xS:-(1/\gR)*\xS] (\x,-{1/\x})
-- plot [domain=-\gR*\xS:-(1/\gR)*\xS] (\x+\xS,{-(1/\x)+(1/\xS)})
-- plot [domain=1/(\gR*\gR)*\xS:\gR*\gR*\xS] (\x,{1/\x})
-- plot [domain=\gR*\xS:{(1/\gR)*\xS}] (\x+\xS,{-1/\x+1/\xS})
-- plot [domain=\gR*\xS:{(1/\gR)*\xS}] (\x,{-1/\x})
-- plot [domain=-1/(\gR*\gR)*\xS:-\gR*\gR*\xS] (\x+\xS,{1/\x+1/\xS})
-- cycle;
}
\end{tikzpicture}

But if you don't know the coordinates, there is always a solution using two clip paths with chained plots (works if \bndmax and \bndmin are choose correctly):

\documentclass{standalone}
\usepackage{tikz}

\def\bndmax{5}
\def\bndmin{0.2}
\def\xS{1.5}
\def\gR{1.618034} % The golden ratio
\begin{document}
\begin{tikzpicture}
\draw (-\bndmax,-1/\bndmin) grid (\bndmax,1/\bndmin);

\path[clip] plot [samples=200,domain=-\bndmax:-\bndmin] (-\x,{1/\x})
-- plot [samples=200,domain=-\bndmin:-\bndmax] (\x,{1/\x})
-- plot [samples=200,domain=-\bndmax:-\bndmin] (\x,{-1/\x})
-- plot [samples=200,domain=-\bndmin:-\bndmax] (-\x,{-1/\x})
-- cycle;

\fill[green,fill opacity=.3]
(-\bndmax,-1/\bndmin) rectangle (\bndmax,1/\bndmin);

\begin{scope}[shift={(\xS,1/\xS)}]
\path[clip] plot [samples=200,domain=-\bndmax:-\bndmin] (-\x,{1/\x})
-- plot [samples=200,domain=-\bndmin:-\bndmax] (\x,{1/\x})
-- plot [samples=200,domain=-\bndmax:-\bndmin] (\x,{-1/\x})
-- plot [samples=200,domain=-\bndmin:-\bndmax] (-\x,{-1/\x})
-- cycle;

\fill[red,fill opacity=.7]
(-\bndmax,-1/\bndmin) rectangle (\bndmax,1/\bndmin);
\end{scope}
\end{tikzpicture}
\end{document}

-
Nice! To avoid the colored rectangles you can directly use \clip[postaction={fill=green,fill opacity=.3}] plot.... etc. Shortens the code a little bit more :) –  percusse Aug 23 '12 at 21:46
Cool..................... –  Nicholas Hamilton Nov 12 '13 at 5:15

You can use PGFPlots for this.

I defined two functions,

declare function={f(\x)=min(1/\x,-1/\x);},
declare function={g(\x)=max(1/\x,-1/\x);}

which correspond to the negative (positive) parts of the hyperbolas, and then used these to define two new functions

declare function={h(\x)=max(f(x),f(x-1.5)+1/1.5);},
declare function={i(\x)=min(g(x),g(x-1.5)+1/1.5);}

which correspond to the greater (lower) of the positive (negative) unshifted and shifted parts.

These can then be used in a stacked plot to colour the area. To make sure that only the parts between your p1 and p6 are coloured, we can make use of the fact that undefined coordinates are automatically discarded, so I add the term

*1/(h(x)<i(x))

which leads to a division by zero outside of our region of interest, so the plot starts and stops where we want it to.

\documentclass{article}

\usepackage{pgfplots}

\begin{document}

\begin{tikzpicture}[
declare function={f(\x)=min(1/\x,-1/\x);},
declare function={g(\x)=max(1/\x,-1/\x);},
declare function={h(\x)=max(f(x),f(x-1.5)+1/1.5);},
declare function={i(\x)=min(g(x),g(x-1.5)+1/1.5);}
]
\begin{axis}[
domain=-5:5,
ymin=-5,ymax=5,
samples=101,
no markers,
smooth
]

\addplot [draw=none, stack plots=y] {h(x)*1/(h(x)<i(x))};
\addplot [draw=none, fill=yellow, thick, stack plots=y] {i(x)*1/(h(x)<i(x))- h(x)*1/(h(x)<i(x))}\closedcycle;

\addplot [black, dashed] {f(x-1.5)+1/1.5};
\addplot [black, dashed] {g(x-1.5)+1/1.5};

\end{axis}
\end{tikzpicture}
\end{document}
-
Very cool, but since I have the coordinates of the vertices, and I have to use them any way I guess this is approach is an overkill. –  Dror Aug 24 '12 at 7:11

For those who are searching for the PSTricks equivalent.

\documentclass[pstricks,border=0pt]{standalone}
\usepackage{pst-eucl,pst-plot}

\def\f(#1){1 #1 div}
\def\F(#1){\f(#1 1.5 sub) 1 1.5 div add}
\def\g(#1){\f(#1 neg)}
\def\G(#1){\g(#1 1.5 sub) 1 1.5 div add}
\def\x(#1){\psGetNodeCenter{#1}#1.x}

\psset{yMaxValue=4,yMinValue=-4,plotpoints=6001}

\begin{document}

\begin{pspicture}[showgrid=false](-4.25,-4.25)(5.5,4.5)
\psclip{\psframe[linestyle=none,linewidth=0pt](-4,-4)(5,4)}
\pstInterFF[PosAngle=135]{\g(x)}{\F(x)}{-2}{P_1}
\pstInterFF[PosAngle=135]{\g(x)}{\G(x)}{-1}{P_2}
\pstInterFF[PosAngle=180]{\G(x)}{\f(x)}{1}{P_3}
\pstInterFF[PosAngle=90]{\G(x)}{\f(x)}{3}{P_4}
\pstInterFF[PosAngle=-45]{\G(x)}{\g(x)}{2}{P_5}
\pstInterFF[PosAngle=0]{\g(x)}{\F(x)}{1}{P_6}
\pscustom*[linecolor=yellow]
{
\psplot{\x(P_1)}{\x(P_2)}{\g(x)}
\psplot{\x(P_2)}{\x(P_3)}{\G(x)}
\psplot{\x(P_3)}{\x(P_4)}{\f(x)}
\psplot{\x(P_4)}{\x(P_5)}{\G(x)}
\psplot{\x(P_5)}{\x(P_6)}{\g(x)}
\psplot{\x(P_6)}{\x(P_1)}{\F(x)}
}
\psplot[linecolor=red]{-4}{5}{\f(x)}
\psplot[linecolor=blue]{-4}{5}{\g(x)}
\psset{linestyle=dashed,dash=3pt 1pt}
\psplot[linecolor=red]{-4}{5}{\F(x)}
\psplot[linecolor=blue]{-4}{5}{\G(x)}
\endpsclip
\psaxes[labelFontSize=\scriptscriptstyle,linecolor=gray]{->}(0,0)(-4,-4)(5,4)[$x$,0][$y$,90]
\end{pspicture}

\end{document}

## Notes

\psset{saveNodeCoors}
\def\x(#1){N-#1.x}

can be used to substitute for

\def\x(#1){\psGetNodeCenter{#1}#1.x}

## Latest update

With infix notation for the sake of convenience.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-eucl,pst-plot}

\def\f(#1){(1/(#1))}
\def\F(#1){(\f(#1-1.5)+1/1.5)}
\def\g(#1){(\f(-(#1)))}
\def\G(#1){(\g(#1-1.5)+1/1.5)}
\def\x(#1){N-#1.x}

\pstVerb{/I2P {exec AlgParser cvx exec} def}

\begin{document}

\begin{pspicture}[showgrid=false,saveNodeCoors,algebraic,yMaxValue=4,yMinValue=-4,plotpoints=6001](-4.25,-4.25)(5.5,4.5)
\psclip{\psframe[linestyle=none,linewidth=0pt](-4,-4)(5,4)}
\pstInterFF[PosAngle=135]{{\g(x)} I2P}{{\F(x)} I2P}{-2}{P_1}
\pstInterFF[PosAngle=135]{{\g(x)} I2P}{{\G(x)} I2P}{-1}{P_2}
\pstInterFF[PosAngle=180]{{\G(x)} I2P}{{\f(x)} I2P}{1}{P_3}
\pstInterFF[PosAngle=90]{{\G(x)} I2P}{{\f(x)} I2P}{3}{P_4}
\pstInterFF[PosAngle=-45]{{\G(x)} I2P}{{\g(x)} I2P}{2}{P_5}
\pstInterFF[PosAngle=0]{{\g(x)} I2P}{{\F(x)} I2P}{1}{P_6}
\pscustom*[linecolor=yellow]
{
\psplot{\x(P_1)}{\x(P_2)}{\g(x)}
\psplot{\x(P_2)}{\x(P_3)}{\G(x)}
\psplot{\x(P_3)}{\x(P_4)}{\f(x)}
\psplot{\x(P_4)}{\x(P_5)}{\G(x)}
\psplot{\x(P_5)}{\x(P_6)}{\g(x)}
\psplot{\x(P_6)}{\x(P_1)}{\F(x)}
}
\psplot[linecolor=red]{-4}{5}{\f(x)}
\psplot[linecolor=blue]{-4}{5}{\g(x)}
\psset{linestyle=dashed,dash=3pt 1pt}
\psplot[linecolor=red]{-4}{5}{\F(x)}
\psplot[linecolor=blue]{-4}{5}{\G(x)}
\endpsclip
\psaxes[labelFontSize=\scriptscriptstyle,linecolor=gray]{->}(0,0)(-4,-4)(5,4)[$x$,0][$y$,90]
\foreach \i in {1,...,6}{\qdisk(P_\i){2pt}}
\end{pspicture}

\end{document}
-