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).
Asked
Active
Viewed 6,229 times
4
2 Answers
8
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
\advance\pgf@x by-.5\pgflinewidth
% The hull point:
\pgfutil@tempdima=0.25\pgfarrowlength
\advance\pgfutil@tempdima by.5\pgflinewidth
\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}

Neil G
- 17,947
Mark Wibrow
- 70,437
-
Thank you. Is there any way to make it so that the
borderis unnecessary? The other arrow tips automatically extend the border. No problem if that's difficult, but it's definitely nice to have :) – Neil G Feb 09 '14 at 13:28 -
@NeilG just add
\pgfarrowshullpoint{0pt}{0pt} \pgfarrowshullpoint{0pt}{-.25\pgfarrowlength} \pgfarrowshullpoint{0pt}{.25\pgfarrowlength}to thesetup code. The documentation explains what they do. – Mark Wibrow Feb 09 '14 at 14:07 -
-
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. – Mark Wibrow Feb 10 '14 at 07:15 -
Thank you. I don't know what "changing the catcode of @" means though :( – Neil G Feb 10 '14 at 07:15
-
I incorporated your suggestions into your answer for the benefit of others. Thanks again for making this solution perfect. – Neil G Feb 10 '14 at 07:49
1
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
\pgfutil@tempdima.5\pgfarrowlength\advance\pgfutil@tempdima by-.5\pgfarrowlinewidth
\pgfutil@tempdimb.5\pgfarrowlength\advance\pgfutil@tempdimb by.5\pgfarrowlinewidth
\ifpgfarrowreversed
\pgfarrowssetlineend{.5\pgfarrowlength\advance\pgf@x by-.5\pgfarrowlinewidth}
\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%
},
}
Neil G
- 17,947
Arc Barb[]) is already opened... – Paul Gaborit Feb 08 '14 at 08:56Arc Barbextends back onto the line. I'd like it to like this------------Dwith the perpendicular edge and the open space. – Neil G Feb 08 '14 at 09:45