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-мя Х-ами: положительная, равна нулю, или отрицательная (т.е. x1<x2). тоже самое делаю и с Y-ами. Если одно из значений равно нулю, то я просто выполняю цикл, в котором одна координата остается неизменной, а вторая изменяется от меньшей к большей. После цикла процедура завершается. Если ни одна из разниц не равна нулю, то вычисляем коэффициенты наклона X-а и Y-а по этим формулам: Xslope = Xlength / Ylength Yslope = Ylength / Xlength Как Вы видите, Xslope, Yslope - вещественные числа. Примечание: XSlope = 1 / YSlope Теперь у нас есть 2 формулы рисования линии: X = XSlope * Y Y = YSlope * X Вопрос в том, какую же из них использовать? Если Вы возьмете не ту формулу, то Ваша линия возможно будет выглядеть так: o o o вместо : ooo ooo ooo Чтобы избежать этого, есть одно верное решение: *\``|``/* ***\|/*** ----+---- ***/|\*** */``|``\* Если угол наклона входит в область со звездочками (*), то используйте первую формулу, если в другую область (`), тогда вторую формулу. Итак, законченная процедура для рисования линии на экране: Procedure Line (x1,y1,x2,y2:integer;col:byte); VAR x,y,xlength,ylength,dx,dy:integer; xslope,yslope:real; BEGIN xlength:=abs (x1-x2); if (x1-x2)<0 then dx:=-1; if (x1-x2)=0 then dx:=0; if (x1-x2)>0 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<m) THEN BEGIN s := s - m; a:= a +round(d1x); b := b + round(d1y); END ELSE BEGIN a := a + round(d2x); b := b + round(d2y); END; end; END; Этот код очень быстрый, и должен удовлетворить все ваши требования. Процедуры по рисованию окружностей и линий могут показаться довольно незначительными вещами, но на самом деле это жизненно важные компоненты многих программ. Если Вы хотите узнать о других методах рисования, то можете найти их описания в книгах. Одним из самых быстрых методов рисования линии является метод Брезенхема (Bressenhams). Также есть его метод рисования окружностей (который тоже является одним из самых быстрых). =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= В заключение [ "What does it do?" she asks. "It's a computer," he replies. "Yes, dear, but what does it do?" "It ..er.. computes! It's a computer." "What does it compute?" "What? Er? Um. Numbers! Yes, numbers!" He smiles worriedly. "Why?" "Why? Well ..um.. why?" He starts to sweat. "I mean, is it just something to dust around, or does it actually do something useful?" "Um...you can call other computers with it!" Hope lights up his eyes. "So you can get programs from other computers!" "I see. Tell me, what do these programs do?" "Do? I don't think I fol..." "I see. They compute. Numbers. For no particular reason." He withers under her gaze. "Yes, but..." She smiles, and he trails off, defeated. She takes another look at the thing. "Although," she says, with a strange look in her eyes. He looks up, an insane look of hope on his face. "Does it come in pink?" she asks. ] - Grant Smith Tue 27 July, 1993 9:35 pm. Увидимся в следующий раз, - Denthor