8

I tried making an inverted diamond arrow based on the Diamond arrow included in TikZ, but I'm having a lot of trouble getting the arrow tip in the right place. Here's my code. All I changed from the Diamond arrow code is the drawing code.

\documentclass[tikz,border=0.25cm]{standalone}
\usetikzlibrary{arrows.meta}
\makeatletter
%\input{tikz_tips.tex}
\pgfdeclarearrow{
  name = InvertedKite,
  defaults = {
    length  = +3.6pt +5.4,
    width'  = +0pt +0.5,
    inset'  = +0pt 0.25,
    line width = +0pt 1 1,
  },
  setup code = {
    % Cap the line width at 1/4th of the length
    \pgf@x.4\pgfarrowlength
    \ifdim\pgf@x<\pgfarrowlinewidth
      \pgfarrowlinewidth\pgf@x
    \fi
    \pgf@x.4\pgfarrowwidth
    \ifdim\pgf@x<\pgfarrowlinewidth
      \pgfarrowlinewidth\pgf@x
    \fi
    % Compute front miter length:
    \pgf@xa\pgfarrowlength%
    \advance\pgf@xa by-\pgfarrowinset%
    \pgfmathdivide@\pgf@xa\pgfarrowwidth%
    \let\pgf@temp@quot\pgfmathresult%
    \pgf@x\pgfmathresult pt%
    \pgf@x\pgfmathresult\pgf@x%
    \pgf@x4\pgf@x%
    \advance\pgf@x by1pt%
    \pgfmathsqrt@\pgf@x%
    \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter
    \pgf@xc.5\pgf@xc
    \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter
    % Compute back miter length:
    \pgfmathdivide@\pgfarrowinset\pgfarrowwidth%
    \let\pgf@temp@quot\pgfmathresult%
    \pgf@x\pgfmathresult pt%
    \pgf@x\pgfmathresult\pgf@x%
    \pgf@x4\pgf@x%
    \advance\pgf@x by1pt%
    \pgfmathsqrt@\pgf@x%
    \pgf@yc\pgfmathresult\pgfarrowlinewidth% yc is back miter
    \pgf@yc.5\pgf@yc
    \pgf@ya\pgf@temp@quot\pgfarrowlinewidth% ya is extra harpoon miter
    % Compute top miter length:
    {%
      \pgfutil@tempdimb.5\pgfarrowwidth%
      \pgfutil@tempdima\pgfarrowlength\advance\pgfutil@tempdima by-\pgfarrowinset%
      \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfutil@tempdima}{\pgfmath@tonumber\pgfutil@tempdimb}%
      \pgf@yb\pgfmathresult pt%
      \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfarrowinset}{\pgfmath@tonumber\pgfutil@tempdimb}%
      \pgf@ya\pgfmathresult pt%
      \advance\pgf@yb by\pgf@ya%
      \pgf@yb.5\pgf@yb% half angle in yb
      \ifdim\pgf@yb=45pt%
        \def\pgfmathresult{1.414213}%
      \else%
        \pgfmathsin@{\pgf@yb}%
        \pgfmathreciprocal@{\pgfmathresult}%
      \fi%
      \pgf@yc\pgfmathresult\pgfarrowlinewidth%
      \pgf@yc.5\pgf@yc%
      \pgf@ya-\pgf@ya%
      \advance\pgf@ya by-90pt%
      \advance\pgf@ya by\pgf@yb%
      \pgfmathsincos@{\pgf@ya}%
      \pgf@xb\pgfmathresultx\pgf@yc% ya is the back miter
      \pgf@yb\pgfmathresulty\pgf@yc% yb is the top miter
      \expandafter\expandafter\expandafter%
    }\expandafter\expandafter\expandafter\pgf@xb\expandafter\the\expandafter\pgf@xb\expandafter\pgf@yb\the\pgf@yb%
    % Inner length (pgfutil@tempdima) is now arrowlength - front miter - back miter
    \pgfutil@tempdima\pgfarrowlength%
    \advance\pgfutil@tempdima by-\pgf@xc%
    \pgfutil@tempdimb.5\pgfarrowwidth%
    \advance\pgfutil@tempdimb by\pgf@yb%
    % Set back end
    \ifpgfarrowroundjoin
      \pgfarrowssetbackend{\pgf@ya\advance\pgf@x by-.5\pgfarrowlinewidth}
    \else
      \pgfarrowssetbackend{0pt}
    \fi
    % harpoon miter correction
    \ifpgfarrowreversed
      \pgfarrowssetlineend{\pgfutil@tempdima\advance\pgf@x by-\pgflinewidth\advance\pgf@x by\pgfarrowlinewidth}
    \else
      \pgfarrowssetlineend{\pgf@yc\advance\pgf@x by\pgflinewidth\advance\pgf@x by-\pgfarrowlinewidth}
    \fi
    \ifpgfarrowroundjoin
      \pgfarrowssettipend{\pgfutil@tempdima\advance\pgf@x by.5\pgfarrowlinewidth}
    \else
      \pgfarrowssettipend{\pgfarrowlength\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi}
    \fi
    % The hull:
    \pgfarrowshullpoint{\pgfarrowlength\ifpgfarrowroundjoin\else\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi\fi}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else0pt\fi}%
    \pgfarrowsupperhullpoint{\pgfarrowinset}{.5\pgfarrowwidth}%
    \pgfarrowshullpoint{0pt}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else0pt\fi}%
    % Adjust the inset:
    \advance\pgfarrowinset by\pgf@xb%
    % The following are needed in the code:
    \pgfarrowssavethe\pgfutil@tempdima
    \pgfarrowssavethe\pgfutil@tempdimb
    \pgfarrowssavethe\pgfarrowlinewidth
    \pgfarrowssavethe\pgf@yc
    \pgfarrowssavethe\pgfarrowinset
  },
  drawing code = {
    \pgfsetdash{}{+0pt}
    \ifpgfarrowroundjoin\pgfsetroundjoin\else\pgfsetmiterjoin\fi
    \ifdim\pgfarrowlinewidth=\pgflinewidth\else\pgfsetlinewidth{\pgfarrowlinewidth}\fi
    \pgfpathmoveto{\pgfqpoint{\pgf@yc}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{0pt}}
    \ifpgfarrowharpoon \else
    \pgfpathlineto{\pgfqpoint{\pgfutil@tempdima}{-\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{-\pgfutil@tempdimb}}
    \fi
    \pgfpathclose
    \ifpgfarrowopen\pgfusepathqstroke\else\ifdim\pgfarrowlinewidth>0pt\pgfusepathqfillstroke\else\pgfusepathqfill\fi\fi
  },
  parameters = {
    \the\pgfarrowlinewidth,%
    \the\pgfarrowlength,%
    \the\pgfarrowwidth,%
    \the\pgfarrowinset,%
    \ifpgfarrowharpoon h\fi%
    \ifpgfarrowopen o\fi%
    \ifpgfarrowroundjoin j\fi%
  },
}
\tikzset{
  InvertedDiamond/.tip={InvertedKite[inset'=0pt 0.5]},
}
\begin{document}
\begin{tikzpicture}
\draw [help lines, step=0.5cm] grid (6,2);
\draw [ultra thick, {Diamond[open, length=2cm, line width=6pt]}-{InvertedDiamond[red, open, length=2cm, line width=6pt]}] (0,1) -- (6,1);
\end{tikzpicture}

\end{document}

The tip of the arrow is too far forward, and looking closely, the top and bottom of the arrow are maybe half a point too far from the bounding help lines.

enter image description here

2

The best I could do:

\documentclass[tikz]{standalone}
\usetikzlibrary{arrows.meta}
\pgfdeclarearrow{
  name = InvertedKite,
  defaults = {
    length  = +3.6pt +5.4,
    width'  = +0pt +0.5,
    inset'  = +0pt 0.25,
    line width = +0pt 1 1,
  },
  setup code = {
    % Cap the line width at 1/4th of the length
    \pgf@x.4\pgfarrowlength
    \ifdim\pgf@x<\pgfarrowlinewidth
      \pgfarrowlinewidth\pgf@x
    \fi
    \pgf@x.4\pgfarrowwidth
    \ifdim\pgf@x<\pgfarrowlinewidth
      \pgfarrowlinewidth\pgf@x
    \fi
    % Compute front miter length:
    \pgf@xa\pgfarrowlength%
    \advance\pgf@xa by-\pgfarrowinset%
    \pgfmathdivide@\pgf@xa\pgfarrowwidth%
    \let\pgf@temp@quot\pgfmathresult%
    \pgf@x\pgfmathresult pt%
    \pgf@x\pgfmathresult\pgf@x%
    \pgf@x4\pgf@x%
    \advance\pgf@x by1pt%
    \pgfmathsqrt@\pgf@x%
    \pgf@xc\pgfmathresult\pgfarrowlinewidth% xc is front miter
    \pgf@xc.5\pgf@xc
    \pgf@xa\pgf@temp@quot\pgfarrowlinewidth% xa is extra harpoon miter
    % Compute back miter length:
    \pgfmathdivide@\pgfarrowinset\pgfarrowwidth%
    \let\pgf@temp@quot\pgfmathresult%
    \pgf@x\pgfmathresult pt%
    \pgf@x\pgfmathresult\pgf@x%
    \pgf@x4\pgf@x%
    \advance\pgf@x by1pt%
    \pgfmathsqrt@\pgf@x%
    \pgf@yc\pgfmathresult\pgfarrowlinewidth% yc is back miter
    \pgf@yc.5\pgf@yc
    \pgf@ya\pgf@temp@quot\pgfarrowlinewidth% ya is extra harpoon miter
    % Compute top miter length:
    {%
      \pgfutil@tempdimb.5\pgfarrowwidth%
      \pgfutil@tempdima\pgfarrowlength\advance\pgfutil@tempdima by-\pgfarrowinset%
      \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfutil@tempdima}{\pgfmath@tonumber\pgfutil@tempdimb}%
      \pgf@yb\pgfmathresult pt%
      \csname pgfmathatan2@\endcsname{\pgfmath@tonumber\pgfarrowinset}{\pgfmath@tonumber\pgfutil@tempdimb}%
      \pgf@ya\pgfmathresult pt%
      \advance\pgf@yb by\pgf@ya%
      \pgf@yb.5\pgf@yb% half angle in yb
      \ifdim\pgf@yb=45pt%
        \def\pgfmathresult{1.414213}%
      \else%
        \pgfmathsin@{\pgf@yb}%
        \pgfmathreciprocal@{\pgfmathresult}%
      \fi%
      \pgf@yc\pgfmathresult\pgfarrowlinewidth%
      \pgf@yc.5\pgf@yc%
      \pgf@ya-\pgf@ya%
      \advance\pgf@ya by-90pt%
      \advance\pgf@ya by\pgf@yb%
      \pgfmathsincos@{\pgf@ya}%
      \pgf@xb\pgfmathresultx\pgf@yc% ya is the back miter
      \pgf@yb\pgfmathresulty\pgf@yc% yb is the top miter
      \expandafter\expandafter\expandafter%
    }\expandafter\expandafter\expandafter\pgf@xb\expandafter\the\expandafter\pgf@xb\expandafter\pgf@yb\the\pgf@yb%
    % Inner length (pgfutil@tempdima) is now arrowlength - front miter - back miter
    \pgfutil@tempdima\pgfarrowlength%
    \advance\pgfutil@tempdima by-\pgf@xc%
    \advance\pgfutil@tempdima by-\pgfarrowlinewidth%
    \pgfutil@tempdimb.5\pgfarrowwidth%
    \advance\pgfutil@tempdimb by\pgf@yb%
    % Set back end
    \ifpgfarrowroundjoin
      \pgfarrowssetbackend{\pgf@ya\advance\pgf@x by-.5\pgfarrowlinewidth}
    \else
      \pgfarrowssetbackend{0pt}
    \fi
    % harpoon miter correction
    \ifpgfarrowreversed
      \pgfarrowssetlineend{\pgfutil@tempdima\advance\pgf@x by-\pgflinewidth\advance\pgf@x by\pgfarrowlinewidth}
    \else
      \pgfarrowssetlineend{\pgf@yc\advance\pgf@x by\pgflinewidth\advance\pgf@x by-\pgfarrowlinewidth}
    \fi
    \ifpgfarrowroundjoin
      \pgfarrowssettipend{\pgfutil@tempdima\advance\pgf@x by.5\pgfarrowlinewidth}
    \else
      \pgfarrowssettipend{\pgfarrowlength\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi}
    \fi
    % The hull:
    \pgfarrowshullpoint{\pgfarrowlength\ifpgfarrowroundjoin\else\ifpgfarrowharpoon\advance\pgf@x by\pgf@xa\fi\fi}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else0pt\fi}%
    \pgfarrowsupperhullpoint{\pgfarrowinset}{.5\pgfarrowwidth}%
    \pgfarrowshullpoint{0pt}{\ifpgfarrowharpoon-.5\pgfarrowlinewidth\else0pt\fi}%
    % Adjust the inset:
    \pgf@ya\pgfarrowinset%
    \advance\pgfarrowinset by\pgf@xb%
    \advance\pgfarrowinset by\pgf@xb%
    %\advance\pgfarrowinset by\pgfarrowlinewidth%
    % The following are needed in the code:
    \pgfarrowssavethe\pgfutil@tempdima
    \pgfarrowssavethe\pgfutil@tempdimb
    \pgfarrowssavethe\pgfarrowlinewidth
    \pgfarrowssavethe\pgf@yc
    \pgfarrowssavethe\pgf@ya
    \pgfarrowssavethe\pgfarrowinset
  },
  drawing code = {
    \pgfsetdash{}{+0pt}
    \ifpgfarrowroundjoin\pgfsetroundjoin\else\pgfsetmiterjoin\fi
    \ifdim\pgfarrowlinewidth=\pgflinewidth\else\pgfsetlinewidth{\pgfarrowlinewidth}\fi
    \pgfpathmoveto{\pgfqpoint{\pgf@yc}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgfutil@tempdima}{\pgfutil@tempdimb}}  % too far
    \pgfpathlineto{\pgfqpoint{\pgf@ya}{0pt}}  % too close
    \ifpgfarrowharpoon \else
    \pgfpathlineto{\pgfqpoint{\pgfutil@tempdima}{-\pgfutil@tempdimb}}
    \pgfpathlineto{\pgfqpoint{\pgfarrowinset}{-\pgfutil@tempdimb}}
    \fi
    \pgfpathclose
    \ifpgfarrowopen\pgfusepathqstroke\else\ifdim\pgfarrowlinewidth>0pt\pgfusepathqfillstroke\else\pgfusepathqfill\fi\fi
  },
  parameters = {
    \the\pgfarrowlinewidth,%
    \the\pgfarrowlength,%
    \the\pgfarrowwidth,%
    \the\pgfarrowinset,%
    \ifpgfarrowharpoon h\fi%
    \ifpgfarrowopen o\fi%
    \ifpgfarrowroundjoin j\fi%
  },
}

