You are on page 1of 7

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ НАЦІОНАЛЬНИЙ

УНІВЕРСИТЕТ
"ЛЬВІВСЬКА ПОЛІТЕХНІКА”

МЕТОДИЧНІ ВКАЗІВКИ ДО ЛАБОРАТОРНОЇ РОБОТИ № 5


з курсу "Компютерна графіка"

Для студентів бакалаврського рівня


підготовки по спеціальності
«Видавничо-поліграфічна справа»

Затверджено на засіданні
кафедри АСУ. Протокол № 3
від 10.05.2004.

Львів – 2010
Цифровий диференціальний аналізатор: Методичні вказівки до лабораторної
роботи № 5 з курсу "Комп’ютерна графіка" для студентів спеціальності «Видавничо-
поліграфічна справа» / Укл.: О.Я. Різник, М.А. Назаркевич, Д. Скрибайло-Леськів -
Львів: Видавництво Національного університету "Львівська політехніка", 2004. - 12 с.

Укладач О.Я. Різник,


М.А. Назаркевич,
Д. Скрибайло-Леськів

Відповідальний за випуск Шпак З.Я., канд. техн. наук, доц.

Рецензент Вальковський В.А., д-р техн. наук, проф.


Лабораторна робота № 5.

Тема: Цифровий диференціальний аналізатор.

Теоретичні відомості

Один з методів розкладання відрізка в растр полягає в розв’язуванні диференціального


рівняння, що описує цей процес. Для прямої лінії маємо dy/dx=const чи Dy/Dx=(y2-y1)/(x2-x1)
Розв’язок представляється у вигляді yi+1=yi+Dy yi+1=yi+Dx(y2-y1)/(x2-x1)

де x1, y1 і x2, y2 - кінці відрізка, що розкладається, і yi - початкове значення для чергового


кроку вздовж відрізка. Фактично рівняння [1] являє собою рекурентне співвідношення для
послідовних значень y вздовж потрібного відрізка. Цей метод, використовуваний для
розкладання в растр відрізків, називається цифровим диференціальним аналізатором (ЦДА).
У простому ЦДА або Dx, або Dy (більше із збільшень) вибирається як одиниця растра. Нижче
наводиться простий алгоритм, що працює у всіх квадрантах:
Процедура розкладання в растр відрізка по методу цифрового диференціального
аналізатора (ЦДА)
передбачається, що кінці відрізка (x1, y1) і (x2, y2) не збігаються
апроксимуємо довжину відрізка
if abs(x2-x1)>=abs(y2-y1) then
Довжина=abs(x2-x1)
else
Довжина=abs(y2-y1)
End { if }
назначаємо більше із збільшень Dx чи Dy рівним одиниці растра
Dx=(x2-x1)/Довжина
Dy=(y2-y1)/Довжина
округляємо величини, а не відкидаємо дробову частину
використання знакової функції робить алгоритм придатним для всіх квадрантів
x=x1;
y=y1;
Plot (round(x), round(y)) //промалювання пікселя
початок основного циклу
i=1
while (i<=Довжина) do
x=x+Dx
y=y+Dy
i=i+1
Plot (round(x), round(y))
End; {while}
finish
Розглянемо відрізок із точки (0,0) у точку (-8,-4) в третьому квадранті. Використовуємо
ЦДА для розкладання цього відрізка в растр. Результати роботи алгоритму такі:
початкові установки
x1=0
y1=0
x2=-8
y2=-4
Довжина=8
Dx=-1
Dy=-0,5
x=-0,5
y=-0,5
результати роботи покрокового циклу

