TikZ 中的“缩短 >=”选项会导致贝塞尔曲线的形状发生变化。例如,对于循环边缘,它会使循环不对称(图中的节点 A)。
我可以使用 curveto,post=moveto 和 mark 装饰使其对称,但是:
- 箭头没有出现在正确的位置。
- 它没有指向节点。
参见图中节点B。
可以使用自定义箭头代码并在装饰(节点 C)中手动调整来修复这些问题:
以下是代码:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,arrows,decorations.pathmorphing,decorations.markings}
\begin{document}
\begin{tikzpicture}
\node [circle,draw] (A) at (0, 0) {A};
\path (A) edge [out=240,in=300,min distance=8mm,-angle 90 reversed,shorten >=6pt] (A);
\node [circle,draw] (B) at (2, 0) {B};
\path (B) edge [out=240,in=300,min distance=8mm,
decoration={curveto,post=moveto,post length=8pt},
postaction={decoration={post length=0,markings,mark=at position 1
with {\arrow{angle 90 reversed}}},decorate},
decorate] (B);
\node [circle,draw] (C) at (4, 0) {C};
\path (C) edge [out=240,in=300,min distance=8mm,
decoration={curveto,post=moveto,post length=8pt},
postaction={decoration={post length=0,markings,mark=at position 1
with {\draw [-angle 90 reversed] (0, 0) --
($(0, 0)!2.5pt!(\tikztotarget.center)$);}},decorate},
decorate] (C);
\end{tikzpicture}
\end{document}
但是它有点复杂,需要手动调整。有人知道更好的方法吗?
答案1
我要在这里稍微冒险一下——也许通过说出我要说的话,有人会受到启发来证明我错了。
有谁看到更好的方法吗?
不。
当然,您可以将复杂的代码包装成一个装饰,但在引擎盖下它仍然会做同样的事情。
我的推理是基于 PGF 在修饰路径时可用的信息。这是只是原始路径。PGF 不知道路径实际上是如何指定的。TikZ 知道这一点,但它不会将该信息传递给 PGF。因此,即使您已经写入\draw (C) DoSomethingComplicated (C);
[^1],TikZ 也会将调整(C)
为节点边界上的某个点,然后忘记(C)
您关心的是什么,只将实际坐标传递给 PGF。
因此,PGF 仅获取恰好位于节点边界上的两点之间的路径(C)
,但 PGF 不知道(C)
。您想尽早终止此路径,然后绘制箭头。这似乎在 PGF 的出处之内:对于终止,您可以使用现有的装饰,也可以使用截断贝塞尔曲线的低级宏\pgfpathcurvebetweentime
。前一种方法的优点是您可以精确指定截断距离,后一种方法的优点是它更快并且为输出生成实际的贝塞尔曲线(而不是大量短线)。这对于 PGF 来说很容易,因为它只涉及路径和终止标准。
但是,你随后想在路径上放置一个箭头。这时,PGF 知道的并不像你那么多,这一点就变得很重要了。PGF 只知道曲线。因此,它可以计算出曲线在各个点的方向,包括终止点和实际的终点。但是,这些都不是你想要的。您想要的是从终点到终点所看方向的方向。但是从终点开始的方向只能给出该点所在的线,而不是它有多远。由于终点与终点有距离(这更像是整个过程的...点...),您无法从终点的方向确定您应该在哪里看终点,因此 PGF 无法确定将箭头放在哪个方向。因此您需要指定它,这实际上就是您要做的事情。可能存在稍微更简单的指定方向的方法,但可能并不多。
(实际上,当我写这篇文章时,我找到了一种方法,即 PGF 可以使用给出的信息来计算箭头的方向,但计算肯定比你已经拥有的更复杂,所以我将它留给一个比我有更多的时间的 TikZ 爱好者作为练习。)
[^1]:DoSomethingComplicated
路径规范目前正在 TeX-SX 实验室中开发。