Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么立方贝塞尔函数与windows api PolyBezier相比不精确?_C++_Graphics_Bezier - Fatal编程技术网

C++ 为什么立方贝塞尔函数与windows api PolyBezier相比不精确?

C++ 为什么立方贝塞尔函数与windows api PolyBezier相比不精确?,c++,graphics,bezier,C++,Graphics,Bezier,我一直在寻找一种使用自定义函数绘制曲线/三次贝塞尔曲线的方法。然而,在互联网上找到的所有例子和类似的例子,彼此之间有点不同,通常会产生不同的结果,为什么。我尝试过的所有产品都不能产生与windows api PolyBezier相同的结果,这正是我所需要的 这是我当前绘制三次贝塞尔曲线的代码: double Factorial(int number) { double factorial = 1; if (number > 1) { for (in

我一直在寻找一种使用自定义函数绘制曲线/三次贝塞尔曲线的方法。然而,在互联网上找到的所有例子和类似的例子,彼此之间有点不同,通常会产生不同的结果,为什么。我尝试过的所有产品都不能产生与windows api PolyBezier相同的结果,这正是我所需要的

这是我当前绘制三次贝塞尔曲线的代码:

double Factorial(int number)
{
    double factorial = 1;

    if (number > 1)
    {
        for (int count = 1; count <= number; count++) factorial = factorial * count;
    }

    return factorial;
}

double choose(double a, double b)
{
    return Factorial(a) / (Factorial(b) * Factorial(a - b));
}

VOID MyPolyBezier(HDC hdc, PPOINT Pts, int Total)
{
    float x, y;

    MoveToEx(hdc, Pts[0].x, Pts[0].y, 0);

    Total -= 1;

    //for (float t = 0; t <= 1; t += (1./128.))
    for (float t = 0; t <= 1; t += 0.0078125)
    {
        x = 0;
        y = 0;
        for (int I = 0; I <= Total; I++)
        {
            x += Pts[I].x * choose(Total, I) * pow(1 - t, Total - I) * pow(t, I);
            y += Pts[I].y * choose(Total, I) * pow(1 - t, Total - I) * pow(t, I);
        }
        LineTo(hdc, x, y);
    }
}
并附上我的坏结果的图片: 注:底部贝塞尔线为windowsPolyBezier版本

编辑: 最后一个目标,左边的窗口VS自定义功能。希望这在某种程度上有所帮助。
所以三次贝塞尔曲线是一条数学曲线。三次贝塞尔曲线是更一般曲线的一种特殊情况

三次贝塞尔曲线由4个控制点定义——一个起点和终点,以及2个控制点。通常,贝塞尔曲线按顺序有n个控制点

当时间参数t从0变为1时,绘制该线

要找出在时间t时n阶的一般贝塞尔函数的位置,请执行以下操作:

对于bezier中的每一对相邻控制点,找到它们的加权平均值,由t控制。因此,对于b之前的控制点a,在+b1-t处

使用这些n-1点形成n-1阶贝塞尔曲线

在时间t求解新的贝塞尔

当你碰到1度贝塞尔,停止。这就是你的观点


尝试编写一个基于贝塞尔曲线真实定义的算法,看看它与windows曲线的区别。这可能比采用某种近似值并协调两组错误更令人沮丧。

Beziers无法直接绘制,因为公式适用于与x或y不直接相关的变量t。它是近似的,不同的算法会产生不同的近似值,更不用说舍入效果了。你可以将直线细分为128段,并在它们之间线性绘制。因此,在这128点上,你应该是好的-线是噪声-你的答案在节点之间是错误的。检查这128个点,看看它们是否在windows行上:如果不在,则表示windows使用的不是您的意思。半像素,不同的近似值,四舍五入-谁知道呢。这并不容易。顺便说一句,你的意思是精确。在找到实际的贝塞尔曲线并演示其渲染方式之前,以上内容不包含任何准确性证据。只是两个不同的近似值。我需要的精度与windows PolyBezier相同。我正在加载原始TrueType字体数据,并使用此处找到的windows方法将线条转换为立方贝塞尔:函数AppendPolyLineObezier和AppendQuadBsLineToBezier正在进行转换,我正在查看它们,如果我发现了什么,我将发布。对,因此步骤1:实现绘图以使用真实函数,不要选择和pow,然后查看您的代码是否生成相同的曲率。应该是这样的,因为只有一种方法可以计算贝塞尔曲线,好的,两种。这是一个对称函数,所以作为一个完整的图,你可以从t或1-t开始,结果是一样的。然后,如果它看起来太直线分段,开始增加你的t间隔精度,比如说0.001而不是0.007。最后:四舍五入问题。不要计算你在整数区域的坐标。计算浮点,然后在仅绘制时取整。
POINT TestPts[4];
BYTE TestType[4] = {PT_MOVETO, PT_BEZIERTO, PT_BEZIERTO, PT_BEZIERTO};
//set x, y points for the curved line.
TestPts[0].x = 50;
TestPts[0].y = 200;
TestPts[1].x = 100;
TestPts[1].y = 100;
TestPts[2].x = 150;
TestPts[2].y = 200;
TestPts[3].x = 200;
TestPts[3].y = 200;
//Draw using custom function.
MyPolyBezier(hdc, TestPts, 4);
//Move the curve down some.
TestPts[0].y += 10;
TestPts[1].y += 10;
TestPts[2].y += 10;
TestPts[3].y += 10;
//Draw using windows api.
//PolyDraw(hdc, TestPts, TestType, 4); //PolyDraw gives the same result as PolyBezier.
PolyBezier(hdc, TestPts, 4);