Увод в компютърната графика


Основни алгоритми за растеризация



страница2/2
Дата25.08.2016
Размер395.67 Kb.
1   2

Основни алгоритми за растеризация

1.Осветяване на един пиксел – с директен запис на стойността на атрибута на пиксела във видеопаметта. Записва се началния адрес и в зависимост от него и позицията на пиксела се записва на различно място в паметта. При режим с 256 цвята атрибута на всеки пиксел се записва в един байт. Когато стойността на пиксела се преставя в 4 бита, всеки от тях стои в различни области от паметта. Използва се BIOS прекъсване INT 10H, функция OCH

MOV AH,OCH; Номер на функцията

MOV AL,Color; Атрибут

MOV CX,X; Х – координата

MOV DX,Y Y – координата

INT 10H;

2. Растеризиране на отсечка – нека отсечката е с координати (X1,Y1) и (X2,Y2). Трябва да получим права, близка до идеалната. Използваме уравнение на права.




Алгоритъм DDA (Digital Differentical Analyser) – На всяка стъпка се проверява дали error е по-голяма от ½ - ако не е y не се увеличава, а ако е се увеличава. Недостатък – при използване на реални числа работата на програмата се забавя.
П

ример:

program Lines_And_Circles;

Uses Graph;

var Color:integer;

xa,ya:word;

AspectRatio:real;

procedure Initialize;

var GraphDriver, GraphMode, ErrorCode:integer;

begin

GraphDriver:=Detect;



InitGraph(GraphDriver, GraphMode, 'c:\bp\bgi');

ErrorCode:=GraphResult;

if ErrorCode <> grOK then

begin


Writeln('Графична грешка', GraphErrorMsg(ErrorCode));

Halt(1);


end;

end;


procedure DrawLine(x1,y1,x2,y2:integer);

var x,dx,dy:integer;

m,b,y:real;

begin


dx:=x2-x1;

dy:=y2-y1;

m:=dy/dx;

b:=y1-m*x1;

x:=x1;

repeat


y:=m*x+b;

PutPixel(x,round(y),Color);

x:=x+1;

until x>x2;



end;

procedure DDA(x1,y1,x2,y2:integer);

var Diff,Error:real;

x,y:integer;

begin

Diff:=(y2-y1)/(x2-x1);



x:=x1; y:=y1;

PutPixel(x,y,Color);

Error:=0;

while x

begin

x:=x+1;


Error:=Error+Diff;

if Error>=0.5 then

begin

y:=y+1;


Error:=Error-1;

end;


PutPixel(x,y,Color);

end;


end;
procedure SWAP(var x,y:integer);

var b:integer;

begin

b:=x;


x:=y;

y:=b


end;
procedure Bresenham(x1,y1,x2,y2:integer);

var x,y,dx,dy,xInc,yInc,Error:integer;

procedure BresenhamI(x1,y1,x2,y2,yInc:integer);

var Error,x,y:integer;

begin

x:=x1; y:=y1;



PutPixel(x,y,Color);

Error:=-(dx div 2);

while x

begin


x:=x+1;

Error:=Error+dy;

if Error>=0 then

begin


y:=y+yInc;

Error:=Error-dx;

end;

PutPixel(x,y,Color);



end;

end;
procedure BresenhamII(x1,y1,x2,y2,xInc:integer);

var Error,x,y:integer;


Алгоритъм на Брезенхам – усъвършенстван DDA

y и x са цели, но - Error – не са цели.

Умножаваме по x -> Diff става цяла стойност : мени се не от 0 до 1, а от 0 до x; сравнението става не с ½, а с x/2


begin

x:=x1; y:=y1;

PutPixel(x,y,Color);

Error:=-(dy div 2);

while y

begin


y:=y+1;

Error:=Error+dx;

if Error>=0 then

begin


x:=x+xInc;

Error:=Error-dy;

end;

PutPixel(x,y,Color);



end;

end;


begin

dx:=x2-x1; dy:=y2-y1;

