²  贝塞尔曲线

贝塞尔曲线是通过一组多边折线的各顶点来定义。在各顶点中,曲线经过第一点和最后一点,其余各点则定义曲线的导数、阶次和形状。第一条和最后一条则表示曲线起点和终点的切线方向。

²  B样条曲线

针对贝塞尔曲线存在的一些缺点,数学家们提出了B样条方法,在保留贝塞尔全部优点的同时,克服可贝塞尔方法的弱点。

1)      二次B样条曲线

2)      三次B样条曲线

QT中的QPainter提供了绘制贝塞尔曲线的相关API:

void QPainterPath::quadTo(const QPointF &c, const QPointF &endPoint)

void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &endPoint)

void QPainter::drawPath(const QPainterPath &path)

Widget.h 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 
/////////////////////////////////////////////////////////////
/// @file   Widget.h
/// @brief  绘制B样条曲线Widget类
///
/// 通过鼠标点击来绘制B样条曲线
/// @author Michael Joessy
/// @date   2019-07-02
/////////////////////////////////////////////////////////////
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QVector>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    virtual void mousePressEvent(QMouseEvent *event);
    virtual void mouseReleaseEvent(QMouseEvent *event);
    virtual void mouseDoubleClickEvent(QMouseEvent *event);
    virtual void mouseMoveEvent(QMouseEvent *event);
    virtual void paintEvent(QPaintEvent *event);

private:
    void drawSpline();
    qreal N(int k, int i, qreal u);
    qreal N1(int i, qreal u);
    qreal N2(int i, qreal u);
    qreal N3(int i, qreal u);

private:
    QVector<QPointF>    m_ctrlPoints;       // 控制点
    QVector<QPointF>    m_curvePoints;      // 曲线上的点
};

#endif // WIDGET_H

Widget.pp 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
 
#include "Widget.h"
#include <QMouseEvent>
#include <QPainter>
#include <cmath>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
}

Widget::~Widget()
{

}

void Widget::mousePressEvent(QMouseEvent *event)
{
    // 单击鼠标左键获取控制点
    if (event->buttons() == Qt::LeftButton){
        m_ctrlPoints.push_back(event->pos());
    }
    // 单击鼠标右键清空控制点
    else if (event->buttons() == Qt::RightButton) {
        m_ctrlPoints.clear();
    }
    update();
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{

}

void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{

}

void Widget::mouseMoveEvent(QMouseEvent *event)
{

}

void Widget::paintEvent(QPaintEvent *event)
{
    drawSpline();
}

void Widget::drawSpline()
{
    QPainter painter(this);
    ;       // 阶数
    m_curvePoints.clear();
    ){
        QPointF pt();
        ; i < m_ctrlPoints.size(); ++i){
            QPointF pts = m_ctrlPoints[i];
            pts *= N(currentK, i, u);
            pt += pts;
        }
        m_curvePoints.push_back(pt);
    }

// draw control points
));
    ctrlPen1.setWidth();
    painter.setPen(ctrlPen1);
    ; i < m_ctrlPoints.size(); ++i){
        painter.drawPoint(m_ctrlPoints[i]);
    }
    // draw control lines
));
    ctrlPen2.setWidth();
    ctrlPen2.setStyle(Qt::DashDotDotLine);
    painter.setPen(ctrlPen2);
    ; ++i){
        painter.drawLine(m_ctrlPoints[i], m_ctrlPoints[i + ]);
    }
    // draw spline curve
));
    curvePen.setWidth();
    painter.setPen(curvePen);
    ; ++i){
        painter.drawLine(m_curvePoints[i], m_curvePoints[i + ]);
    }
}

qreal Widget::N(int k, int i, qreal u)
{
    switch (k) {
    :
        return N1(i, u);
    :
        return  N2(i, u);
    :
        return  N3(i, u);
    default:
        break;
    }
}

qreal Widget::N1(int i, qreal u)
{
    qreal t = u - i;
    ){
        return t;
    }
    ){
         - t;
    }
    ;
}

qreal Widget::N2(int i, qreal u)
{
    qreal t = u - i;
    ){
         * t * t;
    }
    ){
        ;
    }
    ){
        );
    }
    ;
}

qreal Widget::N3(int i, qreal u)
{
    qreal t = u - i;
    qreal a = ;
    ){
        return a * t * t * t;
    }
    ){
        );
    }
    ){
        );
    }
    ){
        );
    }
    ;
}

上述算法有点简单,https://github.com/vkorchagin/animated-b-spline提供了比较好的算法例子,值得参考。