Plot x y
-0,5 -0,5
1 (-1,-1)
-1,5 -1,0
2 (-2,-1)
-2,5 -1,5
3 (-3,-2)
-3,5 -2,0
4 (-4,-2)
-4,5 -2,5
5 (-5,-3)
-5,5 -3,0
6 (-6,-3)
-6,5 -3,5
7 (-7,-4)
-7,5 -4,0
8 (-8,-4)
-8,5 -4,5
Незважаючи на те що результати, представлені на рис.2.2, виглядають цілком
прийнятними, аналіз відрізків, проведених із точки (0,0) у точку (-8,4) і (8,-4), показує, що
розкладений у растр відрізок лежить по одну сторону від реального і що на одному з кінців
відрізка з'являється зайва точка, тобто результат роботи алгоритму залежить від орієнтації.
Отже точність у кінцевих точках зменшується.

Рис.5.1. Результати роботи простого ЦДА в третьому квадранті.


ЗМІСТ ЗВІТУ
Звіт повинен містити:
1) назву роботи;
2) мету роботи;
3) короткий теоретичний вступ;
4) завдання до лабораторної роботи;
5) тексти розроблених і відлагоджених програм
6) малюнки з реалізацією програми
7) висновки

Текст програми

unit Unit1; implementation


{$R *.DFM}
interface procedure draw;
var pos_x,pos_y,pos_xx,pos_yy:real;
uses i:integer;
Windows, Messages, SysUtils, Classes, Dy,Dxx,l:real;
Graphics, Controls, Forms, Dialogs, begin
ExtCtrls,math, StdCtrls, Spin; form1.p.Canvas.Brush.Style:=bssolid;
type if abs(pos[2,1]-
b=array[1..2,1..2] of real; pos[1,1])>=abs(pos[2,2]-pos[1,2]) then
TForm1 = class(TForm) L:=abs((pos[2,1]-pos[1,1])) else
p: TPaintBox; L:=abs(pos[2,2]-pos[1,2]) ;
Label1: TLabel; dxx:=((pos[2,1]-pos[1,1])/l)*dx;
Label2: TLabel; dy:=((pos[2,2]-pos[1,2])/l)*dx;
SpinEdit1: TSpinEdit; pos_x:=((pos[1,1]*dx));
Panel1: TPanel; pos_y:=((pos[1,2]*dx));
Panel2: TPanel; i:=1;
procedure pPaint(Sender: TObject); form1.p.Canvas.Brush.Color:=cllime;
procedure pMouseDown(Sender: TObject; form1.p.Canvas.Rectangle(round(pos_x),rou
Button: TMouseButton; nd(pos_y),
Shift: TShiftState; X, Y: Integer); round(pos_x+dx),round(pos_y+dx));
procedure pMouseMove(Sender: TObject; form1.p.Canvas.Brush.Color:=clblack;
Shift: TShiftState; X, while i<=l do
Y: Integer); begin
procedure pMouseUp(Sender: TObject; pos_xx:=0;
Button: TMouseButton; pos_yy:=0;
Shift: TShiftState; X, Y: Integer); pos_x:=(pos_x+dxx);
procedure SpinEdit1Change(Sender: pos_y:=(pos_y+dy);
TObject); form1.p.Canvas.Brush.Style:=bssolid;
procedure FormCreate(Sender: TObject); form1.p.Canvas.Brush.Color:=cllime;
procedure Panel2Click(Sender: TObject); if (round(pos_y) mod dx) <>0 then
procedure Panel1Click(Sender: TObject); begin
end; pos_yy:=(round(pos_y) / dx);
pos_yy:=pos_Y-
var (round(pos_yy)*DX); //D(X)
Form1: TForm1; pos_yy:=pos_y-pos_YY; //x-
pos:b; dx pos_xx:=pos_x;
DR:boolean=false; end else pos_yy:=pos_y;
temp_x,temp_y:real; if (round(pos_x) mod dx) <>0 then
dx:integer; begin
pos_xx:=(round(pos_x) / dx);
pos_xx:=pos_x-(round(pos_xx)*dx); label1.Caption:='X =
pos_xx:=pos_x-pos_xx; '+IntToStr(Round(pos[2,1]/dx))+#10+#13+'Y
pos_yy:=pos_y; = '+IntToStr(Round(pos[2,2]/dx));
end else pos_xx:=pos_x; p.Canvas.MoveTo(round(pos[1,1]),round(pos
form1.p.Canvas.Rectangle(round(pos_xx),ro [1,2]));
und(pos_yy), p.Canvas.lineTo(round(x),round(y));
round(pos_xx+dx),round(pos_yy+dx)); temp_x:=x;
form1.p.Canvas.Brush.Color:=clblack; temp_y:=y;
inc(i); end;
end; end;
end; procedure TForm1.pMouseUp(Sender:
procedure TForm1.pPaint(Sender: TObject); TObject; Button: TMouseButton;
var i:integer; Shift: TShiftState; X, Y: Integer);
begin var i:byte;
p.Canvas.FillRect(clientrect); i:=0; begin
p.Canvas.Pen.Color:=clwhite; i:=0;
while i<=p.Width do if round(pos[1,1]) mod dx <>0 then
begin while round(pos[1,1]-i) mod dx <>0 do
p.Canvas.moveto(i,0); inc(i);
p.Canvas.lineto(i,p.Height); pos[1,1]:=pos[1,1]-i;
inc(i,dx); i:=0;
end; i:=0; if round(pos[1,2]) mod dx <>0 then
while i<=p.height do while round(pos[1,2]-i) mod dx <>0 do
begin inc(i);
p.Canvas.moveto(0,i); pos[1,2]:=pos[1,2]-i ;
p.Canvas.lineto(p.width,i); i:=0;
inc(i,dx); if round(x) mod dx <>0 then
end; while round(x-i) mod dx <>0 do
end; inc(i);
procedure TForm1.pMouseDown(Sender: pos[2,1]:=x-i;
TObject; Button: TMouseButton; i:=0;
Shift: TShiftState; X, Y: Integer); if round(y) mod dx <>0 then
begin while round(y-i) mod dx <>0 do
ppaint(form1); inc(i);
DR:=true; pos[2,2]:=y-i ;
pos[1,1]:=x; pos[2,1]:=pos[2,1] / dx;
pos[1,2]:=y; pos[2,2]:=pos[2,2] / dx;
temp_x:=pos[1,1]; pos[1,1]:=pos[1,1] / dx;
temp_y:=pos[1,2]; pos[1,2]:=pos[1,2] / dx;
end; dr:=false;
procedure TForm1.pMouseMove(Sender: if LAb=2 then
TObject; Shift: TShiftState; X, if
Y: Integer); (pos[1,1]<>pos[2,1])or(pos[2,2]<>pos[1,2])
begin then
if dr then draw else else
begin if
p.Canvas.Pen.Mode:=pmxor; (pos[1,1]<>pos[2,1])or(pos[2,2]<>pos[1,2])
p.Canvas.MoveTo(round(pos[1,1]),round(pos and (lab=1)then
[1,2])); draw1;
p.Canvas.lineTo(round(temp_x),round(temp_ end;
y)); procedure TForm1.SpinEdit1Change(Sender:
p.Canvas.Pen.Color:=clyellow; TObject);
pos[2,1]:=x; begin
pos[2,2]:=y; if SpinEdit1.Value>1 then
form1.Canvas.Font.Color:=cllime; dx:=SpinEdit1.Value;
ppaint(form1);
end;
procedure TForm1.FormCreate(Sender:
TObject);
begin
SpinEdit1.Value:=50;
dx:=SpinEdit1.value;
end;
procedure TForm1.Panel2Click(Sender:
TObject);
begin
panel2.BevelOuter:=bvLowered;
panel2.Color:=clActiveBorder;
panel1.BevelOuter:=bvRaised;
panel1.Color:=clBtnFace;
form1.Caption:='LAB 4';
lab:=1;
end;
procedure TForm1.Panel1Click(Sender:
TObject);
begin
panel1.BevelOuter:=bvLowered;
panel1.Color:=clActiveBorder;
panel2.BevelOuter:=bvRaised;
panel2.Color:=clBtnFace;
form1.Caption:='LAB 5';
lab:=2;
end;
end.

You might also like