从x co-ord得到y为立方贝塞尔曲线,快速Newton-Raphson方法

时间:2012-03-09 17:23:47

标签: c++ numerical-methods bezier numerical-stability

给定2D中Bezier曲线(P0,P1,P2,P3)的点,我想找到给定x坐标的y坐标。由于以下限制,问题已明确定义:

  • P0 =(0,0),P3 =(1,1)
  • P1 =(t,1-t),t为0,1
  • P2 = 1 - P1(x和y)

我有以下功能来计算答案,并已加入所有限制 以上是贝塞尔曲线公式CubicBezier.html。我正在使用Newton-Raphson计算出我想要的点的参数,我知道这是有效的,因为我不会让循环完成,直到它具有(在规定的公差范围内)。

我正在使用此功能将对比度滤镜应用于图像。为此,0.5给出相同的图像,0.0对比度最大减少,1.0最大增加。

编辑以下功能已得到纠正,现在可以完美运行。

/*
 * 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,我们应该得到一条直线,但是当我为linspace做这个时 并绘制点,我得到0.5和1.0之间的弯曲。任何人都可以看到为什么会发生这种情况,如果有什么我能做些什么呢?

1 个答案:

答案 0 :(得分:1)

我编译了你的代码并注意到循环只运行0或1次迭代。可能是因为收敛检查中某处遗漏了fabs