By DENTHOR of ASPHYXIA --==[ PART 3 ]==-- .Вступление. Здорово всем. Это 3-я часть из Серии Программ по изучению VGA. Итак, сегодня мы займемся такими важными вещами, как Окружности и Линии. Тема же следующей части: Виртуальный экран (Virtual Screen). Так что не пропустите:) =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= .Алгоритм окружности. Вы все знаете как выглядит окружность. Но как вы ее нарисуете на компьютере? В Паскале окружность (с градусными значениями) представляется примерно так: 270 ЬЫ|ЫЬ ЫЫЫ|ЫЫЫ 180 ----+---- 0 ЫЫЫ|ЫЫЫ ЯЫ|ЫЯ 90 *Замечание WiZarDX'a. как я понимаю значения градусов перевернуты из-за того, что ось Y в Паскале направлена вниз (что и показано на рисунке). Извиняюсь за мой ASCII ;-) Как бы то ни было, Паскаль значений в градусах не понимает, только в радианах. (Вы, конечно, можете перевести градусы в радианы, но о том, как это сделать я сейчас распространяться не буду). В любом случае вы все равно можете использовать знаменитые формулы для того, чтобы нарисовать окружность... (их можно получить используя теорему нашего дорогого друга Пифагора) Sin (deg) = Y/R Cos (deg) = X/R Где: Y - координата по оси Y X - координата по оси Х R - радиус deg - градусы Чтобы получить значения X и Y, приведенные выше формулы можно записать так: Y = R*Sin(deg) X = R*Cos(deg) это просто замечательно, т.к. это позволяет найденные значения X и Y подставить в нашу процедуру putpixel. (см. Часть.1) А т.к. результатом функций синуса и косинуса являются вещественные числа (т.е. числа типа real), мы их преобразуем в целые, используя функцию round. Procedure Circle (oX,oY,rad:integer;Col:Byte); VAR deg:real; X,Y:integer; BEGIN deg:=0; repeat X:=round(rad*COS (deg)); Y:=round(rad*sin (deg)); putpixel (x+ox,y+oy,Col); deg:=deg+0.005; until (deg>6.4); END; В данном примере чем меньше значение, на которое увеличивается deg, тем пиксели в окружности ближе друг к другу, но тем медленнее процедура. Похоже, что значение 0.005 лучше всего подходит для разрешения 320x200. ASPHYXIA не использует данный алгоритм для рисования окружности, (наша написана на языке assembler) но в большинстве случаев этой процедуры должно хватить. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= .Алгоритм линии. Существует множество способов для рисования линии на компьютере. Я опишу один и дам Вам два способа. (2-ой Вы сможете понять сами, т.к. он основан на 1-ом, но 2-ой быстрее). Перво наперво Вам надо решить, какие параметры вы будете передавать Вашей процедуре, чтобы линия выглядела так, как Вы хотите. Для начала это координаты двух точек, которые являются концами линии. Координата первой точки - (x1, y1), второй - (x2, y2). (Не забудьте, что координаты левого верхнего угла экрана (0, 0). (см. Часть.1)) Еще Вам надо передать процедуре цвет Вашей линии. Напр. o (X1,Y1) ooooooooo ooooooooo oooooooo (X2,Y2) Еще раз извиняюсь за свои рисунки ;-) Для того чтобы найти длину линии, вычислим следущее: XLength = ABS (x1-x2) YLength = ABS (y1-y2) Надеюсь Вы знаете, что делает функция ABS. Если нет, то напомню, что это модуль числа. В переменной (в первом примере это dx) я указываю какая получается разница между 2-мя Х-ами: положительная, равна нулю, или отрицательная (т.е. x10 then dx:=+1; ylength:=abs (y1-y2); if (y1-y2)<0 then dy:=-1; if (y1-y2)=0 then dy:=0; if (y1-y2)>0 then dy:=+1; if (dy=0) then BEGIN if dx<0 then for x:=x1 to x2 do putpixel (x,y1,col); if dx>0 then for x:=x2 to x1 do putpixel (x,y1,col); exit; END; if (dx=0) then BEGIN if dy<0 then for y:=y1 to y2 do putpixel (x1,y,col); if dy>0 then for y:=y2 to y1 do putpixel (x1,y,col); exit; END; xslope:=xlength/ylength; yslope:=ylength/xlength; if (yslope/xslope<1) and (yslope/xslope>-1) then BEGIN if dx<0 then for x:=x1 to x2 do BEGIN y:= round (yslope*x); putpixel (x,y,col); END; if dx>0 then for x:=x2 to x1 do BEGIN y:= round (yslope*x); putpixel (x,y,col); END; END ELSE BEGIN if dy<0 then for y:=y1 to y2 do BEGIN x:= round (xslope*y); putpixel (x,y,col); END; if dy>0 then for y:=y2 to y1 do BEGIN x:= round (xslope*y); putpixel (x,y,col); END; END; END; Большевата, Вам так не кажется? А ниже приводится более короткий вариант. function sgn(a:real):integer; begin if a>0 then sgn:=+1; if a<0 then sgn:=-1; if a=0 then sgn:=0; end; procedure line(a,b,c,d,col:integer); var u,s,v,d1x,d1y,d2x,d2y,m,n:real; i:integer; begin u:= c - a; v:= d - b; d1x:= SGN(u); d1y:= SGN(v); d2x:= SGN(u); d2y:= 0; m:= ABS(u); n := ABS(v); IF NOT (M>N) then BEGIN d2x := 0 ; d2y := SGN(v); m := ABS(v); n := ABS(u); END; s := INT(m / 2); FOR i := 0 TO round(m) DO BEGIN putpixel(a,b,col); s := s + n; IF not (s