改进平滑曲线

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/miniblink.jpg)
![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 "qfile.h"
#include "qfiledialog.h"
#include "qdatetime.h"
#include "qdebug.h"
#define TIMEMS QTime::currentTime().toString("hh:mm:ss zzz")
frmPngTool::frmPngTool(QWidget *parent) : QWidget(parent), ui(new Ui::frmPngTool)
{
ui->setupUi(this);
@ -63,7 +66,7 @@ void frmPngTool::on_btnOk_clicked()
ui->txtMain->clear();
int count = 0;
foreach (QString file, files) {
ui->txtMain->append(file);
ui->txtMain->append(QString("%1 -> %2").arg(TIMEMS).arg(file));
QImage image(file);
image.save(file, "png");
count++;
@ -71,5 +74,5 @@ void frmPngTool::on_btnOk_clicked()
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 "qdebug.h"
#define TIMEMS QTime::currentTime().toString("hh:mm:ss zzz")
frmSmoothCurve::frmSmoothCurve(QWidget *parent) : QWidget(parent), ui(new Ui::frmSmoothCurve)
{
ui->setupUi(this);
@ -19,17 +21,27 @@ frmSmoothCurve::frmSmoothCurve(QWidget *parent) : QWidget(parent), ui(new Ui::fr
x += qMin(qrand() % 30 + 5, 300);
}
//根据曲线上的点创建平滑曲线
smoothCurve = SmoothCurve::createSmoothCurve(datas);
// 直接连接点的创建非平滑曲线曲线
smoothCurve2.moveTo(datas[0]);
//正常曲线
pathNormal.moveTo(datas.at(0));
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()));
connect(ui->showSmoothCurveCheckBox, SIGNAL(clicked(bool)), this, SLOT(update()));
//平滑曲线1
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()
@ -49,20 +61,22 @@ void frmSmoothCurve::paintEvent(QPaintEvent *)
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);
if (ui->rbtnPathSmooth1->isChecked()) {
painter.drawPath(pathSmooth1);
} else if (ui->rbtnPathSmooth2->isChecked()) {
painter.drawPath(pathSmooth2);
} else {
painter.drawPath(smoothCurve2);
painter.drawPath(pathNormal);
}
//如果曲线上的点可见则显示出来
if (ui->showKnotsCheckBox->isChecked()) {
if (ui->ckShowPoint->isChecked()) {
painter.setPen(Qt::black);
painter.setBrush(Qt::gray);
foreach (QPointF p, datas) {
painter.drawEllipse(p, 3, 3);
foreach (QPointF point, datas) {
painter.drawEllipse(point, 3, 3);
}
}
}

View File

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

View File

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

View File

@ -1,4 +1,5 @@
#include "smoothcurve.h"
#include "qdebug.h"
QPainterPath SmoothCurve::createSmoothCurve(const QVector<QPointF> &points)
{
@ -20,6 +21,29 @@ QPainterPath SmoothCurve::createSmoothCurve(const QVector<QPointF> &points)
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)
{
result = new double[n];
@ -41,8 +65,8 @@ void SmoothCurve::calculateFirstControlPoints(double *&result, const double *rhs
}
void SmoothCurve::calculateControlPoints(const QVector<QPointF> &datas,
QVector<QPointF> *firstControlPoints,
QVector<QPointF> *secondControlPoints)
QVector<QPointF> *firstControlPoints,
QVector<QPointF> *secondControlPoints)
{
int n = datas.size() - 1;
for (int i = 0; i < n; ++i) {

View File

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