我正在研究包含路径的箭头。
只要路径是直的,它就可以正常工作。
当路径弯曲时,\pgfpathquadraticcurveto
会产生一些奇怪的结果。看起来第一个二次曲线以某种方式从弯曲处获取了一个控制点。在 MWE 中,从倒钩向下延伸到轴的曲线会获得一个控制点,该控制点似乎是弯曲控制点的一部分。
如果我们将倒钩改为直线,而不是二次曲线,那么轴就会变形。
有没有什么办法可以解决这个问题?或者可以排除故障?在我看来,这似乎是一个错误,但我对 tikz/pgf 还不够熟悉,所以不确定。
以下是代码:
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
%\usepackage{calc}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{bending}
\usetikzlibrary{decorations}
\newlength{\mypathlength}
\pgfdeclaredecoration{stashlength}{final}{
\state{final}{
\setlength{\mypathlength}{\pgfdecoratedpathlength}
%\pgftext{\mypathlength}
\global\mypathlength=\mypathlength}}
\newdimen\pgftaillength % Length of tail of arrow
\newdimen\pgfheadlength % length of arrow head
\newdimen\pgfheadwidth % half width of arrow shaft where it connects to head
\newdimen\pgftaildepth % depth of circular dip in tail
\pgfkeys{/pgf/arrow keys/tail length/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgftaillength\expandafter=\the\somedimen}}
\pgfkeys{/pgf/arrow keys/head length/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgfheadlength\expandafter=\the\somedimen}}
\pgfkeys{/pgf/arrow keys/head width/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgfheadwidth\expandafter=\the\somedimen}}
\pgfkeys{/pgf/arrow keys/tail depth/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgftaildepth\expandafter=\the\somedimen}}
\pgfdeclarearrow{%
name=networkarrow,
parameters={%
\the\pgfarrowlength,
\the\pgfarrowwidth,
\the\pgftaillength,
\the\pgfheadlength,
\the\pgfheadwidth,
\the\pgftaildepth
},
setup code={%
% The different end values:
\pgfarrowssettipend{0pt}
\pgfarrowssetlineend{-.75\pgfarrowlength}
\pgfarrowssetvisualbackend{-.9\pgfarrowlength}
\pgfarrowssetbackend{-\pgfarrowlength}
% The hull
\pgfarrowshullpoint{0pt}{0pt}
\pgfarrowshullpoint{-\pgfarrowlength}{.5\pgfheadwidth}
%\pgfarrowshullpoint{-.75\pgfarrowlength}{-.5\pgfarrowlength}
% Saves: All the necessary parameters
\pgfarrowssavethe\pgfarrowlength
\pgfarrowssavethe\pgfarrowwidth
\pgfarrowssavethe\pgftaillength
\pgfarrowssavethe\pgfheadlength
\pgfarrowssavethe\pgfheadwidth
\pgfarrowssavethe\pgftaildepth
},
drawing code={%
%\pgftext{\mypathlength}
\pgfpathmoveto{\pgfqpoint{0pt}{0pt}} % tip of arrow
\pgfpathlineto{\pgfpoint{ -\pgfheadlength-.5\pgftaildepth}
{.5\pgfheadwidth}} % end of barb
\pgfpathquadraticcurveto{\pgfpoint{-\pgfheadlength-.25\pgftaildepth}
{.375\pgfheadwidth}}
{\pgfpoint{-\pgfheadlength}
{.5\pgfarrowwidth}} %shaft/head junction
% uncomment the next two lines, and comment out the previous 4 to see the
% problem with \pgfpathquadraticcurveto move to the shaft curve, instead of
% the head curve
%\pgflineto{\pgfpoint{-\pgfheadlength}
% {.5\pgfarrowwidth}} %shaft/head junction
\pgfpathquadraticcurveto{\pgfpoint{-\mypathlength+\pgftaillength}
{.5\pgfarrowwidth}}
{\pgfpoint{-\mypathlength-\pgftaildepth}
{.5\pgfheadwidth}} %tail barb
\pgfpathcurveto{\pgfpoint{-\mypathlength-.25\pgftaildepth}
{.375\pgfheadwidth}}
{\pgfpoint{-\mypathlength}{.25\pgfheadwidth}}
{\pgfpoint{-\mypathlength}{0pt}} %center of tail
% mirror image of top half
\pgfpathcurveto{\pgfpoint{-\mypathlength}{-.25\pgfheadwidth}}
{\pgfpoint{-\mypathlength-.25\pgftaildepth}
{-.375\pgfheadwidth}}
{\pgfpoint{-\mypathlength-\pgftaildepth}
{-.5\pgfheadwidth}} % back to barb
\pgfpathquadraticcurveto{\pgfpoint{-\mypathlength+\pgftaillength}
{-.5\pgfarrowwidth}}
{\pgfpoint{-\pgfheadlength}
{-.5\pgfarrowwidth}} % shaft head junction
\pgfpathquadraticcurveto{\pgfpoint{-\pgfheadlength-.25\pgftaildepth}
{-.375\pgfheadwidth}}
{\pgfpoint{ -\pgfheadlength-.5\pgftaildepth}
{-.5\pgfheadwidth}} % arrow barb
% temporarily make half arrow so I have less to fix
\pgfpathclose
\pgfusepathqstroke
},
defaults={%
length=0pt,
width=1.2mm,
tail length=8mm,
head length=8mm,
head width=5mm,
tail depth=.5mm
},
}
\begin{document}
\begin{tikzpicture}
\draw [-{networkarrow[bend]},preaction={decorate,decoration=stashlength}] (0,0) -- (8,0);
\draw [-{networkarrow[bend]},preaction={decorate,decoration=stashlength}] (0,-2) to [bend left] (8,-2);
\draw [-{networkarrow[bend]},preaction={decorate,decoration=stashlength}] (0,-4) to [bend right] (8,-4);
\end{tikzpicture}
\end{document}
答案1
虽然我不知道是什么导致了这个问题或者如何在 pgf 级别对其进行调试,但我找到了一种似乎可以解决问题的解决方法。
只需将箭头中的第一条曲线设为pgfpathcurveto
而不是 即可pgfpathquadraticcurveto
。我通过将控制点加倍来实现。虽然不完全相同,但对于我的目的来说已经足够接近了。
这使得所有其余曲线都能正常工作,这让我有点惊讶。
\documentclass[border=10pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{bending}
\usetikzlibrary{decorations}
\newlength{\mypathlength}
\pgfdeclaredecoration{stashlength}{final}{
\state{final}{
\setlength{\mypathlength}{\pgfdecoratedpathlength}
%\pgftext{\mypathlength}
\global\mypathlength=\mypathlength}}
\newdimen\pgftaillength % Length of tail of arrow
\newdimen\pgfheadlength % length of arrow head
\newdimen\pgfheadwidth % half width of arrow shaft where it connects to head
\newdimen\pgftaildepth % depth of circular dip in tail
\pgfkeys{/pgf/arrow keys/tail length/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgftaillength\expandafter=\the\somedimen}}
\pgfkeys{/pgf/arrow keys/head length/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgfheadlength\expandafter=\the\somedimen}}
\pgfkeys{/pgf/arrow keys/head width/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgfheadwidth\expandafter=\the\somedimen}}
\pgfkeys{/pgf/arrow keys/tail depth/.code=
\newdimen\somedimen
\pgfmathsetlength{\somedimen}{#1}
\expandafter\pgfarrowsaddtooptions\expandafter
{\expandafter\pgftaildepth\expandafter=\the\somedimen}}
\pgfdeclarearrow{%
name=networkarrow,
parameters={%
\the\pgfarrowlength,
\the\pgfarrowwidth,
\the\pgftaillength,
\the\pgfheadlength,
\the\pgfheadwidth,
\the\pgftaildepth
},
setup code={%
% The different end values:
\pgfarrowssettipend{0pt}
\pgfarrowssetlineend{-.75\pgfarrowlength}
\pgfarrowssetvisualbackend{-.9\pgfarrowlength}
\pgfarrowssetbackend{-\pgfarrowlength}
% The hull
\pgfarrowshullpoint{0pt}{0pt}
\pgfarrowshullpoint{-\pgfarrowlength}{.5\pgfheadwidth}
%\pgfarrowshullpoint{-.75\pgfarrowlength}{-.5\pgfarrowlength}
% Saves: All the necessary parameters
\pgfarrowssavethe\pgfarrowlength
\pgfarrowssavethe\pgfarrowwidth
\pgfarrowssavethe\pgftaillength
\pgfarrowssavethe\pgfheadlength
\pgfarrowssavethe\pgfheadwidth
\pgfarrowssavethe\pgftaildepth
},
drawing code={%
\pgfpathmoveto{\pgfqpoint{0pt}{0pt}} % tip of arrow
\pgfpathlineto{\pgfpoint{ -\pgfheadlength-.5\pgftaildepth}
{.5\pgfheadwidth}} % end of barb
\pgfpathcurveto{\pgfpoint{-\pgfheadlength-.25\pgftaildepth}
{.375\pgfheadwidth}}
{\pgfpoint{-\pgfheadlength-.25\pgftaildepth}
{.375\pgfheadwidth}}
{\pgfpoint{-\pgfheadlength}
{.5\pgfarrowwidth}} %shaft/head junction
\pgfpathquadraticcurveto{\pgfpoint{-\mypathlength+\pgftaillength}
{.5\pgfarrowwidth}}
{\pgfpoint{-\mypathlength-\pgftaildepth}
{.5\pgfheadwidth}} %tail barb
\pgfpathcurveto{\pgfpoint{-\mypathlength-.25\pgftaildepth}
{.375\pgfheadwidth}}
{\pgfpoint{-\mypathlength}{.25\pgfheadwidth}}
{\pgfpoint{-\mypathlength}{0pt}} %center of tail
% mirror image of top half
\pgfpathcurveto{\pgfpoint{-\mypathlength}{-.25\pgfheadwidth}}
{\pgfpoint{-\mypathlength-.25\pgftaildepth}
{-.375\pgfheadwidth}}
{\pgfpoint{-\mypathlength-\pgftaildepth}
{-.5\pgfheadwidth}} % back to barb
\pgfpathquadraticcurveto{\pgfpoint{-\mypathlength+\pgftaillength}
{-.5\pgfarrowwidth}}
{\pgfpoint{-\pgfheadlength}
{-.5\pgfarrowwidth}} % shaft head junction
\pgfpathquadraticcurveto{\pgfpoint{-\pgfheadlength-.25\pgftaildepth}
{-.375\pgfheadwidth}}
{\pgfpoint{ -\pgfheadlength-.5\pgftaildepth}
{-.5\pgfheadwidth}} % arrow barb
% temporarily make half arrow so I have less to fix
\pgfpathclose
\pgfusepathqstroke
},
defaults={%
length=0pt,
width=1.2mm,
tail length=8mm,
head length=8mm,
head width=5mm,
tail depth=.5mm
},
}
\begin{document}
\begin{tikzpicture}
\draw [-{networkarrow[bend]},preaction={decorate,decoration=stashlength}] (0,0) -- (8,0);
\draw [-{networkarrow[bend]},preaction={decorate,decoration=stashlength}] (0,-2) to [bend left] (8,-2);
\draw [-{networkarrow[bend]},preaction={decorate,decoration=stashlength}] (0,-4) to [bend right] (8,-4);
\end{tikzpicture}
\end{document}