如何发现旋转/缩放的值?例如,在我发出以下命令后:
90 rotate
当前旋转设置为90.如何找到旋转设置为?
答案 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
不幸的是,如果您使用setmatrix
或gsave ... grestore
,这还不够。