是否存在一些 tikz 寄存器(比如说 \zoomfactor)来提供当前的比例因子。例如,我可以这样做:
\begin{tikzpicture}[scale=2]
\begin{scope}[scale=1.5]
\draw (0,0) circle (\zoomfactor);
\end{scope}
\end{tikzpicture}
并得到大小为 3=2*1.5 的圆?
答案1
您可以获取当前变换条目来提取比例,但如果存在不同的 x 和 y 比例(或组合,例如全矩阵),则此操作将失败并仅检索 x 比例。此外,它使用 1cm 作为单位向量。
\documentclass{article}
\usepackage{tikz}
\newcommand{\getzoomfactor}{%
\pgfgettransformentries{\myxscale}{\@tempa}{\@tempa}{\myyscale}{\@tempa}{\@tempa}
\gdef\zoomfactor{\myxscale*1cm}
}
\begin{document}
\begin{tikzpicture}[scale=2]
\begin{scope}[scale=1.5]
\getzoomfactor
\draw (0,0) circle (\zoomfactor);
\node {\zoomfactor};
\end{scope}
\end{tikzpicture}
\end{document}
答案2
获得适用于所有角度保持变换(即缩放 + 旋转 + 反射的组合)的整体比例因子的可靠方法是取变换矩阵行列式绝对值的平方根。可以使用以下两行获得此数字:
\pgfgettransformentries{\myscaleA}{\myscaleB}{\myscaleC}{\myscaleD}{\mytmp}{\mytmp}
\pgfmathsetmacro{\scalefactor}{sqrt(abs(\myscaleA*\myscaleD-\myscaleB*\myscaleC))}
在下面的演示中,我将这两行代码包装在一个名为的命令中\getscale
,该命令将命令序列作为参数并为其分配当前活动的比例因子。因此,如果您调用\getscale{\scalefactor}
,则宏\scalefactor
将扩展到此因子。此定义中的其他三行不太重要;它们只是为了限制等的范围,\myscaleA
以便这些不会被此命令(重新)定义。
下面每个圆圈内的数字是当前活动的比例因子,我已经根据该因子缩放了该文本和线宽。
\documentclass[tikz,margin=1mm]{standalone}
\newcommand*\getscale[1]{%
\begingroup
\pgfgettransformentries{\scaleA}{\scaleB}{\scaleC}{\scaleD}{\whatevs}{\whatevs}%
\pgfmathsetmacro{#1}{sqrt(abs(\scaleA*\scaleD-\scaleB*\scaleC))}%
\expandafter
\endgroup
\expandafter\def\expandafter#1\expandafter{#1}%
}
\begin{document}
\begin{tikzpicture}
\foreach \angle/\yshift in {0/0cm,60/1.6cm,120/3.2cm,180/4.8cm} {
\foreach \scale/\xshift in {1/0cm,.7071/1.6cm,.5/2.73cm,.3536/3.53cm,.25/4.10cm} {
\begin{scope}[xshift=\xshift,yshift=-\yshift,scale=\scale,rotate=\angle]
\getscale{\scalefactor}
\draw[->,line cap=round,line width=\scalefactor*1pt] (.75,0) arc (2:358:.75);
\node[scale=\scalefactor] at (0,0) {\scalefactor};
\end{scope}%
}\par
}
\end{tikzpicture}
\end{document}
我没有在这个演示中包含反射,因为我不想让它太长,但您可以通过将例如添加xscale=-1
到范围来测试它们。不要担心舍入误差;它们是 TeX 固有的,无关紧要。
值得注意的是,通过将键添加transform shape
到节点而不是scale=…
,文本可以与其他所有内容一起转换,但这不适用于线宽。使用此键,上面的文本将被旋转和缩放。
解释
- 将
\pgfgettransformentries{\myA}{\myB}{\myC}{\myD}{\myx}{\myy}
活动2×2变换矩阵“ ”的四个元素(A&B\\C&D)
以及平移点的平移向量的两个分量分配给\myA
、\myB
等。 - 该矩阵的行列式为A 德 − 乙 C,我们感兴趣的量是这个表达式的绝对值的平方根,即√(| A 德 − 乙 C |)。
- 这决定因素一般 2×2 矩阵的 是应用相应变换时所有(有符号)区域缩放的因子。它在一个方向上随缩放线性缩放,在均匀缩放时随缩放二次(因此为
sqrt(…)
),其符号通过沿线反射反转(因此为abs(…)
)。对于恒等变换以及所有旋转和剪切,它为 1,如果应用多个变换,则这些数字只需相乘即可。 - 对于涉及非均匀缩放和/或剪切的变换,缩放因子与方向有关,并且指定的值
\getscale
将是所有可能方向的平均值。 - 您也可以用类似的方式恢复旋转角度。
为什么这是必要的
Percusse 的方法如果应用的变换只有缩放,则效果很好,但如果还涉及旋转或反射(或其他变换),则效果会很差。当示波器按因子 λ 缩放,按角度 θ 旋转,然后可选地通过垂直轴反射时,传递给的第一个参数 \pgfgettransformentries
设置为 ± λ cos(θ),其中 ± 可以是 + 或 −,具体取决于是否应用了反射。因此,它基本上只有在完全不应用旋转或反射(或它们恰好抵消)的情况下才会产生正确的答案。
为了教育目的/为了好玩,这里演示了如果只使用变换矩阵的第一个条目会出现什么问题。第一个圆是正常的,第二个圆旋转了 60º,第三个圆通过垂直轴反射。最后一个圆的线宽为-1pt
,看起来它的外观取决于观察者(我不知道打印出来会是什么样子)。
\documentclass[tikz]{standalone}
\begin{document}\begin{tikzpicture}
\begin{scope}[xshift=0cm,rotate=0,scale=1] %% <- does nothing
\pgfgettransformentries{\scalefactor}{\tmp}{\tmp}{\tmp}{\tmp}{\tmp}
\draw[->,line cap=round,line width=\scalefactor*1pt] (.75,0) arc (2:358:.75);
\node at (0,0) {\scalefactor};
\end{scope}
\begin{scope}[xshift=1.6cm,rotate=60,scale=1] %% <- translation + rotation
\pgfgettransformentries{\scalefactor}{\tmp}{\tmp}{\tmp}{\tmp}{\tmp}
\draw[->,line cap=round,line width=\scalefactor*1pt] (.75,0) arc (2:358:.75);
\node[scale=\scalefactor] at (0,0) {\scalefactor};
\end{scope}%
\begin{scope}[xshift=3.2cm,rotate=0,xscale=-1] %% <- translation + reflection
\pgfgettransformentries{\scalefactor}{\tmp}{\tmp}{\tmp}{\tmp}{\tmp}
\draw[->,line cap=round,line width=\scalefactor*1pt] (.75,0) arc (2:358:.75);
\node[scale=\scalefactor] at (0,0) {\scalefactor};
\end{scope}%
\end{tikzpicture}
\end{document}