algoritmy_postroenija_geometricheskikh_figur

advertisement
Алгоритмы построения
геометрических фигур
Построение простых фигур
Простые фигуры состоят из отрезков.
Алгоритм Брезенхема
Построение отрезка
Алгоритм Брезенхэма
— это алгоритм, определяющий, какие точки
двухмерного растра нужно закрасить, чтобы получить
близкое приближение прямой линии между двумя
заданными точками . Это один из старейших алгоритмов
в машинной графике — он был разработан Джеком Е.
Брезенхэмом (Jack E. Bresenham) в компании IBM в 1962
году. Алгоритм широко используется, в частности, для
рисования линий на экране компьютера. Существует
обобщение алгоритма Брезенхэма для построения
кривых 2-го порядка.
Построение отрезка
Алгоритм
Отрезок рисуется между двумя точками — (x0,y0)
и (x1,y1), где в этих парах указаны колонка и
строка, соответственно, номера которых
растут вправо и вниз. Сначала мы будем
предполагать, что наша линия идёт вниз и
вправо, причём горизонтальное расстояние x1
− x0 превосходит вертикальное y1 − y0, т.е.
наклон линии от горизонтали — менее 45°.
Наша цель состоит в том, чтобы для каждой
колонки x между x0 и x1, определить, какая
строка y ближе всего к линии, и нарисовать
точку (x,y).
Иллюстрация работы алгоритма
Построение отрезка
Общая формула линии между двумя
точками:
Поскольку мы знаем колонку — x, то строка — y —
получается округлением к целому следующего
значения:
Построение отрезка

Однако, вычислять точное значение
этого выражения — глупо; достаточно
заметить, что y растет от y0 и за
каждый шаг мы добавляем к x
единичку и добавляем к y значение
наклона которое можно вычислить
заранее. Более того, на каждом шаге
мы делаем одно из двух: либо
сохраняем тот же y, либо увеличиваем
его на 1.
Построение отрезка
Построение отрезка

Что из этих двух выбрать — можно решить, отслеживая
значение ошибки, которое означает — вертикальное
расстояние
между
текущим
значением
y
и
точным
значением y для текущего x. Всякий раз, когда мы
увеличиваем x, мы увеличиваем значение ошибки на
величину наклона s, приведенную выше. Если ошибка
превысила 0.5, линия стала ближе к следующему y, поэтому
мы увеличиваем y на единицу, одновременно уменьшая
значение
ошибки
на
1.
В
реализации
алгоритма,
приведенной ниже, plot(x,y) рисует точку, а abs возвращает
абсолютную величину числа:
Построение отрезка
function line(x0, x1, y0, y1)

int deltax := abs(x1 - x0)

int deltay := abs(y1 - y0)

real error := 0

real deltaerr := deltay / deltax

int y := y0

for x from x0 to x1

plot(x,y) error := error + deltaerr

if error >= 0.5

y := y + 1

error := error - 1.0

Построение отрезка

