后记:发现旋转/比例值

时间:2012-08-02 12:21:03

标签: postscript

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

90 rotate

当前旋转设置为90.如何找到旋转设置为?

3 个答案:

答案 0 :(得分:2)

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

您可以在PostScript语言参考手册中找到有关CTM和转换的精彩描述,尤其是4.3.1至4.3.3节。它是了解PostScript的一个重要领域,因为CTM是所有绘图操作的基础。在我认为这个论坛中解释起来真的太复杂了。

简短的回答是没有简单的解决方案,你必须做一些矩阵代数来找出点映射的位置。一个常见的技巧是通过CTM(点0,0和1,1)传递单位平方的坐标,并查看转换点的最终位置。

答案 1 :(得分:1)

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

所以这是在postscript中执行此操作的一种方法。它做了一些矩阵操作,不在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

答案 2 :(得分:0)

执行此操作的一种可能方法是重载rotate,以便 以方便的形式跟踪值。

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

不幸的是,如果您使用setmatrixgsave ... grestore,这还不够。