问题
How can I discover the values of rotate/scale? For example, after I issue the following command:
90 rotate
the current rotation is set to 90. How do I discover what rotate is set to?
回答1:
Rotation (also scaling and shearing) do not have individual values. All such transformations are rolled up into the Current Transformation Matrix (CTM).
You can find an excellent description of the CTM and the transformations in the PostScript Language Reference Manual, especially sections 4.3.1 to 4.3.3. Its an important area to understand for PostScript as the CTM underpins all drawing operations. Its really too complex to explain in this forum I think.
The short answer is that there is no simple solution, you have to do some matrix algebra to find out where points map to. A common trick is to pass the co-ordinates of the unit square through the CTM (points 0,0 and 1,1) and see where the transformed points end up.
回答2:
If you really have been doing nothing but rotations, translations, and uniform scaling, then you can decompose the affine transformation matrix (3x2) into a translation vector (1x2) and a linear transformation matrix (2x2). Then, a little trig can, in fact, give you the rotation.
So here's one way to do this in postscript. It does some matrix manipulations to operate not on the CTM, but on a matrix which would yield the CTM if multiplied by the Default Matrix. It returns the rotation angle, scaling factors, and translation offsets, in that order. Applying the operator sequence translate scale rotate
to these values -- if the Default Matrix were in effect -- would produce the Current Matrix.
And I got a little carried away trying to make it elegantly reject matrices it can't handle by using the PS error mechanism (not completely standardized across interpreters because it was largely undocumented in the standard). And to test it, I brought in some random-seed code from elsewhere. But hidden in the middle is a relatively simple formula b a atan
which yields the angle (where [a b c d e f]
are names of the matrix values, and a == d, and 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
回答3:
One possible way to do this would be to overload rotate
so that it does track the value in a convenient form.
/oldrotate /rotate load def
/rotate { dup oldrotate
/currentrotation dup load 3 2 roll add 360 mod store
}
/currentrotation 0 def
Unfortunately, this isn't sufficient if you're using setmatrix
or gsave ... grestore
.
来源:https://stackoverflow.com/questions/11777305/postscript-discover-rotate-scale-value