
- •Компьютерная графика Курс лекций
- •Оглавление
- •Предисловие
- •Лекция 1. Введение
- •1.1. История компьютерной графики
- •1.2.Области применения компьютерной графики
- •1.3. Классификация графических изображений
- •1.4. Виды компьютерной графики
- •1.4.1. Растровая графика
- •1.4.2. Векторная графика
- •1.4.3. Фрактальная графика
- •Лекция 2. Аппаратная база машинной графики
- •2.1. Видеосистема персонального компьютера
- •2.2. Цвет
- •2.3. Форматы графических файлов
- •Лекция 3. Отображение геометрических объектов
- •1. Двумя точками ( а и в ).
- •Лекция 4. Аппарат проецирования
- •4.1. Аксонометрические проекции
- •4.2. Способы преобразования комплексного чертежа
- •Лекция 5. Представление объектов и их машинная генерация
- •5.1. Аффинные преобразования на плоскости
- •5.2. Растровая развертка отрезка
- •3.1 Растровая развертка отрезка
- •5.3. Алгоритм вывода окружности
- •5.4. Кривая Безье
- •5.5. Отсечение отрезка
- •5.6. Закраска области, заданной цветом границы
- •5.7. Удаление невидимых линий и поверхностей
- •Алгоритм робертса
- •Лекция 6. Фрактальная графика
- •6.1. Алгоритм построения фрактала
- •6.2. Природные фракталы
- •6.3. Геометрические фракталы
- •6.4. Алгебраические фракталы
- •6 .5. Стохастические фракталы
- •Лекция 7. Графические редакторы
- •Лекция 8. СЖатие изображений
- •8.1. Необратимое сжатие
- •8.2. Обратимое сжатие
- •8.3. Общие положения алгоритмов сжатия изображений
- •8.4. Алгоритмы архивации без потерь
- •8.5. Алгоритмы архивации с потерями
- •Литература
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();
}