microbik.ru
  1 ... 4 5 6 7 8 ... 11 12

Сглаживание углов


Пересекающиеся линии часто бывает необходимо соединить плавной кривой. В PostScript для этого существует удобный оператор arcto. В качестве операндов ему в стеке задаются координаты двух точек и радиус, т. е.:

x1 y1 x2 y2 r arcto

Он рисует сегмент прямой линии от текущей точки по направлению к точке х1, у1, а затем дугу до её пересечения со второй прямой.

<рисунок 4 R4.psc на бумаге>

Arcto возвращает в стеке координаты начала и конца дуги. Если они не нужны, то эти числа следует удалить из стека:

4 {pop} repeat

Используя оператор arcto, нарисуем какую-нибудь карточку:

/clearstack {4{ pop} repeat} def

200 300 translate

0 20 moveto

0 72 108 72 20 arcto clearstack

108 72 108 0 20 arcto clearstack

108 0 0 0 20 arcto clearstack

0 0 0 72 20 arcto clearstack

fill

0.5 setgray

80 45 20 0 360 arc fill

/Helvetica findfont 25 scalefont setfont

30 50 moveto

(My Card) show

showpage

Условные переходы



Введем понятие выполняемого массива. Это более формальное название объекта, который ранее был назван процедурой.

Какая разница для PostScript между строками
12 5 sub

и

{ 12 5 sub} ?
В первом случае числа 12 и 5 будут помещены в стек и будет выполнена операция вычитания, а во втором -- эти числа и оператор sub будут помещены в массив, который затем будет занесен в стек. Выполняемому массиву может предшествовать имя, задаваемое в виде литерала, а закрывать его может оператор def, который ассоциирует его с именем в текущем словаре.

Выполняемый массив может использоваться также в некоторых управляющих операторах, таких как repeat. В этом случае выполняемый массив содержит операции, которые будут иметь место, когда выполнятся условия для условного оператора.

Оператор if



Прежде чем рассмотреть этот популярный во всех процедурных языках оператор, посмотрим, как записываются операции сравнения чисел. В PostScript, напоминаю, операторы сравнения следуют за сравниваемыми величинами.

Оператор Значение

eg = (равно)

gt > (больше)

ge >= (больше или равно)

ne <> (не равно)

lt < (меньше)

le <= (меньше или равно)

Логические операторы: not and or и xor.


Результат операции сравнения или логической операции -- логическое значение true или false. Оператор if берет из стека логический объект и выполняемый массив. Если значение логического объекта true, то выполняются операции, записанные в этом массиве.

Пример.

/step 15 def

/rightmargin 450 def

/checkmargin

{currentpoint pop % оставляет в стеке х

rightmargin gt % >450

{ 0 step translate 0 0 moveto} if

} def

Процедура получает координату текущей точки и сравнивает её со значением правой границы рабочего поля. Если условие выполняется, то происходит перенос начала координат на следующую строку.

Оператор ifelse


Позволяет выбрать в зависимости от условия выполнение одной или другой последовательности операторов. Его формат:

условие {op.1} {op>2} ifelse

Если результат выполнения условия true, выполняется последовательность {op.1}, иначе -- {op.2}.

У попа была собака

Эта фраза замечательна тем, что мы с детства получаем представление о рекурсии. PostScript поддерживает рекурсивный вызов процедур, т. е. когда процедура вызывает сама себя. Классический пример -- вычисление факториала:

/factorial % в стеке n

{dup 1 gt

{ dup 1 sub factorial mul} if

} def

% вызов

5 factorial

cvs show

Новый оператор cvs преобразует число из вершины стека и помещает его в заданную строку. Дело в том, что оператор show может печатать только строки. Кроме чисел, cvs преобразует и логические величины -- они заменяются в зависимости от значения словами true или false. Вот пример процедуры, печатающей целое число из стека:

/printint

{( ) cvs show} def % строка первоначально содержит 3 пробела

Оператор string создает строку длиной n. Определение строковой переменной выглядит так:

/nstr 7 string def

где 7 -- длина строки (знаков).

