1

如何发现旋转/缩放的值?例如,在我发出以下命令后:

90 rotate

当前旋转设置为 90。如何发现旋转设置为?

4

3 回答 3

2

旋转(也包括缩放和剪切)没有单独的值。所有此类转换都汇总到当前转换矩阵 (CTM) 中。

您可以在 PostScript 语言参考手册中找到对 CTM 和转换的出色描述,尤其是第 4.3.1 到 4.3.3 节。它是 PostScript 理解的一个重要领域,因为 CTM 支持所有绘图操作。我认为在这个论坛上解释它真的太复杂了。

简短的回答是没有简单的解决方案,您必须做一些矩阵代数才能找出点映射到的位置。一个常见的技巧是通过 CTM(点 0,0 和 1,1)传递单位正方形的坐标,然后查看变换后的点在哪里结束。

于 2012-08-02T15:32:18.313 回答
2

如果你真的只做旋转、平移和统一缩放,那么你可以将仿射变换矩阵 (3x2) 分解为平移向量 (1x2) 和线性变换矩阵 (2x2)。然后,一个小三角实际上可以给你旋转。

所以这是在后记中做到这一点的一种方法。它做了一些矩阵操作,不是对 CTM 进行操作,而是对一个矩阵进行操作,如果乘以默认矩阵,则该矩阵将产生 CTM。它按顺序返回旋转角度、缩放因子和平移偏移量。将运算符序列translate scale rotate应用于这些值(如果默认矩阵有效)将生成当前矩阵。

我有点得意忘形,试图让它优雅地拒绝使用 PS 错误机制无法处理的矩阵(在解释器之间没有完全标准化,因为它在标准中基本上没有记录)。为了测试它,我从其他地方引入了一些随机种子代码。但隐藏在中间的是一个相对简单的公式b a atan,它产生角度(其中[a b c d e f]是矩阵值的名称,a == d,b == -c)。

%!
%make Adobe-style interpreters mimic ghostscript's error call
/.error where { pop /signalerror {.error} def } if

%"Safe" seed randomizer
{ 0 4{ 8 bitshift (/dev/random)(r)file read pop add }repeat srand } stopped
{ usertime 10 { %can't open file, chop some vegetables
    save 128 string 99 2 getinterval 1 vmreclaim pop restore
              } repeat usertime 8 bitshift add srand } if

%translate, scale, rotate
% extracts rotation, scaling and translation parameters
% from the CTM (assuming it's "easy" to do)
%
%eg.
% PS> rand 100 mod          %get random number 0..99
% PS> { 1 rotate } repeat   %rotate
% PS> tsr 4 pop =           %print rotation angle
%
% -  tsr  theta Sx Sy Tx Ty
/tsr { {
    6 dict begin
    matrix currentmatrix % get CTM
    matrix defaultmatrix % get Default
    matrix invertmatrix  % get the "undo" of the Default
    matrix concatmatrix  % CTM * Default^-1 =  Default-->CTM
    aload pop % dump the matrix components
    {/ty/tx/d/c/b/a}{exch def}forall % name the components
        a d ne
        b neg c ne or  %ie. not "Jacobian", not "conformal"
        { [ a b c d tx ty ] /tsr cvx /undefinedresult signalerror } if

        b a atan % theta
        a a mul b b mul add sqrt dup % Sx Sy (uniform scaling factors)
        tx ty % translation
    end
exit } loop } def

%1 2 scale resolve  %test error trigger
rand 100 mod
{ 1 rotate } repeat
rand 100 mod
{ rand 3 mod .5 add dup scale } repeat
tsr pstack
于 2012-08-13T21:31:49.573 回答
0

一种可能的方法是重载rotate,以便它方便的形式跟踪值。

/oldrotate /rotate load def
/rotate { dup oldrotate
    /currentrotation dup load 3 2 roll add 360 mod store
}
/currentrotation 0 def

setmatrix不幸的是,如果您使用的是or ,这还不够gsave ... grestore

于 2012-08-06T03:53:52.753 回答