TikZ is great at drawing diagrams but there is one feature which I find quite annoying and that's the fact that the default arrowhead provided by TikZ does not necessarily respect the math mode in whichever font you are using. I know that the TikZ library arrows lets you chose between several different types of arrowheads but none of which offers the same arrowhead as the one drawn in math mode.

When drawing a diagram in TikZ I want the arrowheads to match arrowheads drawn by commands like \to or \xrightarrow{foo}.

Does anyone know how to fix this?

As suggested by Andrew Stacey in the comments below, I should really provide you with an example of what I am talking about.

Using the following code:

An arrow tip produced by TikZ:
\begin{tikzpicture}
\node (A) at (0,0){$A$};
\node (B) at (1,0){$B$.};

\path (A) edge[->] node[midway,above]{$f$} (B);
\end{tikzpicture}

An arrow tip produced by \texttt{amsmath}: $A \xrightarrow{f} B$.


I get the following output:

I want these two arrowheads to be identical.

-
Isn't this the to arrow tip? (See Section 15.3.4 of the manual.) If not, could you post code and a screenshot showing the arrow that you'd like (and, for comparison, what TikZ produces with the to tip.) –  Loop Space Dec 6 '11 at 18:25
@AndrewStacey Isn't >=to the default arrow tip? In any case it doesn't produce the desired result. Thanks for the tip (no pun) on including examples. They will be posted shortly. –  Marius Dec 6 '11 at 18:30
@Marius The look for example of \xrightarrow{foo} depends of the font used, you can try with fourier and with lmodern and see the difference. A good question is : "how to draw arrows in math text like arrows used in tikz" ? Your problem is very complex because you need to create your personal arrow that depends of your font ! –  Alain Matthes Dec 6 '11 at 18:42
Maybe it would be easier the other way round: redefine \to so that it draws a TikZ arrow. Though, if you have many arrows, this might seriously impact compilation speed. –  Caramdir Dec 7 '11 at 0:12
@Caramdir: That's my current "solution" when I want a consistent look for arrows throughout my document. I have that many pictures already that scattering a few little \tikz \draw[->] (0,0) -- +(1,0);s around doesn't affect the speed that much. –  Loop Space Dec 7 '11 at 8:29

I have prepared a comprehensive set of arrow tips matching the Computer Modern arrows, and posted it on CTAN (along with some discussion on this issue and some more stuff that might be useful for mathematical diagrams).

My arrow tips are not as precise as Christian's, but they are about as good as one can get using a few line strokes (as opposed to filling a region), and in practice I find the result good enough.

Here is a comparison (Computer Modern above, tikz-drawn arrow below).

\documentclass{article}
\usepackage{tikz,tikz-cd,graphicx}
\begin{document}
\noindent\hspace{2mm} \scalebox{20}{$\hookrightarrow$}
\vspace{2cm}
\tikz \draw[line width=8pt,cm right hook-cm to] (0,0) to (7,0);
\end{document}


-
+1 and congrats on the CTAN package! Could you add the source which produced your image? –  doncherry Mar 18 '12 at 15:53
I have included your code into your answer. I hope you don't mind. Thanks for the nice package by the way. –  percusse Mar 18 '12 at 16:10
+1 Absolute fantastic package. –  Yiannis Lazarides Mar 18 '12 at 17:53

Here is another way to draw arrowheads that look like the Computer Modern ones, by using a thin outline and filling it in. The problem with this solution is that, when printed at 10 points, the arrowhead becomes almost invisible. So please do not use this code before someone finds a workaround. On screen, the result looks fine, of course; an example is included below.

Here is the code:

    \usepackage{tikz}
\usetikzlibrary{matrix,arrows}
\newlength{\myarrowsize}
\newlength{\myoldlinewidth}

