贝塞尔曲线学习

1、一阶贝塞尔曲线

一阶贝塞尔曲线其实是一条直线------给定点 P0、P1,线性贝塞尔曲线就是一条两点之间的直线,公式如下:

一阶曲线很好理解, 就是根据t来线性插值。

复制代码
void MainWindow::mousePressEvent(QMouseEvent *e)
{
    list.append(e->pos());
    update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    if(list.size() >= 2)
    {
        QPoint p0 = list.at(list.size() - 2);
        QPoint p1 = list.last();

        // 生成贝塞尔曲线路径
        QPainterPath path;
        path.moveTo(p0);
        for (float t = 0.0; t <= 1.000001; t += 0.1)
        {
            QPointF pt = linearBezier(t, p0, p1);
            path.lineTo(pt);
            drawPoint(painter, pt);
        }
        // 绘制曲线
        painter.setPen(Qt::blue);
        painter.drawPath(path);
    }
    else
        painter.fillRect(rect(), Qt::white);
}

QPointF MainWindow::linearBezier(float t, const QPointF &P0, const QPointF &P1)
{
    float x = (1 - t) * P0.x() + t * P1.x();
    float y = (1 - t) * P0.y() + t * P1.y();
    return QPointF(x, y);
}

void MainWindow::drawPoint(QPainter &painter, const QPointF &p)
{
    painter.save();
    QPen pen;
    pen.setWidth(8);
    pen.setColor(Qt::red);
    painter.setPen(pen);
    painter.drawPoint(p);
    painter.restore();
}

void MainWindow::on_pushButton_clicked()
{
    list.clear();
    update();
}

2、二阶贝塞尔曲线

二阶贝塞尔曲线由三个控制点构成:起始点 ‌P₀ ‌、控制点 ‌P₁ ‌ 和终止点 ‌P₂‌‌。其数学表达式为:

其中,参数 ‌t 从 0 到 1 变化时,曲线从 ‌P₀ ‌ 平滑过渡到 ‌P₂ ‌,形状由 ‌P₁‌ 的位置决定‌。

复制代码
void MainWindow::mousePressEvent(QMouseEvent *e)
{
    list.append(e->pos());
    update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    if(list.size() >= 3)
    {
        QPoint p0 = list.at(list.size() - 3);
        QPoint p1 = list.at(list.size() - 2);
        QPoint p2 = list.last();

        painter.setPen(Qt::green);
        painter.drawLine(p0, p1);
        painter.drawLine(p1, p2);

        // 生成贝塞尔曲线路径
        QPainterPath path;
        path.moveTo(p0);
        for (float t = 0.0; t <= 1.000001; t += 0.1)
        {
            QPointF pt = quadraticBezier(t, p0, p1, p2);
            path.lineTo(pt);
            drawPoint(painter, pt);
        }
        // 绘制曲线
        painter.setPen(Qt::blue);
        painter.drawPath(path);
    }
    else
        painter.fillRect(rect(), Qt::white);
}

QPointF MainWindow::quadraticBezier(float t, const QPointF& P0, const QPointF& P1, const QPointF& P2)
{
    QPointF result = (1 - t) * (1 - t) * P0 + 2 * (1 - t) * t * P1 + t * t * P2;
    return result;
}

void MainWindow::drawPoint(QPainter &painter, const QPointF &p)
{
    painter.save();
    QPen pen;
    pen.setWidth(8);
    pen.setColor(Qt::red);
    painter.setPen(pen);
    painter.drawPoint(p);
    painter.restore();
}

void MainWindow::on_pushButton_clicked()
{
    list.clear();
    update();
}

3、三阶贝塞尔曲线

三阶贝塞尔曲线由4个控制点 ‌P₀、P₁、P₂、P₃‌ 定义,参数方程为:

其中 ‌t ∈ [0,1]。

该公式通过递归插值实现,支持生成含两个拐点的平滑曲线‌。

复制代码
void MainWindow::mousePressEvent(QMouseEvent *e)
{
    list.append(e->pos());
    update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    if(list.size() >= 4)
    {
        QPoint p0 = list.at(list.size() - 4);
        QPoint p1 = list.at(list.size() - 3);
        QPoint p2 = list.at(list.size() - 2);
        QPoint p3 = list.last();

        drawPoint(painter, p0);
        drawPoint(painter, p1);
        drawPoint(painter, p2);
        drawPoint(painter, p3);

        painter.setPen(Qt::green);
        painter.drawLine(p0, p1);
        painter.drawLine(p1, p2);
        painter.drawLine(p2, p3);

        // 生成贝塞尔曲线路径
        QPainterPath path;
        path.moveTo(p0);
        for (float t = 0.0; t <= 1.000001; t += 0.1)
        {
            QPointF pt = cubicBezier(t, p0, p1, p2, p3);
            path.lineTo(pt);
            drawPoint(painter, pt);
        }
        // 绘制曲线
        painter.setPen(Qt::blue);
        painter.drawPath(path);
    }
    else
        painter.fillRect(rect(), Qt::white);
}

// 计算三阶贝塞尔曲线上的点
QPointF MainWindow::cubicBezier(float t, const QPointF &P0, const QPointF &P1, const QPointF &P2, const QPointF &P3) {
    float x = pow(1 - t, 3) * P0.x() + 3 * pow(1 - t, 2) * t * P1.x() + 3 * (1 - t) * pow(t, 2) * P2.x() + pow(t, 3) * P3.x();
    float y = pow(1 - t, 3) * P0.y() + 3 * pow(1 - t, 2) * t * P1.y() + 3 * (1 - t) * pow(t, 2) * P2.y() + pow(t, 3) * P3.y();
    return QPointF(x, y);
}

void MainWindow::drawPoint(QPainter &painter, const QPointF &p)
{
    painter.save();
    QPen pen;
    pen.setWidth(8);
    pen.setColor(Qt::red);
    painter.setPen(pen);
    painter.drawPoint(p);
    painter.restore();
}

void MainWindow::on_pushButton_clicked()
{
    list.clear();
    update();
}

觉得有帮助的话,打赏一下呗。。

需要商务合作(定制程序)的欢迎私信!!

相关推荐
别给迷住了3 个月前
WPF 绘制过顶点的圆滑曲线(样条,贝塞尔)
wpf·贝塞尔曲线·样条曲线·圆滑曲线·过顶点·beziersegment
艾恩小灰灰1 年前
探索CSS中的贝塞尔曲线cubic-bezier()函数:掌握自定义动画曲线的艺术
前端·css·css3·贝塞尔曲线·css动画·cubic-bezier·css函数
牛老师讲GIS1 年前
二阶贝塞尔曲线生成弧线
贝塞尔曲线·弧段·被萨尔曲线
w风雨无阻w2 年前
Android 实战项目分享(一)用Android Studio绘制贝塞尔曲线的艺术之旅
android·java·android studio·android 项目·贝塞尔曲线