Міністерство освіти і науки України
Національний університет «Львівська політехніка»
Інститут комп’ютерних наук та інформаційних технологій
Кафедра автоматизованих систем управління
Лабораторна робота №6
З курсу:
«Комп’ютерна графіка»
Тема: Алгоритм Брезенхема для побудови прямих.
Мета: Освоїти алгоритм Брезенхема для побудови прямих
ТЕОРЕТИЧНІ ОСНОВИ
Загальний алгоритм Брезенхема.
Щоб реалізація алгоритму Брезенхема була повною необхідно розглянути відрізки у всіх октантах. Модифікацію легко зробити, враховуючи в алгоритмі номер квадранта, в якому лежить відрізок і його кутовий коефіцієнт. Коли абсолютна величина кутового коефіцієнта більше 1, у постійно змінюється на одиницю, а критерій похибки Брезенхема використовується для ухвалення рішення про зміну величини x. Вибір постійно змінюваної координати (на +1 чи -1) залежить від квадранта (рис.4.1.). Загальний алгоритм може бути оформлений у наступному вигляді:
Узагальнений цілочисельний алгоритм Брезенхема квадрантів
передбачається, що кінці відрізка (x1, y1) і (x2, y2) не збігаються
усі змінні вважаються цілими
Sign - функція, що повертає -1, 0, 1 для від’ємного, нульового і додатнього аргумента відповідно
ініціалізація змінних
x=x1
y=y1
Dx=abs(x2-x1)
Dy=abs(y2-y1)
s1=Sign(x2-x1)
s2=Sign(y2-y1)
обмін значень Dx і Dy в залежності від кутового коефіцієнта нахилу відрізка
if Dy<Dx then
Temp=Dx
Dx=Dy
Dy=Temp
Обмін=1
else
Обмін=0
end if
ініціалізація e з виправленням на половину піксела
e=2*Dy-Dx
основний цикл
for i=1 to Dx
Plot(x,y)
while(e=>0)
if Обмін=1 then
x=x+s1
else
y=y+s2
end if
e=e-2*Dx
end while
if Обмін=1 then
y=y+s2
else
x=x+s1
end if
e=e+2*Dy
next i
finish
Рис.4.1. Розгляд випадків для узагальненого алгоритму Брезенхема.
Текст программного коду:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
StringGrid1: TStringGrid;
StringGrid2: TStringGrid;
Button1: TButton;
Image1: TImage;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
procedure koord();
procedure draw_P(x_k,y_k:integer);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
x0,y0,delta:integer;
implementation
procedure TForm1.koord();
var delta_p,x1,x2,x3,x4,y1,y2,y3,y4,i:integer;
begin
x0:=round(image1.Width/2);
y0:=round((image1.Height)/2);
with image1.Canvas do
begin
if (image1.Width-x0)>(image1.Height-y0) then
delta:=round((image1.Height-y0)/10)
else
delta:=round((image1.Width-x0)/10);
x1:=x0;
x2:=x0;
x3:=x0;
x4:=x0;
y1:=y0;
y2:=y0;
y3:=y0;
y4:=y0;
for i:=0 to 30 do begin
delta_p:=delta;
MoveTo(x0,y1);
LineTo(x0,y1-delta_p);
moveto(x0-2,y1-delta_p);
LineTo (x0+2,y1-delta_p);
y1:=y1-delta_p;
MoveTo(x0,y2);
LineTo(x0,y2+delta_p);
moveto(x0-2,y2+delta_p);
LineTo (x0+2,y2+delta_p);
y2:=y2+delta_p;
MoveTo(x3,y0);
LineTo(x3+delta_p,y0);
moveto(x3+delta_p,y0-2);
LineTo (x3+delta_p,y0+2);
x3:= x3+delta_p;
MoveTo(x4,y0);
LineTo(x4-delta_p,y0);
moveto(x4-delta_p,y0-2);
LineTo (x4-delta_p,y0+2);
x4:= x4-delta_p;
end;
x1:=x0;
x2:=x0;
x3:=0;
x4:=x0;
y1:=Image1.Height;
y2:=y0;
y3:=y0;
y4:=y0;
for i:=0 to 30 do begin
delta_p:=delta;
pen.Style:=psDot;
moveto(0,y1-delta_p);
LineTo (image1.Width,y1-delta_p);
moveto(x3+delta_p,0);
LineTo (x3+delta_p,image1.Height);
y1:=y1-delta_p;
x3:= x3+delta_p;
end;
end;
end;
procedure TForm1.draw_P(x_k,y_k:integer);
var xx,yy,col:integer;
begin
with image1.Canvas do
begin
pen.Color:=clgray;
pen.Width:=5;
xx:=x0+x_k*delta;
yy:= y0-y_k*delta;
MoveTo(xx,yy);
LineTo(xx,yy);
pen.Width:=1;
col:= brush.Color;
brush.Color:=clblack;
fillRect(rect(xx,yy,xx+delta,yy-delta));
brush.Color:=col;
TextOut(x0+x_k*delta,y0+7,inttostr(x_k));
TextOut(x0+7,y0-y_k*delta,inttostr(y_k));
pen.Style:=psSolid;
end;
end;
{$R *.dfm}
function Sign(x:integer):integer;
begin
if x>0 then
result:=1
else if x<0 then
result:=-1
else if x=0 then
result:=0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
str: array[0..2] of array[0..2] of integer;
x:array[0..2]of array[0..2] of integer;
a:array[0..2]of array[0..2] of integer;
i,j,l,x_t,y_t,x_t0,y_t0,x_tk,y_tk,flag:integer;
dx,dy,s1,s2,obm,temp:integer;
m,e:double;
begin
image1.Canvas.FillRect(Rect(0,0,image1.Width,image1.Height));
image1.Transparent:=true;
koord();
x_t0:=strtoint(StringGrid1.Cells[0,0]);
y_t0:=strtoint(StringGrid1.Cells[1,0]);
draw_P(x_t0,y_t0);
///*****************
x_tk:=strtoint(StringGrid2.Cells[0,0]);
y_tk:=strtoint(StringGrid2.Cells[1,0]);
draw_P(x_tk,y_tk);
//**********
//e:=0;
x_t:=x_t0;
y_t:=y_t0;
dx:=abs(x_tk-x_t0);
dy:=abs(y_tk-y_t0);
s1:=Sign(x_tk-x_t0);
s2:=Sign(y_tk-y_t0);
if dy>dx then begin
temp:=dx;
dx:=dy;
dy:=temp;
obm:=1; end
else
obm:=0;
e:=2*dy-dx;
for i:=1 to dx do begin
draw_P(x_t,y_t);
while (e>=0) do begin
if obm=1 then begin
x_t:=x_t+s1;
end
else begin
y_t:=y_t+s2;
end;
e:=e-2*dx;
end;//while
if obm=1 then
y_t:=y_t+s2
else
x_t:=x_t+s1;
e:=e+2*dy ;
end;//for
end;
end.
Результати роботи програми:
//
/ /
Рис. 1. Отримані результати
Висновок: На даній лабораторній роботі був програмно реалізований алгоритм Брезенхема для побудови прямих