\pgfarrowsdeclare{myto}{myto}{
\pgfsetdash{}{0pt}
\pgfsetbeveljoin
\pgfsetroundcap
\setlength{\myarrowsize}{0.6pt}
\pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth}
\pgfarrowsrightextend{.7\pgflinewidth}
}{
\setlength{\myarrowsize}{0.6pt}
\setlength{\myoldlinewidth}{\pgflinewidth}
\pgfsetroundjoin
% draw top half
\pgfsetlinewidth{0.0001pt}
\pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
\pgfpatharc{0}{70}{0.14\myarrowsize}
\pgfpatharc{-110}{-169.5}{4\myarrowsize}
\pgfpatharc{10.5}{189}{0.25\myarrowsize and 0.12\myarrowsize}
\pgfpatharc{-170}{-119.5}{4.48\myarrowsize}
% draw bottom half
\pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
\pgfpatharc{0}{-70}{0.14\myarrowsize}
\pgfpatharc{110}{169.5}{4\myarrowsize}
\pgfpatharc{-10.5}{-189}{0.25\myarrowsize and 0.12\myarrowsize}
\pgfpatharc{170}{119.5}{4.48\myarrowsize}
\pgfpathclose
\pgfsetstrokeopacity{0.25}
\pgfusepathqfillstroke
}

\pgfarrowsdeclare{myonto}{myonto}{
\pgfsetdash{}{0pt}
\pgfsetbeveljoin
\pgfsetroundcap
\setlength{\myarrowsize}{0.6pt}
\pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth}
\pgfarrowsrightextend{.7\pgflinewidth}
}{
\setlength{\myarrowsize}{0.6pt}
\setlength{\myoldlinewidth}{\pgflinewidth}
\pgfsetroundjoin
% draw top half
\pgfsetlinewidth{0.0001pt}
\pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
\pgfpatharc{0}{70}{0.14\myarrowsize}
\pgfpatharc{-110}{-169.5}{4\myarrowsize}
\pgfpatharc{10.5}{189}{0.25\myarrowsize and 0.12\myarrowsize}
\pgfpatharc{-170}{-119.5}{4.48\myarrowsize}
\pgfpathlineto{\pgfpoint{0.43\myarrowsize-0.3em}{0}}
\pgfpatharc{0}{70}{0.14\myarrowsize}
\pgfpatharc{-110}{-169.5}{4\myarrowsize}
\pgfpatharc{10.5}{189}{0.25\myarrowsize and 0.12\myarrowsize}
\pgfpatharc{-170}{-119.5}{4.48\myarrowsize}
% draw bottom half
\pgfpathmoveto{\pgfpoint{0.43\myarrowsize}{0}}
\pgfpatharc{0}{-70}{0.14\myarrowsize}
\pgfpatharc{110}{169.5}{4\myarrowsize}
\pgfpatharc{-10.5}{-189}{0.25\myarrowsize and 0.12\myarrowsize}
\pgfpatharc{170}{119.5}{4.48\myarrowsize}
\pgfpathlineto{\pgfpoint{0.43\myarrowsize-0.3em}{0}}
\pgfpatharc{0}{-70}{0.14\myarrowsize}
\pgfpatharc{110}{169.5}{4\myarrowsize}
\pgfpatharc{-10.5}{-189}{0.25\myarrowsize and 0.12\myarrowsize}
\pgfpatharc{170}{119.5}{4.48\myarrowsize}
\pgfpathclose
\pgfsetstrokeopacity{0.25}
\pgfusepathqfillstroke
}

\pgfarrowsdeclare{myhook}{myhook}{
\setlength{\myarrowsize}{0.6pt}
\pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth}
\pgfarrowsrightextend{.7\pgflinewidth}
}{
\setlength{\myarrowsize}{0.6pt}
\pgfsetdash{}{+0pt}
\pgfsetroundcap
\pgfpathmoveto{\pgfqpoint{0pt}{-4.667\pgflinewidth}}
\pgfpathcurveto
{\pgfqpoint{4\pgflinewidth}{-4.667\pgflinewidth}}
{\pgfqpoint{4\pgflinewidth}{0pt}}
{\pgfpointorigin}
\pgfusepathqstroke
}

-
You could also add this information to your other answer instead of posting a new one. –  N.N. Jan 18 '12 at 14:28

