3.3. Алгоритм плавающего горизонта

Алгоритм плавающего горизонта применяется для удаления невидимых линий при изображении поверхностей.

Сначала разберем, каким образом осуществляется вывод изображения без удаления невидимых линий, а потом опишем алгоритм плавающего горизонта.

Как мы уже отмечали в пп. 1.5 на экран компьютера вместо графика функции y=f(x) фактически строится интерполяционный линейный сплайн, т.е. изображение, состоящее из отрезков. При построении изображения поверхности определенной непрерывной функцией z=f(x,y), фактически строится интерполяционный многогранник. В дальнейшим мы будем рассматривать только такие многогранники, гранями которых являются четырехугольники. В литературе рассматриваются также многогранники, сторонами которых являются треугольники.

Для вывода изображения поверхности z=f(x,y), прежде всего, определяется, какую часть поверхности будем выводить. Для этого выводится объемлющий параллелепипед, полностью содержащий нужную нам часть поверхности. Таким образом, предполагаем, что точки (x,y,z) выводимой части поверхности принадлежат объемлющему параллелепипеду: xmin£x£xmax, ymin£y£ymax, zmin£z£zmax.

Затем выбираем проекцию (центральную или параллельную) с помощью которой мы получим изображение. Пусть функции ex и ey переводят мировые координаты (x,y,z) в координаты проекции (x¢,y¢): x¢=ex, y¢=ey. Так как выводимое нами изображение полностью принадлежит объемлющему параллелепипеду, то и изображение на плоскости проекции тоже будет полностью принадлежать некоторому прямоугольнику, координаты вершин (exmin, exmax, eymin, eymax) которого вычисляются по формулам:

exmin=ex(xmax,ymin,zmin),exmax=ex(xmin,ymax,zmax),

eymin=ey(xmax,ymax,zmin),eymax=ey(xmin,ymin,zmax).

Затем от координат точек проекции переходим к экранным координатам:

X=(ex-exmin)×getmaxx()/(exmax-exmin),

Y=(ey-eymin)×getmaxy()/(eymax-eymin).

Поверхность z=f(x,y) мы заменяем многогранником. Для этого вводится прямоугольная сетка в плоскости Oxy с шагом hx=(xmax-xmin)/nx по x, и hy=(ymax-ymin)/ny по y. Каждому прямоугольнику ((xj,yi), (xj,yi+1), (xj+1,yi+1), (xj+1,yi)), 0£j£nx-1, 0£i£ny-1 на плоскости Oxy соответствует четырехугольник (f(xj,yi), f(xj,yi+1), f(xj+1,yi+1), f(xj+1,yi)) в пространстве Oxyz. Будем приближать поверхность z=f(x,y) многогранником, состоящим из таких четырехугольников.

На экран будем выводить проекции этих четырехугольников следующим образом. Последовательно  будем выводить на экран проекции сторон этих многоугольников. Сначала выведем проекции тех сторон многоугольника, для которых i=0 (так называемая «первая строка»). Эти линии всегда видимы. При этом j меняется от ny-1 до 0. Затем последовательно выводим проекции сторон в порядке их удаления от наблюдателя. Таким образом, будут выведены все четырехугольники, но элементом изображения в этом методе является отрезок, а именно сторона четырехугольника. При этом мы не выводим последовательно четырехугольники, а выводим стороны различных четырехугольников.

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

горизонта. Так как элементом изображения является отрезок, то для удаления невидимых линий требуется удалить невидимые части каждого отрезка. Таким образом, на каждом шаге выводится не весь отрезок, а только его видимая часть. Для этого просматриваются все точки выводимого отрезка (по одному из алгоритмов генерации точек отрезка) и анализируется видимость текущей точки отрезка при помощи нижней и верхней границ уже полученной к этому моменту части изображения /20/. Эти границы называются нижним и верхним плавающими горизонтами. А плавающими их называют потому, что в процессе работы алгоритма положение горизонтов изменяется в зависимости от того, является точка видимой или нет. Верхний и нижний горизонт реализуются, как правило, как два целочисленных массива fimin[x] (нижний горизонт) и fimax[x] (верхний горизонт, где x=0,1,…getmaxx()), В начале всем элементам массива fimax присваивается значение 0, а всем элементам массива fimin – число равное разрешающей способности экрана по y (getmaxy()), в результате чего все отрезки первой строки всегда видимы. Затем при выводе каждого отрезка, используя алгоритм генерации точек отрезка, находятся экранные координаты (x,y) текущей точки. Если y большее, чем fimax[x], то fimax[x] присваивается значение y. Если y меньше, чем fimin[x], то fimin[x] присваивается значение y. Таким образом, видимы те точки отрезка, которые выше верхнего горизонта и ниже нижнего горизонта. Точки расположенные между горизонтами, невидимы. Как только все точки отрезка сгенерированы, соединяем последовательно между собой все точки массивов fimax и fimin  в пределах проекции отрезков на ось OX. Таким образом, просматриваются все точки отрезка, а на экран выводятся участки верхнего и нижнего горизонтов.

Пример реализации этого алгоритма приведен в расчетно-графическом задании 3.