如何在 C++ 中实现贝塞尔曲线?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/785097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:16:37  来源:igfitidea点击:

How do I implement a Bézier curve in C++?

c++mathinterpolationspline

提问by Nick Bolton

I'd like to implement a Bézier curve. I've done this in C# before, but I'm totally unfamiliar with the C++ libraries. How should I go about creating a quadratic curve?

我想实现一个贝塞尔曲线。我以前在 C# 中做过这个,但我完全不熟悉 C++ 库。我应该如何创建二次曲线?

void printQuadCurve(float delta, Vector2f p0, Vector2f p1, Vector2f p2);

Clearly we'd need to use linear interpolation, but does this exist in the standard math library? If not, where can I find it?

显然我们需要使用线性插值,但是标准数学库中是否存在这种方法?如果没有,我在哪里可以找到它?

Update 1:

更新 1:

Sorry, I forgot to mention I'm using Linux.

抱歉,我忘了提及我正在使用 Linux。

采纳答案by dirkgently

Did you use a C# library earlier?

您之前使用过 C# 库吗?

In C++, no standard library function for Bezier curves is available (yet). You can of course roll your own (CodeProject sample) or look for a math library.

在 C++ 中,没有贝塞尔曲线的标准库函数可用(目前)。您当然可以推出自己的(CodeProject示例)或寻找数学库。

Thisblogpost explains the idea nicely but in Actionscript. Translation should not be much of a problem.

这篇博文很好地解释了这个想法,但在 Actionscript 中。翻译应该问题不大。

回答by Jakob Riedle

Recently I ran across the same question and wanted to implemented it on my own. This image from Wikipedia helped me:

最近我遇到了同样的问题,想自己实现它。来自维基百科的这张图片帮助了我:

http://upload.wikimedia.org/wikipedia/commons/3/35/Bezier_quadratic_anim.gif

http://upload.wikimedia.org/wikipedia/commons/3/35/Bezier_quadratic_anim.gif

The following code is written in C++ and shows how to compute a quadratic bezier.

以下代码是用 C++ 编写的,展示了如何计算二次贝塞尔曲线。

int getPt( int n1 , int n2 , float perc )
{
    int diff = n2 - n1;

    return n1 + ( diff * perc );
}    

for( float i = 0 ; i < 1 ; i += 0.01 )
{
    // The Green Line
    xa = getPt( x1 , x2 , i );
    ya = getPt( y1 , y2 , i );
    xb = getPt( x2 , x3 , i );
    yb = getPt( y2 , y3 , i );

    // The Black Dot
    x = getPt( xa , xb , i );
    y = getPt( ya , yb , i );

    drawPixel( x , y , COLOR_RED );
}

With (x1|y1), (x2|y2) and (x3|y3) being P0, P1 and P2 in the image. Just for showing the basic idea...

其中 (x1|y1)、(x2|y2) 和 (x3|y3) 是图像中的 P0、P1 和 P2。只是为了展示基本的想法......

For the ones who ask for the cubic bezier, it just works analogue (also from Wikipedia):

对于那些要求三次贝塞尔曲线的人,它只是模拟(也来自维基百科):

http://upload.wikimedia.org/wikipedia/commons/a/a3/Bezier_cubic_anim.gif

http://upload.wikimedia.org/wikipedia/commons/a/a3/Bezier_cubic_anim.gif

Thisanswer provides Code for it.

这个答案为它提供了代码。

回答by iforce2d

Here is a general implementation for a curve with any number of points.

这是具有任意数量点的曲线的一般实现。

vec2 getBezierPoint( vec2* points, int numPoints, float t ) {
    vec2* tmp = new vec2[numPoints];
    memcpy(tmp, points, numPoints * sizeof(vec2));
    int i = numPoints - 1;
    while (i > 0) {
        for (int k = 0; k < i; k++)
            tmp[k] = tmp[k] + t * ( tmp[k+1] - tmp[k] );
        i--;
    }
    vec2 answer = tmp[0];
    delete[] tmp;
    return answer;
}

Note that it uses heap memory for a temporary array which is not all that efficient. If you only need to deal with a fixed number of points you could hard-code the numPoints value and use stack memory instead.

请注意,它使用堆内存作为临时数组,但效率并不高。如果您只需要处理固定数量的点,您可以对 numPoints 值进行硬编码并改用堆栈内存。

Of course, the above assumes you have a vec2 structure and operators for it like this:

当然,上面假设您有一个 vec2 结构和运算符,如下所示:

struct vec2 {
    float x, y;
    vec2(float x, float y) : x(x), y(y) {}
};

vec2 operator + (vec2 a, vec2 b) {
    return vec2(a.x + b.x, a.y + b.y);
}

vec2 operator - (vec2 a, vec2 b) {
    return vec2(a.x - b.x, a.y - b.y);
}

vec2 operator * (float s, vec2 a) {
    return vec2(s * a.x, s * a.y);
}

回答by Malcolm McLean

You have a choice between de Casteljau's method, which is to recursively split the control path until you arrive at the point using a linear interpolation, as explained above, or Bezier's method which is to blend the control points.

您可以选择 de Casteljau 的方法,即递归分割控制路径,直到使用线性插值到达该点,如上所述,或者 Bezier 的方法,即混合控制点。

Bezier's method is

贝塞尔方法是

 p = (1-t)^3 *P0 + 3*t*(1-t)^2*P1 + 3*t^2*(1-t)*P2 + t^3*P3 

for cubics and

对于立方体和

 p = (1-t)^2 *P0 + 2*(1-t)*t*P1 + t*t*P2

for quadratics.

为二次方。

t is usually on 0-1 but that's not an essential - in fact the curves extend to infinity. P0, P1, etc are the control points. The curve goes through the two end points but not usually through the other points.

t 通常在 0-1 上,但这不是必需的 - 事实上曲线延伸到无穷大。P0、P1 等是控制点。曲线通过两个端点,但通常不通过其他点。

回答by dirkgently

  • If you just want to display a Bezier curve, you can use something like PolyBezierfor Windows.

  • If you want to implement the routine yourself, you can find linear interpolation codeall over the Intarnetz.

  • I believe the Boost librarieshave support for this. Linear interpolation, not Beziers specifically. Don't quote me on this, however.

  • 如果您只想显示贝塞尔曲线,您可以使用PolyBezierfor Windows 之类的东西。

  • 如果你想自己实现例程,你可以在 Intarnetz 上找到线性插值代码

  • 我相信Boost 库对此有支持。线性插值,而不是专门的贝塞尔曲线。但是,不要在这方面引用我的话。