Правильность оценки сплайна Безье
Каков наилучший / наиболее правильный способ оценки сплайновых кривых в произвольных точках?
Я составил результаты своей оценки и сравнил их с результатами, полученными при использовании библиотеки пользовательского интерфейса, и обнаружил, что мои результаты отключены.
Я использую кубическую формулу для центральных сегментов и квадратичную для первого и последнего сегментов кривой.
Я думаю, что причина, по которой у меня возникла эта проблема, заключается в том, что при ее оценке координата X изменяется (сдвигается), и в настоящее время я оцениваю ее по постоянным ступенчатым координатам, что вызывает некоторые различия между входным x и выходным (что я в данный момент игнорирую)
Я могу предоставить код, если это необходимо. (Я использую Qt как способ проверить правильность на случай, если это поможет)
1 ответ
Оказалось, что это сочетание математики и программирования.
С тех пор я расширил свои знания о конкретном типе кривых, которые я внедрял, и теперь я могу лучше объяснить, чего я пытался достичь и в чем заключалась моя проблема. Извиняюсь за любую путаницу, которую это могло вызвать.
Я реализовывал FCurve, и мне нужно было "оценить" его при произвольных входных значениях. FCurves - это сплайны, представляющие функцию (то есть для любого заданного ввода они возвращают один уникальный вывод)
При оценке моей более старой реализации сплайна я получал неверные результаты оценки, потому что мой код оценки не учитывал длину дуги кривых, за исключением того факта, что FCurves немного более ограничивающие.
В настоящее время я использую для получения точных значений оценки заполнение набора "выборок сегмента" разной буквой "t" вдоль сегмента, а затем итерацию по нему для нахождения ближайших совпадений и выполнения линейной интерполяции между ними. Позже я вернусь к нему и попытаюсь найти разумный способ узнать, сколько сэмплов действительно требуется для оценки сегмента с минимальной ошибкой, но сейчас это работает очень хорошо.
Все это происходило потому, что при применении вышеуказанной формулы (кубического Безье) довольно часто можно получить различные значения "x" из входных данных "x" и "t".
Вот фрагмент кода, который я получил, оценивая его:
const uint32_t sampleCount = 20;
Vec2 samples[sampleCount];
fillSegmentSamples(x, &samples[0], sampleCount);
uint32_t best = 0;
for(uint32_t i = 0; i < sampleCount; i++)
{
if(samples[i].x > x)
break;
best = i;
}
uint32_t nxt = best + 1;
if(nxt >= sampleCount)
{
best--;
nxt--;
}
float t = (x - samples[best].x) / (samples[nxt].x - samples[best].x);
y = lerp(samples[best].y, samples[nxt].y, t);
Раньше я выполнял эквивалент следующего, что было неправильно, так как он не делал никакой компенсации за смещение оси X. (обратите внимание, что в этом случае "t" извлекается из "x")
Vec2 samples[1];
fillSegmentSamples(x, &samples[0], 1);
y = samples[0].y;
Вот два вопроса / ответа, которые помогли мне понять, что происходит не так:
- http://catlikecoding.com/unity/tutorials/curves-and-splines/
- https://gamedev.stackexchange.com/questions/5373/moving-ships-between-two-planets-along-a-bezier-missing-some-equations-for-acce/5427
они не касаются fcurves конкретно, но длина дуги дала мне подсказку, чтобы исправить это.
Ура!