改进平滑曲线

master
feiyangqingyun 2021-03-09 09:56:41 +08:00
parent 982ee44840
commit dd4f979511
9 changed files with 91 additions and 31 deletions

BIN
0snap/smoothcurve.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -98,4 +98,4 @@
![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/designer.png) ![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/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) ![avatar](https://gitee.com/feiyangqingyun/QWidgetDemo/raw/master/0snap/smoothcurve.gif)

View File

@ -3,8 +3,11 @@
#include "ui_frmpngtool.h" #include "ui_frmpngtool.h"
#include "qfile.h" #include "qfile.h"
#include "qfiledialog.h" #include "qfiledialog.h"
#include "qdatetime.h"
#include "qdebug.h" #include "qdebug.h"
#define TIMEMS QTime::currentTime().toString("hh:mm:ss zzz")
frmPngTool::frmPngTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmPngTool) frmPngTool::frmPngTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmPngTool)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -63,7 +66,7 @@ void frmPngTool::on_btnOk_clicked()
ui->txtMain->clear(); ui->txtMain->clear();
int count = 0; int count = 0;
foreach (QString file, files) { foreach (QString file, files) {
ui->txtMain->append(file); ui->txtMain->append(QString("%1 -> %2").arg(TIMEMS).arg(file));
QImage image(file); QImage image(file);
image.save(file, "png"); image.save(file, "png");
count++; count++;
@ -71,5 +74,5 @@ void frmPngTool::on_btnOk_clicked()
qApp->processEvents(); qApp->processEvents();
} }
ui->txtMain->append(QString("处理完成, 共 %1 个文件").arg(files.count())); ui->txtMain->append(QString("%1 -> 处理完成, 共 %2 个文件").arg(TIMEMS).arg(files.count()));
} }

View File

@ -5,6 +5,8 @@
#include "qdatetime.h" #include "qdatetime.h"
#include "qdebug.h" #include "qdebug.h"
#define TIMEMS QTime::currentTime().toString("hh:mm:ss zzz")
frmSmoothCurve::frmSmoothCurve(QWidget *parent) : QWidget(parent), ui(new Ui::frmSmoothCurve) frmSmoothCurve::frmSmoothCurve(QWidget *parent) : QWidget(parent), ui(new Ui::frmSmoothCurve)
{ {
ui->setupUi(this); ui->setupUi(this);
@ -19,17 +21,27 @@ frmSmoothCurve::frmSmoothCurve(QWidget *parent) : QWidget(parent), ui(new Ui::fr
x += qMin(qrand() % 30 + 5, 300); x += qMin(qrand() % 30 + 5, 300);
} }
//根据曲线上的点创建平滑曲线 //正常曲线
smoothCurve = SmoothCurve::createSmoothCurve(datas); pathNormal.moveTo(datas.at(0));
// 直接连接点的创建非平滑曲线曲线
smoothCurve2.moveTo(datas[0]);
for (int i = 1; i < datas.size(); ++i) { for (int i = 1; i < datas.size(); ++i) {
smoothCurve2.lineTo(datas[i]); pathNormal.lineTo(datas.at(i));
} }
connect(ui->showKnotsCheckBox, SIGNAL(clicked(bool)), this, SLOT(update())); //平滑曲线1
connect(ui->showSmoothCurveCheckBox, SIGNAL(clicked(bool)), this, SLOT(update())); qDebug() << TIMEMS << "createSmoothCurve start";
pathSmooth1 = SmoothCurve::createSmoothCurve(datas);
qDebug() << TIMEMS << "createSmoothCurve stop";
//平滑曲线2
qDebug() << TIMEMS << "createSmoothCurve2 start";
pathSmooth2 = SmoothCurve::createSmoothCurve2(datas);
qDebug() << TIMEMS << "createSmoothCurve2 stop";
ui->ckShowPoint->setChecked(true);
connect(ui->ckShowPoint, SIGNAL(clicked(bool)), this, SLOT(update()));
connect(ui->rbtnPathNormal, SIGNAL(clicked(bool)), this, SLOT(update()));
connect(ui->rbtnPathSmooth1, SIGNAL(clicked(bool)), this, SLOT(update()));
connect(ui->rbtnPathSmooth2, SIGNAL(clicked(bool)), this, SLOT(update()));
} }
frmSmoothCurve::~frmSmoothCurve() frmSmoothCurve::~frmSmoothCurve()
@ -49,20 +61,22 @@ void frmSmoothCurve::paintEvent(QPaintEvent *)
painter.drawLine(-250, 0, 250, 0); painter.drawLine(-250, 0, 250, 0);
painter.drawLine(0, 150, 0, -150); painter.drawLine(0, 150, 0, -150);
//被选中时显示平滑曲线,否则显示非平滑曲线 //根据选择绘制不同的曲线路径
painter.setPen(QPen(QColor(80, 80, 80), 2)); painter.setPen(QPen(QColor(80, 80, 80), 2));
if (ui->showSmoothCurveCheckBox->isChecked()) { if (ui->rbtnPathSmooth1->isChecked()) {
painter.drawPath(smoothCurve); painter.drawPath(pathSmooth1);
} else if (ui->rbtnPathSmooth2->isChecked()) {
painter.drawPath(pathSmooth2);
} else { } else {
painter.drawPath(smoothCurve2); painter.drawPath(pathNormal);
} }
//如果曲线上的点可见则显示出来 //如果曲线上的点可见则显示出来
if (ui->showKnotsCheckBox->isChecked()) { if (ui->ckShowPoint->isChecked()) {
painter.setPen(Qt::black); painter.setPen(Qt::black);
painter.setBrush(Qt::gray); painter.setBrush(Qt::gray);
foreach (QPointF p, datas) { foreach (QPointF point, datas) {
painter.drawEllipse(p, 3, 3); painter.drawEllipse(point, 3, 3);
} }
} }
} }