if abs(dx)>abs(dy) then {I,IV,V или VIII октант}

begin


if dx<0 then {IV или V октант}

begin


SWAP(x2,x1);

SWAP(y2,y1);

dx:=x2-x1;

dy:=y2-y1;

end;

if y2>y1 then yInc:=1 {I октант}



else begin yInc:=-1; dy:=abs(dy) end; {VIII октант}

BresenhamI(x1,y1,x2,y2,yInc);

end

else begin {II,III,VI или VII октант}



if dy<0 then {VI или VII октант}

begin


SWAP(x2,x1);

SWAP(y2,y1);

dx:=x2-x1;

dy:=y2-y1;

end;

if x2>x1 then xInc:=1 {II октант}



else begin xInc:=-1; dx:=abs(dx) end;{III октант}

BresenhamII(x1,y1,x2,y2,xInc);

end;

end;


Procedure CircleI(x0, y0, R : integer);

{ Апроксимация на окръжност с отсечки }

{ x0 и y0 са координати на центъра на окръжността, }

{ а R е радиусът й }

const thinc = 2.0*Pi / 100; { Апроксимация със 100 отсечки }

var x1, y1, { Координати на първата точка на отсечката }

x2, y2 : integer; { Координати на втората точка на отсечката }

i : integer;

th : real;

begin


th := 0;

x1 := x0+R;

y1 := y0;

for i := 1 to 100 do

begin

th := th + thinc;



x2 := x0 + round(R*cos(th));

y2 := y0 + round(R*sin(th)* AspectRatio);

Line(x1, y1, x2, y2);

x1 := x2; y1 := y2;

end;

end;
Procedure CircleII(x0, y0, R : integer);



{ Апроксимация на окръжност с точки }

{ x0 и y0 са координати на центъра на окръжността, }

{ а R е радиусът й }

const Re = 45.0 * Pi / 180.0; { 45 градуса в радиани }

var dx, dy : integer; { Координати на точка от окръжността }

{ спрямо началото на координатната система }

th, thinc : real; { Текущ ъгъл и стойност на промяна на ъгъла }

begin


th := 0; thinc := 1/R;

while th <= Re do

begin

dx := round(R * cos(th));



dy := round(R * sin(th) * AspectRatio);

PutPixel(x0 + dx, y0 + dy, Color);

PutPixel(x0 - dx, y0 + dy, Color);

PutPixel(x0 + dx, y0 - dy, Color);

PutPixel(x0 - dx, y0 - dy, Color);

PutPixel(x0 + dy, y0 + dx, Color);

PutPixel(x0 - dy, y0 + dx, Color);

PutPixel(x0 + dy, y0 - dx, Color);

PutPixel(x0 - dy, y0 - dx, Color);

th := th + thinc;

end;

end;


begin

Initialize;

DrawLine(10,300,400,20);

DDA(10,30,400,300);


Color:=1; Bresenham(370,215,560,120);

Color:=2; Bresenham(345,190,440,0);

Color:=3; Bresenham(295,190,200,0);

Color:=4; Bresenham(270,215,80,120);

Color:=5; Bresenham(270,265,80,360);

Color:=6; Bresenham(295,290,200,480);

Color:=7; Bresenham(345,290,440,480);

Color:=8; Bresenham(370,265,560,360);

readln;

ClearViewPort;



GetAspectRatio(xa,ya);

AspectRatio:=xa/ya;

Color:=4; CircleI(100,100,80);

Color:=12; CircleII(400,300,80);

readln;

CloseGraph;



end.
П

ълен алгоритъм на Брезенхам – отчитат се всички положения на отсечката.






      1. Разтягане по вертикала

PutPixel (x,y+1,Color)

PutPixel (x,y-1, Color)

PutPixel (x,y,Color)