给定B样条曲线的控制点。 这些点在屏幕上移动,从而使样条动画。
B样条通过de Boor算法转换为合成Bezier曲线。 贝塞尔曲线用de Casteljau算法进行插值。
特征:
添加和删除控制点。
通过de Casteljau算法更改插值质量。
切换抗锯齿。
不断变化的动画速度。
切换可见点和线。

QT绘制B样条曲线的更多相关文章

  1. QT绘制饼图

    QT版本:QT5.6.1 QT绘制饼图,出问题的代码如下 void DrawPieDialog::paintEvent(QPaintEvent *event) { float startAngle=0 ...

  2. Qt 学习之路 2(24):Qt 绘制系统简介

    Qt 学习之路 2(24):Qt 绘制系统简介 豆子 2012年10月30日 Qt 学习之路 2 77条评论 Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于Q ...

  3. Qt绘制异形窗体

    异形窗体即不规则窗体,一般采用png图片,一般绘制异形窗体分两步: 1.设置遮罩区 2.绘制图片   使用png图片的透明部分作为遮罩区,然后绘制图片,这样我们就看到一个只绘制了非透明部分的图形,废话 ...

  4. Qt 学习之路 :Qt 绘制系统简介

    Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类. QPainter用来执行绘制的 ...

  5. qt绘制设备

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.QtGui import  * from Py ...

  6. QT绘制系统简介

    #3个类:QPainter,QPainterDevice 和 QPaintEngine 三个类 #qpainter用于执行绘制操作 #QPainterDevice是一个二维空间抽象,允许qpainte ...

  7. QT 绘制按钮 paintEvent enterEvent leaseEvent mouseEvent

    案例2:绘制按钮 main.cpp #include<QApplication> #include “demoWidget.h” int  main(int  args , int arg ...

  8. Qt绘制文本一

    QPainterPath,使用 drawText且设置字体,再使用painter.drawText方式 效果图: void WgtText::paintEvent(QPaintEvent *event ...

  9. Qt绘制简单的风向玫瑰图代码

    1.绘制简单的风向玫瑰图代码2.主要使用QPainter3.在子widget上绘制需要使用widget监视事件 eventfilter update();//更新界面 //镜头12 QPainter ...

随机推荐

  1. python批量创建txt文件,以demo.txt内的内容为文件名

    #批量创建txt文件import sys,osa=open("demo.txt")n=0aList=[]for line in a.readlines(): aList.appen ...

  2. 文件上传-pubsec-文件上传大小限制

    文件上传-pubsec-文件上传大小限制 Caused by: java.lang.IllegalArgumentException: ContextPath must start with '/' ...

  3. zz致力于变革未来的智能技术

    有 R-CNN SPPNet Fast R-CNN Faster R-CNN ... 的论文翻译 现在已经不能访问了...     [私人整理]空间金字塔池化网络SPPNet详解 SPP-Net是出自 ...

  4. 论文阅读笔记六十六:Wide Activation for Efficient and Accurate Image Super-Resolution(CVPR2018)

    论文原址:https://arxiv.org/abs/1808.08718 代码:https://github.com/JiahuiYu/wdsr_ntire2018 摘要 本文证明在SISR中在Re ...

  5. python之路—从入门到放弃

    python基础部分 函数 初识函数 函数进阶 装饰器函数 迭代器和生成器 内置函数和匿名函数 递归函数 常用模块 常用模块 模块和包 面向对象 初识面向对象 面向对象进阶 网络编程 网络编程 并发编 ...

  6. python的小数据池

    一.什么是小数据池? 小数据池是一种缓存机制,也被称为驻留机制.各种编程语言中都有类似的东西(常量池.小数据池都是指得同一个内容). python自动将-5~256的整数.有一定规则的字符串.都放在一 ...

  7. [LeetCode] 921. Minimum Add to Make Parentheses Valid 使括号有效的最少添加

    Given a string S of '(' and ')' parentheses, we add the minimum number of parentheses ( '(' or ')', ...

  8. Linux 使用squid3搭建代理服务器

    在对接微信/支付宝等3方业务时,往往都有ip白名单的设置,由于内网往往都是动态ip,频繁配置白名单是件及其繁琐的事情. 使用代理转发就是最方便的做法. 下面就使用squid3配置一台代理服务器. sq ...

  9. oracle-报错 RMAN-03002,RMAN-06172

    RMAN> restore standby controlfile from "/data/oracle/contral.ctl"; Starting restore at ...

  10. web版聊天功能简单实现

    一.问题 核心点:如何找到要发送的人? 要完成一个功能我觉得首先要分析该功能的逻辑及技术难点,而不是盲目的直接就撸代码,这样非常浪费时间.个人觉得web版聊天功能没什么实际应用场景,以前看过中国移动好 ...