- •Комп’ютерна графіка
- •1.3 Перетворення прямих ліній (відрізків)
- •1.4 Обертання
- •1.5 Відображення
- •1.6 Зміна масштабу
- •1.7 Двовимірний зсув і однорідні координати
- •2.6 Відображення в просторі
- •2.2 Тривимірна зміна масштабу
- •2.3 Перетворення трьохвимірних координат в двовимірні
- •2.4 Тривимірний зсув
- •2.7 Просторовий перенос
- •2.8 Тривимірне обертання навколо довільної осі
- •3.2 Косокутні проекції
- •Лабораторна робота №4 Алгоритм креслення відрізків
- •Теоретичні основи
- •Лабораторна робота № 5 Метод цифрового диференціального аналізатора
- •Теоретичні відомості
- •Алгоритм Брезенхема розкладання в растр відрізка для першого октанта
- •6.2. Загальний алгоритм Брезенхема.
- •Узагальнений цілочисельний алгоритм Брезенхема для усіх квадрантів
- •Лабораторна робота № 7 Алгоритм Брезенхема для генерації кола
- •Теоретичні основи
- •8.2 . Простий алгоритм з упорядкованим списком ребер
- •Простий алгоритм з упорядкованим списком ребер
- •8.3. Більш ефективні алгоритми з упорядкованим списком ребер
- •Більш ефективний алгоритм з упорядкованим списком ребер
- •9.1 Простий алгоритм заповнення з запалом і стеком
- •9.2 Простий алгоритм заповнення
- •Приклад 9.1. Простий алгоритм заповнення з запалом
- •Приклад 9.2. Алгоритм заповнення з запалом для багатокутника з діркою
- •9.3 Порядковий алгоритм заповнення з запалом
- •9.4 Алгоритм порядкового заповнення з запалом
- •9.5 Порядковий алгоритм заповнення з запалом
- •Приклад 9.3. Порядковий алгоритм заповнення з запалом
- •Література
- •Комп’ютерна графіка Методичні вказівки
Лабораторна робота № 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 - початкове значення для чергового кроку вздовж відрізка. Фактично рівняння являє собою рекурентне співвідношення для послідовних значень 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
Таблиця 1
Результати роботи покрокового циклу
Незважаючи на те що результати, представлені на рис.2.2, виглядають цілком прийнятними, аналіз відрізків, проведених із точки (0,0) у точку (-8,4) і (8,-4), показує, що розкладений у растр відрізок лежить по одну сторону від реального і що на одному з кінців відрізка з’являється зайва точка, тобто результат роботи алгоритму залежить від орієнтації. Отже точність у кінцевих точках зменшується.
Рис.5.1. Результати роботи простого ЦДА в третьому квадранті.
ПОРЯДОК ВИКОНАННЯ РОБОТИ
1. Побудуйте декартову двовимірну систему координат, у якій максимальне значення по осях x i y було би близько 10 і початок координат був би по центру.
2. Розграфте площину побудови відрізків у вигляді сітки, на якій будуть будуватися піксели.
3. Побудуйте псевдовідрізок, який би з’єднував початок з кінцем відрізку.
4. Приведіть результат роботи алгоритму накреслення відрізку, методом цифрового диференціального аналізатора, у якому би підсвічувалися піксели, або ж клітинки сітки.
5. Проаналізуйте результати.
ЗМІСТ ЗВІТУ
Звіт повинен містити:
1) назву роботи;
2) мету роботи;
3) короткий теоретичний вступ;
4) завдання до лабораторної роботи;
5) тексти розроблених і відлагоджених програм
6) малюнки з реалізацією програми
7) висновки
ПРИКЛАД ПРОГРАМНОЇ РЕАЛІЗАЦІЇ
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls,math, StdCtrls, Spin;
type
b=array[1..2,1..2] of real;
TForm1 = class(TForm)
p: TPaintBox;
Label1: TLabel;
Label2: TLabel;
SpinEdit1: TSpinEdit;
Panel1: TPanel;
Panel2: TPanel;
procedure pPaint(Sender: TObject);
procedure pMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure pMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure pMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure SpinEdit1Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Panel2Click(Sender: TObject);
procedure Panel1Click(Sender: TObject);
end;
var
Form1: TForm1;
pos:b;
DR:boolean=false;
temp_x,temp_y:real;
dx:integer;
implementation
{$R *.DFM}
procedure draw;
var pos_x,pos_y,pos_xx,pos_yy:real;
i:integer;
Dy,Dxx,l:real;
begin form1.p.Canvas.Brush.Style:=bssolid;
if abs(pos[2,1]-pos[1,1])>=abs(pos[2,2]-pos[1,2]) then
L:=abs((pos[2,1]-pos[1,1])) else L:=abs(pos[2,2]-pos[1,2]) ;
dxx:=((pos[2,1]-pos[1,1])/l)*dx;
dy:=((pos[2,2]-pos[1,2])/l)*dx;
pos_x:=((pos[1,1]*dx));
pos_y:=((pos[1,2]*dx));
i:=1; form1.p.Canvas.Brush.Color:=cllime; form1.p.Canvas.Rectangle (round(pos_x),round(pos_y), round(pos_x+dx),round(pos_y+dx)); form1.p.Canvas.Brush.Color:=clblack;
while i<=l do
begin
pos_xx:=0;
pos_yy:=0;
pos_x:=(pos_x+dxx);
pos_y:=(pos_y+dy); form1.p.Canvas.Brush.Style:=bssolid; form1.p.Canvas.Brush.Color:=cllime;
if (round(pos_y) mod dx) <>0 then
begin
pos_yy:=(round(pos_y) / dx);
pos_yy:=pos_Y-(round(pos_yy)*DX); //D(X)
pos_yy:=pos_y-pos_YY; //x-dx pos_xx:=pos_x;
end else pos_yy:=pos_y;
if (round(pos_x) mod dx) <>0 then
begin
pos_xx:=(round(pos_x) / dx);
pos_xx:=pos_x-(round(pos_xx)*dx);
pos_xx:=pos_x-pos_xx;
pos_yy:=pos_y;
end else pos_xx:=pos_x; form1.p.Canvas.Rectangle(round(pos_xx), round(pos_yy), round(pos_xx+dx),round(pos_yy+dx)); form1.p.Canvas.Brush.Color:=clblack;
inc(i);
end;
end;
procedure TForm1.pPaint(Sender: TObject);
var i:integer;
begin
p.Canvas.FillRect(clientrect); i:=0;
p.Canvas.Pen.Color:=clwhite;
while i<=p.Width do
begin
p.Canvas.moveto(i,0);
p.Canvas.lineto(i,p.Height);
inc(i,dx);
end; i:=0;
while i<=p.height do
begin
p.Canvas.moveto(0,i);
p.Canvas.lineto(p.width,i);
inc(i,dx);
end;
end;
procedure TForm1.pMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ppaint(form1);
DR:=true;
pos[1,1]:=x;
pos[1,2]:=y;
temp_x:=pos[1,1];
temp_y:=pos[1,2];
end;
procedure TForm1.pMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if dr then
begin
p.Canvas.Pen.Mode:=pmxor; p.Canvas.MoveTo(round(pos[1,1]), round(pos[1,2])); p.Canvas.lineTo(round(temp_x), round(temp_y));
p.Canvas.Pen.Color:=clyellow;
pos[2,1]:=x;
pos[2,2]:=y;
form1.Canvas.Font.Color:=cllime;
label1.Caption:=’X = ‘+IntToStr(Round(pos[2,1]/dx))+#10+#13+’Y = ‘+IntToStr(Round(pos[2,2]/dx)); p.Canvas.MoveTo(round(pos[1,1]), round(pos[1,2])); p.Canvas.lineTo(round(x),round(y));
temp_x:=x;
temp_y:=y;
end;
end;
procedure TForm1.pMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var i:byte;
begin
i:=0;
if round(pos[1,1]) mod dx <>0 then
while round(pos[1,1]-i) mod dx <>0 do
inc(i);
pos[1,1]:=pos[1,1]-i;
i:=0;
if round(pos[1,2]) mod dx <>0 then
while round(pos[1,2]-i) mod dx <>0 do
inc(i);
pos[1,2]:=pos[1,2]-i ;
i:=0;
if round(x) mod dx <>0 then
while round(x-i) mod dx <>0 do
inc(i);
pos[2,1]:=x-i;
i:=0;
if round(y) mod dx <>0 then
while round(y-i) mod dx <>0 do
inc(i);
pos[2,2]:=y-i ;
pos[2,1]:=pos[2,1] / dx;
pos[2,2]:=pos[2,2] / dx;
pos[1,1]:=pos[1,1] / dx;
pos[1,2]:=pos[1,2] / dx;
dr:=false;
if LAb=2 then
if (pos[1,1]<>pos[2,1])or(pos[2,2]<>pos[1,2]) then
draw else else
if (pos[1,1]<>pos[2,1])or(pos[2,2]<>pos[1,2]) and (lab=1)then
draw1;
end;
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
if SpinEdit1.Value>1 then
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.
Лабораторна робота № 6
Алгоритм Брезенхема для побудови прямих
Мета роботи: Освоїти алгоритм Брезенхема для побудови прямих
Теоретичні відомості
6.1. Алгоритм Брезенхема для побудови прямих у першому октанті
Хоча алгоритм Брезенхема був спочатку розроблений для цифрових графопобудовувачів. Проте він має застосування для растрових пристроїв з ЕПТ. Алгоритм вибирає оптимальні растрові координати для представлення відрізка. У процесі роботи одна з координат - або x, або y (в залежності від кутового коефіцієнта) - змінюється на одиницю. Зміна іншої координати (на 0 чи 1) залежить від відстані між дійсним положенням відрізка і найближчих координат сітки. Таку відстань ми назвемо похибкою.
Алгоритм побудований так, що потрібно перевірити лише знак цієї похибки. На рис.6.1 це ілюструється для відрізка в першому октанті, тобто для відрізка з кутовим коефіцієнтом, що лежить у діапазоні від 0 до 1. З рисунка можна помітити що, якщо кутовий коефіцієнт відрізка з точки (0,0) більший, ніж 1/2, то перетин з прямою x=1 буде розташований ближче до прямої y=1, ніж до прямої y=0. Отже, точка растра (1,1) краще апроксимує хід відрізка, ніж точка (1,0). Якщо кутовий коефіцієнт менше 1/2, то навпаки. для кутового коефіцієнта, рівного 1/2, немає кращого вибору. У даному випадку вибирається точка (1,1).
Рис.6.1. Вибір точки за методом Брезенхема.
Не усі відрізки проходять через точки растра. Подібна ситуація ілюструється рис.3.2, де відрізок з тангенсом кута нахилу 3/8 спочатку проходить через точку растра (0,0) і послідовно перетинає три піксели. Також ілюструється обчислення похибки при представленні відрізка дискретними пікселами.
Рис.6.2. Графік похибки в алгоритмі Брезенхема
Оскільки бажано перевіряти тільки знак похибки, то вона спочатку встановлюється рівною -1/2. Таким чином, якщо кутовий коефіцієнт відрізка дорівнює чи більший 1/2, то величина похибки в наступній точці растра з координатами (1,0) може бути обчислена як
e=e+m
де m - кутовий коефіцієнт. У нашому випадку при початковому значенні похибки -1/2
e=-1/2+3/8=-1/8
Тому що е від’ємне, відрізок пройде нижче середини піксела. Отже, піксел на тому ж самому горизонтальному рівні краще апроксимує положення відрізка, тому в не збільшується. Аналогічно обчислюємо похибку
e=-1/8+3/8=1/4
у наступній точці растра (2,0). Тепер е додатне, значить відрізок пройде вище середньої точки. Растровий елемент (2,1) з наступною по величині координатою в краще апроксимує положення відрізка. Отже, у збільшується на 1. Перше ніж розглядати наступний піксел, необхідно відкоректувати похибку відніманням від неї 1. Маємо
e=1/4-1=-3/4
Помітимо, що перетин вертикальної прямої x=2 із заданим відрізком лежить на 1/4 нижче прямої у=1. Якщо ж перенести відрізок 1/2 вниз, ми одержимо саме величину -3/4. Продовження обчислень для наступного піксела дає
e=-3/4+3/8=-3/8
Тому що е від’ємне, то y не збільшується. З усього сказаного випливає, що похибка - це інтервал, що відтинається по осі y розглянутим відрізком у кожному растровому елементі (відносно -1/2).
Приведемо алгоритм Брезенхема для першого октанта, тобто для випадку
0 <= Dy<= Dx.