Запълване на многоъгълници – Използват се два вида алгоритми:

  • Геометрични данни (сканираща линия). Известни са координатите на върховете на многоъгълника. Разглеждат се множество от сканиращи линии (хоризонтални или вертикални) представляващи редове от пиксели. Интересуваме се от тези, които започват от най-високия до най-ниския връх. Трябва да се определят точките на пресичане на сканиращата линия и отрязъците. В дясно от първата точка на пресичане започва осветяването на пикселите.



За всеки ръб намираме пресечните точки с всички сканиращи линии. Получаваме списък от сканиращи линии и точки на пресичане. Точките се записват в списък за всеки ръб.








  • Информацията във видеопаметта на вече растеризирани отсечки или на части от тях



      1. 3.Управление на мишката.


unit Mouse_Un;

{ Подпрограми за поддържане на Microsoft съвместима мишка }

{ в графичен режим }

interface

const

LeftButton = 0; { Ляв бутон на мишката }

RightButton = 1; { Десен бутон на мишката }

EitherButton = 2; { Един от двата бутона - ляв или десен }

procedure Mouse(var m1, m2, m3, m4 : integer);

procedure HideMouse;

procedure ShowMouse;

procedure MoveMouse(x, y : integer);

function InitMouse : boolean;

procedure GetMouseCoords(var x, y : integer);

procedure GetMouseMovement(var x, y : integer);

function MouseButtonReleased(WhichButton : integer) : boolean;

function MouseButtonPressed(WhichButton : integer) : boolean;

function GetInput(WhichButton : integer) : integer;

function WaitForInput(WhichButton : integer) : integer;
implementation

uses Graph, Crt, Dos;

const

{ Константи за обръщане към прекъсване 33h }

MouseReset = 0;

MouseShow = 1;

MouseHide = 2;

GetMouseStatus = 3;

SetMouseCoord = 4;

CheckButtonPress = 5;

CheckButtonRelease = 6;

MouseMovement = 11;
procedure Mouse(var m1, m2, m3, m4 : integer);

{ Осъществява връзка между драйвера на мишката и приложна }

{ програма. Параметрите се изпращат към и връщат от драйвера }

{ чрез регистри AX, BX, CX и DX. }

var Regs : Registers;

{ Тип за регистрите на микропроцесора от модул DOS }

begin

Regs.AX := m1; Regs.BX := m2;

Regs.CX := m3; Regs.DX := m4;

Intr($33, Regs);

m1 := Regs.AX; m2 := Regs.BX;

m3 := Regs.CX; m4 := Regs.DX;

end;
procedure HideMouse;

{ Изтрива курсора на мишката от екрана. Повиква се преди }

{ извеждане на текст или графика в графичен режим. }

{ Курсорът на мишката се възстановява на екрана с ShowMouse. }

var m1, m2, m3, m4 : integer;

begin

m1 := MouseHide; { Повиква функцията за скриване на мишката }

Mouse(m1, m2, m3, m4);

end;
procedure ShowMouse;

{ Показва курсора на мишката на екрана }

var m1, m2, m3, m4 : integer;

begin

m1 := MouseShow; { Повиква функцията за показване на мишката }

Mouse(m1, m2, m3, m4);

end;
function TestButton(TestType, WhichButton : integer) : boolean;

{ Повиква се от MouseButtonPressed и MouseButtonRealeased за }

{ определяне на състоянието на бутоните на мишката. }

{ Връща true, ако посоченият в WhichButton бутон е претърпял }

{ посоченото в TestType действие. }

{ Връща false, ако тестваното действие не се е състояло. }

{ TestType приема стойност CheckButtonPress }

{ или CheckButtonRelease. }
var m1, m2, m3, m4 : integer;

FoundAction : boolean;

begin

TestButton := false;

FoundAction := false;

if (WhichButton = LeftButton) or (WhichButton = EitherButton)

then begin

m1 := TestType; m2 := LeftButton;

Mouse(m1, m2, m3, m4);

if m2 > 0 then begin

TestButton := true;

FoundAction := true;

end;

end;

if not FoundAction and (WhichButton = RightButton)

or (WhichButton = EitherButton) then

begin

m1 := TestType; m2 := RightButton;

Mouse(m1, m2, m3, m4);

if m2 > 0 then

TestButton := true;

end;

end;
function ResetMouse : boolean;

{ Инициализира курсора на мишката в центъра на екрана, }

{ скрита мишка, курсор във вид на стрелка. }

{ Връща true, ако е зареден драйверът за мишката. }

var m1, m2, m3, m4 : integer;

begin

m1 := MouseReset;

Mouse(m1, m2, m3, m4);

ResetMouse := m1 < 0 ;

end;
procedure MoveMouse(x, y : integer);

{ Премества мишката в позиция (x,y) }

var m1, m2, m3, m4 : integer;

begin

m1 := SetMouseCoord;

m3 := x; m4 := y;

Mouse(m1, m2, m3, m4);

end;
function InitMouse : boolean;

{ Използва се след инициализация на графичния драйвер за }

{ инициализиране на драйвера на мишката и преместване на }

{ мишката в горния ляв ъгъл }

begin

if ResetMouse then begin

MoveMouse(0, 0);

ShowMouse;

InitMouse := true;

end

else InitMouse := false;

end;
procedure GetMouseCoords(var x, y : integer);

{ Определя текущата позиция на мишката }

var m1, m2, m3, m4 : integer;

begin

m1 := GetMouseStatus;

m3 := x; m4 := y;

Mouse(m1, m2, m3, m4);

x := m3; y := m4;

end;
procedure GetMouseMovement(var x, y : integer);

{ Определя относителното преместване на мишката спрямо }

{ позицията от предишното обръщане към тази процедура. }

var m1, m2, m3, m4 : integer;

begin

m1 := MouseMovement;

m3 := x; m4 := y;

Mouse(m1, m2, m3, m4);

x := m3; y := m4;

end;
function MouseButtonPressed(WhichButton : integer) : boolean;

{ Връща true, ако посоченият бутон на мишката е бил натиснат }

{ след последната проверка с тази функция. }

var Button : integer;

begin

MouseButtonPressed :=

TestButton(CheckButtonPress, WhichButton);

end;
function MouseButtonReleased(WhichButton : integer) : boolean;

{ Връща true, ако посоченият бутон на мишката е бил отпуснат }

{ след последната проверка с тази функция. }

var Button : integer;

begin

MouseButtonReleased :=

TestButton(CheckButtonRelease, WhichButton);

end;
function GetInput(WhichButton : integer) : integer;

{ Връща ASCII код на символ, ако е натиснат клавиш, -1 при }

{ натиснат бутон на мишката и 0 в останалите случаи. }

begin

if KeyPressed then GetInput := Ord(ReadKey)

else begin

if MouseButtonPressed(WhichButton) then

begin

while not MouseButtonReleased(WhichButton) do;

GetInput := -1;

end

else if MouseButtonReleased(WhichButton)

then GetInput := -1

else GetInput := 0;

end;

end;
function WaitForInput(WhichButton : integer) : integer;

{ Изчаква въвеждане на символ или натискане на бутон на мишката}

var c : integer;

begin

repeat

c := GetInput(WhichButton)

until c <> 0;

WaitForInput := c;

end;
end.


    1. Увод

Системата за мишката се състои от механизъм и резидентна програма (драйвер). Драйверът осигурява всички действия за работа с мишката, подържа автоматично управление и открива натискането на бутоните. Обикновенно се зарежда в AUOEXEC.BAT.

    1. Достъпът до драйвера.

Получава се с програмно прекъсване №33 (16). Това прекъсване има множество функции (около 50 функции за Microsoft). Номера на функцията се записва предварително в регистъра АХ. В регистрите ВХ, СХ и DX се записват входни параметри. В Паскал се използва оператора: INTR($33,Regs); Regs – променлива от тип Registers, дефинирана в модула DOS.

Procedure Mouse

Списък на функциите по номера:

№ 0 – инициализира мишката и връща състоянието й.

