新增平滑曲线demo
parent
1a00016148
commit
982ee44840
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
|
@ -35,6 +35,7 @@ SUBDIRS += screenwidget #屏幕截图控件
|
|||
SUBDIRS += imageswitch #图片开关控件
|
||||
SUBDIRS += netserver #网络中转服务器
|
||||
SUBDIRS += base64 #图片文字base64互换
|
||||
SUBDIRS += smoothcurve #平滑曲线
|
||||
|
||||
win32 {
|
||||
SUBDIRS += ffmpegdemo #视频流播放ffmpeg内核
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
| 40 | mpvdemo | 视频流播放mpv内核 |
|
||||
| 41 | miniblink | miniblink示例 |
|
||||
| 42 | base64 | 图片文字base64互换 |
|
||||
| 43 | smoothcurve | 平滑曲线 |
|
||||
|
||||
### 二、学习群
|
||||
1. **Qt交流大会群 853086607(雨田哥)**
|
||||
|
@ -96,4 +97,5 @@
|
|||
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/netserver.jpg)
|
||||
![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/base64.png)
|
||||
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/smoothcurve.png)
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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>
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue