35

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

enter image description 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}
4
  • 1
    What goes wrong if you use the lines to define clipped region and then fill it? Commented Aug 23, 2012 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. Commented Aug 23, 2012 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. Commented Aug 23, 2012 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>); Commented Aug 23, 2012 at 17:33

4 Answers 4

23

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}

enter image description here


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}

enter image description here

21

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}

enter image description here

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}

enter image description here

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}

enter image description here

1
  • 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
    Commented Aug 23, 2012 at 21:46
19

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] {f(x)};
\addplot [black] {g(x)};

\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}
1
  • 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
    Commented Aug 24, 2012 at 7:11
11

For those who are searching for the PSTricks equivalent.

enter image description here

\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}

enter image description here

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}
0

You must log in to answer this question.

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