\tikzset{
  InvertedDiamond/.tip={InvertedKite[inset'=0pt 0.5]},
}
\begin{document}
\begin{tikzpicture}
\draw [help lines, step=0.5cm] grid (6,7);
\draw [ultra thick, {Diamond[open, length=2cm, line width=6pt]}-{InvertedDiamond[red, open, length=2cm, line width=6pt]}] (0,0.5) -- (6,0.5);
\draw [ultra thick, {Diamond[round, open, length=2cm, line width=6pt]}-{InvertedDiamond[round, red, open, length=2cm, line width=6pt]}] (0,2) -- (6,2);
\draw [ultra thick, {Diamond[open, length=2cm, line width=6pt]}-{InvertedDiamond[reversed, red, open, length=2cm, line width=6pt]}] (0,3.5) -- (6,3.5);
\draw [ultra thick, {Diamond[round, open, length=2cm, line width=6pt]}-{InvertedDiamond[reversed, round, red, open, length=2cm, line width=6pt]}] (0,5) -- (6,5);
\draw [ultra thick, {Diamond[open, length=2cm, line width=3pt]}-{InvertedDiamond[red, open, length=2cm, line width=3pt]}] (0,6.5) -- (6,6.5);
\end{tikzpicture}
\end{document}

enter image description here

3
  • And as an aside, I wish it weren't \pgf this, \expandafter that. It should be an easy scripting language like lua or Python, maybe restricted to some subset of the language. This macro expansion thing is extremely time-consuming and frustrating. Talk about paying for a (terrible) historical design decision!
    – Neil G
    Feb 19 '14 at 21:11
  • Where is the document to produce this picture? Feb 19 '14 at 22:34
  • @PaulGaborit: Added, sorry.
    – Neil G
    Feb 20 '14 at 9:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.