Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Turbo Pascal / Методические указание / Линейчатые графические образы.DOC
Скачиваний:
22
Добавлен:
15.06.2014
Размер:
878.59 Кб
Скачать

3 Практическое задание

3.1 Модернизировать процедуру построения окружности,

задав разные цвета по ее секторам.

3.2 Составить процедуру рисования отрезков с чередованием

цвета составляющих их пикселов.

3.3 Модернизировать алгоритм Брезенхейма, организовав

построение 4-связных отрезков прямых. Проконтролировать работу этого алгоритма на крупной сетке.

4 Построение кривых второго порядка

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

, где p - параметр; e - эксцентриситет; alf - угол для радиус-вектора R, конец которого определяет множество точек кривой. Полюс находится в фокусе кривой, а полярная ось направлена от фокуса к ближайшей вершине. При 0<=e<1 получаем эллипс,

при e=1 - параболу, при e>1 - гиперболу.

Для построения непрерывной кривой из множества точек используется процедура _TRACE, в которой для получения очередной точки кривой первоначально полярный угол от предшествующей точки увеличивается на 1/R - для получения перпендикулярного радиусу смещения единичной длины. Если условие связности очередной и предшествующей точек не выполняется, то приращение угла уменьшается.

Кривые ограничиваются либо диапазоном изменения полярного угла, либо величиной полярного радиуса.

{----------------------------------------------------------}

PROCEDURE _TRACE( xf,yf, s, alf1,alf2, co,d: integer;

p,e,ug: real);

{ построение кривой второго порядка:

xf,yf - координаты фокусаF;

s - размер (ограничение величины R

полярного радиуса);

alf1...alf2 - диапазон изменения alfось кривой

полярного угла; F

co - цвет; d - направление приращения полярного угла ( 1 - по часовой стрелке, -1 - против);p - фокальный параметр; e - эксцентриситет;ug - угол наклона оси симметрии кривой }

var r,alf,du,rot: real;

x,y, x_old,y_old: integer;

begin

{ полярный угол как параметр - начальное значение }

alf:= d*alf1*pi/180+ug;

r:= p/(1+e*cos(alf-ug)); { радиус-вектор из фокуса }

{ координаты первой точки - высчитываем и запоминаем }

x:=xf +round( r*cos(alf));

y:=yf +round( r*sin(alf));

x_old:=x; y_old:=y;

rot:=0; { счетчик угла поворота радиус-вектора }

REPEAT

{ определение очередной точки приращением полярного угла

начальное приближение обратно пропорционально радиусу }

du:=d/r;

Repeat

r:=p/(1+e*cos(alf-ug+du)); { радиус-вектор из фокуса }

x:=xf+round( r*cos(alf+du)); { координаты новой точки }

y:=yf+round( r*sin(alf+du));

If(abs( x-x_old)>1){ если очередная точка несвязна с предыдущей }

or(abs( y-y_old)>1)

then du:=du/2 { то уменьшаем приращение угла }

Until(abs(x-x_old)<=1)and(abs(y-y_old)<=1);

alf:=alf+du; { очередной угол обхода }

rot:=rot+abs(du); { расчет поворота радиус-вектора }

PutPixel( x,y,co); { очередная точка контура }

x_old:=x; y_old:=y { запоминаем координаты выведенной точки }

{ заканчиваем построение при полном проходе интервала по углу обхода или достижении нужного размера ( расстояния от точки кривой до фокуса ) }

UNTIL( rot>(alf2-alf1)*pi/180)or( r>s) end;

{----------------------------------------------------------}

PROCEDURE _ELLIPSE(xc,yc,ugol,r1,r2,alf1,alf2,co: integer);

{ xc,yc - центр эллипса,

ugol - наклон первой оси по горизонтали (град.),

r1,r2 - полуоси,

alf1...alf2 - диапазон изменения полярного угла,

со - цвет }

var r0: integer; f,p,e: real;

begin if( r1<=0)or( r2<=0) then exit;

{ если первая полуось меньше второй, то меняем оси

и их ориентацию на 90 градусов }

if( r1<r2) then begin r0:=r1; r1:=r2; r2:=r0;

ugol:=90-ugol end;

{ перевод в радианы с ориентацией против часовой стрелки }

ug:=-ugol*pi/180;

{ расстояние от фокуса до центра } R r2

f:=sqrt( abs(1.*r1*r1-r2*r2)); p r1

p:=r2*r2/r1; { фокальный параметр } F f (xc,yc)

e:=f/r1; { эксцентриситет }

{ координаты фокуса }

xf:=round( xc +f*cos(ug));

yf:=round( yc +f*sin(ug));

{ Вызов процедуры рисования без ограничения по R }

_TRACE(xf,yf, 3*r1, alf1,alf2, co,1, p,e,ug)

end;

{---------------------------------------------------------}

PROCEDURE _HIPERB(xc,yc, a, ugol,delta, s, alf1,alf2, co:

integer);

{ xc,yc - вершина гиперболы,a - расстояние до центра,

ugol - наклон оси, delta - угол между асимптотами (град.),

s - размер, alf1...alf2 - диапазон изменения полярного угла,

со - цвет }

var xf,yf: integer; b,c,f,p,e, ug,dlt: real;

begin

if( delta<=0)or( s<=0) then exit;

{ перевод из градусов в радианы } R

dlt:=-delta*pi/180;

b:=a*sin(dlt/2)/cos(dlt/2); C c

{ расстояние от фокуса до центра } b F

c:=sqrt(1.*a*a +b*b); delta/2

f:=c-a; { от фокуса до вершины } a

p:=b*b/a; { фокальный параметр }

e:=c/a; { эксцентриситет }

ug:=pi-ugol*pi/180;

{ координаты фокуса } xf:=round( xc +f*cos(ug-pi));

yf:=round( yc +f*sin(ug-pi));

_TRACE(xf,yf,s,alf1,alf2,co, 1, p,e,ug);{ первая ветка кривой }

_TRACE(xf,yf,s,alf1,alf2,co,-1, p,e,ug) { вторая ветка кривой }

end;

{---------------------------------------------------------}

PROCEDURE _PARAB(xc,yc, ugol, a,s,alf1,alf2, co: integer);

{ xc,yc - вершина параболы, ugol - наклон оси,

a - расстояние от вершины до фокуса, s - размер,

alf1..alf2 - диапазон изменения полярного угла, со - цвет }

var xf,yf: integer; p,ug: real;

begin

if( a<=0)or( s<=0) then exit; R

ug:=pi-ugol*pi/180; p

p:=2*a; { фокальный параметр }

{ координаты фокуса } С F

xf:=round( xc+a*cos(ug-pi));

yf:=round( yc+a*sin(ug-pi));

_TRACE(xf,yf,s,alf1,alf2,co, 1,p,1,ug); { первая ветка кривой }

_TRACE(xf,yf,s,alf1,alf2,co,-1,p,1,ug) { вторая ветка кривой }

end;