Правильность оценки сплайна Безье

Каков наилучший / наиболее правильный способ оценки сплайновых кривых в произвольных точках?

Я составил результаты своей оценки и сравнил их с результатами, полученными при использовании библиотеки пользовательского интерфейса, и обнаружил, что мои результаты отключены.

Я использую кубическую формулу для центральных сегментов и квадратичную для первого и последнего сегментов кривой.

http://www.it.hiof.no/~borres/j3d/jlatexmath/BezierFunction0small.png

Я думаю, что причина, по которой у меня возникла эта проблема, заключается в том, что при ее оценке координата 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;

Вот два вопроса / ответа, которые помогли мне понять, что происходит не так:

они не касаются fcurves конкретно, но длина дуги дала мне подсказку, чтобы исправить это.

Ура!

Другие вопросы по тегам