Алгоритм плавающего горизонта
Алгоритм плавающего горизонта можно отнести к классу алгоритмов, работающих в пространстве изображения. Алгоритм плавающего горизонта чаше всего используется для удаления невидимых линий трехмерного представления функций, описывающих поверхность в виде:
F(x, у, z) = 0
Подобные функции возникают во многих приложениях в математике, технике, естественных науках и других дисциплинах.
Главная идея данного метода заключается в сведении трехмерной задачи к двумерной путем пересечения исходной поверхности последовательностью параллельных секущих плоскостей, имеющих постоянные значения координат х, у или z.
На рис. 5.2 приведен пример, где указанные параллельные плоскости определяются постоянными значениями z. Функция F(x,у,z) = 0 сводится к последовательности кривых, лежащих в каждой из этих параллельных плоскостей, например к последовательности у=f(x,z) или х=g(у,z), где z постоянно на каждой из заданных параллельных плоскостей.
Рис. 4.2 Секущие плоскости с постоянной координатой
Рис. 4.3 Секущие плоскости с постоянной координатой
Итак, поверхность теперь складывается из последовательности кривых, лежащих в каждой из этих плоскостей, как показано на рис. 5.3. Здесь предполагается, что полученные кривые являются однозначными функциями независимых переменных. Если спроецировать полученные кривые на плоскость z = 0, как показано на рис. 5.4, то сразу становится ясна идея алгоритма удаления невидимых участков исходной поверхности.
Рис. 4.4 Проекция кривых на плоскость z = 0
Алгоритм сначала упорядочивает плоскости z = const по возрастанию расстояния до них от точки наблюдения. Затем для каждой плоскости, начиная с ближайшей к точке наблюдения, строится кривая, лежащая на ней, т. е. для каждого значения координаты х в пространстве изображения определяется соответствующее значение y. Алгоритм удаления невидимой линии заключается в следующем:
Если на текущей плоскости при некотором заданном значении x соответствующее значение у на кривой больше значения y для всех предыдущих кривых при этом значении x, то текущая кривая видима в этой точке; в противном случае она невидима.
Невидимые участки показаны пунктиром на рис. 5.4. Реализация данного алгоритма достаточно проста. Для хранения максимальных значений y при каждом значении x используется массив, длина которого равна числу различимых точек (разрешению) по оси x в пространстве изображения. Значения, хранящиеся в этом массиве, представляют собой текущие значения "горизонта". Поэтому по мере рисования каждой очередной кривой этот горизонт "всплывает". Фактически этот алгоритм удаления невидимых линий работает каждый раз с одной линией.
Алгоритм работает очень хорошо до тех пор, пока какая-нибудь очередная кривая не окажется ниже самой первой из кривых, как показано на рис. 5.5а.
Рис. 4.5 Обработка нижней стороны поверхности
Подобные кривые, естественно, видимы и представляют собой нижнюю сторону исходной поверхности, однако алгоритм будет считать их невидимыми. Нижняя сторона поверхности делается видимой, если модифицировать этот алгоритм, включив в него нижний горизонт, который опускается вниз по ходу работы алгоритма. Это реализуется при помощи второго массива, длина которого равна числу различимых точек по оси x в пространстве изображения. Этот массив содержит наименьшие значения y для каждого значения x. Алгоритм теперь становится таким:
Если на текущей плоскости при некотором заданном значении x соответствующее значение y на кривой больше максимума или меньше минимума по y для всех предыдущих кривых при этом x, то текущая кривая видима. В противном случае она невидима.
Полученный результат показан на рис. 5.5b.
В изложенном алгоритме предполагается, что значение функции, т.е. y, известно для каждого значения x в пространстве изображения. Однако если для каждого значениях нельзя указать (вычислить) соответствующее ему значение y, то невозможно поддерживать массивы верхнего и нижнего плавающих горизонтов. В таком случае используется линейная интерполяция значений y между известными значениями для того, чтобы заполнить массивы верхнего и нижнего плавающих горизонтов.
Изложенный алгоритм приводит к некоторым дефектам, когда кривая, лежащая в одной из более удаленных от точки наблюдения плоскостей, появляется слева или справа из-под множества кривых, лежащих в плоскостях, которые ближе к указанной точке наблюдения. Этот эффект продемонстрирован на рис. 5.6, где уже обработанные плоскости n-1 и n расположены ближе к точке наблюдения. На рисунке показано, что получается при обработке плоскости n+1. После обработки кривых n-1 и n верхний горизонт для значений x = 0 и 1, равен начальному значению y; для значений x от 2 до 17 он равен ординатам кривой n; а для значений 18, 19, 20 - ординатам кривой n-1. Нижний горизонт для значений x = 0 и 1 равен начальному значению y; для значений x = 2, 3, 4 - ординатам кривой n; а для значений x от 5 до 20 - ординатам кривой n-1. При обработке текущей кривой (n+1) алгоритм объявляет ее видимой при x = 4. Это показано сплошной линией на рис. 5.6. Аналогичный эффект возникает и справа при х = 18. Такой эффект приводит к появлению зазубренных боковых ребер. Проблема с зазубренностью боковых ребер решается включением в массивы верхнего и нижнего горизонтов ординат, соответствующих штриховым линиям на рис. 5.6. Это можно выполнить эффективно, создав ложные боковые ребра.
Рис. 4.6 Эффект зазубренного ребра
Если функция содержит очень острые участки (пики), то приведенный алгоритм также может дать некорректные результаты. Этот эффект вызван вычислением значений функции и оценкой ее видимости на участках, меньших, чем разрешающая способность экрана, т.е. тем, что функция задана слишком малым количеством точек. Если встречаются узкие участки, то функцию следует вычислять в большем числе точек.
На рис. 5.7 показан типичный результат работы алгоритма плавающего горизонта для функции y=(1/5)sin x cos z – (3/2) cos (7a/4) e(-a), a = (x - p)2+(z - p)2, в интервале (0, 2p).
Рис. 4.7 Результат работы алгоритма плавающего горизонта