Полтора дня разбирался в работе B-сплайна и как это применяется на практике. Хочу поделиться с вами результатами моих изысканий.
Немного теории
Допустим, у вас есть некий массив точек размером . Что вам потребуется для работы B-сплайна:
- определить количество интерполируемых точек (от этого зависит скорость работы, гладкость получившейся кривой и размер формулы для вычисления, количество точек равно )
- избавится от рекурсии формулы для вычисления
Общая формула для расчета коэффициентов:
Формула рекурсивная и заканчивается на равном единице:
Пояснения к формуле:
- если делитель получается равным или близким по значению к нулю, значит вся дробь равна нулю
- параметр — это индекс текущей точки
- — значение от до с нужным вам шагом (например, равно 7, и нам нужно создать 3 точки для интерполяции, значит берем равным 7.0, 7.5, 8.0)
- — неубывающий массив индексов
Вычисление элементов массива :
Практика
Мне нужно было интерполировать по четырем точкам, поэтому я заранее на бумажке вычислил формулу без рекурсии:
Про бумажку я, конечно, соврал, мне было удобнее сделать функцию на питоне вот такого вида:
def div(a, b): try: return a / float(b) except ZeroDivisionError: return 0 def N(i, k, x, t): if 1 == k: if t[i] <= x < t[i + 1]: return 1.0 return 0.0 a = div(x - t[i], t[i + k - 1] - t[i]) * N(i, k - 1, x, t) b = div(t[i + k] - x, x[i + k] - x[i + 1]) * N(i + 1, k - 1, x, t) return a + b |
После этого добавил условие и все возможные возвращаемые значения в зависимости от , затем условие , значения которого зависят от . Может вам будет удобнее все это сделать на бумажке.
Наконец можно приступать к интерполяции. Формула такая:
Если индекс точки меньше нуля, берем нулевую точку, если индекс точки больше размера массива, то берем последнюю точку в массиве.
Небольшой пример
У нас есть некий массив точек, нам надо интерполировать с пятой по шестую точки с шагом 0.25, при этом $k$ равно 3 (значит для интерполяции нужно взять четыре точки).
Итого четыре новых точки вместо двух.
Спасибо за внимание, надеюсь нигде не ошибся. На несложные вопросы по теме могу ответить в комментариях.