我在用此解决方案针对这个问题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}