当前位置: 首页 > news >正文

QT实现单个控制点在曲线上的贝塞尔曲线

最终效果:
在这里插入图片描述
一共三个文件
main.cpp

#include <QApplication>
#include "SplineBoard.h"
int main(int argc,char** argv) {
    QApplication a(argc, argv);
    SplineBoard b;
    b.setWindowTitle("标准的贝塞尔曲线");
    b.show();

    SplineBoard b2(0.0001);
    b2.show();
    b2.setWindowTitle("控制点在曲线上的贝塞尔曲线");

    b.move(0,0);
    b2.move(800,0);
    return a.exec();
}

SplineBoard.h

#ifndef SPLINEBOARD_H
#define SPLINEBOARD_H
#include <QPainter>
#include <QWidget>
class SplineBoard:public QWidget
{
    Q_OBJECT
public:
    SplineBoard(double terminalRatio = 0.25);

protected:
    void mouseMoveEvent(QMouseEvent* e);
    void mousePressEvent(QMouseEvent* e);
    void mouseReleaseEvent(QMouseEvent* e);
    void paintEvent(QPaintEvent* e);
    int mPressedPos;
    QPointF mStart;
    QPointF mEnd;
    QPointF mCont;
    const double termRatio;
};

#endif // SPLINEBOARD_H

SplineBoard.cpp

#include "SplineBoard.h"
#include <QDebug>
#include <QMouseEvent>
#include <QPainterPath>

static int radius = 8;
static const int PosEmpty = 0;
static const int PosStart = 1;
static const int PosCont = 2;
static const int PosEnd = 4;

static void buildQuadBezier(QPainterPath& pp, const QPointF& p0,const QPointF& p1,
                     const QPointF& p2, qreal term){
    pp.moveTo(p0);
    const qreal a = (term-0.5)*-4;
    const qreal d = (1-2*term)*-4;
    for (qreal t = 0; t < 1.01; t += 0.01) {
        qreal A = a*t*t+(-1-a)*t+1;
        qreal B = d*t*t - d*t;
        qreal C = a*t*t + (1-a)*t;
        qreal x = A * p0.x() + B * p1.x() + C * p2.x();
        qreal y = A * p0.y() + B * p1.y() + C * p2.y();
        pp.lineTo(x, y);
    }
}
SplineBoard::SplineBoard(double terminalRatio):mPressedPos(PosEmpty),termRatio(terminalRatio)
{
    resize(800,600);
    setWindowTitle("spline board");

    mStart = QPointF(50,300);
    mEnd = QPointF(750,300);
    mCont = QPointF(400,300);
}

void SplineBoard::mouseMoveEvent(QMouseEvent* e){
    auto cur = e->pos();
    if(mPressedPos == PosStart){
        mStart = cur;
    }
    else if(mPressedPos == PosCont){
        mCont = cur;
    }
    else if(PosEnd == mPressedPos){
        mEnd = cur;
    }
    else{
        return;
    }
    update();
}
void SplineBoard::mousePressEvent(QMouseEvent* e){
    auto pos = e->pos();
    auto startRect = QRectF(mStart,QSize(radius*2,radius*2));
    startRect.translate(-radius,-radius);
    auto contRect = QRectF(mCont,QSize(radius*2, radius*2));
    contRect.translate(-radius,-radius);
    auto endRect = QRectF(mEnd , QSize(radius*2, radius*2));
    endRect.translate(-radius,-radius);

    if(startRect.contains(pos)){
        mPressedPos = PosStart;
    }
    else if(contRect.contains(pos)) {
        mPressedPos = PosCont;
    }
    else if(endRect.contains(pos)){
        mPressedPos = PosEnd;
    }
    else{
        mPressedPos = PosEmpty;
    }

}
void SplineBoard::mouseReleaseEvent(QMouseEvent* e){
    mPressedPos = PosEmpty;
}

void SplineBoard::paintEvent(QPaintEvent* e){
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QPen pen(Qt::blue);
    pen.setWidth(2);
    painter.setPen(pen);

    QPainterPath path;

    buildQuadBezier(path,mStart,mCont,mEnd,termRatio);
    painter.drawPath(path);

    painter.setPen(Qt::NoPen);
    painter.setBrush(Qt::magenta);
    painter.drawEllipse(mStart,radius,radius);  // Draw start point
    painter.drawEllipse(mCont, radius,radius);  // Draw control point
    painter.drawEllipse(mEnd, radius,radius);  // Draw end point

    QWidget::paintEvent(e);

}

相关文章:

  • 数据结构入门篇——什么是数据结构。
  • C#进阶指南
  • 在 UniApp 中实现中间凸起 TabBar 的完整指南
  • No manual entry for printf in section 3
  • 第四十五:创建一个vue 的程序
  • MyBatisPlus搭建教程
  • 国产免费AI的IDE-TRAE
  • iOS安全和逆向系列教程 第4篇:搭建iOS逆向开发环境 (下) - 越狱设备与高级工具配置
  • Kali换源-pikachu
  • Docker 深度解析:适合零基础用户的详解
  • iOS安全和逆向系列教程 第5篇 iOS基础开发知识速览 - 理解你要逆向的目标
  • 【开源项目-AI研发】ai-engineer-toolkit
  • Android Studio安装教程
  • IvorySQL v4 逻辑复制槽同步功能解析:高可用场景下的数据连续性保障
  • 驱动开发系列40 - Linux 显卡KMD驱动代码分析(一) - 设备初始化过程
  • Xcode 无限循环闪退解决方案
  • 费曼学习法13 - 数据表格的魔法:Python Pandas DataFrame 详解 (Pandas 基础篇)
  • 探索IntelliJ IDEA的Tongyi Lingma插件:AI编程助手的新体验
  • 移动端浏览倾斜模型、三维地图、专题地图、矢量数据等,支持互联网公开免费地图的加载及浏览
  • 【异常解决】Unable to start embedded Tomcat Nacos 启动报错
  • 龙泉市住房和城乡建设局网站/windows优化大师收费吗
  • 工业设计专业最佳出路/搜索引擎推广与优化
  • dz论坛怎么做视频网站/百度官方优化指南
  • 北京国贸网站建设/厦门网络推广培训
  • 安徽网站开发费用/站长工具樱花
  • 公司主营网站开发怎么做账/网络营销的六大功能