Bending 库和 pfgpathquadraticcurveto 不能很好地协同工作

Bending 库和 pfgpathquadraticcurveto 不能很好地协同工作

我正在研究包含路径的箭头。

只要路径是直的,它就可以正常工作。

当路径弯曲时,\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}

相关内容