Проблема такого подхода — в том что с
вещественными величинами, такими как error и
deltaerr, компьютеры работают относительно
медленно. Кроме того, при вычислениях с
плавающей точкой может накапливаться ошибка.
По этим причинам, лучше работать только с
целыми числами. Это можно сделать, если
умножить все используемые вещественные
величины на deltax. Единственная проблема — с
константой 0.5 — но в данном случае достаточно
умножить обе части неравенства на 2. Получаем
следующий код:
Построение отрезка
function line(x0, x1, y0, y1)
int deltax := abs(x1 - x0)
int deltay := abs(y1 - y0)
int error := 0
int deltaerr := deltay
int y := y0
for x from x0 to x1
plot(x,y)
error := error + deltaerr
if 2 * error >= deltax
y := y + 1
error := error – deltax
Алгоритм построения
окружности
Построение окружности
Вспомним формулы, параметрически определяющие
окружность. Эти формулы достаточно просты и могут
быть получены непосредственно из определения
тригонометрических функций. Согласно им окружность
радиуса R с центром в точке (x0, y0) может быть
определена как множество точек M(x, y), координаты
которых удовлетворяют системе уравнений
x = x0 + R cos a
y = y0 + R sin a,
где a принадлежит [0;2p).
Построение окружности
Необходимо сделать следующее замечание: на самом
деле мы строим не окружность, а правильный 360угольник. Весьма вероятно, что в недалеком будущем
аппаратные средства позволят добиться такой
разрешающей способности дисплеев, что отличие
многоугольника от окружности станет заметным на
глаз. Что мы станем делать тогда? Уменьшим шаг
приращения угла? Это неплохой выход, но такая
ситуация обещает повториться. Итак, приведенный
алгоритм нас не устраивает. Надо поискать что-нибудь
свободное от упомянутых недостатков.
Алгоритм построения
окружности Брезенхема
Алгоритм Брезенхема
Окружность обладает центром симметрии и
бесконечным количеством осей симметрии.
Поэтому нет необходимости строить всю
окружность, достаточно построить некоторую ее
часть и последовательным применением
преобразований симметрии получить из нее полную
окружность. Мы станем строить 1/8 часть
окружности, заключенную в угле AOB.
Алгоритм Брезенхема
Каждая точка этого фрагмента должна быть еще семь
раз отображена с помощью преобразований
симметрии для получения полной окружности.
Разбор ключевой идеи алгоритма
Пусть мы находимся в некоторой промежуточной
фазе построения. Мы только что поставили точку
(xi, yi) и теперь должны сделать выбор между
точками 1(xi+1, yi-1) и 2(xi+1, y) .
Мы строим часть окружности, заключенную в угле
AOB, следовательно, подняться выше мы не можем
и спуститься вниз более чем на одну точку не можем
тоже.
Разбор ключевой идеи алгоритма
Разбор ключевой идеи алгоритма
Реальная окружность может быть расположена
относительно точек 1 и 2 одним из пяти способов 1-5.
Если мы выбераем точку 1, то тем самым говорим, что
(xi+1)2+(yi-1)2 » R2. Если же выбераем точку 2, то
допускаем, что (xi+1)2+(yi)2 » R2. Рассмотрим две
погрешности Di1 и Di2:
Di1 = (xi+1)2+(yi-1)2-R2
Di2 = (x1+1)2+(yi)2-R2
и контрольную величинуDi = Di1+Di2.
Разбор ключевой идеи алгоритма
При выборе точки, следующей за (xi, yi), станем
руководствоваться следующим критерием:
если Di > 0, выберем точку 1;
если Di £ 0, выберем точку 2.
Обоснуем разумность такого выбора. Рассмотрим
знаки погрешностей Di1 и Di2 и их влияние на знак
контрольной величины Di для всех пяти возможных
положений окружности.
Разбор ключевой идеи алгоритма
Обоснуем разумность такого выбора. Рассмотрим знаки
погрешностей Di1 и Di2 и их влияние на знак контрольной
величины Di для всех пяти возможных положений окружности.
Для положения 1.
Di1 < 0, Di2 < 0  Di1+Di2 < 0  выбирается 2.
Для положения 2.
Di1 < 0, Di2 = 0  Di1+Di2 < 0  выбирается 2.
Для положения 3.
возможны варианты (учитывая, что Di1 < 0, Di2 > 0).
Вариант 3.1. |Di1| ³ |Di2| Þ Di1+Di2 < 0 Þ выбирается 2.
Вариант 3.2. |Di1| < |Di2| ÞDi1+Di2 > 0 Þ выбирается 1.
Разбор ключевой идеи алгоритма
Для положения 4.
Di1 = 0, Di2 > 0  Di1+Di2 > 0  выбирается 1.
Для положения 5.
Di1 > 0, Di2 > 0  Di1+Di2 > 0  выбирается 1.
Далее получим выражение для контрольной величины Di
Di = Di1+Di2 = (xi+1)2+(yi-1)2-R2+(xi+1)2+(yi)2-R2 = 2xi2+2yi2+4xi-
2yi+3-2R2.
Разбор ключевой идеи алгоритма
Выражение для Di+1 существенным образом зависит от
выбора следующей точки. Необходимо рассмотреть
два случая: yi+1 = yi и yi+1 = yi-1.
Di+1 [при yi+1 = yi] = 2x2i+1+2y2i+1+4xi+1-2yi+1+3-2R2 =
2(xi+1)2+2yi2+4(xi+1)-2yi+3-2R2 = Di+4xi+6.
Di+1 [при yi+1 = yi-1] = 2x2i+1+2y2i+1+4xi+1-2yi+1+3-2R2 =
2(xi+1)2+2(yi-1)2+4(xi+1)-2(yi-1)+3-2R2 = Di+4(xi-yi)+10.
Разбор ключевой идеи алгоритма
Теперь, когда получено рекуррентное выражение для Di+1
через Di, остается получить D1 (контрольную величину в
начальной точке.) Она не может быть получена
рекуррентно, ибо не определено предшествующее
значение, зато легко может быть найдена
непосредственно
x1 = 0, y1 = R  D11 = (0+1)2+(R-1)2-R2 = 2-2R,
D12 = (0+1)2+R2-R2 = 1
D1 = D11+D12 = 3-2R.
Разбор ключевой идеи алгоритма
Таким образом, алгоритм построения окружности,
реализованный в bres_circle, основан на
последовательном выборе точек; в зависимости от
знака контрольной величины Di выбирается
следующая точка и нужным образом изменяется сама
контрольная величина. Процесс начинается в точке
(0, r), а первая точка, которую ставит процедура sim,
имеет координаты (xc, yc+r). При x = y процесс
заканчивается.
Download