Как реализовать кривую Безье в C++?
Я хотел бы реализовать кривой Безье. Я делал это на C# раньше, но я совершенно не знаком с библиотеками c++. Как мне создать квадратичную кривую?
void printQuadCurve(float delta, Vector2f p0, Vector2f p1, Vector2f p2);
очевидно, что нам нужно использовать линейную интерполяцию, но существует ли это в стандартной математической библиотеке? Если нет, то где я могу его найти?
обновление 1:
Извините, я забыл упомянуть, что использую Linux.
5 ответов
вы использовали библиотеку C# ранее?
в C++ стандартная библиотечная функция для кривых Безье недоступна (пока). Вы можете, конечно, свернуть свой собственный (CodeProject пример) или найдите математическую библиотеку.
этой blogpost объясняет идею красиво, но в Actionscript. Перевод не должен быть большой проблемой.
недавно я столкнулся с тем же вопросом и хотел реализовать его самостоятельно. Это изображение из Википедии помогло мне:

следующий код написан на 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 );
}
С (x1|y1), (x2|y2) и (x3 / y3), являющимися P0, P1 и P2 на изображении. Просто чтобы показать основную идею...
для тех, кто просит кубический Безье, он просто работает аналоговый (также от Википедия):

этой ответ содержит код для него.
вот общая реализация для кривой с любым количеством точек.
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;
}
обратите внимание, что он использует память кучи для временного массива, который не так эффективен. Если вам нужно только иметь дело с фиксированным количеством точек, вы можете жестко закодировать значение numPoints и использовать память стека.
конечно, вышеизложенное предполагает, что у вас есть структура 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);
}
у вас есть выбор между методом де Кастельжау, который заключается в рекурсивном разделении пути управления до тех пор, пока вы не прибудете в точку с помощью линейной интерполяции, как описано выше, или методом Безье, который заключается в смешивании контрольных точек.
метод Безье
 p = (1-t)^3 *P0 + 3*t*(1-t)^2*P1 + 3*t^2*(1-t)*P2 + t^3*P3 
для кубиков и
 p = (1-t)^2 *P0 + 2*(1-t)*t*P1 + t*t*P2
для квадратичных.
t обычно находится на 0-1, но это не существенно - на самом деле кривые простираются до бесконечности. P0, P1, etc управление точки. Кривая проходит через две конечные точки, но обычно не через другие точки.
- Если вы просто хотите, чтобы отобразить кривую Безье, вы можете использовать что-то вроде PolyBezier для Windows. 
- Если вы хотите реализовать процедуру самостоятельно, вы можете найти код линейной интерполяции по всему Интарнетцу. 
- Я считаю библиотеки Boost иметь поддержку для этого. Линейная интерполяция, а не конкретно Безье. Не цитируй меня., однако. 