View File

@ -24,8 +24,9 @@ protected:
private: private:
Ui::frmSmoothCurve *ui; Ui::frmSmoothCurve *ui;
QVector<QPointF> datas; //曲线上的点 QVector<QPointF> datas; //曲线上的点
QPainterPath smoothCurve; //平滑曲线 QPainterPath pathNormal; //正常曲线
QPainterPath smoothCurve2; //直接连接点的非平滑曲线 QPainterPath pathSmooth1; //平滑曲线1
QPainterPath pathSmooth2; //平滑曲线2
}; };
#endif // FRMSMOOTHCURVE_H #endif // FRMSMOOTHCURVE_H

View File

@ -6,15 +6,15 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>714</width> <width>800</width>
<height>523</height> <height>600</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Widget</string> <string>Widget</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="2"> <item row="0" column="5">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -27,14 +27,28 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="2">
<widget class="QRadioButton" name="rbtnPathSmooth1">
<property name="text">
<string>平滑曲线1</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QRadioButton" name="rbtnPathSmooth2">
<property name="text">
<string>平滑曲线2</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="showKnotsCheckBox"> <widget class="QCheckBox" name="ckShowPoint">
<property name="text"> <property name="text">
<string>显示坐标点</string> <string>显示坐标点</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="4">
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -47,10 +61,13 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="2"> <item row="1" column="1">
<widget class="QCheckBox" name="showSmoothCurveCheckBox"> <widget class="QRadioButton" name="rbtnPathNormal">
<property name="text"> <property name="text">
<string>平滑</string> <string>正常曲线</string>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -1,4 +1,5 @@
#include "smoothcurve.h" #include "smoothcurve.h"
#include "qdebug.h"
QPainterPath SmoothCurve::createSmoothCurve(const QVector<QPointF> &points) QPainterPath SmoothCurve::createSmoothCurve(const QVector<QPointF> &points)
{ {
@ -20,6 +21,29 @@ QPainterPath SmoothCurve::createSmoothCurve(const QVector<QPointF> &points)
return path; return path;
} }
QPainterPath SmoothCurve::createSmoothCurve2(const QVector<QPointF> &points)
{
//采用Qt原生方法不做任何处理
int count = points.count();
if (count == 0) {
return QPainterPath();
}
QPainterPath path(points.at(0));
for (int i = 0; i < count - 1; ++i) {
//控制点的 x 坐标为 sp 与 ep 的 x 坐标和的一半
//第一个控制点 c1 的 y 坐标为起始点 sp 的 y 坐标
//第二个控制点 c2 的 y 坐标为结束点 ep 的 y 坐标
QPointF sp = points.at(i);
QPointF ep = points.at(i + 1);
QPointF c1 = QPointF((sp.x() + ep.x()) / 2, sp.y());
QPointF c2 = QPointF((sp.x() + ep.x()) / 2, ep.y());
path.cubicTo(c1, c2, ep);
}
return path;
}
void SmoothCurve::calculateFirstControlPoints(double *&result, const double *rhs, int n) void SmoothCurve::calculateFirstControlPoints(double *&result, const double *rhs, int n)
{ {
result = new double[n]; result = new double[n];
@ -41,8 +65,8 @@ void SmoothCurve::calculateFirstControlPoints(double *&result, const double *rhs
} }
void SmoothCurve::calculateControlPoints(const QVector<QPointF> &datas, void SmoothCurve::calculateControlPoints(const QVector<QPointF> &datas,
QVector<QPointF> *firstControlPoints, QVector<QPointF> *firstControlPoints,
QVector<QPointF> *secondControlPoints) QVector<QPointF> *secondControlPoints)
{ {
int n = datas.size() - 1; int n = datas.size() - 1;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {

View File

@ -1,4 +1,4 @@
#ifndef SMOOTHCURVE_H #ifndef SMOOTHCURVE_H
#define SMOOTHCURVE_H #define SMOOTHCURVE_H
#include <QObject> #include <QObject>
@ -16,6 +16,7 @@ class SmoothCurve : public QObject
public: public:
//创建平滑曲线路径 //创建平滑曲线路径
static QPainterPath createSmoothCurve(const QVector<QPointF> &points); static QPainterPath createSmoothCurve(const QVector<QPointF> &points);
static QPainterPath createSmoothCurve2(const QVector<QPointF> &points);
private: private:
static void calculateFirstControlPoints(double *&result, const double *rhs, int n); static void calculateFirstControlPoints(double *&result, const double *rhs, int n);