我如何告诉 TikZ 再次计算“in”值而不是使用前一个值?

我如何告诉 TikZ 再次计算“in”值而不是使用前一个值?

前两行正是我想要的:

\node (F) at (1,1) {$F$};

\draw (0,2) to [out=-90] (F);

也就是说,它从点向下绘制一条边(0,0),并将其弯曲以击中(F),以大约 135 度进入节点。我不必指定in=135

但是下一行使用相同的~135 度值in,而我希望它的值在 45 度左右并且不指定它

\draw (2,2) to [out=-90] (F);

我如何告诉再次tikz计算该in值而不是使用前一个值?

这是一个最小工作示例,现在已进行了修改,因为很明显我是“马戏团的受害者”:

\documentclass{article}
\usepackage{tikz}

\begin{document}
  \begin{tikzpicture}
    \node [circle, draw=black] (F) at (1,1) {$F$};
    \draw (0,2) to [out=-90] (F);
    \draw (0.7,2) to [out=-90, in=110] (F);
    \draw (2,2) to [out=-90, in=45] (F);
    \draw (F) to [out=-135, in=90] (0,0);
    \draw (F) to [out=-45, in=90] (2,0);
  \end{tikzpicture}
\end{document}

答案1

你是马戏团的受害者。

“不必指定in=135”这一事实纯属巧合。而第二种情况下 TikZ “使用前一个”的结论是错误的。观察到的行为完全归因于文件中的两行小代码tikzlibrarytopaths.code.tex

\def\tikz@to@out{45}
\def\tikz@to@in{135}

