当我试图理解这个问题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}
然后当 Ti钾Z 定位节点,这些坐标用于 和变换...也就是说,例如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}