Получение y из координаты x для кубической кривой Безье, быстрый метод Ньютона-Рафсона - PullRequest
0 голосов
/ 09 марта 2012

Учитывая точки кривой Безье (P0, P1, P2, P3) в 2D, я хотел бы найти координату y для данной координаты x.Проблема хорошо определена из-за следующих ограничений:

  • P0 = (0,0), P3 = (1,1)
  • P1 = (t, 1-t)для t между 0, 1
  • P2 = 1 - P1 (x и y)

У меня есть следующая функция для вычисления ответа, вставив все вышеупомянутые ограничения в формулу кривой Безьездесь CubicBezier.html .Я использую Ньютона-Рафсона для определения параметра нужной точки, и я знаю, что это работает, поскольку я не позволяю циклу завершиться, пока он не достигнет (в пределах определенного допуска).

Я использую этофункция, чтобы применить контрастный фильтр к изображению.Для этого 0,5 возвращает то же изображение, 0,0 - максимальное уменьшение контрастности, а 1,0 - максимальное увеличение.

EDIT Следующая функция была исправлена ​​и теперь работает отлично.

/*
 * Parameters: p - x co-ord of P1, 
 *             x - x we want to find y for
 *
 * This method is unstable for p ~= 0.5, maybe needs refinement.
 */

#include <iostream>
#include <math.h>

#define ITER_TOL  0.00001

float maths::bezier(float p, float x)
{
    if(p < 0.f || p > 1.f || x < 0.f || x > 1.f)
    {
        std::cerr << "Both parameters must be between 0 and 1, returning dummy value" << std::endl;
        return 0.f;
    }
    //First guess for u
    float u = x;
    //Coefficients of curve (for x and y co-ord)
    float x3 = 6 * p - 2;
    float x2 = 3 - 9 * p;
    float x1 = 3 * p;
    float x0 = -x;

    float y3 = 6 * (1-p) - 2;
    float y2 = 3 - 9 * (1-p);
    float y1 = 3 * (1-p);

    //Newton-Raphson refinement
    for(int i=0; fabs(x3*u*u*u + x2*u*u + x1*u + x0) > ITER_TOL && i<1000; i++)
    {
        u = u - (x3*u*u*u + x2*u*u + x1*u + x0) /
                (3*x3*u*u + 2*x2*u + x1);
        //std::cout << i << ": " << u << std::endl;
        //Deal with non-convergence
        if(i==999)
        {
            std::cerr << "Warning, Newton-Raphson method did not converge in Maths.cpp, returning dummy" << std::endl;
            return 0.f;
        }
    }
    //Calculate y co-ord
    return y3*u*u*u + y2*u*u + y1*u;
}

Если мы установим p = 0,5, мы должны получить прямую линию, но когда я делаю это для линейного пространства и строю точки, я получаю изгиб между 0,5 и 1,0.Кто-нибудь может понять, почему это происходит, и могу ли я что-то с этим сделать?

1 Ответ

1 голос
/ 09 марта 2012

Я скомпилировал ваш код и заметил, что цикл выполняет только 0 или 1 итераций. Вероятно, это потому, что где-то в проверке сходимости отсутствует fabs?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...