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

qt贝塞尔曲线演示工具

贝塞尔曲线演示工具

该代码实现了一个基于Qt的贝塞尔曲线演示工具,主要功能包括:

1.可视化组件:

  • 绘制网格背景和贝塞尔曲线控制线
  • 显示可拖动的控制点(起点绿色,终点红色,中间点蓝色)
  • 实时渲染贝塞尔曲线路径

2.交互功能:

  • 鼠标拖动调整控制点位置
  • 点选控制点高亮显示
  • 动画演示贝塞尔曲线生成过程

3.技术特点:

  • 使用QWidget实现自定义绘制
  • 支持反锯齿渲染
  • 通过QTimer实现平滑动画效果
  • 采用面向对象设计分离控制点和曲线逻辑
    该工具适用于教学演示和图形算法学习,直观展示贝塞尔曲线的数学原理和可视化效果。
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>#include <QApplication>
#include <QMainWindow>
#include <QWidget>
#include <QPainter>
#include <QPointF>
#include <QVector>
#include <QTimer>
#include <QPushButton>
#include <QLabel>
#include <QMouseEvent>
#include <QGridLayout>
#include <cmath>class BezierPoint : public QWidget {
public:BezierPoint(QWidget *parent = nullptr) : QWidget(parent), selected(false) {setFixedSize(24, 24);}void setSelected(bool sel) {selected = sel;update();}protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);if (selected) {painter.setPen(QPen(Qt::red, 2));painter.setBrush(Qt::yellow);} else {painter.setPen(QPen(QColor(232, 196, 142), 2));painter.setBrush(Qt::white);}painter.drawEllipse(rect().center(), 8, 8);}private:bool selected;
};class BezierWidget : public QWidget {Q_OBJECTpublic:BezierWidget(QWidget *parent = nullptr) : QWidget(parent), t(0.0), animating(false) {setMinimumSize(800, 600);setMouseTracking(true);// Initialize control pointscontrolPoints << QPointF(100, 500) << QPointF(250, 200) << QPointF(500, 300) << QPointF(700, 450);// Create point widgetsfor (int i = 0; i < controlPoints.size(); ++i) {BezierPoint *point = new BezierPoint(this);point->move(controlPoints[i].x() - 12, controlPoints[i].y() - 12);bezierPoints << point;}// Set up timer for animationtimer = new QTimer(this);connect(timer, &QTimer::timeout, this, [this]() {t += 0.005;if (t > 1.0) {t = 1.0;timer->stop();animating = false;emit animationFinished();}update();});}void startAnimation() {t = 0.0;animating = true;timer->start(30);}void stopAnimation() {animating = false;timer->stop();}bool isAnimating() const { return animating; }signals:void animationFinished();protected:void paintEvent(QPaintEvent *) override {QPainter painter(this);painter.setRenderHint(QPainter::Antialiasing);// Draw background griddrawGrid(painter);// Draw control linesdrawControlLines(painter);// Draw Bezier curvedrawBezierCurve(painter);// Draw animation lines and points if animatingif (animating) {drawAnimation(painter);}}void mousePressEvent(QMouseEvent *event) override {if (event->button() == Qt::LeftButton) {for (int i = 0; i < bezierPoints.size(); ++i) {QRect pointRect(bezierPoints[i]->geometry());if (pointRect.contains(event->pos())) {selectedPoint = i;bezierPoints[i]->setSelected(true);return;}}selectedPoint = -1;}}void mouseMoveEvent(QMouseEvent *event) override {if (selectedPoint >= 0 && selectedPoint < controlPoints.size()) {// Move control pointcontrolPoints[selectedPoint] = event->pos();bezierPoints[selectedPoint]->move(event->x() - 12, event->y() - 12);update();}}void mouseReleaseEvent(QMouseEvent *event) override {Q_UNUSED(event);if (selectedPoint >= 0 && selectedPoint < bezierPoints.size()) {bezierPoints[selectedPoint]->setSelected(false);}selectedPoint = -1;}private:void drawGrid(QPainter &painter) {painter.save();painter.setPen(QPen(QColor(200, 200, 200), 0.5));// Draw grid linesfor (int x = 50; x < width(); x += 50) {painter.drawLine(x, 50, x, height() - 50);}for (int y = 50; y < height(); y += 50) {painter.drawLine(50, y, width() - 50, y);}// Draw borderpainter.setPen(QPen(Qt::black, 1, Qt::DashLine));painter.drawRect(50, 50, width() - 100, height() - 100);painter.restore();}void drawControlLines(QPainter &painter) {painter.save();painter.setPen(QPen(QColor(232, 196, 142), 2));// Draw control linesfor (int i = 0; i < controlPoints.size() - 1; ++i) {painter.drawLine(controlPoints[i], controlPoints[i+1]);}// Draw control pointsfor (int i = 0; i < controlPoints.size(); ++i) {painter.setPen(QPen(Qt::black, 1));painter.setBrush(i == 0 ? Qt::green : (i == controlPoints.size()-1 ? Qt::red : Qt::blue));painter.drawEllipse(controlPoints[i], 4, 4);// Draw point labelpainter.setPen(Qt::black);painter.drawText(controlPoints[i] + QPointF(10, -10), QString::number(i+1));}painter.restore();}void drawBezierCurve(QPainter &painter) {painter.save();painter.setPen(QPen(Qt::red, 2));// Draw Bezier curveQPainterPath path;path.moveTo(controlPoints[0]);// Cubic Bezier curve with 4 pointsif (controlPoints.size() == 4) {path.cubicTo(controlPoints[1], controlPoints[2], controlPoints[3]);}// Quadratic Bezier curve with 3 pointselse if (controlPoints.size() == 3) {path.quadTo(controlPoints[1], controlPoints[2]);}// Linear Bezier curve with 2 pointselse if (controlPoints.size() == 2) {path.lineTo(controlPoints[1]);}painter.drawPath(path);painter.restore();}void drawAnimation(QPainter &painter) {// Draw intermediate points and linesQVector<QPointF> currentLevel = controlPoints;QVector<QVector<QPointF>> levels;levels.append(currentLevel);while (currentLevel.size() > 1) {QVector<QPointF> nextLevel;QColor lineColor;switch (currentLevel.size() % 3) {case 0: lineColor = QColor(0, 170, 0); break; // Greencase 1: lineColor = Qt::blue; break;case 2: lineColor = Qt::red; break;default: lineColor = Qt::darkGray;}painter.setPen(QPen(lineColor, 1.5));// Draw lines between points in the current levelfor (int i = 0; i < currentLevel.size() - 1; ++i) {painter.drawLine(currentLevel[i], currentLevel[i+1]);// Calculate next level pointsQPointF p = interpolate(currentLevel[i], currentLevel[i+1], t);nextLevel.append(p);// Draw intermediate pointspainter.setPen(QPen(Qt::black, 1));painter.setBrush(lineColor);painter.drawEllipse(p, 3, 3);painter.setPen(QPen(lineColor, 1.5));}currentLevel = nextLevel;levels.append(currentLevel);}// Draw the final point on the curveif (!currentLevel.isEmpty()) {painter.setPen(QPen(Qt::red, 2));painter.setBrush(Qt::red);painter.drawEllipse(currentLevel[0], 5, 5);}// Draw t valuepainter.setPen(Qt::black);painter.drawText(20, 30, QString("t: %1").arg(t, 0, 'f', 3));}QPointF interpolate(const QPointF &p1, const QPointF &p2, qreal t) {return p1 + t * (p2 - p1);}private:QVector<QPointF> controlPoints;QVector<BezierPoint*> bezierPoints;int selectedPoint = -1;qreal t;bool animating;QTimer *timer;
};class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {setWindowTitle("贝塞尔曲线可视化工具");QWidget *centralWidget = new QWidget(this);QGridLayout *layout = new QGridLayout(centralWidget);bezierWidget = new BezierWidget(this);layout->addWidget(bezierWidget, 0, 0, 1, 2);// Create control buttonsQPushButton *startButton = new QPushButton("开始动画", this);connect(startButton, &QPushButton::clicked, this, [=,this]() {if (bezierWidget->isAnimating()) {bezierWidget->stopAnimation();startButton->setText("开始动画");} else {bezierWidget->startAnimation();startButton->setText("停止动画");}});QPushButton *resetButton = new QPushButton("重置曲线", this);connect(resetButton, &QPushButton::clicked, this, [=,this]() {bezierWidget->stopAnimation();startButton->setText("开始动画");bezierWidget->update();});layout->addWidget(startButton, 1, 0);layout->addWidget(resetButton, 1, 1);// Add information labelQLabel *infoLabel = new QLabel("使用说明:\n""1. 拖动控制点改变曲线形状\n""2. 点击'开始动画'查看曲线生成过程\n""3. 不同颜色线段展示递归插值过程\n""4. 红色圆点是曲线上的点(t值)");layout->addWidget(infoLabel, 2, 0, 1, 2);setCentralWidget(centralWidget);resize(850, 700);}private:BezierWidget *bezierWidget;
};#endif // WIDGET_H
http://www.lryc.cn/news/606986.html

相关文章:

  • MongoDB 详细用法与 Java 集成完整指南
  • 如何安全管理SSH密钥以防止服务器被入侵
  • Java应用服务器选型指南:WebLogic vs. Tomcat、WebSphere、JBoss/Wildfly
  • Vue3中Markdown解析与渲染的完整解决方案:从安全到性能优化
  • 区块链技术如何确保智能合约的安全性和可靠性?
  • Qt 开发 IDE 插件开发指南
  • 在SQL SERVER 中如何用脚本实现每日自动调用存储过程
  • 将本地commit已经push到orgin后如何操作
  • 微波(Microwave)与毫米波(Millimeter wave)简介
  • windows mamba-ssm环境配置指南
  • 在 Docker 中启动 Nginx 并挂载配置文件到宿主机目录
  • 代码随想录算法训练营第三十八天
  • Mermaid流程图可视化系统:基于Spring Boot与Node.js的三层架构实现
  • h5独立部署
  • (转)mybatis和hibernate的 缓存区别?
  • AG-UI 协议全面解析--下一代 AI Agent 交互框架医疗应用分析(上)
  • 【BUUCTF系列】[GXYCTF2019]Ping Ping Ping 1
  • 智能体的未来:AGI路径上的关键技术突破
  • springboot助农平台
  • 探索 VMware 虚拟机:开启虚拟化世界的大门
  • 人大金仓数据库Kingbase主备集群搭建和部署
  • Spring Boot 2.1.18 集成 Elasticsearch 6.6.2 实战指南
  • 工业环境中无人叉车安全标准深度解析
  • 我用提示词A 对qwen3-4b大模型进行 nl2sql 任务 grpo 强化学习,评估的时候换新提示词,会影响nl2sql测评准确率吗?
  • 数据结构常见时间复杂度整理
  • 数据结构(10)栈和队列算法题
  • 4-verilog简单状态机
  • Linux 硬盘分区管理
  • FEVER数据集:事实验证任务的大规模基准与评估框架
  • spring boot 启动报错---java: 无法访问org.springframework.boot.SpringApplication 错误的类文件