Рекурсивный вызов процедур даёт возможность рисовать фрактальные картинки, но это мы попробуем сделать на следующем занятии, когда изучим конструкции циклов.
Занятие четвёртое
Начиная весной эту серию уроков у меня было сомнение -- хватит ли материала на семь занятий. Задав в Интернет поиск по ключевому слову PostScript и получив сообщение, что найдено более 99 тыс. документов, где оно встречается, я успокоился – об этом языке писать можно до 2000 года. Кроме того, обнаружилась книга по PostScript и на русском языке. Это изданный Физматлитом в 1993 г. учебник: Ф.Доймлинг, Д.Стиллеску "Язык программирования PostScript. 20 уроков быстрого освоения". В ней очень детально описывается то, что нами будет пройдено на четырех первых уроках. Следует отметить, что наши занятия методически следуют книге "PostScript Language Tutorial and Cookbook" (Adobe Systems & Addison Wesley, 1987), являющейся де-факто описанием стандарта языка и потому именуемой "Голубой книгой". Тем у кого это издание есть, я рекомендую подождать седьмого урока, который будет отчасти посвящён текущему состоянию языка, литературе и другим не описанным в "Голубой книге" вопросам.

Ну, а если у вас по ходу чтения уроков возникли вопросы, предложения или пожелания, вы можете связаться с автором по телефону (095)237-8901 или по адресу chief@pcweek.ru.
Циклы
В языке PostScript имеется три основных конструкции циклов: простой цикл, индексируемый цикл и условный цикл.

Простой цикл неявным образом уже использовался в примерах предыдущего занятия. Он реализуется с помощью оператора repeat, который берет из стека два операнда: счетчик цикла и повторяемую процедуру. Например, для очистки стека мы использовали следующий цикл:

4 {pop} repeat
Здесь всё достаточно прозрачно, непривычно, может быть, только то, что в качестве одного из аргументов выступает повторяемая процедура.

Задание. Нарисуйте последовательность из N вложенных кругов, квадратов, эллипсов.

Индексируемый цикл напоминает широко известную по Бейсику конструкцию for... to... next. Оператор for берет из стека четыре операнда: начальное значение счетчика цикла, его приращение, конечное значение счетчика цикла и повторяемую процедуру. За исключением последнего операнда всё выглядит как и в обычной конструкция for. Следует учитывать, что непосредственно перед выполнением этой процедуры for помещает в стек текущее значение счетчика и, если он не используется, то его следует оттуда явным образом удалять.

Следующая строка напечатает звездочку через каждые 15 единиц на странице:

0 15 450 {0 moveto (*) show } for

Задание. Нарисуйте пунктирную линию.

Вторая важная особенность for в том, что его операнды не обязательно должны быть целыми числами. Вот пример использования этого для возможной модификации шрифта:

/Helvetica findfont 30 scalefont setfont

/printword

{ 0 0 moveto (PC Magazine) show} def

200 300 translate

.95 -.05 0 % начало приращения, конец

{setgray printword -1.5 translate} for

1 setgray printword

showpage

<рис. файл p4_1.ps>

Условный цикл соответствует конструкции repeat...until в Паскале. Строится он из двух операторов: loop и exit. Опертор loop повторяет выполнение процедуры до тех пор пока в ней не встретится оператор exit, который заканчивает циклическое выполнение, причем не только в конструкции loop, но и в for, repeat и forall (об этой специальной форме цикла будет расказано ниже). Если в повторяемой процедуре нет оператора exit, то цикл будет бесконечным, например:

{(PC Magazine) show} loop

будет бесконечно печатать слово PC Magazine.

Нарисуем незамысловатую последовательность кругов просто, чтобы продемонстрировать работу loop - exit.

/pagewidth 8 72 mul def

/circle

{x y radius 0 360 arc stroke} def

/new-x

{x radius add

/x exch def} def

/dolineofcrle

{/y exch def

/radius exch def

/x 0 def

{x pagewidth le

{circle new-x}

{exit} ifelse

} loop

} def

% main

15 200 dolineofcrle

25 200 dolineofcrle

showpage


<< предыдущая страница   следующая страница >>