# Custom arrow tip with arrows.meta TikZ library

In the spirit of this question, how do I make a custom arrow tip using the new arrows.meta TikZ library? I would like to make a semicircular tip that accepts the open option, ideally, and perhaps other options like length (or radius or whatever the Circle arrow tip accepts).

• A semicircular tip (as Arc Barb[]) is already opened... Feb 8, 2014 at 8:56
• @PaulGaborit: Arc Barb extends back onto the line. I'd like it to like this ------------D with the perpendicular edge and the open space. Feb 8, 2014 at 9:45
• Please don't edit questions to include answers. Either add an answer of your own or edit an existing one. The question space should be reserved for ..., well, questions, really.
– cfr
Aug 1, 2016 at 0:20

The documentation for declaring new arrow tips is fairly comprehensive, but there appear to some errors in the examples. I'm not an expert on the arrows.meta stuff but the following appears to be the minimal requirements to get things started:

\documentclass[tikz,border=0.25cm]{standalone}
\usetikzlibrary{arrows.meta}
\makeatletter
\pgfdeclarearrow{
name=semicircle,
parameters={
\the\pgfarrowlength,%
\ifpgfarrowopen o\fi%
},
setup code={
% The line end value:
\pgfarrowssettipend{0pt}
\pgf@x=-.25\pgfarrowlength
% The hull point:
\pgfutil@tempdima=0.25\pgfarrowlength
\pgfarrowssetlineend{\pgf@x}
\pgfarrowssetvisualbackend{-.25\pgfarrowlength}
\pgfarrowssetbackend{-.75\pgfarrowlength}
\pgfarrowssavethe\pgfarrowlength
\pgfarrowlinewidth=\pgflinewidth
\pgfarrowssavethe\pgfarrowlinewidth
\pgfarrowshullpoint{0pt}{0pt}
\pgfarrowshullpoint{0pt}{-\pgfutil@tempdima}
\pgfarrowshullpoint{0pt}{\pgfutil@tempdima}
},
drawing code={
\pgfpathmoveto{\pgfpoint{-.25\pgfarrowlength-.5\pgflinewidth}{.25\pgfarrowlength}}
\pgfpathlineto{\pgfpoint{-.25\pgfarrowlength-.5\pgflinewidth}{-.25\pgfarrowlength}}
\pgfpatharc{-90}{90}{0.25\pgfarrowlength}
\pgfpathclose
\ifpgfarrowopen\pgfusepathqstroke\else\ifdim\pgfarrowlinewidth>0pt\pgfusepathqfillstroke\else\pgfusepathqfill\fi\fi
},
defaults={ length=10pt }
}

\begin{document}

\begin{tikzpicture}
\draw [help lines] grid (3,2);
\draw [semicircle-{semicircle[open]}] (0,0) -- (3,2);
\draw [very thick, {semicircle[length=40pt,open]}-{semicircle[length=20pt]}]
(0,2) -- (3,0);
\end{tikzpicture}

\end{document}


• Thank you. Is there any way to make it so that the border is unnecessary? The other arrow tips automatically extend the border. No problem if that's difficult, but it's definitely nice to have :) Feb 9, 2014 at 13:28
• @NeilG just add \pgfarrowshullpoint{0pt}{0pt} \pgfarrowshullpoint{0pt}{-.25\pgfarrowlength} \pgfarrowshullpoint{0pt}{.25\pgfarrowlength} to the setup code. The documentation explains what they do. Feb 9, 2014 at 14:07
• Hmm, I need to add 0.5 \pgflinewidth I believe. How do I do that? Feb 9, 2014 at 14:39
• You probably need to use a temporary dimension to do the calculation, for example, \pgfutil@tempdima=0.25\pgfarrowlength \advance\pgfutil@tempdima by.5\pgflinewidth \pgfarrowshullpoint{\pgfutil@tempdima}{\pgfutil@tempdima}. Don't forget to change the catcode of @ though. Feb 10, 2014 at 7:15
• Thank you. I don't know what "changing the catcode of @" means though :( Feb 10, 2014 at 7:15

I made some improvements to Mark's answer so that semicircle is totally consistent with Circle.

\pgfdeclarearrow{
name=semicircle,
defaults={
length  = +2.39365pt +3.191538,
line width = +0pt 1 1,
},
setup code={
% Cap the line width at 1/2th of the length
\pgf@x.5\pgfarrowlength
\ifdim\pgf@x<\pgfarrowlinewidth
\pgfarrowlinewidth\pgf@x
\fi
\ifpgfarrowreversed
\else
\pgfarrowssetlineend{.5\pgfarrowlinewidth}
\fi
\pgfarrowssettipend{\pgfutil@tempdimb}
% The hull:
\pgfarrowsupperhullpoint{0pt}{.5\pgfarrowlength}
\pgfarrowsupperhullpoint{0.20710678118\pgfarrowlength}{.5\pgfarrowlength}
\pgfarrowsupperhullpoint{0.5\pgfarrowlength}{0.20710678118\pgfarrowlength}
% The following are needed in the code:
\pgfarrowssavethe\pgfarrowlinewidth
\pgfarrowssavethe\pgfarrowlength
\pgfarrowssavethe\pgfutil@tempdima
\pgfarrowssavethe\pgfutil@tempdimb
},
drawing code = {
\pgfsetdash{}{+0pt}
\ifpgfarrowroundjoin\pgfsetroundjoin\else\pgfsetmiterjoin\fi
\ifdim\pgfarrowlinewidth=\pgflinewidth\else\pgfsetlinewidth{+\pgfarrowlinewidth}\fi
\pgfpathmoveto{\pgfpoint{.5\pgfarrowlinewidth}{\pgfutil@tempdima}}
\pgfpathlineto{\pgfpoint{.5\pgfarrowlinewidth}{-\pgfutil@tempdima}}
\pgfpatharc{-90}{90}{\pgfutil@tempdima}
\pgfpathclose
\ifpgfarrowopen\pgfusepathqstroke\else\ifdim\pgfarrowlinewidth>0pt\pgfusepathqfillstroke\else\pgfusepathqfill\fi\fi
},
parameters = {
\the\pgfarrowlinewidth,%
\the\pgfarrowlength,%
\ifpgfarrowopen o\fi%
\ifpgfarrowroundjoin j\fi%
},
}