This question on meta arrow tips points to the manual that says that arrow tips should not normally scale in proportion to the supporting line width. Here I have defined a -my to arrow style which is a tweaked version of the -bad to arrow style in the above linked question. This is about as close as I can get to match the one you provided.

## Notes:

• Since this is adapted from a version that scales with line widths, this is not going to produce very good results with other line widths (in fact it is quite horrible). I attempted to get the line width from the tikz version as close to the one from amsmath.

## Code:

\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}

\pgfarrowsdeclare{my to}{my to}
{
\pgfarrowsleftextend{-2\pgflinewidth}
\pgfarrowsrightextend{\pgflinewidth}
}
{
\pgfsetlinewidth{0.8\pgflinewidth}
\pgfsetdash{}{0pt}
\pgfsetroundcap
\pgfsetroundjoin
\pgfpathmoveto{\pgfpoint{-5.5\pgflinewidth}{7.5\pgflinewidth}}
\pgfpathcurveto
{\pgfpoint{-4.0\pgflinewidth}{0.1\pgflinewidth}}
{\pgfpoint{0pt}{0.25\pgflinewidth}}
{\pgfpoint{0.75\pgflinewidth}{0pt}}
\pgfpathcurveto
{\pgfpoint{0pt}{-0.25\pgflinewidth}}
{\pgfpoint{-4.0\pgflinewidth}{-0.1\pgflinewidth}}
{\pgfpoint{-5.5\pgflinewidth}{-7.5\pgflinewidth}}
\pgfusepathqstroke
}

\begin{document}
\begin{tikzpicture}
\node (A) at (0,0){$A$};
\node (B) at (0.82,0){$B$};
\path (A) edge[-my to,line width=0.42pt]  (B);
\end{tikzpicture}

\hspace{0.33em}$A \xrightarrow{} B$
\end{document}

-
if you use usepackage{fourier} you need to modify your code... I don't know exactly the number of math fonts but you have a lot of work ! –  Alain Matthes Dec 6 '11 at 20:59
@Altermundus: Yep, this is by no means a complete solution. More of a "hack" that works in this one case. –  Peter Grill Dec 6 '11 at 21:02

The problem appears to be to get TikZ to copy, by drawing, the shape of the arrow that is in the current font. One problem with this is that when the font changes, TikZ has to learn how to draw a new arrow. An alternative solution is simply for TikZ to use that arrow directly without copying it into "low level" drawing commands. This can be done by "marking" the end of the line with the \to arrow. It needs a little adjustment to ensure that everything lines up, and that adjustment might need adjusting if the font changes, but that's an order of magnitude easier than reconstructing the drawing commands for the arrowhead!

Here's some code that does this:

\documentclass{article}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}

\begin{document}
\begin{gather*}
A \xrightarrow{\hspace*{1cm}} B \\
%
A \mathrel{\tikz[baseline=0pt] \draw[postaction={decorate,decoration={markings,mark=at position 1 with {\node[yshift=-.75pt,inner sep=0pt] {$$\to$$};}}}] (0,.5ex) -- ++(1,0);} B
\end{gather*}
\end{document}


And here's the result:

Hmm, that picture shows one of the problems with this method: the arrowhead comes from the font and is treated as a character, whereas the line is a graphic element. The two are treated differently when rendered to a PNG. Here's a screenshot with the PDF on the bottom and the PNG on the top. The PNG was created from that PDF.

-

Here is the code that I am using; it reproduces the Computer Modern arrowheads fairly well. In particular, the tip is thinner and less rounded than what one gets with the method of Section 74 of the manual. The idea is to use several arcs (drawn with half the thickness) to create an outline, and then fill it in.

Here is an example of the result: the black arrow is the Computer Modern one (produced with \longrightarrow), the red arrow is produced by the code below.

I am not enough of an expert to make the size of the arrowhead adjust to the font size etc. A second problem is that, at low zoom levels or in print, the lines seem to be slightly too thick. Since the code does not work with \pgfdeclarearrowsdouble, I have included code for \into and \onto arrows as well.

    \usepackage{tikz}
