ГЛАВА 2
От реальных координат к пикселям
Для изображения SPECTRUM представляет графический экран, т.е. матрицу адресуемых точек и пикселей. Пиксели сгруппированы в 256 вертикальных столбцов(МХР1Х) и 176 горизонтальных строк (NYPIX). Установка NXPIX и NYPIX осуществляется парой целых чисел, называемых вектором пикселей (I,J), где 0<=I<=NXPIX-1 и 0<=J<=NYPIX-1. Этот вектор задает позицию пикселя в I-ом столбце и J-ой строке. Вектор (0,0) идентифицирует самый нижний левый пиксель экрана. SPECTRUM имеет специальные команды бейсика для оперирования матрицей пикселей. Они позволяют "включать" их. Это делает возможным аппроксимировать линии, или полигоны, или другие графические объекты последовательностью цветных точек.
В главе будут описаны возможности создания двумерных и трехмерных графических объектов на SPECTRUMe при помощи программ на бейсике. Эти элементарные подпрограммы приведены в данной главе. Примитивы, обеспечивающие карту пространства на графическом экране
В целом компьютерная графика состоит из точек, линий, областей и координат вне прерывном двумерном и трехмерном евклидовом пространстве. Пиксельная графика довольно ограничена. Изображение объекта в дискретном поле очень усложняет практическое использование этого способа.
Рассмотрим отношение между двумерным реальным пространством и экранными пикселями. Мы можем вообразить себе двумерное пространство как плоскость. Для использования координатной геометрии (планиметрии) мы должны зафиксировать точку в этом пространстве, которую мы будем называть началом координат. Через начало координат проведем две взаимно перпендикулярные линии, Х-ось и Y-ось. Теперь начертим шкалу вдоль каждой из осей. (см. рис. 9)
Мы полагаем, что значения на Х-оси положительны справа, а слева отрицательны; значения на Y-оси положительны выше начала координат и отрицательны ниже.
Теперь позиция любой точки Р на плоскости однозначно определяется ее координатами. Координата по Х-оси, обозначим ее X, определяется как расстояние от начала координат до точки пересечения прямой, перпендикулярной оси X и проходящей через точку Р с осью X, взятое с положительным знаком, если эта точка находится справа от начала координат, и с противоположным, если слева. Аналогичным образом определяется Y-координата. Эти два значения, называемые парой координат двумерного вектора, обычно записываются в скобках: (X,Y). Обратите внимание, что первой записывается X координата, за которой следует Y-координата. Как правило, мы будем называть эту пару вектором, размерность которого будет ясна из контекста. Кроме точки (X,Y), вектор определяет также и направление, которое параллельно прямой, соединяющей начало координат с точкой (X,Y); дополнительные сведения по этим вопросам вы найдете в главе 3.
Сейчас мы должны развить средства (упомянутые выше примитивные функции) для переноса геометрических понятий на состоящую из точек двумерную матрицу.
Здесь мы ограничимся случаем двух измерений: трехмерная геометрия рассматривается, начиная с главы 7. В обоих случаях нам потребуется отображение прямоугольной области двумерной действительной плоскости на дискретную графическую плоскость. Для простоты предположим, что стороны этой области параллельны координатным осям. Вначале предположим, что левый нижний угол прямоугольника находится в начале координат. (0.0,0.0), а длина горизонтальной стороны равна HORIZ,вертикальной - VERT; отождествим также начало координат с пикселем (0,0), а затем выберем такой масштаб прямоугольной области, чтобы она поместилась в дисплейном поле. Область может в точности совпадать с дисплейным окном, если только соотношение HORIZ: VERT и NXPIX: NYPIX равны. Эта ситуация встречается крайне редко, и поэтому мы используем масштабирующий множитель XYSCALE, который помещает точку (HORIZ,VERT) либо на правой стороне рамки дисплейного окна, либо на верхней. Мы можем считать этот прямоугольник окном в декартову плоскость; оно уже не привязано к началу координат, а может перемещаться по плоскости, при этом стороны остаются параллельными координатами осям; при таком движении это окно сканирует области плоскости, по форме совпадающие с первоначальной. Как правило, мы будем выбирать HORIZ примерно в полтора раза больше VERT.
В любой момент выполнения программы начало координат может быть передвинуто из первоначального положения в левом нижнем углу в любую другую точку с координатами XORG и YORG, обозначающие значение Х-координаты и Y-координаты точки. Точка (XORG,YORG) отождествляется с началом координат (0.0,0.0), а точка декартовой плоскости с координатами (XPT.YPT) отображается в элементе изображения с горизонтальной компонентой INT ((XORG+XPT) * XYSCALE+0.5) и вертикальной компонентой INT ((YORG+YPT) * XYSCALE+ 0.5). (INT - функция бейсика, возвращающая целое число, равное целой части вещественного аргумента).
Эти две компоненты хранятся функциями FNX и FNY (см. листинг 2.2). Во время рисования на экране мы имеем дело с точечным пером, управляемым парой целых чисел и перемещающимся по экрану; вначале это перо находится в точке (0,0), а в общем случае в точке (XPEN,YPEN). Константы NXPIX, NYPIX и переменные XYSCALE, XPEN, YPEX, XORIZ, YORIG должны быть доступными для приведенных ниже подпрограмм нанесения точек на экран в любой момент времени, так что эти имена нельзя использовать для других целей. Эти подпрограммы написаны специально для SPECTRUMa, но мы обсуждаем принципы составления аналогичных подпрограмм для других устройств. Перед тем, как использовать иное устройство, нам для начала пришлось бы изменить значения NXPIX и NYPIX.
Наша первая подпрограмма START присваивает значения переменным и подготавливает экран для работы. Листинг 2.1 содержит пример такой подпрограммы для SPECTRUM. LI STING 2.1
9700 REM START
9701 REM IN - HORIZ,VERT
9702 REM OUT - NXPIX,NYPIX,XORIG,YORIG,XYSCALE,XPEN,YPEN 9710 LET XORIG=0: LET YORIG=0
9720 LET XPEN=0: LET YPEN=0 9730 LET NXPIX=256: LET NYPIX=176
9740 LET XYSCALE=NXPIX/HORIZ: LET YSCALE=NYPIX/VERT 9750 IF XYSCALE>YSCALE THEN LET XYSCALE=YSCALE 9760 RETURN
Если мы хотим использовать цветовые возможности, то нам следует ввести два дополнительных параметра COLPAP и COLINK (целые числа в диапазоне от 0 до 7) для определения цвета фона и цвета изображения. Соответствующий оператор:
9725 PAPER COLPAP: INK COLINK
Если мы хотим написать эту программу для другого компьютера, то необходимо заменить команды графики SPECTRUMa на эквивалентные команды для него.
В подпрограмме START и во многих других подпрограммах, приведенных ниже, нам потребуется переводить X и Y координаты точки в их аналог для пикселей, с этой целью мы вводим две функции FNX и FNY на листинге 2.2.
LISTING 2.2
9650 DEF FN X(Z)= INT ((XORIG+Z)*XYSCALE+0.5) 9660 DEF FN Y(Z)= INT ((YORIG+Z)*XYSCALE+0.5)
Следующая подпрограмма SETORIGIN позволяет передвигать начало координат на величину XMOVE по горизонтали и YMOVE по вертикали (в масштабе координатной системы) и соответствующим образом меняет величину (XORIG.YORIG). После этого перо устанавливается на пиксель, соответствующий новому началу координат.
LISTING 2.3
9600 REM SETORIGIN
9601 REM IN - XORIG,YORIG,XMOVE,YMOVE
9602 REM OUT - XORIG,YORIG,XPEN,YPEN
9610 LET XORIG=XORIG+XMOVE: LET YORIG=YORIG+YMOVE 9620 LET XPEN=FN X(0) 9630 LET YPEN=FN Y(0) 9640 RETURN
Мы сможем чертить прямые после того, как введем еще две функции: "MOVETO", которая помещает перо в элемент изображения, соответствующий началу отрезка, и "LINETO", которая проводит прямую из первоначального положения (задаваемого обращением к подпрограммам "SETORIGIN", "MOVETO", "LINETO") на пиксель, соответствующий другому концу отрезка. На листингах 2.4 и 2.5 приводятся тексты программ "LINETO" и "MOVETO", написанные специально для SPECTRUMa. Подпрограмма "LINETO" использует машинно-зависимую программу бейсика DRAW, для того, чтобы начертить прямую (обратите внимание на то, что PLOT использует абсолютные координаты, a DRAW - относительные); подпрограмма "MOVETO" является машинно-независимой. Таким образом, если вы хотите использовать эти программы для другого устройства, то вам придется модифицировать только подпрограмму "LINETO". LISTING 2.4
9500 REM MOVETO
9501 REM IN - XPT,YPT
9502 REM OUT - XPEN,YPEN 9510 LET XPEN=FN X(XPT) 9520 LET YPEN=FN Y(YPT) 9530 RETURN
LISTING 2.5 9400 REM LINETO
9401 REM IN - XPT,YPT, XPEN.YPEN
9402 REM OUT- XPEN,YPEN 9410 LET NXPEN=FN X(XPT) 9420 LET NYPEN=FN Y(YPT) 9430 PLOT XPEN,YPEN
9440 DRAW NXPEN=XPEN, NYPEN=YPEN 9450 LET XPEN=NXPEN: LET YPEN=NYPEN 9460 RETURN
Во всех компьютерах, кроме самых примитивных, эти программы можно поместить в библиотеку или в фоновую память (BACKING STORE), что избавит вас от необходимости впечатывать их в тело каждой новой программы. В SPECTRUMe вы можете хранить эти программы в виде файлов на кассете (загружая их командой MERGE). У нас эти программы хранятся в библиотеке "LIBIA". Упражнение 2.1
Отождествите прямоугольную область на декартовой плоскости со сторонами 30 ед. х 20 ед. с графическим полем дисплея SPECTRUMa нарисуйте в центре этого прямоугольника квадрат со стороной 15 ед.
Мы помещаем квадрат в центр, помещая начало координат в точке (±7.5; ±7.5). См. листинг 2.6.
LISTING 2.6
100 REM SQUARE
109 REM SETUR IDENTIFIERS TO GRAPHICS ROUTINES.
110 LET START=9700: LET SETORIGIN=9600: LET MOVETO=9500: LET LINETO=9400
119 REM DEFINE GRAPHCS AREA.
120 LET HORIZ=30: LET VERT=20 130 GO SUB START
140 LET XMOVE=HORIZ*0.5: LET YMOVE=VERT*0.5 150 GO SUB SETORIGIN
159 REM JOIN CORNERS OF SQUARE IN ORDER.
160 LET XPT=7.5: LET YPT=7.5: GO SUB MOVETO 170 LET XPT=-7.5: LET YET=7.5: GO SUB LINETO 180 LET XPT=-7.5: LET YPT=-7.5: GO SUB LINETO 190 LET XPT=7.5: LET YPT=-7.5: GO SUB LINETO 200 LET XPT=7.5: LET YPT=7.5: GO SUB LINETO 210 STOP
Отметим, что порядок соединения вершин в этой задаче существенен.
Теперь мы составим программу "POLIGON", которая чертит многоугольники, используя команды SPECTRUMa для вычерчивания прямых (см. листинг 2.7). LISTING 2.7
100 REM MAIN PROGRAM/CALLING POLIGON
110 LET START=9700: LET SETORIGIN=9600: LET MOVETO=9500: LET LINETO=9400: LET POLIGON=300
120 LET HORIZ=30: LET VERT=20 130 GO SUB START 140 LET XMOVE=0: LET YMOVE=0 150 GO SUB SETORIGIN
159 REM DECLARE AND INPUT VERTICES OF POLIGON.
160 DIM X(50): DIM Y(50)
170 INPUT "NUMBER OF VERTICES-";NPOL 180 FOR I=1 TO NPOL
190 INPUT ("X("+STR$ I+")-");X(I);(" Y("+STR$ I+")=");Y(I)
200 NEXT I
210 GO SUB POLIGON
220 STOP
300 REM POLIGON
301 REM IN - NPOL,X(POL),Y(POL) 310 FOR I=1 TO NPOL
320 LET XPT=X(I): LET YPT=Y(I): GO SUB MOVETO
330 LET XPT=X(I+1): LET YPT=Y(I+1): IF I=NPOL THEN LET XPT=X(1): LET YPT=Y(1)
340 GO SUB LINETO
350 NEXT I
360 RETURN
Упражнение 2.2
Если вы используете SPECTRUM, то вы можете рисовать орнаменты с различным сочетанием цветов, но для этого необходимо вначале установить рисующий цвет INK. Напишите подпрограмму "SETING", выполняющую эту функцию с одним входным параметром COLINK. Упражнение 2.3
Во всех описанных выше подпрограммах значение масштабного множителя XYSCALE фиксировано и одинаково для обеих осей. Введите два масштабных фактора XSCALE и YSCALE и напишите подпрограмму
"FACTOR", которая бы изменяла горизонтальную шкалу подпрограммой FX, а вертикальную шкалу подпрограммой FY. Вам придется изменить программы ("START", "SETORIGIN", "MOVETO", "LINETO", см. главу 6). Упражнение 2.4
Нет никаких особых оснований считать Х-ось горизонталью, а Y-ось - вертикалью; они могут даже не быть перпендикулярными. Поэкспериментируйте с этим, для этого вам придется изменить все программы "START", "MOVETO", и т.д.
Пример 2.А
Один из первых популярных графических пакетов назывался CALCOMP. Он включает подпрограммы для вычерчивания осей и шкал, для построения графиков и много других полезных подпрограмм.
Структура этих подпрограмм во многом определяется подпрограммой "PLOT" (не путать с командой PLOT), программа PLOT содержит три параметра: два действительных ХРТ и YPT, координаты точки в пространстве и информацию о движении MOVE - целое число, принимающее значения ±2 и ±3. Одна эта подпрограмма заменяет три наших - "SETORIGIN", "MOVETO", "LINETO". Если MOVE отрицательно, то начало координат помещается в точку (ХРТ, YPT) старой системы координат, и в этом случае программа "PLOT" эквивалентна "SETORIGIN". Если абсолютное значение MOVE равно 3, то движение пера происходит без вычерчивания прямой, эквивалент MOVETO, если MOVE равно 2, то чертится линия - эквивалент LINETO. Если мы даже не хотим использовать весь пакет CALCOMP, то мы все равно можем заменить подпрограммы "SOTORIGIN", "MOVETO", "LINETO" подпрограммой "PLOT" и использовать ее с последующими в этой главе подпрограммами - см. листинг 2.8. LISTING 2.8
9800 REM PLOT/CALCOMP
9801 REM IN - XPT,YPT,XPEN,YPEN,XORIG,YORIG,MOVE
9802 REM OUT - XPEN,YPEN,XORIG,YORIG 9810 LET NXPEN=FN X(XPT)
9820 LET NYPEN=FN Y(YPT)
9830 IF ABS (MOVE)=2 THEN PLOT XPEN,YPEN: DRAW NXPEN-XPEN,NYPEN-YPEN 9840 LET XPEN=NXPEN: LET YPEN=NYPEN
9850 IF MOVE<0 THEN LET XORIG=XORIG+XPT: LET YORIG=YORIG+YPT 9860 RETURN
Чтобы продемонстрировать практическую пользу от этих функций, нарисуем несколько простейших орнаментов. Некоторые считают рисование орнаментов уделом легкомысленных людей, но мы считаем, что это весьма полезное упражнение на первой стадии ознакомления с машинной графикой. Очень часто весьма сложные рисунки являются результатом простых программ. Быстрое получение результатов стимулирует интерес начинающих и помогает им обрести уверенность в своих силах. Более того, на новый дизайн всегда спрос: он используется для оформления обложек книг, буклетов, в рекламе. Не принесет никакого вреда поупражняться в составлении орнаментов, что может оказаться полезным при дальнейшем изучении графического представления информации. Орнаменты также являются идеальным способом введения некоторых фундаментальных идей машинной графики, делая их вполне осязаемыми. В качестве примера приведем программу, иллюстрирующую важную роль тригонометрических функций (синуса и косинуса) и роль измерения углов в радианах. Напомним, что Pi-радиан эквивалентно 180 градусам. Упражнение 2.5
Фигура на рис. 10 получается, если соединить между собой все вершины правильного N-угольника, где N=10. Мы помещаем начало координат в центр, а вершины располагаем на единичной окружности с центром в начале координат: значения HORIZ и VERT (3,2.1) выбираются так, чтобы рисунок хорошо поместился на экране. Если одна из вершин лежит на оси X (горизонтали), то все вершины являются векторами вида (COS(ALPHA), SIN(ALPHA)), где ALPHA равно (2*PI/N), а I=1....N. В этой программе впервые в данной книге координаты точек вычисляются в программе, а не задаются программистом, как это делается в программе 2.6, Далее, так как эти числа используются программой неоднократно, то имеет смысл их поместить в массив и обращаться к ним с помощью индекса. Обратите внимание, что в программе на листинге 2.9 точка с индексом J не соединяется с точкой с индексом I, где 0 <=I < J <= N, так как эти точки уже были соединены ранее. LISTING 2.9
100 REM JOINING VERTICES OF REGULAR N-GON
110 LET START=9700: LET SETORIGIN=9600: LET MOVETO=9500: LET LINETO=9400 120 LET HORIZ=3: LET VERT =2.1 130 GO SUB START
140 LET XMOVE=HORIZ*0.5: LET YMOVE=VERT*0.5 150 GO SUB SETORIGIN 160 DIM X(30):DIM Y(30)
169 REM SETUR vertices of regular N-GON in ARRAYS X and Y.
170 INPUT "VALUE OF N= ";N
180 LET ALPHA=0: LET ADIF=2*PI/N 190 FOR I=1 TO N
200 LET X(I)=COS ALPHA: LET Y(I)=SIN ALPHA 210 LET ALPHA=ALPHA-ADIF 220 NEXT I
229 REM JOINT POINT I TO POINT J-1<=I<J<=N.
230 FOR I=1 TO N-1
240 |
FOR J=I+1 TO |
N |
|
|
|
250 |
LET XPT=X(I) : |
: LET YPT=Y(I): |
GO |
SUB |
MOVETO |
260 |
LET XPT=X(J) : |
: LET YPT=Y(J): |
GO |
SUB |
LINETO |
270 |
NEXT J |
|
|
|
|
280 |
NEXT I |
|
|
|
|
290 |
STOP |
|
|
|
|
Рис. 10.
В этом простом примере выявляются два обстоятельства, первое относится к разрешающей способности. Так как экран состоит из дискретных точек, то прямые линии приходится аппроксимировать последовательностью точек. К сожалению, разрешающая способность SPECTRUMa, как и большинства микрокомпьютерных систем, низка(что означает, NXPIX и NYPIX величины порядка сотни) поэтому на прямых видны зубчики; на устройствах с более высокой разрешающей способностью эти зубчики становятся неразличимыми невооруженным глазом.
Второе наблюдение - это то, что по мере увеличения в программе на листинге 2.9 контуры N-угольника начинают напоминать окружность. Мы можем использовать это наблюдение с тем, чтобы рисовать окружности, что и делает программа "CIRCLE" (листинг 2.10А), которая рисует окружность радиуса R с центром в точке (XCENT.YCENT) (см. рис. 11).
Обратите внимание на то, что мы измеряем углы в радианах, увеличивая угол на величину 3/(R*XYSCALE) на каждом шаге цикла; эта величина зависит только от радиуса и позволяет построить окружность без лишних действий. Так как каждую точку мы используем только раз, то мы не используем массивы. Как и в случае с прямой, форма окружности искажена из-за ограниченной разрешающей способности дисплея. LISTING 2.10А
10 REM MAIN PROGRAM/CIRCLE1
20 LET START=9700: LET SETORIGIN=9600: LET MOVETO=9500: LET LINETO=9400: LET CIRCLE1=300
30 LET HORIZ=30: LET VERT=20 40 GO SUB START
50 INPUT " XCENT=";XCENT;" YCENT=";YCENT;" R=";R 60 GO SUB CIRCLE1 70 STOP
300 REM CIRCLE1
301 REM IN - XCENT,YCENT,R.XYSCALE
310 LET XMOVE=XCENT: LET YMOVE=YCENT: GO SUB SETORIGIN
320 LET ADIF=3/(R*XYSCALE)
330 LET XPT=R: LET YPT=0: GO SUB MOVETO
339 REM CALCULATE and JOIN points (XPT,YPT) around the circle.
340 FOR A=ADIF TO 2*PI STEP ADIF
350 LET XPT=R*COS A: LET YPT=R*SIN A: GO SUB LINETO 360 NEXT A 370 RETURN LISTING 2.10Б
10 REM MAIN PROGRAM/CIRCLE2 20 LET START=9700: LET circle2=400
30 LET HORIZ=30: LET VERT=20 40 GO SUB START
50 INPUT " XCENT= ";XCENT;" YCENT= ";YCENT;" R= ";R 60 GO SUB circle2 70 STOP
400 REM CIRCLE2
401 REM IN- XCENT,YCENT, R,XYSCALE
410 CIRCLE FN X(XCENT), FN Y(YCENT), R*XYSCALE 420 RETURN
Мы видели, что SPECTRUM - бейсик содержит функцию CIRCLE, с помощью которой можно чертить окружности. Мы можем использовать эту функцию для составления программы CIRCLE2 (листинг 2.10Б), более эффективной, чем CIRCLE 1. Упражнение 2.6
Напишите подпрограмму, вычерчивающую эллипс с большой осью "А" единиц (горизонтальной) и малой осью "В" единиц (вертикальной); точка на эллипсе задается, как (A*COS ALPHA, В*SIN ALPHA), где 0<=ALPHA<=2PI.
Следует помнить, однако, что ALPHA - не угол между прямой, проходящей через точку и положительным направлением оси X, это просто параметр для задания эллипса. Используйте эту подпрограмму для вычерчивания фигуры.
Пример 2. Б
Выполнив предыдущие упражнения, естественно перейти к построению спирали. Эта кривая также имеет вид (R*COS ALPHA, R*SIN ALPHA), но в данном случае изменяется от B до B+2*N*PI, где В (параметр BETA) -начальный угол, который спираль образует с положительным направлением оси X, а N - число витков спирали. Теперь радиус R - это не константа, R вычисляется по формуле R=RMAX*(ALPHA-ВЕТА)/2*N*PI
Отметим, что эта подпрограмма, помещая центр спирали в точку (XCENT, YCENT), не вносит побочных эффектов, т.к. перед выходом из подпрограммы мы возвращаем начало координат в исходную точку. LISTING 2.11А
10 REM MAIN PROGRAM/SPIRAL1
20 LET START=9700: LET SETORIGIN=9600: LET LINETO=9400: LET SPIRAL1=300 30 LET HORIZ=30: LET VERT=20 40 GO SUB START
50 INPUT " XCENT= ";XCENT; " YCENT= ";YCENT;" RMAX= ";RMAX 60 INPUT " N=" ;N; " BETA=";BETA 70 GO SUB SPIRAL1 80 STOP
300 REM SPIRAL1
301 REM IN - XCENT,YCENT,RMAX,N,BETA
310 LET XMOVE=XCENT: LET YMOVE=YCENT: GO SUB SETORIGIN
320 LET ADIF=PI/50: LET ALPHA=BETA
330 LET RDIF=RMAX/(N*100)
340 FOR R=RDIF TO RMAX STEP RDIF
350 LET XPT=R*COS ALPHA: LET YPT=R*SIN ALPHA: GO SUB LINETO 360 LET ALPHA=ALPHA+ADIF 370 NEXT R
380 LET XMOVE=XCENT: LET YMOVE=YCENT: GO SUB SETORIGIN 390 RETURN LISTING 2.11Б
10 REM MAIN PROGRAM/CELTIC
20 LET START=9700: LET SETORIGIN=9600: LET CELTIC=300 30 LET HORIZ=30: LET VERT=20 40 GO SUB START
50 INPUT " XCENT= ";XCENT;" YCENT= ";YCENT;" RMAX= ";RMAX 60 INPUT " N= ";N;" SIGN= ";SIGN 70 GO SUB CELTIC 80 STOP
300 REM CELTIC/SPIRAL
301 REM IN - XCENT,YCENT,RMAX,N,SIGN
310 LET XMOVE=XCENT: LET YMOVE=YCENT: GO SUB SETORIGIN 320 PLOT XPEN,YPEN
330 LET R=0: LET S=1: LET RDIF=RMAX/(N*2)
339 REM Construct the spiral using draw to produce a series of semicircles
340 FOR I=1 TO N*2
350 LET R=R+RDIF: LET XPIX=S*R*XYSCALE 360 DRAW XPIX,XPIX,SIGN*PI 370 LET S=-S
380 NEXT I 390 RETURN Упражнение 2.7
Программа на листинге 2.11А рисует спираль (рис. 12) с XCENT=15, YCENT=10, N=6, BETA=2, RMAX=5. Что произойдет, если положить RMAX=-3? Обратите внимание на то, что если вращать голову перед этой спиралью, оставляя линию глаз параллельной горизонтали экрана, то кажется, что спираль вращается относительно центра.
Пример 2.В
Спирали более тысячи лет используются в искусстве и дизайнерских работах. Большая часть древних спиралей, однако, не являются спиралями, а составлены из полуокружностей. Программа на листинге 2.11Б (использующая параметры RMAX, N, SIGN=±1 - параметр, определяющий ориентацию кривой) позволяет рисовать такие составные спирали; программа использует функцию DRAW и много эффективнее точного метода программы на листинге 2.11 А.
Упражнение 2.8
Просмотрите программу на листинге 2.11Б и измените её так, чтобы конец кривой лежал не на оси X, а образовывал с ней угол BETA. В книге кельтов содержатся рисунки кривой, называющейся трискелом, состоящей из последовательности дуг 1/3 окружности. Попробуйте составить кривую, состоящую из дуг 1/4 окружности, и т.д.
Пример 2.Г
LISTING 2.12
100 REM AN ENVELOPE
110 LET START=9700: LET SETORIGIN=9600: LET MOVETO=9500: LET LINETO=9400 120 LET HORIZ=3: LET VERT=2.1 130 GO SUB START
140 LET XMOVE=HORIZ*0.5: LET YMOVE=VERT*0.5 150 GO SUB SETORIGIN
159 REM DRAW UNIT AXES IN GRAPHICS AREA.
160 INPUT "N=";N
170 LET XPT=1:LET YPT=0: GO SUB MOVETO 180 LET XPT=-1: LET YPT=0: GO SUB LINETO 190 LET XPT=0: LET YPT=1: GO SUB MOVETO 200 LET XPT=0: LET YPT=-1: GO SUB LINETO
209 REM PRODUCE N SETS EACH OF FOUR POINTS. ONE ON EACH AXIS. JOIN THE POINTS OF EACH SET IN ORDER.
210 FOR I=1 TO N
220 LET ID1=I/N: LET ID2=(N+1-I)/N 230 LET XPT=ID1: LET YPT=0: GO SUB MOVETO 240 LET XPT=0: LET YPT=ID2: GO SUB LINETO 250 LET XPT=-ID1: LET YPT=0: GO SUB LINETO 260 LET XPT=0: LET YPT=-ID2: GO SUB LINETO 270 LET XPT=ID1: LET YPT=0: GO SUB LINETO 280 NEXT I 290 STOP
Здесь мы вводим понятие развертки, вместо того, чтобы составлять кривую из последовательности небольших отрезков (как это делается на листинге 2.9), мы рисуем кривую с помощью касательных к кривой. N точек наносится с единичным интервалом на каждый из четырех лучей, которые делят плоскость на четыре части. Таким образом, координаты этих четырех точек (±I/N,0.) и (0.0,±I/N), где I=1,2.. ,,N. Упражнение 2.9
Обобщите результаты предыдущего упражнения, считая, что плоскость разбита М-лучами, выходящими из центра, на сектора с равными углами. Упражнение 2.10
Напишем программу, рисующую такую фигуру: Входным параметром программы служит целое число N. Нанесем 4N точек по периметру квадрата с единичной стороной; каждая из этих точек P(I): (1-1,2..., 4N) расположены на расстоянии 1/N друг от друга. Затем эти точки соединяются друг с другом по такому правилу: точка P(I) соединяется с точкой P(J) для всех положительных I, не больших 4, так что числа J-I (вычитание по модулю 4) принадлежат последовательности I,I+2,I+2+3,... Например, если N-10, то Р(20) соединяется с Р(21),Р(23),Р(26),Р(30),Р(35),Р(1),Р(8),Р(16). Следует вначале начертить квадрат, что избавит от необходимости соединять точки, находящиеся на одной стороне. Пример 2.Д
Создайте программу, имитирующую спирограф, рисующий фигуры, подобные фигуре, приведенной на рис.
14.
Рисунок 15 был получен обращением к подпрограмме "SPIRO" со значениями параметров А=12, В=7, D=5. Значения HORIZ и VERT выбираются такими, чтобы рисунок уместился на экране; в данном случае HORIZ=30, а VERT=20.
Спирограф - это устройство, состоящее из зубчатого диска, расположенного внутри зубчатой окружности, находящейся на листе бумаги.
Пусть радиус внешней окружности равен целому А, а радиус внутренней - целому числу В. В диске имеется небольшое отверстие, расположенное на расстоянии D (D - тоже целое число) от центра. В это отверстие вставляется кончик карандаша. Диск двигают внутри окружности против часовой стрелки, так что он все время касается окружности; зубцы гарантируют отсутствие проскальзывания. Кончик карандаша вырисовывает орнамент, который считается нарисованным, как только кончик карандаша возвращается в исходную точку.
Предположим, что вначале центр диска, окружности и отверстия в диске расположены на оси X, причем центр окружности совпадает с началом координат.
Для того, чтобы имитировать работу спирографа, мы параметрическим образом зададим кривую, которую вычерчивает кончик карандаша. Пусть ALPHA - угол между положительным направлением оси X и лучом, соединяющим точку касания диска и окружности. Тогда координаты точки касания - (A*COS ALPHA, A*SIN ALPHA), а координаты центра окружности ((А-В) GOS ALPHA, (A-В) SIN ALPHA). Пусть BETA обозначает угол, который образует положительное направление оси X и прямая, соединяющая отверстие с центром диска, тогда координаты отверстия:
((А-B) COS ALPHA + D*COS BETA, (A-B) SIN ALPHA + D*SIN BETA)
Когда точка соприкосновения между диском и окружностью перемещается по окружности на расстояние А*ALPHA, то оно перемещается на -0*BETA по диску (знак минус появляется из-за того, что у ALPHA и BETA противоположная ориентация). Так как проскальзывание отсутствует, то эти расстояния должны совпадать и, следовательно, BETA^^^^ALPHA. Карандаш вернется в исходную точку, когда ALPHA и BETA оба кратны 2*PI. Когда ALPHA=2*N*PI, тогда BETA=-N*(А/В)*2*PI; и мы видим, что кончик карандаша вернется в исходное положение в первый раз, когда №(А/В) в первый раз станет целым; это произойдет, когда станет равным В, деленному на наибольший общий множитель А и В. Подпрограмма "EUCLID" (листинг 2.13) использует алгоритм Евклида для вычисления наибольшего общего множителя (целая HCF) двух целых положительных величин А и В.
Эта функция используется в подпрограмме "SPIRO" (листинг 2.13), вычисляющей значение N, а затем вычисляющей значение BETA для каждого значения ALPHA, где ALPHA изменяется в диапазоне от 0 до 2*PI с шагом PI/100, после чего вычерчивается кривая.
LISTING 2.13
10 REM MAIN PROGRAM/SPIRO
20 LET START=9700: LET SETORIGIN=9600: LET MOVETO=9500: LET LINETO=9400: LET EUCLID=200: LET SPIRO=300
30 LET HORIZ=30: LET VERT=20 40 GO SUB START
50 LET XMOVE=HORIZ*0.5: LET YMOVE=VERT*0.5: GO SUB SETORIGIN 60 INPUT" A=";A;" B=";B;" D=";D 70 GO SUB SPIRO 80 STOP
200 REM EUCLID
201 REM IN - A,B
202 REM OUT - HCF
210 LET I=A: LET HCF=B
220 IF A<B THEN LET I=B: LET HCF=A
230 LET J=I-INT (I/HCF)*HCF
240 IF J=0 THEN RETURN
250 LET I=HCF: LET HCF=J: GO TO 230
300 REM SPIRO
301 REM IN - A,B,D
310 LET RAB=A-B: LET ALPHA=0: LET ADIF=PI/50: LET ACB=A/B 320 GO SUB EUCLID: LET N=B/HCF: LET NC=100*N 330 LET XPT=RAB+D: LET YPT=0: GO SUB MOVETO
339 REM CALCULATE AND JOIN POINTES(XPT,YPT).
340 FOR I=1 TO NC
350 LET ALPHA=ALPHA+ADIF
360 LET BETA=ALPHA*ACB
370 LET XPT=RAB*COS ALPHA+D*COS BETA
380 LET YPT=RAB*SIN ALPHA+D*SIN BETA
390 GO SUB LINETO
400 NEXT I
410 RETURN
Эта программа показывает, что построение орнаментов не такое бесхитростное занятие, каким оно кажется на первый взгляд. Даже такая простая фигура, как на рис. 15, требует привлечения алгоритма Евклида. Углубляясь в предмет машинной графики, мы убедимся, что весьма полезным может оказаться знание геометрии, алгебры, теории чисел. Будьте готовы к тому, что вам придется зайти в библиотеку (или к знакомому математику) для получения дополнительной информации.
Список программ
На этом шаге мы объединим листинги 2.1 ("START"), 2.2 (две функции FNX, FNY), 2.3 ("SETORIGIN"), 2.4 ("MOVETO"), 2.5 ("LINETO") подзаголовком "LIBl". Позже мы заменим листинг 2.5 листингом 3.3 ("CLIP" и новая версия программы "LINETO").
1. "LIBl" и листинг 2.6 ("SQUARE" - вычерчивание квадрата): никаких входных данных;
2. "LIB1" и листинг 2.7 (MAIN PROGRAM - основная программа и "POLIGON" - многоугольник): требуется задать количество вершин многоугольника 3<=N<=50 и их координаты X, Y (-15<=Х<=15 и -10<=Y<=10).
3. "LIBl" и листинг 2.9 ("JOINING VERTICES OF REGULAR N-GON" - соединить вершины правильного N-угольника): требуется задать целое число 3<=N<=50.
4. " LIBl" и ваша собственная "MAIN PROGRAM"- основная программа (в качестве примера см. листинг2.7), вызывающая листинги 2.10 А "CIRCLE1" и 2.10Б "CIRCLE2". Для каждой подпрограммы должны быть указаны центр (XCENTER, YCENTER) и радиус R. Выбирайте эти значения так, чтобы они были согласованы со значениями HORIZ, VERT, XMOVE, YMOVE; например, присвойте последним значения 30, 20, 15 и 10 соответственно. В качестве примера вызовите "CIRCLE1" с центром (1,-1), радиусом 8 и "CIRCLE2" с центром (1,2) и радиусом 5.
5. "LIB1" и ваша собственная основная программа, вызывающая листинг 2.11А ("SPIRAL1") и 2.11Б ("CELTIC"). Для каждой из этих подпрограмм следует задать центр (XCENT, YCENT), максимальный радиус RMAX и количество витков спирали N. Для листинга 2.11A ("SPIRAL1") требуется задать также угол BETA, в то время, как для программы 2.11Б требуется задать SIGN, которое принимает значения ±1. Выбирайте значения параметров такими, чтобы они согласовывались со значениями HORIZ, VERT, XMOVE, YMOVE (например, 30, 20, 15 и 10). Например, вызовите "SPIRAL1" с центром (1,-1), RMAX=5, N=5, SIGN=-1. Попробуйте SIGN=±1.
6. "LIB1" и листинг 2.12 ("ENVELORE" - развертка): задайте число N: 2<=N<=30.
7. "LIB1" и листинг 2.13 ("EUCLID" и "SPIRO"): требуется задать три числа А, В и D. Выберите значения HORIZ, VERT и т.д. такими, чтобы изображение уместилось на экране: положите XMOVE=HORIZ*0.5, YMOVE=0.5*VERT (для подпрограммы "SETORIGIN", где HORIZ и VERT больше 2*(А-В+D).