Вы, кажется, путаете узлы и контрольные точки.Есть несколько вещей, которые нам нужно улучшить в вашем решении, чтобы оно работало.
Функции с нулевым градусом
Как уже отмечалось @fang, ваше решение для k==0
странно.Я предлагаю заменить
if (k == 0) return points[knots[i]]/3f;
на что-то более близкое к исходной формуле, например,
if (k==0)
{
if (t <= knots[i] && t < knots[i+1])
return 1;
else
return 0;
}
Вектор узла
Как также отметил @fang, для квадратичного сплайнас четырьмя контрольными точками вам нужно семь узлов.Вы упомянули, что вам нужны единообразные узлы, и, исходя из ожидаемого изображения, я бы порекомендовал
int[] knots = new float[] {0, 1/6, 2/6, 3/6, 4/6, 5/6, 1};
Обратите внимание, что узлы теперь находятся в диапазоне от 0 до 1;это означает, что t
и time
будут одинаковыми, то есть
float t = time; //time ranges from 0 to 1 and so does t
Если вы настаиваете на том, что ваши узлы равны int
с (что, ИМХО, способствовало вашей путанице), используйте
int[] knots = new int[] { 0, 1, 2, 3, 4, 5, 6 };
float t = time * 6; //time ranges from 0 to 1 and t from 0 to 6
Обратите внимание, что порядок обмена: t
должен быть time
масштабирован для охвата всего диапазона узлов.
Оценка
Алгоритм Де Бура оценивает один B-spline , т. Е. Одна из базовых функций (некоторые люди используют противоречивую номенклатуру и используют слово B-spline для всей функции сплайна, а не только для одной из базовых функций; это иногда приводит к путанице).
Неформально говоря, для данной t
ваша функция deBoor
дает вам коэффициент i
-ой контрольной точки, который является скаляром .Следовательно, возвращаемое значение deBoor
должно быть float
или double
или чем-то похожим и, конечно, не point
.
. Для каждого t
вам необходимо сложить контрольные точки, масштабированныепо этим коэффициентам.Таким образом, ваш конечный результат будет выглядеть примерно так:
point value = deBoor(0, 2, t, knots) * points[0]
+ deBoor(1, 2, t, knots) * points[1]
+ deBoor(2, 2, t, knots) * points[2]
+ deBoor(3, 2, t, knots) * points[3];
Обратите внимание, что *
обозначает умножение на float
и point
(вам может потребоваться перегрузить такой оператор), а +
обозначаетсумма двух point
с (опять же, может потребоваться перегрузка оператора).Я не очень разбираюсь в C #, так что может быть более элегантный способ записать это;например, я предлагаю вам использовать петлю for
.
Если вы все еще не уверены, я рекомендую сначала ознакомиться с кривыми Безье, а затем перейти к B-сплайнам.Относительно краткое введение можно найти, например, здесь .Картины выполнены в стиле 90-х годов, но идеи по-прежнему актуальны и представлены в понятной и лаконичной форме.