Сила Postscript заключается в его безжалостном стремлении к идеалу «отложенного связывания». Выполнение вращений не является исключением. Он работает, используя более общий инструмент, матрицу аффинного преобразования.
Вы можете вращать как текст, так и графику (поскольку текст ЯВЛЯЕТСЯ графикой), поскольку все указанные пользователем координаты сначала умножаются на эту матрицу, чтобы получить координаты устройства.
Чтобы выполнить все необходимые трюки (масштабирование, вращение, сдвиг, перемещение), мы сначала должны расширить точки 2d до точек 3d на плоскости z=1 (не спрашивайте меня, почему; прочтите Математические иллюстрации Билла Кассельмана<). /em> или Adobe Blue Book для получения дополнительной информации).
[ x [ a b 0
y * c d 0 = [ x' y' 1 ] = [ ax+cy+e bx+dy+f 1 ]
1 ] e f 1 ]
Поскольку 3-й столбец матрицы всегда [ 0 0 1 ], он опущен во внешнем представлении, и матрица описывается в постскриптуме как:
[ a b c d e f ]
Поэтому, когда вы используете пару координат, скажем, для оператора moveto
, moveto
сначала преобразует ее в координаты устройства, x' = ax+by+e, y' = cx+dy+f, прежде чем добавить элемент <</move [x' y']>>
к текущему пути. . Изменить матрицу: изменить «смысл» пользовательских координат.
Матрица идентичности такова:
[ 1 0 0 1 0 0 ] % x' = x, y' = y
Для масштабирования замените единицы на коэффициенты масштабирования x и y:
[ Sx 0 0 Sy 0 0 ] % x' = Sx*x, y' = Sy*y
Для перевода замените e и f смещениями перевода x и y:
[ 1 0 0 1 Tx Ty ] % x' = x+Tx, y' = y+Ty
Чтобы повернуть, замените a,b,c,d коэффициентами масштабирования и сдвига sin и cos:
[ cosW sinW -sinW cosW 0 0 ] % x' = x*cosW-y*sinW, y' = x*sinW+y*cosW, where W is angle(degrees) from x-axis
Вы «устанавливаете» эту матрицу с помощью concat
, которая берет матрицу текущего преобразования (CTM), умножает ее на вашу новую матрицу и использует продукт в качестве нового CTM. Таким образом, translate
, rotate
и scale
— это просто «удобные функции», которые можно реализовать следующим образом:
/translate { [ 1 0 0 1 7 -2 roll ] concat } def
/scale { [ 3 1 roll 0 0 3 -1 roll 0 0 ] concat } def
/rotate { [ exch dup cos exch sin dup neg 2 index 0 0 ] concat } def
Поскольку CTM является частью графического состояния, вы можете использовать стек графического состояния для иерархического управления вашими преобразованиями:
/box { % x y w h %create a path in the shape of a box w*h with lower left corner at x,y
4 2 roll moveto
exch dup 3 1 roll
0 rlineto
0 exch rlineto
neg 0 rlineto
closepath
} def
/Courier 10 selectfont
100 100 100 100 box stroke % draw an oriented box
120 120 moveto (inside) show
gsave
150 150 translate % make the center of the box the new 0,0 point
45 rotate % rotate CCW 45 degrees
0 0 100 100 box stroke % a rotated, shifted box
20 20 moveto (inside) show
grestore
100 200 100 100 box stroke % another box, just north of the first, in the original coordinte system
120 220 moveto (inside) show
Получается следующее изображение:
![Вращение блоков и текста](https://i.stack.imgur.com/aeMKZ.png)
(источник: googlecode .com)
person
luser droog
schedule
21.10.2011