\usetikzlibrary{matrix,arrows}
\newlength{\myarrowsize}

% Version similar to Computer Modern
\pgfarrowsdeclare{cmto}{cmto}{
\pgfsetdash{}{0pt}
\pgfsetbeveljoin
\pgfsetroundcap
\setlength{\myarrowsize}{0.6pt}
\pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth}
\pgfarrowsrightextend{.8\pgflinewidth}
}{
\setlength{\myarrowsize}{0.6pt}
\pgfsetlinewidth{0.5\pgflinewidth}
\pgfsetroundjoin
% top half
\pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
\pgfpatharc{-109}{-170}{4\myarrowsize}
\pgfpatharc{10}{189}{0.58\pgflinewidth and 0.2\pgflinewidth}
\pgfpatharc{-170}{-115}{4\myarrowsize+\pgflinewidth}
\pgfpathclose
\pgfusepathqfillstroke
% bottom half
\pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
\pgfpatharc{109}{170}{4\myarrowsize}
\pgfpatharc{-10}{-189}{0.58\pgflinewidth and 0.2\pgflinewidth}
\pgfpatharc{170}{115}{4\myarrowsize+\pgflinewidth}
\pgfpathclose
\pgfusepathqfillstroke
% Change line width back
\pgfsetlinewidth{2\pgflinewidth}
}

\pgfarrowsdeclare{cmonto}{cmonto}{
\pgfsetdash{}{0pt}
\pgfsetbeveljoin
\pgfsetroundcap
\setlength{\myarrowsize}{0.6pt}
\pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth}
\pgfarrowsrightextend{.8\pgflinewidth}
}{
\setlength{\myarrowsize}{0.6pt}
\pgfsetlinewidth{0.5\pgflinewidth}
\pgfsetroundjoin
% top half
\pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
\pgfpatharc{-109}{-170}{4\myarrowsize}
\pgfpatharc{10}{189}{0.58\pgflinewidth and 0.2\pgflinewidth}
\pgfpatharc{-170}{-115}{4\myarrowsize+\pgflinewidth}
\pgfpathclose
\pgfusepathqfillstroke
% bottom half
\pgfpathmoveto{\pgfpoint{1.5\pgflinewidth}{0}}
\pgfpatharc{109}{170}{4\myarrowsize}
\pgfpatharc{-10}{-189}{0.58\pgflinewidth and 0.2\pgflinewidth}
\pgfpatharc{170}{115}{4\myarrowsize+\pgflinewidth}
\pgfpathclose
\pgfusepathqfillstroke
% top half (2)
\pgfpathmoveto{\pgfpoint{1.5\pgflinewidth-0.3em}{0}}
\pgfpatharc{-109}{-170}{4\myarrowsize}
\pgfpatharc{10}{189}{0.58\pgflinewidth and 0.2\pgflinewidth}
\pgfpatharc{-170}{-115}{4\myarrowsize+\pgflinewidth}
\pgfpathclose
\pgfusepathqfillstroke
% bottom half (2)
\pgfpathmoveto{\pgfpoint{1.5\pgflinewidth-0.3em}{0}}
\pgfpatharc{109}{170}{4\myarrowsize}
\pgfpatharc{-10}{-189}{0.58\pgflinewidth and 0.2\pgflinewidth}
\pgfpatharc{170}{115}{4\myarrowsize+\pgflinewidth}
\pgfpathclose
\pgfusepathqfillstroke
% Change line width back
\pgfsetlinewidth{2\pgflinewidth}
}

\pgfarrowsdeclare{cmhook}{cmhook}{
\pgfsetdash{}{0pt}
\pgfsetbeveljoin
\pgfsetroundcap
\setlength{\myarrowsize}{0.6pt}
\pgfarrowsleftextend{-4\myarrowsize-.5\pgflinewidth}
\pgfarrowsrightextend{.8\pgflinewidth}
}{
\setlength{\myarrowsize}{0.6pt}