Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm working on this diagram:

\documentclass[border=2mm]{standalone}
\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}
        \clip (-0.1,-0.1) rectangle (5,3);
        \draw[help lines,->] (0,0) -- (4.2,0);
        \draw[help lines,->] (0,0) -- (0,3);% draw axis lines
        \draw[gray,dashed] (0,2) -- (4.2,2); % draw asymptote
        \draw[domain=0.1:4.6,very thick,red,->,samples=400] plot ({\x - 0.4},{1/(-\x) + 2} );% draw plot
    \draw[help lines,->] (1,0) -- (1,1.2);
    \draw[help lines,->] (2,0) -- (2,1.5);
    \draw[help lines,->] (3,0) -- (3,1.65);
    \draw[help lines,->] (4,0) -- (4,1.7);

    % scale to fit marginfigure
\end{tikzpicture}
\end{document}

Asymptote drawing

It gets the job done, more or less, but I'm wondering whether there's a cleaner or more elegant way to do it. Specifically, I'm wondering:

  1. Is there a way to draw the curved line as a ray with an endpoint at (0,0)? The problem with drawing a demihyperbola and then clipping is that I want to label several points on that path (which is what the vertical arrows are for). I can't do that if I have to clip the diagram so closely.

  2. Is there a way to describe the height of the vertical lines as relative to the curved plot (i.e., can I tell tikz, "Draw a vertical line, with an arrowhead, from (1,0) until it intersects the curved line")?

share|improve this question
add comment

5 Answers 5

up vote 8 down vote accepted

If I understand correctly, this is what you're asking for:

 \documentclass[border=2mm]{standalone}
 \usepackage{tikz}   
 \usetikzlibrary{calc}
 \begin{document}
   \begin{tikzpicture}
       \clip (-0.1,-0.1) rectangle (5,3);                                   
       \draw[help lines,->] (0,0) -- (4.2,0);                               
       \draw[help lines,->] (0,0) -- (0,3);   % draw axis lines             
       \draw[gray,dashed] (0,2) -- (4.2,2);   % draw asymptote              
       \draw[domain=0.5:4.6,very thick,red,->,samples=400] plot ({\x - 0.5},{1/(-\x) + 2} );% draw plot

   \foreach \x  in {1,2,3,4}                                                
     {%%                                                                    
       \draw[help lines,->] (\x,0) -- ($(\x,{1/(-(\x+0.5)) +2})-(0,0.6pt)$);
     }%%                                                                    

 \end{tikzpicture}                                                          
 \end{document}

enter image description here

Using the tikzlibrary calc allows you to take into account the thickness of the red curve (hence the offset of 0.6pt).

You could write a macro to handle the y-coordinate:

\documentclass[border=2mm]{standalone}
\usepackage{tikz}   
\usetikzlibrary{calc}
\def\mycurve#1{{1/(-(\x+#1))+2}}
\begin{document}
  \begin{tikzpicture}
    \clip (-0.1,-0.1) rectangle (5,3);                                   
    \draw[help lines,->] (0,0) -- (4.2,0);                               
    \draw[help lines,->] (0,0) -- (0,3);   % draw axis lines             
    \draw[gray,dashed] (0,2) -- (4.2,2);   % draw asymptote              
    \draw[domain=0.5:4.6,very thick,red,->,samples=400] plot ({\x - 0.5},\mycurve{0} );% draw plot

    \foreach \x  in {0.25,0.5,...,4}                                                
      {
        \draw[help lines,->] (\x,0) -- ($(\x,\mycurve{0.5})-(0,0.6pt)$);
      }

\end{tikzpicture}                                                          
\end{document}

enter image description here

share|improve this answer
add comment

This solution proposes finding the intersections and then draw the arrow lines. intersections library from tikz is required. Detail description is commented right after each line of code.

enter image description here

Code

\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}

\begin{document}
    \begin{tikzpicture}[scale=2]
        \clip (-\pgflinewidth,-\pgflinewidth) rectangle (5,3);
        \draw[help lines,->] (0,0) -- (4.2,0);
        \draw[help lines,->] (0,0) -- (0,3);                         % draw axis lines
        \draw[gray,dashed] (0,2) -- (4.2,2);                         % draw asymptote
        \draw[name path=curve,domain=0.1:4.6,very thick,red,->,samples=400] plot ({\x - 0.5},{1/(-\x) + 2} ); 
                                                                     % draw plot
