![](/user_photo/2706_HbeT2.jpg)
- •Введение
- •1. Машинная графика и обработка изображения с помощью эвм
- •2. Типы графических устройств
- •2.1. Графические дисплеи на запоминающей трубке
- •2.2. Векторные графические дисплеи с регенерацией изображения
- •2.3. Растровые графические дисплеи с регенерацией изображения
- •2.4. Диалоговые устройства
- •3. Основы растровой графики
- •3.1. Алгоритмы вычерчивания отрезков
- •3.2. Цифровой дифференциальный анализатор
- •3.3. Алгоритм Брезенхема
- •3.4. Целочисленный алгоритм Брезенхема
- •3.5. Общий алгоритм Брезенхема
- •3.6. Алгоритм Брезенхема для генерации окружности
- •4. Растровая развертка изображения
- •4.1. Растровая развертка в реальном времени
- •4.2. Групповое кодирование
- •4.3. Клеточное кодирование
- •4.4. Буферы кадра
- •4.5. Изображение отрезков
- •4.6. Изображение литер
- •4.7. Растровая развертка сплошных областей и заполнение многоугольников
- •1 X 8 – внутри многоугольника;
- •1 Х 4 – внутри многоугольника;
- •6 Х 8 – внутри многоугольника;
- •4.8. Простой алгоритм с упорядоченным списком ребер
- •4.9. Алгоритм заполнения по ребрам
- •4.10. Алгоритм со списком ребер и флагом
- •4.11. Алгоритм заполнения с затравкой
- •4.12. Построчный алгоритм заполнения с затравкой
- •4.13. Основные методы устранения ступенчатости
- •4.14. Аппроксимация полутонами
- •5. Отсечение
- •5.1. Двумерное отсечение
- •5.2. Алгоритм отсечения Сазерленда-Коэна
- •5.3. Алгоритм разбиения средней точкой
- •5.4. Обобщение: отсечение двумерного отрезка выпуклым окном
- •5.5. Алгоритм Кируса–Бека
- •5.6. Внутреннее и внешнее отсечение
- •5.7. Определение факта выпуклости многоугольника
- •5.8. Разбиение невыпуклых многоугольников
- •5.9. Трехмерное отсечение
- •5.10. Определение выпуклости трехмерного тела
- •5.11. Отсечение невыпуклых тел
- •5.12. Отсечение многоугольников
- •5.13. Последовательное отсечение многоугольника – алгоритм Сазерленда – Ходжмена
- •5.14. Невыпуклые отсекающие области – алгоритм
- •5.15. Литеры
- •6. Удаление невидимых линий и поверхностей
- •6.1. Алгоритм плавающего горизонта
- •6.2. Алгоритм Робертса
- •6.3. Алгоритм Варнока
- •6.4. Алгоритм Вейлера–Азертона
- •6.5. Алгоритм, использующий z-буфер
- •6.6. Алгоритмы, использующие список приоритетов
- •6.7. Алгоритм построчного сканирования
- •6.8. Алгоритм построчного сканирования, использующий
- •Библиографический список рекомендуемой литературы
- •Оглавление
- •1. Машинная графика и обработка изображения с помощью эвм….……..3
3.5. Общий алгоритм Брезенхема
Для получения общего алгоритма растровой развертки необходимо избавиться от ограничений, которые мы до сих пор накладывали на расположение отрезка на плоскости, а именно от требования 0k1.
Чтобы реализация алгоритма Брезенхема была полной, необходимо обрабатывать отрезки во всех квадрантах. Модификацию легко сделать, учитывая номер квадранта, в котором лежит отрезок и его угловой коэффициент. Когда абсолютная величина углового коэффициента больше 1, y постоянно изменяется на единицу, а критерий ошибки Брезенхема используется для принятия решения об изменении величины x. Выбор постоянно изменяющейся (на +1 или –1) координаты зависит от квадранта (рис.3).
x=x-1 y=y+1
|
x=x+1 y=y+1
|
x=x-1 y=y-1 |
x=x+1 y=y-1
|
Рис.3. Общий алгоритм Брезенхема
Таким образом, учитывая ориентацию отрезка относительно положительных направлений осей координат и меняя переменные x,y в случае k по модулю больше 1, получаем окончательную общую версию алгоритма Брезенхема, которая называется восьмисвязной разверткой отрезка.
Пример процедуры общего алгоритма Брезенхема для восьмисвязной развертки отрезка:
Procedure Line_8 (x1,y1,x2,y2: integer);
Var
x,y,s1,s2,dx,dy,e,z: integer;
change: boolean;
Begin
x:=x1; y:=y1; dx:=abs(x2-x1); dy:=abs(y2-y1);
s1:=sign(x2-x1); s2:=sign(y2-y1);
if dy>dx then
begin
z:=dx; dx:=dy; dy:=z; change:=true
end
else change:=false;
e:=2dy-dx;
for i:=1 to dx do
begin
PutPixel (x,y,color);
While e>=0 do
begin
if change then x:=x+s1 else y:=y+s2;
e:=e-2dx
end;
if change then y:=y+s2 else x:=x+s1;
e:=e+2dy
end;
PutPixel (x,y,color)
End.
Функция sign возвращает значения –1,0,+1 для отрицательного, нулевого и положительного аргумента соответственно (реализована не во всех версиях Паскаля).
3.6. Алгоритм Брезенхема для генерации окружности
В растр нужно разлагать не только линейные, но и другие, более сложные функции.
Д
ля
того чтобы нарисовать окружность
необходимо сгенерировать только 1/8
часть. Остальные ее части могут быть
получены последовательными отражениями.
Если сгенерирован первый октант (от 0
до 45 против часовой
стрелки), то второй октант можно получить
зеркальным отражением относительно
прямой y=x,
что дает в совокупности первый квадрант.
Первый квадрант отражается относительно
прямой x=0 для получения
соответствующей части окружности во
втором квадранте. Верхняя полуокружность
отражается относительно прямой y=0
для завершения построения полной
окружности (рис.4).
Рис.4. Генерация окружности
Д
ля
вывода алгоритма рассмотрим первую
четверть окружности с центром в начале
координат (рис.5). Заметим, что если
работа алгоритма начинается в точке
x=0, y=R,
то при генерации окружности по часовой
стрелке в первом квадранте y
является монотонно убывающей функцией
аргумента x. Аналогично,
если исходной точкой является точка
x=R,
y=0, то при генерации
окружности против часовой стрелки x
будет монотонно убывающей функцией
аргумента y.
Предположим, что центр окружности и начальная точка находятся точно в точках растра, выберем для нашего случая генерацию по часовой стрелке с началом в точке x=0, y=R.
Д
ля
любой заданной точки на окружности при
генерации по часовой стрелке существует
только три возможности выбрать следующий
пиксель, наилучшим образом приближающий
окружность (рис.6): горизонтально вправо,
по диагонали вниз и вправо, вертикально
вниз. Алгоритм выбирает пиксель, для
которого минимален квадрат расстояния
между одним из этих пикселов и окружностью,
т.е. минимум из следующих выражений:
,
,
.
Разность
между квадратами расстояний от центра
окружности до диагонального пикселя
()
и от центра до точки на окружности R2
равна
.
Как и в алгоритме Брезенхема для отрезка, для выбора соответствующего пикселя желательно использовать только знак ошибки, а не ее величину.
При
<0
диагональная точка (
)
находится внутри реальной окружности,
в этой ситуации следует выбрать либо
пиксель (
),
т.е.
,
либо пиксель (
),
т.е.
.
Далее проверяется разность квадратов
расстояний от окружности до пикселов
в горизонтальном и диагональном
направлениях:
.
При
<0
расстояние от окружности до диагонального
пикселя ()
больше, чем до горизонтального пикселя
(
).
Напротив, если >0,
расстояние до горизонтального пикселя
(
)
больше. Таким образом:
-
при 0 выбираем
в точке (
),
-
при >0 выбираем
в точке (
),
-
при =0, когда расстояние от окружности до обоих пикселов одинаково, выбираем горизонтальный шаг.
Если
>0,
то диагональная точка (
)
находится вне окружности.
В данной ситуации ясно, что должен
быть выбран либо пиксель (
),
т.е.
,
либо (
),
т.е.
.
Далее проверяется разность между
квадратом расстояний от окружности до
диагонального пикселя
и
вертикального
пикселов, т.е.
.
При
<0
расстояние от окружности до вертикального
пикселя (
)
больше и следует выбирать диагональный
шаг
к пикселю (
).
Напротив, в случае
>0
расстояние от окружности до диагонального
пикселя больше и следует выбрать
вертикальное движение к пикселю (
).
Таким образом:
-
при
0 выбираем
в (
),
-
при
>0 выбираем
(
),
-
здесь в случае
=0, т.е. когда расстояния равны, выбран диагональный шаг.
Подведем итог полученных результатов:
<0
0 выбираем
пиксель ()
,
>0 выбираем
пиксель ()
,
>0
0
выбираем пиксель (
)
,
>0
выбираем пиксель (
)
,
=0
выбираем пиксель (
)
,
Легко
разработать простые рекуррентные
соотношения для реализации пошагового
алгоритма. Сначала рассмотрим
горизонтальный шаг
к пикселю (
).
Обозначим это новое положение пикселов
(i+1). Тогда координаты
нового пикселя и значение
равны:
,
,
Аналогично
координаты нового пикселя и значение
для шага
к пикселю (
)
таковы:
,
,
.
То
же самое для шага
к пикселю (
)
:
,
,
.
Выполняя частные алгебраические преобразования и используя метод Брезенхема, получим следующий алгоритм:
Procedure Mich_Circle (radius; color: integer);
Var
x,y,d: integer;
Begin
x:=0;
y:=radius;
d:=3-2radius
While x<y do
begin
CirclePoint (x,y,color);
if d<0 then d:=d+4x+6
else
begin
d:=d+4(x-y)+10;
y:=y-1
end;
x:=x+1
end;
if x=y then CirclePoint (x,y,color)
End.
Процедура CirclePoint имеет вид:
Procedure CirclePoint (x,y,color: integer);
Begin
PutPixel (x,y,color);
PutPixel (y,x,color);
PutPixel (y,-x, color);
PutPixel (-x,-y, color);
PutPixel (x,-y, color);
PutPixel (-y,-x, color);
PutPixel (-y,x, color);
PutPixel (-x,y, color)
End.