I know that my effort below can be improved upon considerably. In particular, there must be a way of shading the region in a single scope, as opposed to subdividing as I have done (thus necessitating a hidden gray boundary). Neither am I fond of sample points, but this is where my research has led me. Your constructive criticism is appreciated.


    plot[smooth,samples=100,domain=0:1] (\x,{0}) -- 
    plot[smooth,samples=100,domain=1:0] (\x,{1});
\draw[fill=gray!50!white] plot[smooth,samples=100,domain=1:2.71828] (\x,{ln(\x)}) -- 
    plot[smooth,samples=100,domain=2.71828:1] (\x,{1});
\draw[domain=0:4] plot (\x,{1});
\draw[samples=100,domain=.25:4] plot (\x,{ln(\x)}) node[above left]{$y=\ln x$};
%coordinate grid
\draw (-.5,0)--(4.5,0) node[right]{$x$};
\draw (0,-1.5)--(0,2.5) node[above]{$y$};
\foreach \x in {1,2,3,4}
    \draw (\x,2pt)--(\x,-2pt) node[below] {$\x$};
\foreach \y/\ytext in {1,2}
    \draw (2pt,\y)--(-2pt,\y) node[left] {$\y$};    
\node at (.75,.5) {$\mathcal{D}$};


enter image description here


You can do many things only with clipping (if at all).

If you know the specific point you can do this in one entire path:

\draw[fill=gray!50] plot[smooth, samples=100, domain=1:e] (\x,ln \x) -| (0,0) -- cycle;

