如何获取箭头的视觉后端端点的坐标?

如何获取箭头的视觉后端端点的坐标?

我尝试回答一个有趣但被低估的问题老问题

为了使我的答案也适用于倾斜路径,我需要箭头的可视后端点的坐标。

来自 TikZ 手册: 在此处输入图片描述 在此处输入图片描述

我想([xshift=-#1]\tikzinputsegmentlast)在下面的代码中更改箭头的视觉后端的坐标。

是否可以?

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{decorations.pathreplacing}
    
\tikzset{
  mystyle/.style={
    -{Triangle[open, length=#1]},
    decoration={
      show path construction,
      lineto code={
        \coordinate (n0) at (\tikzinputsegmentfirst);
        \coordinate (n3) at ([xshift=-#1]\tikzinputsegmentlast);
        \coordinate (n4) at (\tikzinputsegmentlast);
        \coordinate (n1) at (barycentric cs:n0=2,n3=1);
        \coordinate (n2) at (barycentric cs:n0=1,n3=2);
        \draw [-, color=red] (n0) -- (n1);
        \draw [-, color=green] (n1) -- (n2);
        \draw [-, color=blue] (n2) -- (n3);
        \draw (n3) -- (n4);
        }
      },
    decorate
  },
  mystyle/.default=5pt,
  every node/.style={circle, draw}
}

\begin{document}
\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,0) {B};
\draw[mystyle] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,0) {B};
\draw[mystyle={35pt}] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,1) {B};
\draw[mystyle={20}] (A) -- (B); 
\end{tikzpicture}

\end{document}

正如你所看到的,现在第三张图是错误的。

在此处输入图片描述

答案1

视觉后端的位置存储在

\csname pgf@ar@visual@\pgf@arrow@id\endcsname

带格式

{visual tip end}{visual back end}{}

因此,倾斜减去向后就是您要从线上减去的距离。

要了解\pgf@arrow@id,你需要将箭头规范传递给\pgfsetarrowsend。例如\pgfsetarrowsend{Triangle[length=1cm]}。后一个命令的功能有两方面:

  • 如果箭头规范以前没有使用过,它会计算所需的一切并缓存。
  • 如果箭头规范之前已经使用过,则将其设置\pgf@arrow@id为旧的 id。

不管怎样,您知道\pgf@arrow@id并且现在 \csname pgf@ar@visual@\pgf@arrow@id\endcsname有意义了。剩下的就是 expandafter-exercise。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{calc}
\makeatletter
\def\computevisuallength#1#2#3{% visual end, visual tip, dummy
    \pgf@x#1
    \pgf@y#2
    \advance\pgf@x-\pgf@y
    \xdef\visuallength{\the\pgf@x}
}
\tikzset{
  mystyle/.style={
    decoration={
      show path construction,
      lineto code={
        \coordinate (n0) at (\tikzinputsegmentfirst);
        \coordinate (n4) at (\tikzinputsegmentlast);
        \draw[dash pattern=on0off9999,-{Triangle[open, length=#1]}] (n0) -- (n4);
        {
            \pgfsetarrowsend{Triangle[open, length=#1]}% force pgf recall this arrow
            \def\pgf@arrow@hull@point{hull}%%
            \message{^^J }
            \message{^^J arrow id: pgf@arrow@id\pgf@arrow@id}
            \message{^^J hull: \csname pgf@ar@hull@\pgf@arrow@id\endcsname}
            \message{^^J tip back: \csname pgf@ar@ends@\pgf@arrow@id\endcsname}
            \message{^^J vis tip back: \csname pgf@ar@visual@\pgf@arrow@id\endcsname}
            \message{^^J etc etc}
            \message{^^J }
            \expandafter\expandafter\expandafter\computevisuallength
            \csname pgf@ar@visual@\pgf@arrow@id\endcsname
        }
        \coordinate (n3) at ($(n4)!\visuallength!(n0)$);
        \coordinate (n1) at (barycentric cs:n0=2,n3=1);
        \coordinate (n2) at (barycentric cs:n0=1,n3=2);
        \draw [color=red] (n0) -- (n1);
        \draw [color=green] (n1) -- (n2);
        \draw [color=blue] (n2) -- (n3);
        }
      },
    decorate
  },
  mystyle/.default=5pt,
  every node/.style={circle, draw}
}

\begin{document}
\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,0) {B};
\draw[mystyle] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,0) {B};
\draw[mystyle={35pt}] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,1) {B};
\draw[mystyle={20}] (A) -- (B); 
\end{tikzpicture}

% Repeat the second arrow, can pgf recall the parameter?
\begin{tikzpicture}
\node (A) at (0,0) {A};
\node (B) at (5,0) {B};
\draw[mystyle={35pt}] (A) -- (B);
\end{tikzpicture}

\end{document}

箭头前的线被分成三等份

答案2

\coordinate (n3) at 
          ($(\tikzinputsegmentlast)!#1!(\tikzinputsegmentfirst)$);

有效。这定义n3为从最后一个线段到第一个线段的沿线的坐标,并且距离最后一个线段#1(必须是长度)。#1

奖金:下面的代码片段添加了对 的支持shorten >=<length>,以及 为#1无单位“长度”的用例(通过利用 的“特征” pgfmath)。

\coordinate (n3) at 
          ($(\tikzinputsegmentlast)!#1+\pgf@shorten@end@additional!(\tikzinputsegmentfirst)$);

完整示例

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, calc}
\usetikzlibrary{decorations.pathreplacing}

\makeatletter
\tikzset{
  mystyle/.style={
    -{Triangle[open, length=#1]},
    decoration={
      show path construction,
      lineto code={
        \coordinate (n0) at (\tikzinputsegmentfirst);
        \coordinate (n3) at 
          ($(\tikzinputsegmentlast)!#1+\pgf@shorten@end@additional!(\tikzinputsegmentfirst)$);
        \coordinate (n4) at (\tikzinputsegmentlast);
        \coordinate (n1) at (barycentric cs:n0=2,n3=1);
        \coordinate (n2) at (barycentric cs:n0=1,n3=2);
        \begin{scope}[shorten >=0pt, arrows={-}]
          \draw[red] (n0) -- (n1);
          \draw[green] (n1) -- (n2);
          \draw[blue] (n2) -- (n3);
        \end{scope}
        % this `\draw` will add the end-of-path arrow
        \draw (n3) -- (n4);
        % control group
        \draw[help lines]
           ($ (\tikzinputsegmentfirst) + (0,.2) $) -- 
           ($ (\tikzinputsegmentlast)  + (0,.2) $);
        }
      },
    decorate
  },
  mystyle/.default=5pt,
  every node/.style={circle, draw}
}
\makeatother

\begin{document}
\begin{tikzpicture}
  \node (A) at (0,0) {A};
  \node (B) at (5,0) {B};
  \draw[mystyle] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
  \node (A) at (0,0) {A};
  \node (B) at (5,0) {B};
  \draw[mystyle={35pt}] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
  \node (A) at (0,0) {A};
  \node (B) at (5,1) {B};
  \draw[mystyle={20}] (A) -- (B);
\end{tikzpicture}

\begin{tikzpicture}
  \node (A) at (0,0) {A};
  \node (B) at (5,1) {B};
  \draw[mystyle={20}, shorten >=10pt] (A) -- (B);
\end{tikzpicture}
\end{document}

在此处输入图片描述

备注:为了支持,我猜需要curve to类似的东西。\pgf@prep@curved(start|end)

相关内容