4

I can't seem to find a simple example that shows how to control where the end points are of tikz arrows. I see many complicated examples, and I'm sure simple ones exist, but I can't find them. If some kind soul could point me in the right direction (bad pun), I would appreciate it. In the following example, I want the tips of the double arrows to touch the lines.

\documentclass[11pt,letterpaper]{article}
\usepackage{pgfplots}
\usetikzlibrary{shapes.arrows, fadings}

\pgfmathdeclarefunction{std_norm}{1}{%
  \pgfmathparse{1/(sqrt(2*pi))*exp(-((#1)^2)/(2))}%
}

\begin{document}

\begin{center}
  \begin{tikzpicture}[scale=0.6]
    \begin{axis}[ 
        no markers, 
        domain=-4:4, % Only display z values between -4 and 4.
        samples=100, 
        xlabel=\textbf{z},
        every axis x label/.style={at={(axis description cs:1.0, 0.0)}, anchor=west},
        height=5cm, width=12cm,
        xtick=\empty, ytick=\empty,
        enlargelimits=false, 
        clip=false, 
        axis on top=true,
        hide y axis, 
        axis x line*=middle,
        axis line style ={thick,latex-latex}
      ]

        \addplot [very thick,draw=cyan!50!black] {std_norm(x)};

        \draw [thick] (axis cs:-1.75,0) -- (axis cs:-1.75,{std_norm(-1.75)});
        \draw [thick] (axis cs:1.75,0) -- (axis cs:1.75,{std_norm(1.75)});

        \draw [thick] (axis cs:-1.75,0.53) -- (axis cs:-1.75,{std_norm(-1.75)+0.03});
        \draw [thick] (axis cs:1.75,0.53) -- (axis cs:1.75,{std_norm(1.75)+0.03});

        \node [draw=gray, 
          left color=white,
          right color=green!30,
          double arrow,
          minimum height=4cm,
          minimum width=1cm,
          double arrow head extend=0.05cm
        ] at (axis cs:0.0,0.5) {};

        \draw node at (axis cs:0, 0.5) {Confidence Interval};

    \end{axis}
  \end{tikzpicture}
\end{center}

\end{document}

1 Answers1

4

One of several options is to use the calc library. This allows us to measure distances between nodes/coordinates with the piec

let \p1=($(R)-(L)$) in

In general the distance will be \n1={veclen(\x1,\y1} but here the line is horizontal so it is just \x1.

\documentclass[11pt,letterpaper]{article}
\usepackage{pgfplots}
\usetikzlibrary{shapes.arrows, fadings,calc}

\pgfmathdeclarefunction{std_norm}{1}{%
  \pgfmathparse{1/(sqrt(2*pi))*exp(-((#1)^2)/(2))}%
}

\begin{document}

\begin{center}
  \begin{tikzpicture}[scale=0.6]
    \begin{axis}[ 
        no markers, 
        domain=-4:4, % Only display z values between -4 and 4.
        samples=100, 
        xlabel=\textbf{z},
        every axis x label/.style={at={(axis description cs:1.0, 0.0)}, anchor=west},
        height=5cm, width=12cm,
        xtick=\empty, ytick=\empty,
        enlargelimits=false, 
        clip=false, 
        axis on top=true,
        hide y axis, 
        axis x line*=middle,
        axis line style ={thick,latex-latex}
      ]

        \addplot [very thick,draw=cyan!50!black] {std_norm(x)};

        \draw [thick] (axis cs:-1.75,0) -- (axis cs:-1.75,{std_norm(-1.75)})
        coordinate[pos=1] (L);
        \draw [thick] (axis cs:1.75,0) -- (axis cs:1.75,{std_norm(1.75)})
        coordinate[pos=1] (R);

        \draw [thick] (axis cs:-1.75,0.53) -- (axis cs:-1.75,{std_norm(-1.75)+0.03});
        \draw [thick] (axis cs:1.75,0.53) -- (axis cs:1.75,{std_norm(1.75)+0.03});

        \path let \p1=($(R)-(L)$) in (axis cs:0, 0.5)
          node [draw=gray, 
          left color=white,
          right color=green!30,
          double arrow,
          minimum height=\x1,
          minimum width=1cm,
          double arrow head extend=0.05cm,inner xsep=0pt
        ] {Confidence Interval};

    \end{axis}
  \end{tikzpicture}
\end{center}

\end{document}

enter image description here

Other options worth trying out is to use fit.

  • An advanced version thereof can be found under this post. It also rotates the arrow and so on, but here this is not necessary. –  Apr 13 '20 at 04:42
  • Thanks. This definitely solves the problem as posed. So there is no way using library primitives (in other words, without having to define my own command like in your reference post) to draw something from (x1, y1) to (x2, y2)? – Christopher Donham Apr 13 '20 at 11:22
  • @ChristopherDonham Obviously, I cannot exclude that there is a library. However, I believe that there is no official library that ships with TikZ that has this functionality. I think that Torbjørn's style is very robust and might well be more robust than stuff from random libraries that you could find in the internet. It could be that there is something along those lines in tzk-euclide, if so, it will (also) have very hight quality. –  Apr 13 '20 at 11:35
  • Thanks again. I had found the post you reference, I just had a hard time believing I had to haul out arctan to connect two points... – Christopher Donham Apr 13 '20 at 11:59
  • @ChristopherDonham This is a standard way of measuring the slope. It might well be one of the simplest ways. –  Apr 13 '20 at 12:03
  • Agreed, as a mathematics tool (my issue isn't the geometry/math, its making latex do the geometry/math). I just thought that what I was asking was common enough that there would be tools around that simplified the process, since latex has a library for just about everything else. :-) – Christopher Donham Apr 13 '20 at 13:07
  • @ChristopherDonham I think there was a time when TikZ created libraries for many things (angles, the through library etc.), however now since TikZ is mainly maintained the focus is more on fixing issues. However, if you post a feature request at https://github.com/pgf-tikz/pgf/issues then Henri et al. will look at it and there could be a chance that you are successful. I could imagine that more users would like to have such features. –  Apr 13 '20 at 13:20