恢复 TikZ 中的缩放因子

恢复 TikZ 中的缩放因子

是否存在一些 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}

输出

相关内容