Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
posobie КГ1.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
11.3 Mб
Скачать

5.5. Отсечение отрезка

Необходимость отсечь выводимое изображение по границам некоторой области встречается довольно часто. В простейших ситуациях в качестве такой области, как правило, выступает прямоугольник.

Ниже рассматривается достаточно простой и эффективный алгоритм отсечения отрезков по границе произвольного прямоугольника. Он заключается в разбиении всей плоскости на 9 областей прямыми, образующими прямоугольник. В каждой из этих областей все точки по отношению к прямоугольнику расположены одинаково. Определив, в какие области попали концы рассматриваемого отрезка, легко понять, где именно необходимо отсечение. Для этого каждой области сообщается 4-битовый код.

4-битовый код:

  • бит 0 означает, что точка лежит левее прямоугольника,

  • бит 1 означает, что точка лежит выше прямоугольника,

  • бит 2 означает, что точка лежит правее прямоугольника,

  • бит 3 означает, что точка лежит ниже прямоугольника.

Алгоритм Сазерленда — Коэна

//File clip.cpp

void Swap (int. &a, int &b)

{

int с;

c=a;

a=b;

b=c;

}

int OutCodelint x, int y, int X1, int Y1, int X2, int Y2)

{

int code=0;

if (x<X1) code =0x01;

if (y<Y1) code =0x02;

if (x<X2) code =0x04;

if (y<Y2) cede =0x08;

return code;

}

void ClipLine(int x1, int y1, int x2, int y2, int X1, int Y1, int X2, int Y2)

{

int code1=OutCode(x1, y1, X1, Y1, X2, Y2);

int code2=OutCode(x2, y2, X1, Y1, X2, Y2);

int inside=(code1Icode2)==0;

int outside=(code1&code2)!=0;

while(!outside&&! inside)

{

if (code1==0)

{

Swap fx1,x2) ;

Swap(y1,y2);

Swap(code1,code2);

}

if(code1 & 0x01)

{

y1+=(long)(y2-y1)*(X1-x1)/(x2-x1);

x1=X1l;

}

else

if(code1 & 0x02)

{

x1+=(long)(x2-x1)* (Y1l-y1/(y2-y1);

y1=Y1l;

}

else

if(code1 & 0x04)

{

y1+=(long) (y2-y1)* (X2-x1)/(x2-x1);

x1=X2;

}

else

if(code1 & 0x08)

{

x1+=(long)(x2-x1)* (Y2-y1l)/(y2-y1);

y2=Y2;

}

code1=OutCcde(x1, y1, X1I, Y1, X2, Y2) ;

code2=Out.Code(x2, y2, X1, Y1, X2, Y2) ;

inside=(code1lIccde2)==0;

outside=(code1&code2)!=0;

}

line" (xl, yl, x2, y2);

}

5.6. Закраска области, заданной цветом границы

Рассмотрим область, ограниченную набором пикселей заданного цвета, и точку (х, у), лежащую внутри этой области.

//File fi111.cpp

void Pixe1Fi11(int x, int y, int BorderColor, int color)

{

int c=getpixel(x, y);

if ((c!=BorderColor) && {c!=color))

{

putpixel (x,y,color);

PixelFill (x -1,y, BorderColor,color);

PixelFill (x+1,y, BorderColor,color);

PixelFill (x, y-1, BorderColor,color);

PixelFill (x,y+1, BorderColor, color) ;

}

}

Простейший алгоритм, показанный выше, хотя и абсолютно корректно заполняющий даже самые сложные области, является слишком неэффективным, так как уже для отрисованного пикселя функция вызывается еще три раза, и, кроме того, требует слишком большого стека из-за большой глубины рекурсии.

Поэтому для решения задачи закраски области предпочтительнее алгоритмы, способные обрабатывать сразу целые группы пикселей.

Рассмотрим версию одного из самых популярных алгоритмов подобного типа, когда для заданной точки (х, у) определяется и заполняется максимальный отрезок [х], хr ], содержащий эту точку и лежащий внутри области. После этого в поисках еще не заполненных пикселей проверяются отрезки, лежащие выше и ниже. Если такие пиксели находятся, то функция рекурсивно вызывается для их обработки.

Этот алгоритм эффективно работает даже для областей с отверстиями.

//File fill2.cpp

#include <conic.h>

#include <graphics.h>

#include <process.h>

#include <stdic.h>

#include <stdlib.h>

int BorderColor = WHITE;

int Color = GREEN;

int. LineFill(int x, int y, int. dir, int PrevX1, int PrevXr)

{

int x1=x;

int xr=x;

int c;

do

c=getpixel(--xl,y);

while ( (c!=BorderColor) && (c!=Color) ) ;

do

c=getpixel(t+xr, y) ;

while((c!=BcrderColor)ss(c!=Color));

xl + +;

xr++;

line(x1,у,хг,у);

for(x=x1;x<=xr;x++)

{

c=getpixel(x,y+dir);

if((c!=BorderColor) &&(c!=Color))

x=LineFill(x, y+dir,dir,x1,xr);

}

for(x=x1;x<PrevX1;x++)

{

c=getpixel(x,y-dir);

if((c!=BorderCclor) &&(c!=Color))

x=LineFill(x,y-dir,-dir,x1l,xr);

}

for(x-PrevXr;x<xr;x++)

{

c=getpixel(x,y-dir);

if((c!=BorderCclor) &&(c!=Color))

x=LineFill(x,y-dir, -dir,x1, xr) ;

}

return xr;

}

void Fill(int x,int y);

{

LineFill(x, y, 1, x, x);

}

main()

{

int driver=DETECT;

int mode;

int res;

initgraph(sdriver, smode, "");

if((res=graphresult())!=grOk)

{

printf("\nGraphics error: %s\n", grapherrormsg(res));

exit(1) ;

}

circle(320,200,140);

circle(260,200,40);

circle(380,200,40);

getch() ;

setcolor(C0lcr);

Fill(320,300);

getch();

closegraph();

}

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