Итак, я работал с реализацией кривых B-сплайнов в python (и я знаю, что существуют существующие библиотеки, но я хотел сделать это сам), и это хорошо сработало для неоткрытых однородных кривых B-сплайнов, как показано здесь:
График справа, на котором показаны расчеты базовой функции (формула рекурсии Кокса де Бура), очень хорошо соответствует тому, что показано в этом видео, с той лишь разницей, что количество контрольных точек. (https://www.youtube.com/watch?v=qhQrRCJ-mVg&t=2136):
Как только я попытаюсь сделать это открытой однородной кривой B-Spline. Я ожидаю такой диаграммы (https://www.youtube.com/watch?v=qhQrRCJ-mVg&t=2501):
Но вместо этого я получаю ZeroDivisionError:
a = ((t - knotVector[i]) / (knotVector[i + j] - knotVector[i]) * CoxDeBoorRecursion(i, j - 1, t, knotVector))
ZeroDivisionError: float division by zero
где вектор узла определяется как [0, 0, 0, 1, 2, 3, 3, 3]
, как показано на видео по адресу https://www.youtube.com/watch?v=qhQrRCJ-mVg&t=2460.
Вот мой код:
def UniformBSpline(t, controlPoints, open=False):
sumX, sumY = 0, 0
degree = 2
knotVector = [x for x in range(len(controlPoints) + 2 + degree)]
if open:
knotVector = knotVector[0:len(controlPoints)]
for _ in range(degree):
knotVector.insert(0, knotVector[0])
knotVector.insert(-1, knotVector[-1])
for i in range(len(controlPoints)):
sumX += CoxDeBoorRecursion(i, degree, t, knotVector) * controlPoints[i].x
sumY += CoxDeBoorRecursion(i, degree, t, knotVector) * controlPoints[i].y
return sumX, sumY
def CoxDeBoorRecursion(i, j, t, knotVector):
if j == 0:
return 1 if knotVector[i] <= t < knotVector[i+1] else 0
a = ((t - knotVector[i]) / (knotVector[i + j] - knotVector[i]) * CoxDeBoorRecursion(i, j - 1, t, knotVector))
b = (((knotVector[i + j + 1] - t)/(knotVector[i + j + 1] - knotVector[i + 1])) * CoxDeBoorRecursion(i + 1, j - 1, t, knotVector))
return a + b
Похоже, это проблема в используемой мной функции, которая определяется как:
Как я могу это исправить? и, возможно, это лучший вопрос для Math StackExchange?