在回答这个问题时TikZ 装饰:如何一点一点地绘制一条封闭的路径?@marmot 以一种我不太理解的方式使用了这个装饰自动机选项,但由于 ,它能够完美地运行pgf keys
。
\pgfkeys{pgf/.cd,
close/.code={\pgfpathclose}}
\pgfdeclaremetadecoration{draw part of a path}{initial}{
\state{initial}[width={\pgfmetadecoratedpathlength*\pgfdecorationsegmentlength},next state=final]{
\decoration{lineto}
}
\state{final}{\ifdim\pgfdecorationsegmentlength>0.999pt
\pgfkeys{/pgf/decoration automaton/if input segment is closepath=/pgf/close}
\fi
}
}
%
\tikzset{start segment/.style={decoration={draw part of a path,raise=2mm,segment length=#1},decorate}}
事实上,根据手册,它是装饰自动机的一个选项,因此应该按如下方式使用:\state{final}[if input segment is closepath=\closepath]{}
但路径不再关闭。
手册上说:
/pgf/decoration automaton/if input segment is closepath= < options > (no default)
此键检查当前输入段是否为 closepath 操作。如果是,则
<options>
执行 get;否则不发生任何事情。您可以使用此选项以某种特殊方式处理 closepath,例如,切换到\pgfpathclose
执行的新状态。
第一个问题:
为什么写作state{final}[if input segment is closepath=\pgfpathclose]{}
不起作用?
问题2:
- 如何使用此选项来按照手册指示进行
state
更改decoration automaton
? - 如何使用“输入段是否 closepath=<选项>”?
使用 www.DeepL.com/Translator 翻译
答案1
让我试着给你一个答案,帮助你理解发生了什么。重点是,当我给你上一个答案时,我有点幸运。(好吧,我也尝试了其他不起作用的方法,然后提出了一个起作用的方法。然而,写这个部分答案让我清楚地意识到,当我写另一个答案时,我没有意识到一些重要的事情。)我试图通过重写我的代码来解决你的问题,这样当装饰在关闭路径段时,它就会切换到一个单独的状态。我添加了几个\typeout
s 来说明发生了什么。一切都按我想象的方式工作,除了
\pgfpathclose
现在,尽管执行了,路径也不会关闭。
这就是我说的“我写上一个答案时很幸运”的意思。为什么关闭在这里不起作用?嗯,这是因为必须区分元装饰和装饰,即
\pgfdeclaredecoration
其中if input segment is closepath
定义,并且
\pgfdeclaremetadecoration
代码基于此。(不,我认为用普通装饰做同样的事情不是一个好主意,因为至少让它与由任意长度的直线组成的一般路径一起工作会非常困难。如果对线段的长度有一个量化规则,那是可能的。)这个部分答案在这里做的是将两者混合在一起。这就是为什么\pgfkeys{/pgf/decoration automaton/if input segment is closepath=...}
需要完整路径的原因。这确实有效,因为close
当自动机位于关闭路径段上时,它将切换到称为的新状态。然后它检查它是否快到了尽头,如果是,它会做些什么。然而,与我的天真期望相反,一个天真的人\pgfpathclose
确实不是在这里工作。不幸的是,我无法为您提供比我之前的答案更清晰的工作答案(我很幸运)。我有点明白它为什么在那里工作:代码切换到“普通装饰”模式并在\pgfpathclose
那里注入。我希望我可以让它更清晰。这是代码。
\documentclass[tikz,border=5mm]{standalone}
\usetikzlibrary{decorations}
\pgfdeclaremetadecoration{draw part of a path}{initial}{
\state{initial}[width={\pgfmetadecoratedpathlength*\pgfdecorationsegmentlength},next
state=almost final]{
\decoration{lineto}
} %/pgf/decoration automaton/if input segment is closepath=/pgf/close
\state{almost final}[next state=final,
/pgf/decoration automaton/if input segment is closepath={next
state=close}]{%
\typeout{almost\space final}}
\state{close}[next state=final]{
\typeout{I'm\space on\space close\space path\space segment\space and\space
have\space decorated\space\the\pgfdecorationsegmentlength}
\ifdim\pgfdecorationsegmentlength>0.999pt
\typeout{gonna\space close}
\pgfpathclose % <- does not work this way
\fi}
\state{final}{}
}
%
\tikzset{start segment/.style={decoration={draw part of a path,raise=2mm,segment length=#1},decorate}}
\begin{document}
\foreach \rpos in {0,.03,...,1,0.9999}{%
\begin{tikzpicture}[scale=1]
\fill[green!40](0,0) rectangle (4,4);
\draw[start segment=\rpos,blue,ultra thick] (0,0) -- (4,0) -- (4,4) -- (0,4) --cycle ;
\begin{scope}[xshift=5cm]
\fill[red!40](0,0) rectangle (4,4);
\draw[start segment=\rpos,blue,ultra thick] (0,0) -- (4,0) -- (4,4) -- (0,4);
\end{scope}
\end{tikzpicture}
}
\end{document}
部分摘要:
- 您可能会在某种程度上将
decoration
东西与meta decoration
东西混合在一起,但您需要很幸运才能让它按照您希望的方式发挥作用。 - 这部分 Ti钾Z magic 似乎没有在这个网站上得到充分探索,但肯定还有其他人对此有更好的理解,并且能够给你更好的答案。由于我没有看到 Jake 回答问题,我希望 @cfr 和/或 @percusse 和/或 Mark Wibrow 和/或 @Max 看到这个好问题并提供一个我们都可以学习的答案。;-)
编辑:我实际上认为问题可能比上面概述的更深。考虑 MWE
\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\foreach \rpos in {0,.03,...,1,1.1}{%
\begin{tikzpicture}[scale=1]
\fill[green!40](0,0) rectangle (4,4);
\draw[dash pattern=on \rpos*16cm off 16cm,blue,ultra thick]
(0,0) -- (4,0) -- (4,4) -- (0,4) -- cycle;
\begin{scope}[xshift=5cm]
\fill[red!40](0,0) rectangle (4,4);
\draw[dash pattern=on \rpos*16cm off 16cm,blue,ultra thick] (0,0) -- (4,0) -- (4,4) -- (0,4);
\end{scope}
\end{tikzpicture}
}
\end{document}
没有装饰,只有虚线图案才能达到同样的效果。第一个边界的最终路径是不是关闭
尽管那里的on
相位比路径长。因此出于某种原因 Ti钾Z 甚至没有关闭这条路径。(如果这可行,那么它将成为更简单的解决方案的基础,只需用16cm
一些\pgfdecoratedpathlength
可以读取的内容替换硬编码,例如这里)当然,你总是可以手动关闭这个简单的路径:
\draw[dash pattern=on \rpos*16cm off 16cm,blue,ultra thick]
(0,0) -- (4,0) -- (4,4) -- (0,4) -- (0,-\pgflinewidth/2) -- cycle;
但我个人认为,即使我无法按照您建议的方式重写它,我以前的工作解决方案也会更好。