If you don’t know the points, you will need to use clip or even intersections.


  saveuse path/.code 2 args={
    \pgfkeysalso{#1/.style={insert path={#2}}}%
    \global\expandafter\let\csname pgfk@\pgfkeyscurrentpath/.@cmd\expandafter\endcsname
      % not optimal as it is now global through out the document
                           \csname pgfk@\pgfkeyscurrentpath/.@cmd\endcsname
  /pgf/math set seed/.code=\pgfmathsetseed{#1}}
  \draw[fill=gray!50] plot[smooth, samples=100, domain=1:e] (\x,ln \x) -| (0,0) -- cycle;
  \clip [saveuse path={plot path}{plot[smooth, samples=100, domain=.25:4] (\x, ln \x)}]
     -| (0,0) -- cycle;
  \clip[preaction={draw,fill=gray!50}] (0,0) rectangle (4,1);
\draw [plot path];
  \clip [saveuse path={plot path}{plot[smooth, samples=100, domain=.25:4] (\x, ln \x)}]
     -- (0,5) -- (0,-5) -- cycle ;
  \clip [saveuse path={zigzag}{[math set seed=150, rounded corners=1.5pt] (0,3)
    \foreach \cnt in {1,...,8} {-- ++ (rnd, -.5*rnd)}}]
    [sharp corners] -- (0, -5) -- cycle;
  \clip (2,1) circle [radius=1.9] [draw, preaction={draw,fill=gray}];
\draw [plot path, zigzag];


enter image description here

enter image description here enter image description here

  • Can you seed the pseudo random generator with a real-time constant? In PSTricks we have \pstVerb{realtime srand}. – kiss my armpit Nov 11 '13 at 16:30
  • 1
    @Marienplatz The seed is initialized with \time * \year so you can do the same: \pgfmathsetseed{\time*\year}. Of course, you can use any real-time stuff there is. Here I used a fixed one so that the randomized path is in both cases the same (I haven’t saved it as a soft-path), to retrieve the current seed, see \pgfmathstoreseed. – Qrrbrbirlbel Nov 11 '13 at 19:02
  • Dear all, is there a way to remove the black boundary for this grey shaded area: \tikz \draw[fill=gray!50] plot[smooth, samples=100, domain=1:e] (\x,ln \x) -| (0,0) -- cycle; ? – wonderich Jun 7 '18 at 16:37
  • @wonderich Just do \path[fill=gray!50] …;. \draw is basically \path[draw=black]. – Qrrbrbirlbel Jun 21 '18 at 22:29

For what it's worth, taking a subpath of an existing path is comparatively easy in Asymptote: you use the intersect method to find the path times at which two paths intersect, and the subpath method to generate a subpath of an existing path using those path times.

For more details, including an explanation of "path times," see pages 19-26 of this tutorial. In case the page numbers change in future revisions: look up "path times" in the index.

% to compile, if this is saved in foo.tex:
% pdflatex foo.tex
% asy foo-*.asy
% pdflatex foo.tex
import graph;
real unit = 1cm;

// Set the font size to match the document.

// Compute the desired paths.
path lngraph = graph(log, 0.25, 4);
path xaxis = (-.5,0) -- (4.5,0);
path yaxis = (0,-1.5) -- (0,2.5);
path yEqualsOne = (0,1) -- (4,1);

// Compute the path times of the intersection points.
real lowerisection = intersect(lngraph, xaxis)[0];
real upperisection = intersect(lngraph, yEqualsOne)[0];

// Fill the region.
fill((0,0) --
     subpath(lngraph, lowerisection, upperisection)
     -- (0,1) -- cycle,
     0.5*gray + 0.5*white);

// Draw the paths.
draw(lngraph, L=Label("$y=\ln x$", EndPoint, align=NW));

// Draw the axes.
draw(xaxis, L=Label("$x$", EndPoint));
draw(yaxis, L=Label("$y$", EndPoint));

// Add the ticks.
real ticksize = 2pt / unit;
for (int x = 1; x <= 4; ++x)
  draw((x,ticksize) -- (x,-ticksize), L=Label("$"+(string)x+"$",EndPoint));
for (int y = 1; y <= 2; ++y)
  draw((ticksize,y) -- (-ticksize,y), L=Label("$" + (string)y + "$", EndPoint));

// And the final label.
label("$\mathcal{D}$", (.75,.5));

The result:

  • looks like a sort of semi-real programming language. wouldn't that makes sense ! – nicolas Jun 16 '17 at 22:14

Here is an example with pgfplots. Since v1.10 it provides the fillbetween library, which can be used to fill the area between curves. Since v1.11 you don't need to say axis cs: anymore, for custom annotations such as here.

I just use it to fill an area below the ln curve with white, so removing that part from a filled rectangular area to get the desired shape.

\pgfplotsset{compat = newest}
  \pgfdeclarelayer{pre main}
  \pgfsetlayers{pre main,main}
      axis lines = middle,
      axis equal,
      domain  = 0:4,
      xlabel  = {x},
      ylabel  = {y},
      xmin    = -0.5,
      xmax    = 4,
      ymin    = -1,
      ymax    = 2,
      samples = 300,
      mark    = none,
    \pgfonlayer{pre main}
    \fill[black!30] (0,0) rectangle (e,1);
    \addplot [name path=ln, thin]  {ln(x)};
    \addplot [thin]  {1};
    \addplot [name path=null, draw=none]  {0};
    \addplot[color=white] fill between[of=null and ln,
      soft clip={domain=1:e}];
    \node at (0.7,0.5) {$\mathcal{D}$};
    \node at (3.2,1.6) {$y = \ln(x)$};

filled area


With PSTricks.

\def\f{x ln}

enter image description here

Latest Update

With infix form.



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

    \pstInterFF[PointSymbol=none,PointName=none]{\f I2P}{1}{3}{A}
    \pscustom*[linecolor=gray]{\psplot{0}{N-A.x}{1}\psplot{N-A.x}{1}{\f I2P}\psplot{1}{0}{0}\closepath}
    \psplot{.3}{4}{\f I2P}
  • Labeling is ignored as usual! – kiss my armpit Nov 11 '13 at 16:18
  • Minor point: you're missing the $y=\ln x$ and $\mathcal{D}$ labels. Bigger question: Would this approach work more generally for shading a region bounded by several curves (without knowing, e.g., that the curved one is the graph of the natural logarithm)? – Charles Staats Nov 11 '13 at 17:21
  • 1
    @CharlesStaats: First we have to plot all functions bounding the region. Second, based on the resulting graphs we know the correct order to make the clipping path. So there are at least 2 compilations to generate the diagram. :-) – kiss my armpit Nov 11 '13 at 17:29
  • @CharlesStaats: Except for those who already know the sketch of the graphs, they don't need the first compilation to see the graphs. – kiss my armpit Nov 11 '13 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.