Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
20071227_Chumak_MU.doc
Скачиваний:
4
Добавлен:
09.11.2019
Размер:
694.27 Кб
Скачать

2.2.3 Алгоритм заповнення iз списком ребер I прапорцем

Алгоритм заповнення iз списком ребер i прапорцем є двокроковим.

Перший крок. Креслення контуру, завдяки чому на кожному рядку, що сканується, утворюються пари обмежуючих (граничних) пiкселiв. Користуючись угодою про середину iнтервалу мiж рядками, що скануються, для кожного ребра, яке перетинає такий рядок, потрiбно вiдмiтити самий лiвий пiксел, середина якого лежить справа вiд точки перетину xcross, тобто x+1/2>xcross

Другий крок. Заповнення пiкселiв мiж парами обмежуючих пiкселiв:

Для кожного рядка, що сканується, i який перетинає багатокутник здiйснюємо наступнi дiї.

Початок.

Inside = FALSE;

for X=0 {лiва границя} to X = Xmax {права границя} do

begin

if < x-пiксел має граничне значення > then < iнвертування змiнної Inside >

if Inside=TRUE

then < вiдмiтити x-пiксел як належний до середини багатокутника >

else < вiдмiтити x-пiксел як зовнiшнiй до багатокутника >

Кiнець.

Програмна реалiзацiя

unit SidesAndFlagUnit1;

іnterface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls,

Forms, Dialogs, StdCtrls;

const _Nborder =100; {максимальна кiлькiсть вершин}

type TForm1 = class(TForm)

Button, Button2, Button3: TButton;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

private { Private declarations }

public { Public declarations }

end;

PointInt=array[1..2] of integer;

Polygon=array[1.._NBorder] of PointInt;

var

Form1: TForm1;

YesContour:boolean;{ознака введення вершин}

NP, {число вершин багатокутника}

Xmin,Xmax, {границi по вiсi ОХ багатокутника}

Ymin,Ymax {дiапазон рядкiв, що скануються}

: integer;

P:Polygon; {вершини багатокутника}

implementation {$R *.DFM}

// Iнвертування ознаки Inside

procedure InvBool(var Inside:boolean);

begin {InvBool}

if Inside then Inside:=false else Inside:=true;

end; {InvBool}

// Встановлення вершин багатокутника

procedure SetP(var P:Polygon;var NP:integer);

var

x,y:integer;

fin : text; {файл з вершинами багатокутника}

begin {SetP}

AssignFile(fin,'Polygon.dat'); reset(fin); NP:=0;

while (not Eof(fin)) do

begin

NP:=NP+1;readln(fin,x,y);P[NP,1]:=x;P[NP,2]:=y;

if NP=1

then begin Xmin:=x;Xmax:=x;Ymin:=y;Ymax:=y; end

else begin

if Xmin>x then Xmin:=x; if Xmax<x then Xmax:=x;

if Ymin>y then Ymin:=y; if Ymax<y then Ymax:=y;

end;

end;

CloseFile(fin);

end; {SetP}

// Креслення контуру

procedure AbrisLine(Xs,Ys,Xf,Yf,ColorR:integer);

var

x,y,Ystrt,Yfin,Xcross: real;

begin {AbrisLine}

if Ys<>Yf

then begin {Ys<>Yf}

// встановлення промiжку [Ystrt,Yfin] змiни y

if Ys>Yf then begin Ystrt:=Yf;Yfin:=Ys;end;

if Ys<Yf then begin Ystrt:=Ys;Yfin:=Yf;end;

y:=Ystrt+0.5;

while (y<Yfin) do begin

// знаходження х-координати перетину рядка з вiдрiзком

Xcross:=Xs+(y-Ys)*((Xs-Xf)/(Ys-Yf));

// знаходження найбiльш лiвого цiлого х,

що лежить справа вiд перетину

x:=round(Xcross-0.5);

if x<=Xcross-0.5 then x:=x+1;

// виведення вiдповiдного пiкселя

Form1.Canvas.Pixels[round(x),round(y-0.5)]:=ColorR;

// встановлення наступного значення у

y:=y+1;

end;

end; {Ys<>Yf}

end; {AbrisLine}

// Заповнення середини багатокутника з використанням прапорця

procedure FlagRasterPolygon(P:Polygon;

NP:integer;ColorR:integer);

var Inside:boolean; {прапорець}

i,j:integer;s:string;

begin {FlagRasterPolygon}

for j:=Ymin to Ymax do

begin {j:=Ymin to Ymax}

Inside:=false;

for i:=Xmin to Xmax do

begin {i:=Xmin to Xmax}

if B[i,j] then InvBool(Inside);

if Inside

then begin

B[i,j]:=true;Form1.Canvas.Pixels[i,j]:=ColorR;

end;

end; {i:=Xmin to Xmax}

end; {j:=Ymin to Ymax}

end; {FlagRasterPolygon}

procedure TForm1.Button1Click(Sender: TObject);

var i:integer;

begin {TForm1.Button1Click}

// встановлення списку вершин багатокутника

YesContour:=true;SetP(P,NP);

for i:=1 to NP-1 do

AbrisLine(P[i,1],P[i,2],P[i+1,1],P[i+1,2],clRed);

AbrisLine(P[NP,1],P[NP,2],P[1,1],P[1,2],clRed);

end; {TForm1.Button1Click}

procedure TForm1.Button2Click(Sender: TObject);

begin {TForm1.Button2Click}

if YesContour then FlagRasterPolygon(P,NP,clBlack);

end; {TForm1.Button2Click}

procedure TForm1.Button3Click(Sender: TObject);

begin {TForm1.Button3Click}

Form1.Close;

end; {TForm1.Button3Click}

procedure TForm1.FormCreate(Sender: TObject);

begin {TForm1.FormCreate}

YesCountour:=false;

end; {TForm1.FormCreate}

end. {SidesAndFlagUnit1}

Зауваження 7 У алгоритмі заповнення за ребрами i прапорцем кожен пiксел обробляється тiльки один раз. Тому вiн бiльш доцiльнiший нiж алгоритм з списком ребер або алгоритм з перегородкою.

Зауваження 8 Алгоритм заповнення за ребрами (з перегородкою чи нi) або алгоритм заповнення за ребрами з прапорцем при роботi з буфером кадру не потребують побудови, пiдтримки i сортування будь-яких спискiв.

Зауваження 9 При програмнiй реалiзацiї алгоритм з упорядкованим списком ребер i алгоритм з списком ребер i прапорцем виконуються приблизно з однаковою швидкiстю. Але при апаратнiй реалiзацiї алгоритм з списком ребер i прапорцем виконується на один-два порядка швiдше нiж алгоритм з упорядкованим списком ребер.

Лiтература. [14, стор. 107-111].

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]