循环变换后的相对坐标

循环变换后的相对坐标

当我试图理解这个问题cycle当我在变换路径之后使用相对坐标时,我发现了一种奇怪的行为。

以下是一个例子(黑色路径):

\documentclass[tikz,border=7mm]{standalone}
\begin{document}
  \begin{tikzpicture}
    \draw[green]       (0,0) -- ++(1,0) -- ++(0,1) -- cycle node[red]{.} -- ++(0,1);
    \draw[xshift=15mm] (0,0) -- ++(1,0) -- ++(0,1) -- cycle node[red]{.} -- ++(0,1);
    \draw[green]     (3.5,0) -- ++(1,0) -- ++(0,1) -- cycle node[red]{.} -- ++(0,1);
  \end{tikzpicture}
\end{document}

在此处输入图片描述

如果我们替换cycle所有(current subpath start)三行,它们看起来就一样了。

问题:这种行为是cycle正常的(有记录的)吗,还是一个错误?

编辑:对我来说,cycle(current subpath start)不应该在如何移动当前点上有所不同,而应该在如何“关闭”路径上有所不同。因此,从某种意义上说,tikz 应该--(current subpath start)在任何之后添加cycle(它已经(current subpath start)--在之前添加了cycle如在14.2.1 直线

答案1

问题出在tikz.code.tex第 2846 行

\def\tikz@@close cycle{%
  \tikz@flush@moveto%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}
  \tikz@make@last@position{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}%
  \tikz@path@close{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}%
  \def\pgfstrokehook{}%
  \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \let\tikz@timer=\tikz@timer@line%
  \let\tikz@tangent\tikz@timer@start%
  \tikz@scan@next@command%
}

其中\tikz@make@last@position{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}调用当前子路径的起点。它以绝对坐标存储。因此,在你的情况下,三个调用--cycle涉及 PGF 点

\pgfpoint{0.0pt}{0.0pt}
\pgfpoint{42.67912pt}{0.0pt}
\pgfpoint{99.5846pt}{0.0pt}

然后当 TiZ 定位节点,这些坐标用于 变换...也就是说,例如xshift应用变换两次!为了清楚地看到这一点,可以测试

\tikz\draw(0,0)node[blue]{.}[xshift=1cm](0,0)[yshift=1cm]--(0,0)--cycle node[red]{.};

现在红点在,(2,1)因为旧的xshift应用了两次,而年轻的yshift应用了一次。

要解决这个问题,需要用“未转换”的坐标替换坐标。你实际上给出了一个提示:节点(current subpath start)。可以按如下方式修改定义

\makeatletter
\def\tikz@@close cycle{%
  \tikz@flush@moveto%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}
  %\tikz@make@last@position{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}% replaced by the next line
  \tikz@make@last@position{\expandafter\pgfpointanchor{current subpath start}{center}}%
  \tikz@path@close{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}%
  \def\pgfstrokehook{}%
  \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \let\tikz@timer=\tikz@timer@line%
  \let\tikz@tangent\tikz@timer@start%
  \tikz@scan@next@command%
}

现在它应该可以工作了。


完整代码

\documentclass[tikz,border=7mm]{standalone}
\begin{document}

  \tikz\draw(0,0)node[blue]{.}[xshift=1cm](0,0)[yshift=1cm]--(0,0)--cycle node[red]{.};

\makeatletter
\def\tikz@@close cycle{%
  \tikz@flush@moveto%
  \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}
  %\tikz@make@last@position{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}% replaced by the next line
  \tikz@make@last@position{\expandafter\pgfpointanchor{current subpath start}{center}}%
  \tikz@path@close{\expandafter\pgfpoint\pgfsyssoftpath@lastmoveto}%
  \def\pgfstrokehook{}%
  \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
  \let\tikz@timer=\tikz@timer@line%
  \let\tikz@tangent\tikz@timer@start%
  \tikz@scan@next@command%
}

  \begin{tikzpicture}
    \draw[green]       (0,0) -- ++(1,0) -- ++(0,1) -- cycle node[red]{.} -- ++(0,1);
    \draw[xshift=15mm] (0,0) -- ++(1,0) -- ++(0,1) -- cycle node[red]{.} -- ++(0,1);
    \draw[green]     (3.5,0) -- ++(1,0) -- ++(0,1) -- cycle node[red]{.} -- ++(0,1);
  \end{tikzpicture}

\end{document}

相关内容