这意味着,如果您不指定,out则会自动设置为45,同样,如果您不指定,in则会自动设置为135。(这些仅在以下情况下有效:某物选择curve的变体to path,而不是默认的变体。指定inout足够了。

有一个relative选项可以设置相对于起始和结束坐标之间的线的角度。因此,如果您使用relative,in=180(因为线的方向来源目标),然后为in线选择了正确的角度。然而,这使得out角度相对的,这似乎不是你想要的。

这是我编写的一段代码,如果您没有自行设置,它会自动设置in和。必须提供密钥outauto ends任何覆盖outin因为它无法区分用户所说的out=45和默认值。然而,这似乎并不是什么困难。

它的作用是在调用时将in和设置out为空。然后在处理路径时,将任何仍为空的设置为起始和终止坐标之间的角度。

\documentclass{article}
%\url{http://tex.stackexchange.com/q/39903/86}
\usepackage{tikz}

\makeatletter
\tikzset{
  auto ends/.code={%
    \def\tikz@to@switch@on{\let\tikz@to@path=\tikz@to@curve@path@rel}%
    \tikz@to@switch@on
    \let\tikz@to@in=\pgfutil@empty
    \let\tikz@to@out=\pgfutil@empty
  }
}

\def\tikz@to@curve@path@rel{%
  [every curve to]
  \pgfextra{%
    \ifx\tikz@to@out\pgfutil@empty
     \let\relin@toto=\tikztotarget
    \ifx\tikz@to@in\pgfutil@empty
    \else
     \tikz@to@modify\relin@toto\tikz@to@in
    \fi
     \tikz@scan@one@point\pgfutil@firstofone(\relin@toto)\relax
     \pgf@xa=\pgf@x
     \pgf@ya=\pgf@y
     \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
     \advance\pgf@xa by -\pgf@x
     \advance\pgf@ya by -\pgf@y
     \pgfmathtruncatemacro\tikz@to@out{int(atan2(\pgf@xa,\pgf@ya))}%
    \fi
    \ifx\tikz@to@in\pgfutil@empty
     \let\relin@tofrom=\tikztostart
    \ifx\tikz@to@out\pgfutil@empty
    \else
     \tikz@to@modify\relin@tofrom\tikz@to@out
    \fi
     \tikz@scan@one@point\pgfutil@firstofone(\relin@tofrom)\relax
     \pgf@xa=\pgf@x
     \pgf@ya=\pgf@y
     \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
     \advance\pgf@xa by -\pgf@x
     \advance\pgf@ya by -\pgf@y
     \pgfmathtruncatemacro\tikz@to@in{int(atan2(\pgf@xa,\pgf@ya))}%
    \fi
    \iftikz@to@relative
     \tikz@to@compute@relative
    \else
     \tikz@to@compute
    \fi
  }
  \tikz@computed@path \tikztonodes
}


\makeatother

\begin{document}
  \begin{tikzpicture}
    \node [circle, draw=black] (F) at (1,1) {$F$};
    \draw (0,2) to [auto ends,out=-90] (F);
    \draw (2,2) to [auto ends,out=-90] (F);
    \draw (2,-2) to [auto ends,out=90] (F);
    \draw (-2,-2) to [auto ends] (F);
  \end{tikzpicture}
\end{document}

结果如下:

tikz to path with automatic angles


Marc van Dongen 和我对该请求的解释略有不同。以下是上述代码的改编版,允许使用以下形式的语法:

\draw[every to/.style={auto ends}] (0,2) to [out=-90]  (F) to[intermediate,in=-90] (2,2);

需要代码的原因是如果有人写了类似这样的代码:

\draw (0,0) to[out=90,in=45] (F) to[out=90,in=45] (0,2);

那么结果与写作不同

\draw (0,0) to[out=90,in=45] (F) (F) to[out=90,in=45] (0,2);

证人:

to paths

重点在于to path构建了一条新的路径,该路径附加到当前路径。因此,在上面的构造结果类似于.. controls (some point) and (some other point) .. (the target)。现在(the target)可能已经从路径上最初指定的内容进行了修改。但附加部分中未提及来源(这对于连接路径段很有意义)。因此,两个连续to路径的结果类似于:

.. controls (1st cntrl) and (2nd cntrl) .. (1st modified target) .. controls (3rd cntrl) and (4th cntrl) .. (2nd modified target);

尤其是来源第二个to path不是原始\draw命令中指定的内容但是第一个命令to path所说的内容。 大多数时候这正是我们想要的。然而,要按照原帖者的路径一气呵成,这不是我们想要的。我们想要的是第二种行为,其结果将是:

.. controls (1st cntrl) and (2nd cntrl) .. (1st modified target) (1st original target) .. controls (3rd cntrl) and (4th cntrl) .. (2nd modified target);

为了自动实现这一点,我们需要将原始目标重新插入到流中。但是,我们无法在第一个路径的末尾自动执行此操作,因为我们不知道在路径中是否有第二个路径。我们在第一个路径的末尾所能做的就是保存原始目标,以防再次需要它。然后在第二个路径的开头,我们可以重用它(如果我们愿意的话)以在正确的位置重新启动路径。

以下是修改后的代码,并附有示例。如所写,它与密钥绑定auto ends,但可以很容易地提取到一组单独的密钥中。困​​难在于标准to paths 需要修补才能插入正确的移动。

\documentclass{standalone}
%\url{http://tex.stackexchange.com/q/39903/86}
\usepackage{tikz}

\makeatletter
\tikzset{
  auto ends/.code={%
    \def\tikz@to@switch@on{\let\tikz@to@path=\tikz@to@curve@path@rel}%
    \tikz@to@switch@on
    \let\tikz@to@in=\pgfutil@empty
    \let\tikz@to@out=\pgfutil@empty
    \let\relin@start=\pgfutil@empty
  },
  intermediate/.code={
    \let\relin@start=\relin@target
  },
}

\newif\ifrelin@restartnext
\newif\ifrelin@restart

\def\tikz@to@curve@path@rel{%
  [every curve to]
  \pgfextra{%
    \global\let\relin@target=\tikztotarget
    \ifx\relin@start\pgfutil@empty
    \else
    \let\tikztostart=\relin@start
    \fi
    \ifx\tikz@to@out\pgfutil@empty
     \let\relin@toto=\tikztotarget
    \ifx\tikz@to@in\pgfutil@empty
    \else
     \tikz@to@modify\relin@toto\tikz@to@in
    \fi
     \tikz@scan@one@point\pgfutil@firstofone(\relin@toto)\relax
     \pgf@xa=\pgf@x
     \pgf@ya=\pgf@y
     \tikz@scan@one@point\pgfutil@firstofone(\tikztostart)\relax
     \advance\pgf@xa by -\pgf@x
     \advance\pgf@ya by -\pgf@y
     \pgfmathtruncatemacro\tikz@to@out{int(atan2(\pgf@xa,\pgf@ya))}%
    \fi
    \ifx\tikz@to@in\pgfutil@empty
     \let\relin@tofrom=\tikztostart
    \ifx\tikz@to@out\pgfutil@empty
    \else
     \tikz@to@modify\relin@tofrom\tikz@to@out
    \fi
     \tikz@scan@one@point\pgfutil@firstofone(\relin@tofrom)\relax
     \pgf@xa=\pgf@x
     \pgf@ya=\pgf@y
     \tikz@scan@one@point\pgfutil@firstofone(\tikztotarget)\relax
     \advance\pgf@xa by -\pgf@x
     \advance\pgf@ya by -\pgf@y
     \pgfmathtruncatemacro\tikz@to@in{int(atan2(\pgf@xa,\pgf@ya))}%
    \fi
    \iftikz@to@relative
     \tikz@to@compute@relative
    \else
     \tikz@to@compute
    \fi
    \ifx\relin@start\pgfutil@empty
    \else
    \let\relin@computed@path=\tikz@computed@path
    \edef\tikz@computed@path{(\relin@start)\tikz@computed@path}
    \fi
  }
  \tikz@computed@path \tikztonodes
}


\makeatother

\begin{document}
  \begin{tikzpicture}
    \node [circle, draw=black] (F) at (1,1) {$F$};
\draw[every to/.style={auto ends}] (0,2) to[out=-90] (F) to[intermediate,in=-90] (2,2);
  \end{tikzpicture}
\end{document}

结果:

tikz to path with intermediate node

答案2

您有一个简单的解决方案:

\documentclass{article}
\usepackage{tikz}

\begin{document}
   \begin{tikzpicture}
    \node [circle, draw=black] (F) at (1,1) {$F$};
    \draw (0,2) to [out=-90] (F);
    \draw (F) to [in=-90] (2,2) ;
  \end{tikzpicture} 
\end{document}  

enter image description here

相关内容