\foreach \l  in {0.25,0.5,...,4}{                                    % locations for vertical lines
\path[name path global=l\l, help lines,->] (\l,0) -- (\l,2);         % draw path
\fill  [name intersections={of=curve and l\l, name=i, total=\t}]     % to find
[red, opacity=1, every node/.style={above left, black, opacity=1}]   % intersections
\foreach \s in {1,...,\t}{(i-\s) circle (0.3pt)};                    % and label it
\draw[->] (\l,0)--(i-1);                                             % then draw arrows
}
\end{tikzpicture}
\end{document}
share|improve this answer
add comment

You can use to[out=70,in=180] magic:

\documentclass[border=2mm]{standalone}
\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}
        \clip (-0.1,-0.1) rectangle (5,3);
        \draw[help lines,->] (0,0) -- (4.2,0);
        \draw[help lines,->] (0,0) -- (0,3);% draw axis lines
        \draw[gray,dashed] (0,2) -- (4.2,2); % draw asymptote
        \draw[very thick,red,->] (0,0) to[out=70, in=180] (5,1.8);% draw plot
    \draw[help lines,->] (1,0) -- (1,1.2);
    \draw[help lines,->] (2,0) -- (2,1.5);
    \draw[help lines,->] (3,0) -- (3,1.65);
    \draw[help lines,->] (4,0) -- (4,1.7);

    % scale to fit marginfigure
\end{tikzpicture}
\end{document}

enter image description here

Adjust the angles and also use `looseness/tension properly to get the desired output as in

\draw[very thick,red,->] (0,0) to[out=70, in=180,looseness=0.9] (5,1.8);
share|improve this answer
add comment

I would go with pgfplots for this. After plotting it you can place coordinates at every position you like to have (I made it manual but you can populate more with foreach list syntax). Then you can draw verticals horizontals with respect to corners or the origin of the plot. To shorten the arrows I used shorten < key. For the asymptote I used an explicit line but you can also use the extra y ticks mechanism.

If you don't want it to start from the actual zero but from the point where it crosses the axis, remove xmin=0 or adjust the domain to start from 0.4.

\documentclass[]{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\begin{document}
\begin{tikzpicture}
    \begin{axis}[axis x line=bottom,axis y line=left,
                 xtick=\empty,ytick=\empty,enlarge y limits={upper,value=0.2},xmin=0,ymin=0,
                 ]
    \addplot[domain=0.1:4.6,very thick,red,->,samples=100] ({\x - 0.4},{1/(-\x) + 2} ) 
    \foreach\t[count=\tx] in{0.95,0.87,...,0.5}{coordinate[pos=\t] (c\tx)};
    \pgfplotsinvokeforeach{1,...,4}{\draw[<-,shorten <=2mm] (c#1) -- (c#1|-{axis cs:0,0});}
    \draw[dashed,blue,ultra thick] (axis cs:0,1.9) 
                                      -- ({axis cs:0,1.9} -| {axis description cs:1,0});
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

share|improve this answer
add comment

Here's a version using Metapost.

enter image description here

Code

\documentclass[border=5mm]{standalone}
\usepackage[shellescape]{gmp}
\begin{document}
\begin{mpost}
    % define suitable a point
    z1 = (233,89);
    % define the path representing the function
    path f; f = origin { dir 75 } .. { dir 2 } z1; 
    % draw the function line with a fat red arrow
    drawarrow f withpen pencircle scaled 1 withcolor .67 red;
    % clip the arrow at the bottom left so it does not stick out below the axes
    clip currentpicture to unitsquare xscaled 1.2x1 yscaled 1.2y1;
    % draw the axes
    drawarrow origin -- (x1,0);
    drawarrow origin -- (0,1.5y1);
    % draw the dashed line
    draw (0,1.05y1) -- (x1,1.05y1) dashed evenly;
    % draw the marker arrows 
    for i=1 upto 4:
       x := 0.95x1*i/4;
       drawarrow (x,0) -- (x,y1) cutafter (f shifted 2 down);
    endfor
\end{mpost}
\end{document}

Notes

  • Metapost lets you define a curved path by specifying the direction at each node in curly braces. So {dir 75} makes the path set off at an angle of 75° above the horizontal.

  • If you define a point using the z$ notation, where $ is any valid suffix, you get x$ and y$ defined for free.

  • The construction p cutafter q returns the path p chopped off after it crosses path q. Here, I have shifted the crossing path down a bit so the arrowheads stay clear of the red line.

  • You need to run this with -shellescape option, as explained in the gmp documentation.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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