从x坐标获取y以获得三次贝塞尔曲线,快速牛顿-拉夫森法 [英] Getting y from x co-ord for cubic bezier curve, fast Newton-Raphson method

查看:334
本文介绍了从x坐标获取y以获得三次贝塞尔曲线,快速牛顿-拉夫森法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于二维的贝塞尔曲线(P0,P1,P2,P3)的点,我想找到给定x坐标的y坐标.由于以下限制,该问题得到了很好的定义:

Given the points of a Bezier curve (P0, P1, P2, P3) in 2D, I would like to find the y co-ordinate for a given x co-ordinate. The problem is well defined because of the following restrictions:

  • P0 =(0,0),P3 =(1,1)
  • 对于t在0、1之间,P1 =(t,1-t)
  • P2 = 1-P1(x和y)
  • P0 = (0,0), P3 = (1,1)
  • P1 = (t, 1-t) for t between 0, 1
  • P2 = 1 - P1 (x and y)

已设置了所有限制,我具有以下功能来计算答案 上方 CubicBezier.html .我正在使用Newton-Raphson来计算所需的点的参数,并且我知道这是可行的,因为我不让循环直到它具有(在定义的公差范围内)结束.

I have the following function to calculate the answer, having put in all the restrictions above into the Bezier curve formula here CubicBezier.html. I am using Newton-Raphson to work out the parameter of the point I want, and I know this works as I don't let the loop finish until it has (within defined tolerance).

我正在使用此功能将对比度滤镜应用于图像.为此,0.5可以返回相同的图像,0.0可以最大程度地减少对比度,而1.0可以最大程度增加对比度.

I am using this function to apply a contrast filter to an image. For this 0.5 gives the same image back, 0.0 does max reduction in contrast and 1.0 does max increase.

编辑以下功能已得到纠正,现在可以正常使用.

EDIT The following function has been corrected and now works perfectly.

/*
 * 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之间弯曲.谁能知道为什么会这样吗?如果有什么我可以做的事?

If we set p = 0.5, we should get a straight line, but when I do this for a linspace and plot the points, I get a bend between 0.5 and 1.0. Can anyone see why this is happening, and if there is anything I can do about it?

推荐答案

我编译了您的代码,并注意到该循环仅运行0或1次迭代.可能是因为在收敛检查中某处缺少fabs吗?

I compiled your code and noticed that the loop runs only 0 or 1 iterations. Probably it's because a fabs is missing somewhere in the convergence check?

这篇关于从x坐标获取y以获得三次贝塞尔曲线,快速牛顿-拉夫森法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