新增平滑曲线demo

master
feiyangqingyun 2021-03-08 09:26:04 +08:00
parent 1a00016148
commit 982ee44840
10 changed files with 342 additions and 1 deletions

BIN
0snap/smoothcurve.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@ -35,6 +35,7 @@ SUBDIRS += screenwidget #屏幕截图控件
SUBDIRS += imageswitch #图片开关控件
SUBDIRS += netserver #网络中转服务器
SUBDIRS += base64 #图片文字base64互换
SUBDIRS += smoothcurve #平滑曲线
win32 {
SUBDIRS += ffmpegdemo #视频流播放ffmpeg内核

View File

@ -47,6 +47,7 @@
| 40 | mpvdemo | 视频流播放mpv内核 |
| 41 | miniblink | miniblink示例 |
| 42 | base64 | 图片文字base64互换 |
| 43 | smoothcurve | 平滑曲线 |
### 二、学习群
1. **Qt交流大会群 853086607(雨田哥)**
@ -97,3 +98,4 @@
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/designer.png)
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/miniblink.jpg)
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/base64.png)
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/smoothcurve.png)

View File

@ -0,0 +1,68 @@
#include "frmsmoothcurve.h"
#include "ui_frmsmoothcurve.h"
#include "smoothcurve.h"
#include "qpainter.h"
#include "qdatetime.h"
#include "qdebug.h"
frmSmoothCurve::frmSmoothCurve(QWidget *parent) : QWidget(parent), ui(new Ui::frmSmoothCurve)
{
ui->setupUi(this);
//初始化随机数种子
qsrand(QDateTime::currentDateTime().toMSecsSinceEpoch());
//随机生成曲线上的点
int x = -300;
while (x < 300) {
datas << QPointF(x, qrand() % 300 - 100);
x += qMin(qrand() % 30 + 5, 300);
}
//根据曲线上的点创建平滑曲线
smoothCurve = SmoothCurve::createSmoothCurve(datas);
// 直接连接点的创建非平滑曲线曲线
smoothCurve2.moveTo(datas[0]);
for (int i = 1; i < datas.size(); ++i) {
smoothCurve2.lineTo(datas[i]);
}
connect(ui->showKnotsCheckBox, SIGNAL(clicked(bool)), this, SLOT(update()));
connect(ui->showSmoothCurveCheckBox, SIGNAL(clicked(bool)), this, SLOT(update()));
}
frmSmoothCurve::~frmSmoothCurve()
{
delete ui;
}
void frmSmoothCurve::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(width() / 2, height() / 2);
painter.scale(1, -1);
//画坐标轴
painter.setPen(QColor(180, 180, 180));
painter.drawLine(-250, 0, 250, 0);
painter.drawLine(0, 150, 0, -150);
//被选中时显示平滑曲线,否则显示非平滑曲线
painter.setPen(QPen(QColor(80, 80, 80), 2));
if (ui->showSmoothCurveCheckBox->isChecked()) {
painter.drawPath(smoothCurve);
} else {
painter.drawPath(smoothCurve2);
}
//如果曲线上的点可见则显示出来
if (ui->showKnotsCheckBox->isChecked()) {
painter.setPen(Qt::black);
painter.setBrush(Qt::gray);
foreach (QPointF p, datas) {
painter.drawEllipse(p, 3, 3);
}
}
}

View File

@ -0,0 +1,31 @@
#ifndef FRMSMOOTHCURVE_H
#define FRMSMOOTHCURVE_H
#include <QWidget>
#include <QList>
#include <QPointF>
#include <QPainterPath>
namespace Ui {
class frmSmoothCurve;
}
class frmSmoothCurve : public QWidget
{
Q_OBJECT
public:
explicit frmSmoothCurve(QWidget *parent = 0);
~frmSmoothCurve();
protected:
void paintEvent(QPaintEvent *event);
private:
Ui::frmSmoothCurve *ui;
QVector<QPointF> datas; //曲线上的点
QPainterPath smoothCurve; //平滑曲线
QPainterPath smoothCurve2; //直接连接点的非平滑曲线
};
#endif // FRMSMOOTHCURVE_H

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>frmSmoothCurve</class>
<widget class="QWidget" name="frmSmoothCurve">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>714</width>
<height>523</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>473</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="showKnotsCheckBox">
<property name="text">
<string>显示坐标点</string>
</property>
</widget>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>549</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="showSmoothCurveCheckBox">
<property name="text">
<string>平滑</string>
</property>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

31
smoothcurve/main.cpp Normal file
View File

@ -0,0 +1,31 @@
#pragma execution_character_set("utf-8")
#include "frmsmoothcurve.h"
#include <QApplication>
#include <QTextCodec>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setFont(QFont("Microsoft Yahei", 9));
#if (QT_VERSION <= QT_VERSION_CHECK(5,0,0))
#if _MSC_VER
QTextCodec *codec = QTextCodec::codecForName("gbk");
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
#endif
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
#else
QTextCodec *codec = QTextCodec::codecForName("utf-8");
QTextCodec::setCodecForLocale(codec);
#endif
frmSmoothCurve w;
w.setWindowTitle("平滑曲线");
w.show();
return a.exec();
}