№ 1 – показва курсора на мишката на екрана

№ 2 – изтрива курсора на мишката от екрана

№ 3 – извлича текущото състояние на бутоните и позицията на мишката.

№ 4 – премества курсора на мишката в посочена позиция (х,у)

№ 5 – определя броя натискания на 1 бутон след последното обръщение каъм мишката.

№ 6 – като 5, само че брой отпускания.

№ 7 – задава хоризонтални граници на курсора.

№ 8 – задава вертикални граници на курсора.

№ 9 – определя курсора в графичен режим.

№10 – определя курсора в текстов режим.

№11 – чете броячите на движение на мишката (в 10-чен код).

За тези функции предварително се записват константи.



    1. Инициализация на мишката

В регистъра АХ се връща 1, ако драйверът на мишката е успено открит и зареден.

Function InitMouse.

Пример: Изчертаване на отсечка с мишката.

unit Draw_Un;

{ Модул с интерактивни графични програми за чертане - }

{ допълнете го сами! }

interface

procedure DrawLine(var x1, y1, x2, y2:integer);

implementation

uses Graph, Mouse_Un;

procedure DrawLine(var x1, y1, x2, y2:integer);

{ Изчертава отсечка, докато е натиснат левият бутон на мишката.}

{ Използва XorPut за постигане на ефект на разтягане на }

{ отсечката. След отпускане на левия бутон отсечката }

{ се изчертава окончателно с CopyPut. }

var OldX, OldY : integer; { Съхраняват предишните координати }

{ на втората точка на отсечката, така че повторното }

{ изчертаване на отсечката с XorPut да я изтрие. }

begin

while not MouseButtonPressed(LeftButton) do;

{ Изчаква се ляв бутон }

GetMouseCoords(x1, y1); { Определят се координатите на }

{ мишката => начална точка на отсечката }

SetWriteMode(XorPut);

MoveTo(x1, y1);

OldX := x1; OldY := y1;

while not MouseButtonReleased(LeftButton) do

{ Влачене на мишката }

begin

GetMouseCoords(x2, y2); { Крайна точка на отсечката }

if (x2 <> OldX) or (y2 <> OldY) then

begin

HideMouse; { Винаги се скрива мишката преди чертане }

Line(x1, y1, OldX, OldY); { Изтрива се старата отсечка }

Line(x1, y1, x2, y2); { Чертае се новата отсечка }

ShowMouse; { Показва се мишката }

OldX := x2; OldY := y2;

end;

end;

{ След отпускане на бутона - окончателно изчертаване }

SetWriteMode(CopyPut);

HideMouse;

Line(x1, y1, x2, y2);

ShowMouse;

end;

end.

14. Тримерна графика.

Анализ на тримерното пространство.





  1. Вектори и декартови координати.

1. Избор на координатна система – дясна.

2. Вектори.

а) свободни (определят общата посока)

Еденичен вектор по трите основни оси:

i = [1,0,0], j = [0,1,0], z=[0,0,1]

б) радиус – вектори (позиционни вектори) – представят точка в 3D.

>>>>>>>>>>>>>>>>>……………….>>>>>>>>>>>>
5.11.98 г.
Пример 1 : Пример 2:

А – 0000

D – 01001

Ръб у=уmin EI (1000,0110)

Точка В (код 0000) E : т.F(0000)

BD се отхвурля I : т. H(0010)

H: т. G(0000)


Програма : Алгоритъм на Коен - Съдърленд за изрязване на отсечки



{ Процедура за изрязване на отсечка със зададени координати на крайните й точки P1=(X1,Y1) и P2=(X2,Y2) от прозорец с координати на горния ляв ъгъл (Xmin,Ymin) и на долния десен (Xmax,Ymax) }
procedure Clipper(X1,Y1, X2,Y2, Xmin,Ymin, Xmax,Ymax: real);

type OutCode : array[1..4] of boolean; { true е вън от прозореца }

var Accept, Reject, Done : boolean;

