# How to refine this tikz diagram?

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}


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")?

## 5 Answers

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}


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}


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.

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}


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}


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}


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);


Here's a version using Metapost.

## 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.