如果我在 tikz 中使用这样的代码,它就会按我预期的方式工作:
\draw (0,1) to[out=0, in=180] (1,0);
但是,如果我设置in
但没有设置out
,那么奇怪的事情就会发生:
\draw (0,1) to[in=180] (1,0);
我期望的是,这条线一开始会朝着目标节点前进,然后弯曲,最后变成水平状态,类似于下面的一条曲线:
然而,曲线却以大约 45 度的角度开始向上移动,这似乎有点不合逻辑。
所以问题是,首先这里发生了什么,其次有没有办法实现我想要的?
这是我正在开发的一个小库,所以如果有解决方案,我需要它能够工作并且看起来合理,适用于任何端点位置,而无需任何手动微调。在我上面画的两条曲线中,左边的那条看起来比另一条好得多。
如果这在某些明显的地方描述,请原谅 - 因为搜索“in”,“out”和“to”等术语非常困难。
以下是完整的 MWE 代码:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,1) to[out=0, in=180] (1,0);
\end{tikzpicture}
\begin{tikzpicture}
\draw (0,1) to[in=180] (1,0);
\end{tikzpicture}
\end{document}
答案1
感觉就像你想定义一条仅取决于in
。由于在 TikZ 中,曲线路径是三次贝塞尔曲线,因此仅指定角度是不够的。所以我们需要找出另一个控制点来给出合理的曲线。以下代码以以下方式执行此操作。我们首先定义第二控制点与终点之间的指定角度,距离为起点和终点之间间距的三分之一。然后我们定义第一个控制点,使其意味着路径从起点向第二个控制点的方向离开(同样距离为间距的三分之一 - 三分之一适用于三次贝塞尔曲线)。
最后,将其组合成一个to
路径以方便使用。它确实使用calc
库来简化计算,但可以通过添加更多代码将其删除。
\documentclass{article}
%\url{https://tex.stackexchange.com/q/609102/86}
\usepackage{tikz}
\usetikzlibrary{calc}
\tikzset{
only in/.style={
to path={
let
\p1 = ($ (\tikztotarget) - (\tikztostart) $)
in
.. controls
($(\tikztostart)!{veclen(\x1,\y1)/3}!($(\tikztotarget)+(#1:{veclen(\x1,\y1)/3})$)$)
and
($(\tikztotarget)+(#1:{veclen(\x1,\y1)/3})$)
.. (\tikztotarget)
}
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,1) to[only in=180] (1,0);
\end{tikzpicture}
\end{document}
(分辨率较差是因为截取的是放大的网页。)
looseness
可以使用与通常路径上的键类似的键来定制 1/3 的因子to
。
答案2
以下方法尽可能轻微地修改代码库。
它允许您in looseness
与一起使用in
,并使用传统的计算来计算第二个控制点。然后,它用于out looseness
定义第一个控制点,如下所示
($ the starting point ! out looseness ! the second control point $)
您可以将out
/ from
/start
与in
/ to
/ end
/交换target
来定义only out
。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
\tikzset{
only in/.code={%
\tikzset{in=#1}%
\def\tikz@to@start@compute@looseness{%
\def\tikz@computed@start{($%
(\tikztostart)% the starting point
!\tikz@to@out@looseness!% you choose the looseness
\tikz@computed@end% second control point (TikZ will compute it)
$)}%
}%
\let\tikz@to@start@compute=\tikz@to@start@compute@looseness
% ^ There is an \ifx that tests if \...@compute
% ^ is one of the predefined ones.
% ^ Since we redefine \...@looseness, this \ifx is no longer true.
% ^ I added a \let to honor that \ifx and make the hack works
}
}
\begin{document}
\tikz{
\foreach\A in{1,2,3,4}{
\foreach\B in{1,2,3,4}{
\draw(\A*3,\B*3)
to[only in=180,out looseness=\A/4,in looseness=\B/2]
+(2.5,-2.5);
}
}
}
\tikz{
\foreach\A in{1,2,3,4}{
\foreach\B in{1,2,3,4}{
\draw(\A*3,\B*3)node(S){START}+(2.5,-2.5)node(T){TARGET}
(S)to[only in=180,out looseness=\A/4,in looseness=\B/2](T)
;
}
}
}
\end{document}