{ Флагове за тривиално приемане, отхвърляне на отсечка и за край }

OutCode1, OutCode2 : OutCode;{ Кодове за точките P1 и P2 }

procedure Swap;

{ Разменя стойностите на P1 и P2 }

function AcceptTest(OutCode1, OutCode2 : OutCode) : boolean;

{ Проверка за тривиално приемане на отсечка }

function RejectTest(OutCode1, OutCode2 : OutCode) : boolean;

{ Проверка за тривиално отхвърляне на отсечка }

procedure OutCodes(X,Y : real; var OutCodeXY : OutCode);

{ Определя кода на точка с координати (X,Y) }
begin { Clipper }

Accept := false; Reject := false; Done := false;

repeat

OutCodes(X1, Y1, OutCode1);

OutCodes(X2, Y2, OutCode2);

Reject := RejectTest(OutCode1, OutCode2);

if Reject then Done := true

else { Възможно е тривиално приемане }

begin

Accept := AcceptTest(OutCode1, Outcode2);

if Accept then Done := true

else { Отсечката се дели }

begin

{ Ако P1 е вътре в прозореца, размяна на P1 и P2 }

if not (OutCode1[1] or OutCode1[2] or

OutCode1[3] or OutCode1[4])

then Swap;

{ P1 се премества в точката на пресичане. }

{ Използват се формули: }

{ y = y1 + m*(x-x1) и x = x1 + (1/m)*(y-y1) }

if OutCode1[1] then

begin { Изрязване по y=Ymax }

X1 := X1 + (X2-X1) * (Ymax-Y1)/(Y2-Y1);

Y1 := Ymax; end

else if OutCode1[2] then

begin { Изрязване по y=Ymin }

X1 := X1 + (X2-X1) * (Ymin-Y1)/(Y2-Y1);

Y1 := Ymin end

else if OutCode1[3] then

begin { Изрязване по x=Xmax }

Y1 := Y1 + (Y2-Y1) * (Xmax-X1)/(X2-X1);

X1 := Xmax end

else if OutCode1[4] then

begin { Изрязване по x=Xmin }

Y1 := Y1 + (Y2-Y1) * (Xmin-X1)/(X2-X1);

X1 := Xmin end;

end; { На разделянето на отсечката }

end;

until Done;

if Accept then Line(X1,Y1,X2,Y2);

end; { Clipper }

Изрязване на многоъгълници.


Алгоритъм на Sutherland – Hodeman


Прави се последователно изрязване по всеки един от ръбовете на прозореца. Всеки ръб се удължава до безкрайност. Алгоритъмът получава входен масив от точки, представляващи върхове на многоъгълника, прави изрязване по един ръб и получава изходно множество от точки – върхове на изрязания многоъгълник. Това множество се използва като входно за изрязване с втори безкраен ръб и процедурата се повтаря още веднъж за трети и четвърти ръб.

Изрязване по един ръб:



Последователност от върхове V1, V2, … , Vn . Алгоритъма разделя точките две по две, като започва с Vn – V1, след това Vn-1 – V2. За всеки две точки определя какво е положението спрямо безкрайния изрязващ ръб. Възможните положения са 4.


Каталог: files -> tu files
tu files -> Xii. Защита и безопасност на ос
tu files -> Електрически апарати
tu files -> Средства за описание на синтаксиса
tu files -> Stratofortress
tu files -> Начало Решаване на проблеми
tu files -> Писане на скриптове за bash шел : версия 2
tu files -> 6Технологии на компютърната графика 1Модели на изображението
tu files -> Z=f(x), където x- входни данни; z
tu files -> Body name библиотека global Matrix imports (достъп по име) … var m[N, N] := … end decl., proc … resource f final code imports node, Matrix end name var x: node node; if x … Matrix m[3,4] :=: … end


Поделитесь с Вашими друзьями:
1   2




База данных защищена авторским правом ©obuch.info 2020
отнасят до администрацията

    Начална страница