View File

@ -0,0 +1,96 @@
#include "smoothcurve.h"
QPainterPath SmoothCurve::createSmoothCurve(const QVector<QPointF> &points)
{
QPainterPath path;
int len = points.size();
if (len < 2) {
return path;
}
QVector<QPointF> firstControlPoints;
QVector<QPointF> secondControlPoints;
calculateControlPoints(points, &firstControlPoints, &secondControlPoints);
path.moveTo(points[0].x(), points[0].y());
for (int i = 0; i < len - 1; ++i) {
path.cubicTo(firstControlPoints[i], secondControlPoints[i], points[i + 1]);
}
return path;
}
void SmoothCurve::calculateFirstControlPoints(double *&result, const double *rhs, int n)
{
result = new double[n];
double *tmp = new double[n];
double b = 2.0;
result[0] = rhs[0] / b;
for (int i = 1; i < n; i++) {
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
result[i] = (rhs[i] - result[i - 1]) / b;
}
for (int i = 1; i < n; i++) {
result[n - i - 1] -= tmp[n - i] * result[n - i];
}
delete tmp;
}
void SmoothCurve::calculateControlPoints(const QVector<QPointF> &datas,
QVector<QPointF> *firstControlPoints,
QVector<QPointF> *secondControlPoints)
{
int n = datas.size() - 1;
for (int i = 0; i < n; ++i) {
firstControlPoints->append(QPointF());
secondControlPoints->append(QPointF());
}
if (n == 1) {
(*firstControlPoints)[0].rx() = (2 * datas[0].x() + datas[1].x()) / 3;
(*firstControlPoints)[0].ry() = (2 * datas[0].y() + datas[1].y()) / 3;
(*secondControlPoints)[0].rx() = 2 * (*firstControlPoints)[0].x() - datas[0].x();
(*secondControlPoints)[0].ry() = 2 * (*firstControlPoints)[0].y() - datas[0].y();
return;
}
double *xs = 0;
double *ys = 0;
double *rhsx = new double[n];
double *rhsy = new double[n];
for (int i = 1; i < n - 1; ++i) {
rhsx[i] = 4 * datas[i].x() + 2 * datas[i + 1].x();
rhsy[i] = 4 * datas[i].y() + 2 * datas[i + 1].y();
}
rhsx[0] = datas[0].x() + 2 * datas[1].x();
rhsx[n - 1] = (8 * datas[n - 1].x() + datas[n].x()) / 2.0;
rhsy[0] = datas[0].y() + 2 * datas[1].y();
rhsy[n - 1] = (8 * datas[n - 1].y() + datas[n].y()) / 2.0;
calculateFirstControlPoints(xs, rhsx, n);
calculateFirstControlPoints(ys, rhsy, n);
for (int i = 0; i < n; ++i) {
(*firstControlPoints)[i].rx() = xs[i];
(*firstControlPoints)[i].ry() = ys[i];
if (i < n - 1) {
(*secondControlPoints)[i].rx() = 2 * datas[i + 1].x() - xs[i + 1];
(*secondControlPoints)[i].ry() = 2 * datas[i + 1].y() - ys[i + 1];
} else {
(*secondControlPoints)[i].rx() = (datas[n].x() + xs[n - 1]) / 2;
(*secondControlPoints)[i].ry() = (datas[n].y() + ys[n - 1]) / 2;
}
}
delete xs;
delete ys;
delete rhsx;
delete rhsy;
}

27
smoothcurve/smoothcurve.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef SMOOTHCURVE_H
#define SMOOTHCURVE_H
#include <QObject>
#include <QVector>
#include <QPointF>
#include <QPainterPath>
#ifdef quc
class Q_DECL_EXPORT SmoothCurve : public QObject
#else
class SmoothCurve : public QObject
#endif
{
public:
//创建平滑曲线路径
static QPainterPath createSmoothCurve(const QVector<QPointF> &points);
private:
static void calculateFirstControlPoints(double *&result, const double *rhs, int n);
static void calculateControlPoints(const QVector<QPointF> &datas,
QVector<QPointF> *firstControlPoints,
QVector<QPointF> *secondControlPoints);
};
#endif // SMOOTHCURVE_H

View File

@ -0,0 +1,23 @@
#-------------------------------------------------
#
# Project created by QtCreator 2017-01-09T09:29:12
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = smoothcurve
TEMPLATE = app
DESTDIR = $$PWD/../bin
CONFIG += warn_off
SOURCES += main.cpp
SOURCES += frmsmoothcurve.cpp
SOURCES += smoothcurve.cpp
HEADERS += frmsmoothcurve.h
HEADERS += smoothcurve.h
FORMS += frmsmoothcurve.ui