不同大小的节点之间的平行箭头

不同大小的节点之间的平行箭头

我在用此解决方案针对这个问题TikZ 节点之间的平行边在边缘附近绘制带有平行箭头的图形。

最小工作示例

\documentclass[tikz]{standalone}

\usetikzlibrary{calc}

\tikzset{
  % store of parameters
  parallel distance/.store in=\paradist,
  parallel shorten/.store in=\parashorten,
  parallel label distance/.store in=\paralabdist,
  % default values
  parallel distance=1mm, % distance of parallel arrows from link
  parallel shorten=0mm, % to shorten parallel arrows
  parallel label distance=2.5mm, % distance of label from link
  % main style
  edge with values/.style args={#1 and #2}{
    to path={
      \pgfextra{
        \pgfinterruptpath
        % middle point
        \coordinate (m) at ($(\tikztostart)!.5!(\tikztotarget)$);
        % from-to arrow
        \draw[-stealth,shorten >=\parashorten,shorten <=\parashorten]
        ($(\tikztostart)!\paradist!-90:(\tikztotarget)$)
        --
        ($(\tikztotarget)!\paradist!90:(\tikztostart)$)
        % middle of from-to arrow
        coordinate[pos=.5](m from);
        % label of from-to arrow
        \node[font=\tiny] at ($(m)!\paralabdist!(m from)$){#1};
        % to-from arrow
        \draw[-stealth,shorten >=\parashorten,shorten <=\parashorten]
        ($(\tikztotarget)!\paradist!-90:(\tikztostart)$)
        --
        ($(\tikztostart)!\paradist!90:(\tikztotarget)$)
        % middle of to-from arrow
        coordinate[pos=.5](m to);
        % label of to-from arrow
        \node[font=\tiny] at ($(m)!\paralabdist!(m to)$){#2};
        \endpgfinterruptpath
      }
         (\tikztostart) -- (\tikztotarget)
    },
  },
}

\begin{document}
\begin{tikzpicture}
    %the decorating arrows start at the center of the nodes
    \draw node[draw] (a) {large node}
        ++(3,0) node[draw] (b) {other node}
        edge[edge with values=a and b] (a);
    %if node sizes are about equal, it can be fixed by shortening both ends
    \draw (0,-1) node[draw] (a2) {large node}
        ++(3,0) node[draw] (b2) {other node}
        edge[parallel shorten=1cm,edge with values=a and b] (a2);
    %if the error is asymmetric this won't work
    \draw (0,-2) node[draw] (a3) {large node}
        ++(3,0) node[draw] (b3) {n}
        edge[parallel shorten=1cm,edge with values=a and b] (a3);
\end{tikzpicture}
\end{document}

这将产生以下输出: 带箭头和方框的图像

问题描述

问题是装饰箭头从节点的中心开始,而不是从边界开始。我可以通过为每个边指定和来手动修复这个问题shorten >shorten <但这很麻烦。

我正在寻找一种在正确位置绘制装饰箭头的解决方案。

请注意,让边在指定的锚点处开始/结束不是一个选项,因为我也使用对角边。

我的分析

问题似乎是由于在 中to path,宏\tikztostart\tikztotarget解析为节点(?)或节点的中心。如果您将它们用作 asis,tikz 的智能处理将起作用,并且您绘制的线将从节点的边界开始。这发生在最后的 中(\tikztostart) -- (\tikztotarget)

但是一旦例如\tikztostart被包含在计算中($(\tikztostart)$),路径就从节点中心开始,而不是从节点的边界开始。

如果有办法在内获取路径的“智能”端点to path,那么问题就可以轻松解决。

当然,我也愿意接受另一种等效的解决方案。

我知道通过两个平行箭头连接 Tikz 节点,但这并不适用,因为我还需要为两个箭头设置不同的样式(不同的颜色)。所以我正在寻找真正绘制两个与边平行的附加箭头的代码,就像上面的代码一样。

以下是使用我的答案的申请示例

在此处输入图片描述

答案1

我找到了一种获取所涉及形状边界坐标的方法,方法是使用

\pgfmathanglebetweenpoints{\pgfpointanchor{\tikztostart}{center}}{\pgfpointanchor{\tikztotarget}{center}}

现在shorten不再需要获得良好的结果了。

完整的工作解决方案

\documentclass[tikz]{standalone}

\usetikzlibrary{calc}

\tikzset{
  % store of parameters
  parallel distance/.store in=\paradist,
  parallel shorten/.store in=\parashorten,
  parallel label distance/.store in=\paralabdist,
  % default values
  parallel distance=1mm, % distance of parallel arrows from link
  parallel shorten=0mm, % to shorten parallel arrows
  parallel label distance=2.5mm, % distance of label from link
  % main style
  edge with values/.style args={#1 and #2}{
    to path={
      \pgfextra{
        \pgfinterruptpath
        \pgfmathanglebetweenpoints{\pgfpointanchor{\tikztostart}{center}}{\pgfpointanchor{\tikztotarget}{center}}
        \coordinate (start) at (\tikztostart.\pgfmathresult);
        \pgfmathanglebetweenpoints{\pgfpointanchor{\tikztotarget}{center}}{\pgfpointanchor{\tikztostart}{center}}
        \coordinate (target) at (\tikztotarget.\pgfmathresult);
        % middle point
        \coordinate (m) at ($(start)!.5!(target)$);
        % from-to arrow
        \draw[-stealth,shorten >=\parashorten,shorten <=\parashorten]
        ($(start)!\paradist!-90:(target)$)
        --
        ($(target)!\paradist!90:(start)$)
        % middle of from-to arrow
        coordinate[pos=.5](m from);
        % label of from-to arrow
        \node[font=\tiny] at ($(m)!\paralabdist!(m from)$){#1};
        % to-from arrow
        \draw[-stealth,shorten >=\parashorten,shorten <=\parashorten]
        ($(target)!\paradist!-90:(start)$)
        --
        ($(start)!\paradist!90:(target)$)
        % middle of to-from arrow
        coordinate[pos=.5](m to);
        % label of to-from arrow
        \node[font=\tiny] at ($(m)!\paralabdist!(m to)$){#2};
        \endpgfinterruptpath
      }
         (\tikztostart) -- (\tikztotarget)
    },
  },
}

\begin{document}
\begin{tikzpicture}
    %the decorating arrows start at the center of the nodes
    \draw node[draw] (a) {large node}
        ++(3,0) node[draw] (b) {other node}
        edge[edge with values=a and b] (a);
    %if node sizes are about equal, it can be fixed by shortening both ends
    \draw (0,-1) node[draw] (a2) {large node}
        ++(3,0) node[draw] (b2) {other node}
        edge[edge with values=a and b] (a2);
    %if the error is asymmetric this won't work
    \draw (0,-2) node[draw] (a3) {large node}
        ++(3,0) node[draw] (b3) {n}
        edge[edge with values=a and b] (a3);
\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容