8.1 Сплайны - теоретическое введение. OpenGL.

Построение гладких кривых или поверхностей в соответствии с набором заданных вершин является типовой задачей компьютерной графики. В том случае, если мы используем кубические B-сплайны, из заданной последовательности вершин необходимо выбрать две соседние вершины, после чего между ними будет построена кривая кубического полинома на основе позиции четырех точек: две выбранные и две соседние с ними.
Таким образом, B-сплайн позволяет получить более сглаженные кривые за счет того, что создаваемая кривая не пройдет точно через заданные точки.

Параметрическое представление сплайнов

Для того чтобы использовать сложные кривые на практике, обычно используется их параметрическое представление. Таким образом, у любой из точек на какой-либо части кривой, лежащей между двумя заданными последовательными точками Pi и Pi + 1, с координатами (x(t); y(t)) значение t будет меняться от 0.0 до 1.0 в том случае, если часть кривой строится от Pi до Pi+1.

В том случае, если есть заданные точки P0(x0, y0), P1(x1, y1), … Pn(xn, yn), то часть кривой B-сплайна между точками Pi и Pi+1 определяется как последовательность точек с координатами (x(t), y(t)) при 0,0 ≤ t ≤ 1,0:.
  • x(t) = a0+ a1t + a2t2 + a3t3
  • y(t) = b0+ b1t + b2t2 + b3t3
Эти уравнения содержат следующие коэффициенты:
  • a0 = (xi-1 + 4xi + xi+1)/6
  • a1 = (-xi-1 + xi+1)/2
  • a2 = (xi-1 - 2xi + xi+1)/2
  • a3 = (-xi-1 + 3xi - 3xi+1 + xi+2)/6
Коэффициенты b0, … b3 вычисляются аналогично по значениям yi-1, … yi+2. Для производительности алгоритма важно, что ai и bi вычисляются только один раз для каждого сегмента кривой.

Свойства сплайнов

Кривые типа B-сплайна обладают свойством непрерывности даже вторых производных x²(t) и y²(t) в точках стыковки двух соседних сегментов кривой. Для определения свойств кривой в точках стыковки двух сегментов рассмотрим функцию x(t) и ее первую и вторую производные для значений t = 0 и t = 1.

Функция y(t) будет обладать аналогичными свойствами.

x(0) = a0 = (xi-1 + 4xi + xi+1)/6

x(1) = a1 + a2 + a3 + a2 = (xi + 4xi+1 + xi+2)/6

То есть значение x(0) не равно в точности x-координате xi точки Pi: оно зависит от позиций точек Pi-1 и Pi+1. Для трех последовательных точек на кривой A, B и C точка B принадлежит сегменту AB и одновременно сегменту BC.

Для первого сегмента A = Pi, B = Pi+1, C = Pi+2. Тогда x~B = x(1) = (xA + 4xB + xC)/6, где x~B - вычисленное значение координаты x для точки B.
Уроки OpenGL + C#: Фрагмент сплайна Рисунок 1. Фрагмент сплайна.
Для второго сегмента A = Pi-1, B = Pi, C = Pi+1 и x~B = x(0) = (xA + 4xB + + xC)/6. Одинаковые результаты означают непрерывность функции x(t) в точке B.

Продифференцировав x(t) дважды, найдем x'(t) и x²(t):

x'(t) = a1 + 2a2t + 3a3t2; x²(t) = 2a2 + 6a3t

Подставляя в них значения t = 0 и t = 1, находим:

x'(0) = a1 = (-xi-1 + xi+1)/2; x'(1) = a1 + 2a2 + 3a3 = (-xi + xi+2)/2;

x²(0) = 2a2 = xi-1 - 2xi + xi+1; x²(1) = 2a2 + 6a3 = xi - 2xi+1 + xi+2

Тогда значение первой производной в точке B, вычисленное для первого сегмента кривой (x')~B = x'(1) = (-xA + xC)/2, совпадает со значением первой производной в той же точке, вычисленным для следующего сегмента (x')~B = x'(0).

Точно так же и значение второй производной в точке B, вычисленное для первого сегмента кривой (x²)~B = x²(1) = xA - 2xB + xC совпадает со значением второй производной в той же точке, вычисленным для следующего сегмента (x²)~B = x² (0).

Таким образом, не только сама кривая, но и ее первые две производные непрерывны в каждой точке кривой, то есть вся кривая является очень гладкой.

Для расчета любого сегмента кривой между точками Pi и Pi+1 используются также точки Pi-1 и Pi+2. Тогда, если есть точки P0, P1, … Pn-1 и Pn, то первый сегмент кривой будет располагаться между точками P1 и P2, а последний – между точками Pn-2 и Pn-1. То есть начальной и конечной точками кривой будут P1 и Pn-1, а не P0 и Pn. Поэтому для замкнутой кривой следует три точки в начале или в конце последовательности задавать дважды.
Добавить комментарий
Расширенный режим добавления комментариев доступен на форуме: загрузка изображений, цитирование, форматирование текста, и т.д.
Ваше имя:
Текст сообщения:
Комментарии (4):
mike124
mike124,  
Цитата
Таким образом, любая из точек на какой-либо части кривой, лежащая между двумя заданными последовательными точками Pi и Pi + 1, которая будет иметь координаты (x(t); y(t)) , значение t будет меняться от 0.0 до 1.0, в том случае, если строится часть кривой от Pi до Pi+1.
Мне кажется, что правильнее будет написать так:

Таким образом, у любой из точек на какой-либо части кривой, лежащая между двумя заданными последовательными точками Pi и Pi + 1, которая будет иметь координаты (x(t); y(t)) , значение t будет меняться от 0.0 до 1.0, в том случае, если строится часть кривой от Pi до Pi+1.

Иначе не въехать...
mike124
mike124,  
Получившаяся программа поддерживает только 63 точки - потом отваливается по индексу i + 2.

Надо либо жесткое ограничение ввести, либо немного усложнить работу с точками, но сделать их массив относительно бксконечным.
alita
alita,  
Цитата
Мне кажется, что правильнее будет написать так:

почему правильнее? "любая из точек" разве не равно по смыслу "у любой из точек" ?
alita
alita,  
mike124,
Цитата
Получившаяся программа поддерживает только 63 точки - потом отваливается по индексу i + 2.
Ошибка в уроке исправлена ограничением на кол-во добавляемых точек. Спасибо
^