2025-03-10 09:35:07 +00:00
|
|
|
|
#include <QHBoxLayout>
|
|
|
|
|
|
#include <QRandomGenerator>
|
2025-03-25 08:45:16 +00:00
|
|
|
|
#include <cmath>
|
|
|
|
|
|
#include <limits>
|
|
|
|
|
|
#include <qcustomplot.h>
|
2025-04-15 09:24:25 +00:00
|
|
|
|
#include <QMessageBox>
|
2025-03-10 09:35:07 +00:00
|
|
|
|
|
2025-05-09 09:28:39 +00:00
|
|
|
|
#include "analysisoperationrecorder.h"
|
2025-03-10 09:35:07 +00:00
|
|
|
|
#include "centralwidget.h"
|
2025-03-17 13:16:16 +00:00
|
|
|
|
#include "filemanager.h"
|
2025-04-03 09:24:29 +00:00
|
|
|
|
#include "pointcalculate.h"
|
2025-03-27 09:31:19 +00:00
|
|
|
|
#include "logger.h"
|
2025-04-15 08:03:00 +00:00
|
|
|
|
#include "xlsxhandler.h"
|
2025-05-09 09:28:39 +00:00
|
|
|
|
#include "itemmanager.h"
|
2025-03-10 09:35:07 +00:00
|
|
|
|
|
2025-05-12 09:29:59 +00:00
|
|
|
|
namespace AnaOpRecorder = AnalysisOperationRecorder;
|
2025-05-13 09:33:40 +00:00
|
|
|
|
using AnaOpRecorderOperation = AnalysisOperationRecorder::AnalysisOperation;
|
2025-06-06 09:17:31 +00:00
|
|
|
|
using namespace Global;
|
2025-05-12 09:29:59 +00:00
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
CentralWidget::CentralWidget(QWidget *parent)
|
2025-04-15 08:03:00 +00:00
|
|
|
|
: QWidget(parent)
|
2025-04-28 09:31:29 +00:00
|
|
|
|
,_customPlot(new LocalCustomPlot(this))
|
|
|
|
|
|
// ,_customPlot(new QCustomPlot(this))
|
2025-04-24 06:35:53 +00:00
|
|
|
|
,_analysisMode(AnalysisMode::Null)
|
2025-04-22 09:33:03 +00:00
|
|
|
|
,_currentCurve(nullptr)
|
2025-03-10 09:35:07 +00:00
|
|
|
|
{
|
2025-03-21 09:28:36 +00:00
|
|
|
|
setMouseTracking(true);
|
|
|
|
|
|
|
2025-03-10 09:35:07 +00:00
|
|
|
|
setStyleSheet("background-color: lightgray;");
|
|
|
|
|
|
resize(888, 666);
|
|
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
QHBoxLayout *layout = new QHBoxLayout();
|
2025-03-21 09:28:36 +00:00
|
|
|
|
layout->setMargin(0);
|
2025-03-10 09:35:07 +00:00
|
|
|
|
layout->addWidget(_customPlot);
|
|
|
|
|
|
this->setLayout(layout);
|
|
|
|
|
|
|
2025-03-20 09:28:22 +00:00
|
|
|
|
// 创建两条竖线
|
|
|
|
|
|
_line1 = new QCPItemStraightLine(_customPlot);
|
|
|
|
|
|
_line1->point1->setCoords(20, _customPlot->yAxis->range().lower);
|
|
|
|
|
|
_line1->point2->setCoords(20, _customPlot->yAxis->range().upper);
|
|
|
|
|
|
_line1->setPen(QPen(Qt::red));
|
|
|
|
|
|
_line1->setSelectable(true);
|
|
|
|
|
|
|
|
|
|
|
|
_line2 = new QCPItemStraightLine(_customPlot);
|
|
|
|
|
|
_line2->point1->setCoords(40, _customPlot->yAxis->range().lower);
|
|
|
|
|
|
_line2->point2->setCoords(40, _customPlot->yAxis->range().upper);
|
|
|
|
|
|
_line2->setPen(QPen(Qt::red));
|
|
|
|
|
|
_line2->setSelectable(true);
|
|
|
|
|
|
|
|
|
|
|
|
// 安装事件过滤器
|
2025-04-09 09:30:32 +00:00
|
|
|
|
// _graph = _customPlot->addGraph(0);
|
2025-04-10 07:20:57 +00:00
|
|
|
|
// _eventHandler = new EventHandler(_customPlot, _line1, _line2, _graph, nullptr);
|
2025-04-09 09:30:32 +00:00
|
|
|
|
|
2025-04-10 07:20:57 +00:00
|
|
|
|
_eventHandler = new EventHandler(_customPlot, _line1, _line2, nullptr);
|
2025-04-09 09:30:32 +00:00
|
|
|
|
_eventHandler->setEnable(true);
|
|
|
|
|
|
|
2025-03-20 09:28:22 +00:00
|
|
|
|
_customPlot->installEventFilter(_eventHandler);
|
2025-04-23 09:25:38 +00:00
|
|
|
|
_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
|
2025-04-15 08:03:00 +00:00
|
|
|
|
// _customPlot->setInteractions( QCP::iRangeZoom | QCP::iSelectPlottables);
|
2025-04-23 09:25:38 +00:00
|
|
|
|
// _customPlot->setInteractions(QCP::iSelectPlottables);
|
2025-03-20 09:28:22 +00:00
|
|
|
|
|
2025-04-10 07:20:57 +00:00
|
|
|
|
connect(_eventHandler,&EventHandler::sigSendLineXCoord,
|
2025-03-21 09:28:36 +00:00
|
|
|
|
this,&CentralWidget::sigSendLineXCoord);
|
2025-05-16 09:01:40 +00:00
|
|
|
|
connect(_eventHandler,&EventHandler::sigDelCurve,
|
|
|
|
|
|
this,&CentralWidget::slotDelCurve);
|
2025-04-10 07:20:57 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
connect(_customPlot, &QCustomPlot::selectionChangedByUser,
|
|
|
|
|
|
this,&CentralWidget::slotSelectionChangedByUser);
|
|
|
|
|
|
|
2025-03-21 09:28:36 +00:00
|
|
|
|
setEventHandlerEnable(false);
|
|
|
|
|
|
//
|
2025-03-10 09:35:07 +00:00
|
|
|
|
#if 0
|
|
|
|
|
|
// init data
|
|
|
|
|
|
QVector<double> x(101), y(101);
|
|
|
|
|
|
for (int i = 0; i < 101; i++) {
|
|
|
|
|
|
x[i] = i / 50.0 - 1;//设置x的范围为-1~1
|
|
|
|
|
|
y[i] = x[i] * x[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->graph(0)->setData(x, y);
|
|
|
|
|
|
//设置坐标轴标签
|
|
|
|
|
|
_customPlot->xAxis->setLabel("x coordinates");
|
|
|
|
|
|
_customPlot->yAxis->setLabel("y coordinates");
|
|
|
|
|
|
//设置坐标轴范围,以便我们可以看到全部数据
|
|
|
|
|
|
_customPlot->xAxis->setRange(0, 1);
|
|
|
|
|
|
_customPlot->yAxis->setRange(0, 100);
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
#endif
|
2025-04-22 08:59:26 +00:00
|
|
|
|
|
|
|
|
|
|
// 设置坐标轴标签
|
2025-05-22 09:31:38 +00:00
|
|
|
|
_customPlot->xAxis->setLabel(AxisTemperature);
|
|
|
|
|
|
_customPlot->yAxis->setLabel(AxisDSC);
|
|
|
|
|
|
|
2025-04-22 08:59:26 +00:00
|
|
|
|
// 设置坐标轴范围,以便我们可以看到全部数据
|
2025-04-23 07:33:39 +00:00
|
|
|
|
_customPlot->xAxis->setRange(0,100);
|
|
|
|
|
|
_customPlot->yAxis->setRange(0,20);
|
|
|
|
|
|
|
2025-04-28 06:16:26 +00:00
|
|
|
|
// startTimer(300);
|
2025-03-10 09:35:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-19 03:19:52 +00:00
|
|
|
|
CentralWidget::~CentralWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-28 09:31:29 +00:00
|
|
|
|
void CentralWidget::switchAxisMode()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(Global::_mode != Global::Mode::Analysis){
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
_axisMode = AxisMode::DoubleY;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
_axisMode = AxisMode::SingleY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
clearData(ClearDataMode::JustUi);
|
2025-05-22 09:31:38 +00:00
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
uiLoadXlsxFileData();
|
2025-04-28 09:31:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-06 09:17:31 +00:00
|
|
|
|
bool CentralWidget::isCurrentCurve(QCPCurve *curve)
|
|
|
|
|
|
{
|
|
|
|
|
|
return _currentCurve == curve;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CentralWidget::deleteCurrentCurve()
|
|
|
|
|
|
{
|
|
|
|
|
|
slotDelCurve(_currentCurve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-13 07:55:18 +00:00
|
|
|
|
void CentralWidget::addCurveData(
|
2025-06-06 09:17:31 +00:00
|
|
|
|
const QVector<ExperimentData> &dataVtr,const QString objectName)
|
|
|
|
|
|
{
|
|
|
|
|
|
PointCalculate::setAnalysisData(dataVtr);
|
|
|
|
|
|
|
|
|
|
|
|
// Load data.
|
|
|
|
|
|
QVector<double> tVtr,xVtr, yVtr;
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
for (const Global::ExperimentData &ed : dataVtr)
|
|
|
|
|
|
{
|
|
|
|
|
|
tVtr.push_back(index++);
|
|
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
xVtr.push_back(ed.sampleTemp);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
xVtr.push_back(ed.runTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
yVtr.push_back(ed.dsc);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_currentCurve = new QCPCurve(_customPlot->xAxis, _customPlot->yAxis);
|
|
|
|
|
|
_currentCurve->setData(tVtr, xVtr, yVtr);
|
|
|
|
|
|
_currentCurve->setSelectable(QCP::stWhole); // 设置曲线可选
|
|
|
|
|
|
_currentCurve->setLineStyle(QCPCurve::lsLine); // 线性连接
|
|
|
|
|
|
|
|
|
|
|
|
_currentCurve->setObjectName(objectName);
|
|
|
|
|
|
|
|
|
|
|
|
// Set axis range.
|
|
|
|
|
|
QPair<float, float> minMaxXAxisPair;
|
|
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
// Axis x is temperature value.
|
|
|
|
|
|
minMaxXAxisPair = PointCalculate::getMinAndMaxOfSampleTemp();
|
|
|
|
|
|
}else{
|
|
|
|
|
|
// Axis x is time value.
|
|
|
|
|
|
minMaxXAxisPair = PointCalculate::getMinAndMaxOfRunTime();
|
|
|
|
|
|
}
|
|
|
|
|
|
QPair<float, float>newXAxisPair = PointCalculate::getMinAndMaxOfAxis(
|
|
|
|
|
|
minMaxXAxisPair.first,minMaxXAxisPair.second);
|
|
|
|
|
|
_customPlot->xAxis->setRange(newXAxisPair.first, newXAxisPair.second);
|
|
|
|
|
|
|
|
|
|
|
|
QPair<float, float> minMaxYAxisPair = PointCalculate::getMinAndMaxOfDSC();
|
|
|
|
|
|
QPair<float, float>newYAxisPair = PointCalculate::getMinAndMaxOfAxis(
|
|
|
|
|
|
minMaxYAxisPair.first,minMaxYAxisPair.second);
|
|
|
|
|
|
_customPlot->yAxis->setRange(newYAxisPair.first ,
|
|
|
|
|
|
newYAxisPair.second);
|
|
|
|
|
|
|
|
|
|
|
|
// Add analysis operation data.
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
if(cfd.analysisOperationVtr.size() > 0){
|
|
|
|
|
|
for(AnaOpRecorder::AnalysisOperation& ao
|
|
|
|
|
|
:cfd.analysisOperationVtr){
|
|
|
|
|
|
loadAnalysisData(ao.mode,ao.x1,ao.x2,cfd.fileName);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// Refresh ui.
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-14 09:30:52 +00:00
|
|
|
|
void CentralWidget::setAnalysisMode(const AnalysisMode mode)
|
2025-03-20 09:28:22 +00:00
|
|
|
|
{
|
2025-04-03 09:24:29 +00:00
|
|
|
|
_analysisMode = mode;
|
2025-03-20 09:28:22 +00:00
|
|
|
|
|
2025-06-12 09:27:45 +00:00
|
|
|
|
if(mode == AnalysisMode::Null){
|
|
|
|
|
|
_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
_customPlot->setInteractions(QCP::iSelectPlottables);
|
|
|
|
|
|
setEventHandlerEnable(true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
2025-03-21 09:28:36 +00:00
|
|
|
|
switch (mode)
|
|
|
|
|
|
{
|
2025-04-24 06:35:53 +00:00
|
|
|
|
case AnalysisMode::Null:
|
|
|
|
|
|
_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
|
|
|
|
|
|
break;
|
2025-03-21 09:28:36 +00:00
|
|
|
|
case AnalysisMode::NumericalLabel:
|
2025-03-24 09:30:42 +00:00
|
|
|
|
case AnalysisMode::StartPoint:
|
|
|
|
|
|
case AnalysisMode::StopPoint:
|
|
|
|
|
|
case AnalysisMode::PeakSynthesisAnalysis:
|
2025-04-03 09:24:29 +00:00
|
|
|
|
case AnalysisMode::GlassTransition:
|
2025-05-07 09:33:03 +00:00
|
|
|
|
case AnalysisMode::OnsetTemperaturePoint:
|
|
|
|
|
|
case AnalysisMode::EndsetTemperaturePoint:
|
2025-04-24 06:35:53 +00:00
|
|
|
|
_customPlot->setInteractions(QCP::iSelectPlottables);
|
2025-03-21 09:28:36 +00:00
|
|
|
|
setEventHandlerEnable(true);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-06-12 09:27:45 +00:00
|
|
|
|
#endif
|
2025-03-20 09:28:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
void CentralWidget::slotModeModify(const Global::Mode mode)
|
2025-03-10 09:35:07 +00:00
|
|
|
|
{
|
2025-04-22 08:59:26 +00:00
|
|
|
|
if (Global::Mode::Experiment == mode)
|
2025-03-12 09:29:52 +00:00
|
|
|
|
{
|
2025-04-09 09:30:32 +00:00
|
|
|
|
#if 0
|
|
|
|
|
|
if (_customPlot->graphCount() > 0 && _currentGraph)
|
2025-03-24 09:30:42 +00:00
|
|
|
|
{
|
|
|
|
|
|
// 清除第一个图表上的数据
|
2025-04-09 09:30:32 +00:00
|
|
|
|
_currentGraph->setData(QVector<double>(), QVector<double>());
|
2025-03-24 09:30:42 +00:00
|
|
|
|
}
|
2025-04-09 09:30:32 +00:00
|
|
|
|
#endif
|
2025-03-24 09:30:42 +00:00
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
// 创建画布,设置画布上的点数据
|
2025-03-24 09:30:42 +00:00
|
|
|
|
// _graph = _customPlot->addGraph();
|
2025-03-12 09:29:52 +00:00
|
|
|
|
|
|
|
|
|
|
// 设置坐标轴标签
|
|
|
|
|
|
_customPlot->xAxis->setLabel("Temp/℃");
|
|
|
|
|
|
_customPlot->yAxis->setLabel("DSC/mW");
|
|
|
|
|
|
// 设置坐标轴范围,以便我们可以看到全部数据
|
|
|
|
|
|
_customPlot->xAxis->setRange(0, 400);
|
|
|
|
|
|
_customPlot->yAxis->setRange(-20, 20);
|
|
|
|
|
|
}
|
2025-03-13 09:27:31 +00:00
|
|
|
|
else if (Global::Mode::Analysis == mode)
|
2025-03-12 09:29:52 +00:00
|
|
|
|
{
|
2025-03-21 09:28:36 +00:00
|
|
|
|
qDebug() << "file close...";
|
2025-03-12 09:29:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-19 07:19:45 +00:00
|
|
|
|
void CentralWidget::slotRecvCommonData(const CommonData &cd)
|
2025-03-12 09:29:52 +00:00
|
|
|
|
{
|
2025-04-22 08:59:26 +00:00
|
|
|
|
static double index = 0.0;
|
|
|
|
|
|
|
2025-04-14 09:11:01 +00:00
|
|
|
|
if(!_currentCurve){
|
2025-04-23 07:33:39 +00:00
|
|
|
|
logde<<"_currentCurve is nullptr";
|
2025-04-14 09:11:01 +00:00
|
|
|
|
_currentCurve = new QCPCurve(_customPlot->xAxis, _customPlot->yAxis);
|
2025-06-13 07:55:18 +00:00
|
|
|
|
_currentCurve->setObjectName(Global::ObjectNameExperiemnt);
|
2025-04-15 08:03:00 +00:00
|
|
|
|
}
|
2025-04-22 09:33:03 +00:00
|
|
|
|
|
2025-05-16 09:01:40 +00:00
|
|
|
|
// logde<<"temp:"<<cd.sample_temp<<",dsc:"<<cd.dsc;
|
2025-04-23 07:33:39 +00:00
|
|
|
|
_currentCurve->addData(index++,cd.sample_temp, cd.dsc);
|
2025-04-22 08:59:26 +00:00
|
|
|
|
|
2025-05-26 06:32:01 +00:00
|
|
|
|
// _customPlot->rescaleAxes();
|
2025-04-23 07:33:39 +00:00
|
|
|
|
_customPlot->replot();
|
2025-04-14 09:11:01 +00:00
|
|
|
|
|
2025-04-15 08:03:00 +00:00
|
|
|
|
// Record data.
|
2025-04-23 07:33:39 +00:00
|
|
|
|
if(!Global::_currentCurveExperimentDataPtr){
|
2025-04-25 09:20:33 +00:00
|
|
|
|
loger<<"_currentCurveExperimentDataPtr is nullptr.";
|
2025-04-23 07:33:39 +00:00
|
|
|
|
exit(0);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
Global::ExperimentData ed;
|
|
|
|
|
|
ed.dsc = cd .dsc;
|
|
|
|
|
|
ed.sampleTemp = cd.sample_temp;
|
|
|
|
|
|
ed.runTime = cd.add_run_time;
|
|
|
|
|
|
ed.constantTempTime = cd.add_constan_temp_time;
|
|
|
|
|
|
|
|
|
|
|
|
Global::_currentCurveExperimentDataPtr->dataVtr.push_back(ed);
|
|
|
|
|
|
Global::_currentCurveExperimentDataPtr->curve = _currentCurve;
|
|
|
|
|
|
}
|
2025-05-16 09:01:40 +00:00
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
logde<<"_curveExperimentDataVtr size:"
|
|
|
|
|
|
<<Global::_curveExperimentDataVtr.size();
|
|
|
|
|
|
|
|
|
|
|
|
logde<<"_currentCurveExperimentDataPtr dataVtr size:"
|
|
|
|
|
|
<<Global::_currentCurveExperimentDataPtr->dataVtr.size();
|
|
|
|
|
|
#endif
|
2025-05-26 06:32:01 +00:00
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-17 09:31:46 +00:00
|
|
|
|
void CentralWidget::slotRecvAnalysisFileName(const QString &filePath)
|
2025-03-19 07:19:45 +00:00
|
|
|
|
{
|
2025-04-29 09:29:14 +00:00
|
|
|
|
if(_analysisFilePathVtr.contains(filePath)){
|
|
|
|
|
|
return;
|
2025-05-16 09:01:40 +00:00
|
|
|
|
}else{
|
|
|
|
|
|
_analysisFilePathVtr.push_back(filePath);
|
2025-04-29 09:29:14 +00:00
|
|
|
|
}
|
2025-05-16 09:01:40 +00:00
|
|
|
|
|
2025-05-13 09:33:40 +00:00
|
|
|
|
// Read xlsx file.
|
2025-04-15 08:03:00 +00:00
|
|
|
|
Global::CurveFileData cfd;
|
2025-04-17 09:31:46 +00:00
|
|
|
|
if(XlsxHandler::readFile(filePath,cfd) != 0){
|
|
|
|
|
|
QMessageBox::warning((QWidget*)this->parent(), "warnning", "File parse error.");
|
|
|
|
|
|
return;
|
2025-04-15 09:24:25 +00:00
|
|
|
|
}
|
2025-05-22 09:31:38 +00:00
|
|
|
|
// Add data to global parameter.
|
|
|
|
|
|
Global::_curveFileDataVtr.push_back(cfd);
|
2025-04-11 05:51:47 +00:00
|
|
|
|
|
2025-05-22 09:31:38 +00:00
|
|
|
|
//
|
|
|
|
|
|
uiLoadXlsxFileData();
|
2025-03-19 07:19:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-21 09:28:36 +00:00
|
|
|
|
void CentralWidget::slotAnalysisSettingApply()
|
|
|
|
|
|
{
|
2025-05-21 08:36:47 +00:00
|
|
|
|
//Set the analysis data corresponding current curve.
|
|
|
|
|
|
if(!_currentCurve){
|
|
|
|
|
|
logde<<"failed. current curve is nullptr.";
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-06 09:17:31 +00:00
|
|
|
|
// Set curve data to PointCalculate.
|
2025-05-22 09:31:38 +00:00
|
|
|
|
if(Global::_curveFileDataVtr.empty()){
|
|
|
|
|
|
// Load experiment data.
|
2025-05-29 09:19:11 +00:00
|
|
|
|
logde<<"experiment vtr size:"<<Global::_curveExperimentDataVtr.size();
|
2025-05-22 09:31:38 +00:00
|
|
|
|
for(Global::CurveExperimentData& ced:Global::_curveExperimentDataVtr){
|
|
|
|
|
|
if(ced.curve == _currentCurve){
|
2025-05-29 09:19:11 +00:00
|
|
|
|
logde<<"load experiment data.";
|
2025-05-22 09:31:38 +00:00
|
|
|
|
PointCalculate::setAnalysisData(ced.dataVtr);
|
2025-06-06 09:17:31 +00:00
|
|
|
|
break;
|
2025-05-22 09:31:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}else{
|
|
|
|
|
|
// Load xlsx file data.
|
|
|
|
|
|
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
|
|
|
|
|
|
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
|
|
|
|
|
|
if(pti.curve == _currentCurve){
|
|
|
|
|
|
PointCalculate::setAnalysisData(pti.dataVtr);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-21 08:36:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-06-06 09:17:31 +00:00
|
|
|
|
#if 0
|
|
|
|
|
|
// Load smoothness data.
|
|
|
|
|
|
for(Global::CurveExperimentData& ced:Global::_curveSmoothnessDataVtr){
|
|
|
|
|
|
if(ced.curve == _currentCurve){
|
|
|
|
|
|
logde<<"load smoothness data.";
|
|
|
|
|
|
PointCalculate::setAnalysisData(ced.dataVtr);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2025-05-21 08:36:47 +00:00
|
|
|
|
//
|
2025-05-09 09:28:39 +00:00
|
|
|
|
double x1 = _line1->point1->coords().x();
|
|
|
|
|
|
double x2 = _line2->point1->coords().x();
|
|
|
|
|
|
|
|
|
|
|
|
if(_x1Record == x1 && _x2Record == x2){
|
|
|
|
|
|
return;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
_x1Record = x1;
|
|
|
|
|
|
_x2Record = x2;
|
|
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
//
|
2025-05-20 09:30:02 +00:00
|
|
|
|
loadAnalysisData(_analysisMode,x1,x2,_currentCurve->objectName());
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
2025-05-19 05:58:34 +00:00
|
|
|
|
if(Global::_mode == Global::Mode::Analysis){
|
|
|
|
|
|
AnalysisOperation ao;
|
|
|
|
|
|
ao.mode = _analysisMode;
|
2025-05-12 09:29:59 +00:00
|
|
|
|
ao.x1 = x1;
|
|
|
|
|
|
ao.x2 = x2;
|
|
|
|
|
|
|
2025-05-19 05:58:34 +00:00
|
|
|
|
AnaOpRecorder::_analysisOperationVtr.push_back(ao);
|
2025-05-07 09:33:03 +00:00
|
|
|
|
}
|
2025-03-21 09:28:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CentralWidget::slotAnalysisSettingConfirm()
|
|
|
|
|
|
{
|
2025-05-09 09:28:39 +00:00
|
|
|
|
ItemManager::confirm();
|
|
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
slotAnalysisSettingApply();
|
2025-04-24 06:35:53 +00:00
|
|
|
|
|
2025-05-14 09:30:52 +00:00
|
|
|
|
setAnalysisMode(AnalysisMode::Null);
|
2025-04-03 09:24:29 +00:00
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
_line1->setVisible(false);
|
2025-04-03 09:24:29 +00:00
|
|
|
|
_line2->setVisible(false);
|
2025-03-21 09:28:36 +00:00
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
emit sigRightDockWidgetHide();
|
2025-03-21 09:28:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-24 09:30:42 +00:00
|
|
|
|
void CentralWidget::slotAnalysisSettingUndo()
|
|
|
|
|
|
{
|
2025-04-01 09:25:12 +00:00
|
|
|
|
clearData(ClearDataMode::Undo);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
|
|
|
|
|
_x1Record = 0.0;
|
|
|
|
|
|
_x2Record = 0.0;
|
2025-03-24 09:30:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CentralWidget::slotAnalysisSettingCancel()
|
|
|
|
|
|
{
|
2025-04-01 09:25:12 +00:00
|
|
|
|
clearData(ClearDataMode::Undo);
|
2025-04-24 06:35:53 +00:00
|
|
|
|
|
2025-05-14 09:30:52 +00:00
|
|
|
|
setAnalysisMode(AnalysisMode::Null);
|
2025-04-03 09:24:29 +00:00
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
_line1->setVisible(false);
|
2025-04-03 09:24:29 +00:00
|
|
|
|
_line2->setVisible(false);
|
2025-03-24 09:30:42 +00:00
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
emit sigRightDockWidgetHide();
|
2025-03-24 09:30:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CentralWidget::slotAnalysisSettingLineXPoint(const int index, const double)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-27 07:27:07 +00:00
|
|
|
|
void CentralWidget::slotDrawCustomText(const QString str)
|
|
|
|
|
|
{
|
|
|
|
|
|
QCPItemText* customLegendItem = new QCPItemText(_customPlot);
|
|
|
|
|
|
customLegendItem->position->setTypeX(QCPItemPosition::ptAbsolute);
|
|
|
|
|
|
customLegendItem->position->setTypeY(QCPItemPosition::ptAbsolute);
|
|
|
|
|
|
customLegendItem->position->setCoords(150, 50); // 稍微向下移动
|
|
|
|
|
|
customLegendItem->setText(str);
|
|
|
|
|
|
|
|
|
|
|
|
QFont font("Arial", 10);
|
|
|
|
|
|
customLegendItem->setFont(font);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置边框和背景
|
|
|
|
|
|
customLegendItem->setPen(QPen(Qt::black));
|
|
|
|
|
|
customLegendItem->setBrush(QBrush(Qt::white));
|
|
|
|
|
|
|
|
|
|
|
|
// 禁止点选
|
|
|
|
|
|
customLegendItem->setSelectable(false);
|
|
|
|
|
|
customLegendItem->setObjectName("fixed");
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-16 09:01:40 +00:00
|
|
|
|
void CentralWidget::slotDelCurve(QCPCurve *curve)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(!curve){
|
2025-06-06 09:17:31 +00:00
|
|
|
|
logde<<"current curve is nullptr.";
|
2025-05-16 09:01:40 +00:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
logde<<"deltel curve object name:"<<curve->objectName().toStdString();
|
2025-05-16 09:01:40 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
deleteCurve(curve->objectName());
|
2025-05-16 09:01:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-29 09:29:14 +00:00
|
|
|
|
void CentralWidget::slotGetAxisInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
QVector<AxisInfo> vtr;
|
|
|
|
|
|
|
|
|
|
|
|
auto func = [&](QCPAxis* axis){
|
|
|
|
|
|
AxisInfo ai;
|
|
|
|
|
|
ai.visiable = axis->visible();
|
|
|
|
|
|
ai.lower = axis->range().lower;
|
|
|
|
|
|
ai.upper = axis->range().upper;
|
|
|
|
|
|
|
|
|
|
|
|
vtr.push_back(ai);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
func(_customPlot->xAxis);
|
|
|
|
|
|
func(_customPlot->yAxis);
|
|
|
|
|
|
func(_customPlot->yAxis2);
|
|
|
|
|
|
|
|
|
|
|
|
emit sigGetAxisInfoWithData(vtr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CentralWidget::slotSetAxisSettings(const QVector<double>vtr)
|
|
|
|
|
|
{
|
|
|
|
|
|
_customPlot->xAxis->setRange(vtr.at(0),vtr.at(1));
|
|
|
|
|
|
_customPlot->yAxis->setRange(vtr.at(2),vtr.at(3));
|
|
|
|
|
|
|
|
|
|
|
|
if(_customPlot->yAxis2->visible()){
|
|
|
|
|
|
_customPlot->yAxis2->setRange(vtr.at(4),vtr.at(5));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
void CentralWidget::timerEvent(QTimerEvent *event)
|
|
|
|
|
|
{
|
2025-04-23 07:33:39 +00:00
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
2025-03-12 09:29:52 +00:00
|
|
|
|
// key的单位是秒
|
2025-03-10 09:35:07 +00:00
|
|
|
|
double key = QDateTime::currentDateTime().toMSecsSinceEpoch() / 1000.0;
|
2025-03-12 09:29:52 +00:00
|
|
|
|
// 添加数据
|
|
|
|
|
|
// 使用随机数产生一条曲线
|
|
|
|
|
|
// double value0 = realDataI();
|
2025-03-10 09:35:07 +00:00
|
|
|
|
double value0 = QRandomGenerator::global()->bounded(10.123);
|
2025-03-12 09:29:52 +00:00
|
|
|
|
_customPlot->graph(0)->addData(key, value0); // 添加数据到曲线
|
2025-03-10 09:35:07 +00:00
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
// 删除8秒之前的数据。这里的8要和下面设置横坐标宽度的8配合起来
|
|
|
|
|
|
// 才能起到想要的效果,可以调整这两个值,观察显示的效果。
|
2025-03-10 09:35:07 +00:00
|
|
|
|
_customPlot->graph(0)->data()->remove(key - 80);
|
2025-03-12 09:29:52 +00:00
|
|
|
|
// 自动设定graph(1)曲线y轴的范围,如果不设定,有可能看不到图像
|
|
|
|
|
|
// 也可以用ui->customPlot->yAxis->setRange(up,low)手动设定y轴范围
|
2025-03-10 09:35:07 +00:00
|
|
|
|
_customPlot->graph(0)->rescaleValueAxis(true);
|
|
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
// 这里的8,是指横坐标时间宽度为8秒,如果想要横坐标显示更多的时间
|
|
|
|
|
|
// 就把8调整为比较大到值,比如要显示60秒,那就改成60。
|
|
|
|
|
|
// 这时removeDataBefore(key-8)中的8也要改成60,否则曲线显示不完整。
|
2025-03-10 09:35:07 +00:00
|
|
|
|
|
2025-03-12 09:29:52 +00:00
|
|
|
|
_customPlot->yAxis->setRange(0, 20); // 设定x轴的范围
|
|
|
|
|
|
_customPlot->xAxis->setRange(key + 0.25, 80, Qt::AlignRight); // 设定x轴的范围
|
2025-03-10 09:35:07 +00:00
|
|
|
|
_customPlot->replot();
|
2025-04-23 07:33:39 +00:00
|
|
|
|
#endif
|
2025-03-10 09:35:07 +00:00
|
|
|
|
}
|
2025-03-12 09:29:52 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
void CentralWidget::slotSelectionChangedByUser()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 获取所有被选中的绘图对象
|
|
|
|
|
|
QList<QCPAbstractPlottable*> selectedPlottables = _customPlot->selectedPlottables();
|
|
|
|
|
|
|
|
|
|
|
|
// 遍历选中的绘图对象
|
|
|
|
|
|
for (QCPAbstractPlottable* plottable : selectedPlottables) {
|
|
|
|
|
|
// 检查是否是 QCPCurve
|
|
|
|
|
|
if (QCPCurve* curve = dynamic_cast<QCPCurve*>(plottable)) {
|
2025-05-29 09:19:11 +00:00
|
|
|
|
logde << "Selected Curve:" << curve->objectName().toStdString();
|
2025-05-20 09:30:02 +00:00
|
|
|
|
_currentCurve = curve; // 更新当前选中的曲线
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-29 09:19:11 +00:00
|
|
|
|
#if 0
|
2025-05-20 09:30:02 +00:00
|
|
|
|
// 如果没有选中的曲线
|
|
|
|
|
|
if (selectedPlottables.isEmpty()) {
|
2025-05-29 09:19:11 +00:00
|
|
|
|
logde<< "No curve selected";
|
2025-05-20 09:30:02 +00:00
|
|
|
|
_currentCurve = nullptr; // 清空当前选中的曲线
|
|
|
|
|
|
}
|
2025-05-29 09:19:11 +00:00
|
|
|
|
#endif
|
2025-05-20 09:30:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-22 09:31:38 +00:00
|
|
|
|
void CentralWidget::uiLoadXlsxFileData()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Set axis.
|
|
|
|
|
|
_customPlot->yAxis->setVisible(true);
|
|
|
|
|
|
_customPlot->yAxis->setLabel(AxisDSC);
|
|
|
|
|
|
|
|
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
_customPlot->xAxis->setLabel(AxisTemperature);
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->yAxis2->setVisible(false);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
_customPlot->xAxis->setLabel(AxisTime);
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->yAxis2->setVisible(true);
|
|
|
|
|
|
_customPlot->yAxis2->setLabel(AxisTemperature);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
|
// Load xlsx file data.
|
|
|
|
|
|
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
|
|
|
|
|
|
for(int i = 0;i < cfd.phaseTotalVtr.size();i++){
|
|
|
|
|
|
Global::PhaseTotalInfo& pti = cfd.phaseTotalVtr[i];
|
|
|
|
|
|
|
|
|
|
|
|
PointCalculate::setAnalysisData(pti.dataVtr);
|
|
|
|
|
|
|
|
|
|
|
|
// Load data.
|
|
|
|
|
|
QVector<Global::ExperimentData> dataVtr;
|
|
|
|
|
|
QVector<double> tVtr,xVtr, yVtr;
|
|
|
|
|
|
int index = 0;
|
|
|
|
|
|
for (Global::ExperimentData &ed : pti.dataVtr)
|
|
|
|
|
|
{
|
|
|
|
|
|
tVtr.push_back(index++);
|
|
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
xVtr.push_back(ed.sampleTemp);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
xVtr.push_back(ed.runTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
yVtr.push_back(ed.dsc);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_currentCurve = new QCPCurve(_customPlot->xAxis, _customPlot->yAxis);
|
|
|
|
|
|
_currentCurve->setData(tVtr, xVtr, yVtr);
|
|
|
|
|
|
_currentCurve->setSelectable(QCP::stWhole); // 设置曲线可选
|
|
|
|
|
|
_currentCurve->setLineStyle(QCPCurve::lsLine); // 线性连接
|
|
|
|
|
|
|
|
|
|
|
|
_currentCurve->setObjectName(cfd.fileName);
|
|
|
|
|
|
|
|
|
|
|
|
// Set axis range.
|
|
|
|
|
|
QPair<float, float> minMaxXAxisPair;
|
|
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
// Axis x is temperature value.
|
|
|
|
|
|
minMaxXAxisPair = PointCalculate::getMinAndMaxOfSampleTemp();
|
|
|
|
|
|
}else{
|
|
|
|
|
|
// Axis x is time value.
|
|
|
|
|
|
minMaxXAxisPair = PointCalculate::getMinAndMaxOfRunTime();
|
|
|
|
|
|
}
|
|
|
|
|
|
QPair<float, float>newXAxisPair = PointCalculate::getMinAndMaxOfAxis(
|
|
|
|
|
|
minMaxXAxisPair.first,minMaxXAxisPair.second);
|
|
|
|
|
|
_customPlot->xAxis->setRange(newXAxisPair.first, newXAxisPair.second);
|
|
|
|
|
|
|
|
|
|
|
|
QPair<float, float> minMaxYAxisPair = PointCalculate::getMinAndMaxOfDSC();
|
|
|
|
|
|
QPair<float, float>newYAxisPair = PointCalculate::getMinAndMaxOfAxis(
|
|
|
|
|
|
minMaxYAxisPair.first,minMaxYAxisPair.second);
|
|
|
|
|
|
_customPlot->yAxis->setRange(newYAxisPair.first ,
|
|
|
|
|
|
newYAxisPair.second);
|
|
|
|
|
|
//
|
|
|
|
|
|
pti.curve = _currentCurve;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Add analysis operation data.
|
|
|
|
|
|
if(cfd.analysisOperationVtr.size() > 0){
|
|
|
|
|
|
for(AnaOpRecorder::AnalysisOperation& ao
|
|
|
|
|
|
:cfd.analysisOperationVtr){
|
|
|
|
|
|
loadAnalysisData(ao.mode,ao.x1,ao.x2,cfd.fileName);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Refresh ui.
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-16 09:01:40 +00:00
|
|
|
|
#if 0
|
2025-03-21 09:28:36 +00:00
|
|
|
|
void CentralWidget::contextMenuEvent(QContextMenuEvent *event)
|
2025-03-20 09:28:22 +00:00
|
|
|
|
{
|
2025-03-21 09:28:36 +00:00
|
|
|
|
qDebug()<<"left menu...";
|
|
|
|
|
|
QPoint point = event->globalPos();
|
|
|
|
|
|
emit sigContextMenuShow(point);
|
|
|
|
|
|
}
|
2025-05-16 09:01:40 +00:00
|
|
|
|
#endif
|
2025-03-20 09:28:22 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
void CentralWidget::glassTransitionHandle(const double x1,const double x2,const QString objectName)
|
2025-04-21 09:31:38 +00:00
|
|
|
|
{
|
2025-05-09 09:28:39 +00:00
|
|
|
|
QPointF point1 = PointCalculate::getClosestPointByX(x1);
|
|
|
|
|
|
QPointF point2 = PointCalculate::getClosestPointByX(x2);
|
2025-04-21 09:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
logde<<"point1:"<<point1.x()<<","<<point1.y();
|
|
|
|
|
|
logde<<"point2:"<<point2.x()<<","<<point2.y();
|
|
|
|
|
|
|
|
|
|
|
|
QVector<QPointF> point1Vtr = PointCalculate::getNearbyPointGroupByX(point1.x());
|
|
|
|
|
|
QVector<QPointF> point2Vtr = PointCalculate::getNearbyPointGroupByX(point2.x());
|
|
|
|
|
|
|
|
|
|
|
|
QVector<double> xVtr,yVtr;
|
|
|
|
|
|
for(QPointF &p:point1Vtr){
|
|
|
|
|
|
xVtr.append(p.x());
|
|
|
|
|
|
yVtr.append(p.y());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PointCalculate::Line line1 = calculateLinearRegression(xVtr,yVtr);
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
|
///line1
|
|
|
|
|
|
// QVector<double> xVtr,yVtr;
|
|
|
|
|
|
xVtr.clear();
|
|
|
|
|
|
yVtr.clear();
|
|
|
|
|
|
|
|
|
|
|
|
xVtr.push_back(point1.x());
|
|
|
|
|
|
yVtr.push_back(point1.y());
|
|
|
|
|
|
|
|
|
|
|
|
xVtr.push_back(point1.x() + 10);
|
|
|
|
|
|
double y1 = line1.slope * (point1.x() + 10) + line1.intercept;
|
|
|
|
|
|
yVtr.push_back(y1);
|
|
|
|
|
|
|
|
|
|
|
|
QCPGraph *lineGraph1 = _customPlot->addGraph();
|
|
|
|
|
|
lineGraph1->setData(xVtr, yVtr);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
ItemManager::addTemporaryQCPGraph(lineGraph1,objectName);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-21 09:31:38 +00:00
|
|
|
|
QPen pen;
|
|
|
|
|
|
pen.setColor(Qt::darkGreen);
|
|
|
|
|
|
lineGraph1->setPen(pen);
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
xVtr.clear();
|
|
|
|
|
|
yVtr.clear();
|
|
|
|
|
|
for(QPointF &p:point2Vtr){
|
|
|
|
|
|
xVtr.append(p.x());
|
|
|
|
|
|
yVtr.append(p.y());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PointCalculate::Line line2 = calculateLinearRegression(xVtr,yVtr);
|
|
|
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
|
///line2
|
|
|
|
|
|
QVector<double> xVtr2,yVtr2;
|
|
|
|
|
|
xVtr2.push_back(point2.x());
|
|
|
|
|
|
yVtr2.push_back(point2.y());
|
|
|
|
|
|
|
|
|
|
|
|
xVtr2.push_back(point2.x() - 10);
|
|
|
|
|
|
double y2 = line2.slope * (point2.x() - 10) + line2.intercept;
|
|
|
|
|
|
yVtr2.push_back(y2);
|
|
|
|
|
|
|
|
|
|
|
|
QCPGraph *lineGraph2 = _customPlot->addGraph();
|
|
|
|
|
|
lineGraph2->setData(xVtr2, yVtr2);
|
|
|
|
|
|
lineGraph2->setPen(pen);
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
ItemManager::addTemporaryQCPGraph(lineGraph2,objectName);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-21 09:31:38 +00:00
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// inflection point.
|
2025-04-22 03:35:39 +00:00
|
|
|
|
QVector<QPointF> originalPointVtr = PointCalculate::getPointVtrInXRange(point1.x(),point2.x());
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-22 03:35:39 +00:00
|
|
|
|
QVector<QPointF> pointVtr = originalPointVtr;
|
2025-04-21 09:31:38 +00:00
|
|
|
|
|
|
|
|
|
|
xVtr.clear();
|
|
|
|
|
|
yVtr.clear();
|
|
|
|
|
|
for(QPointF& p:pointVtr){
|
|
|
|
|
|
xVtr.append(p.x());
|
|
|
|
|
|
yVtr.append(p.y());
|
|
|
|
|
|
}
|
|
|
|
|
|
QMap<double, PointCalculate::Line> tangentLines =
|
|
|
|
|
|
PointCalculate::calculateTangentLine(xVtr,yVtr);
|
|
|
|
|
|
|
|
|
|
|
|
double targetX = 0.0;
|
|
|
|
|
|
PointCalculate::Line targetLine;
|
|
|
|
|
|
double maxSlopeAbs = 0.0; // 初始化最大斜率绝对值为0
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-22 03:35:39 +00:00
|
|
|
|
#if 0
|
2025-04-21 09:31:38 +00:00
|
|
|
|
for (auto it = tangentLines.begin(); it != tangentLines.end(); ++it) {
|
|
|
|
|
|
if (std::fabs(it.value().slope) > maxSlopeAbs) {
|
|
|
|
|
|
maxSlopeAbs = std::fabs(it.value().slope); // 更新最大斜率绝对值
|
|
|
|
|
|
|
|
|
|
|
|
targetX = it.key();
|
|
|
|
|
|
targetLine = it.value();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-22 03:35:39 +00:00
|
|
|
|
#endif
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-22 03:35:39 +00:00
|
|
|
|
// new method
|
|
|
|
|
|
for (auto it = tangentLines.begin(); it != tangentLines.end(); ++it) {
|
|
|
|
|
|
if (std::fabs(it.value().slope) > maxSlopeAbs) {
|
|
|
|
|
|
maxSlopeAbs = std::fabs(it.value().slope); // 更新最大斜率绝对值
|
|
|
|
|
|
|
|
|
|
|
|
targetX = it.key();
|
|
|
|
|
|
targetLine = it.value();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-04-21 09:31:38 +00:00
|
|
|
|
|
2025-04-22 03:35:39 +00:00
|
|
|
|
int index = 0;
|
|
|
|
|
|
QPointF prePoint,currentPoint,lastPoint;
|
|
|
|
|
|
for (int i = 0;i < pointVtr.size();i++) {
|
|
|
|
|
|
currentPoint = pointVtr[i];
|
|
|
|
|
|
if(currentPoint.x() == targetX){
|
|
|
|
|
|
index = i;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
prePoint = pointVtr[index - 1];
|
|
|
|
|
|
lastPoint = pointVtr[index + 1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
targetLine.slope = PointCalculate::calculateSlope(lastPoint.x(),lastPoint.y(),prePoint.x(),prePoint.y());
|
|
|
|
|
|
targetLine.intercept = currentPoint.y() - targetLine.slope * currentPoint.x();
|
|
|
|
|
|
//
|
2025-04-21 09:31:38 +00:00
|
|
|
|
#if 1
|
|
|
|
|
|
QPointF intersection1 = PointCalculate::getIntersection(targetLine,line1);
|
|
|
|
|
|
QPointF intersection2 = PointCalculate::getIntersection(targetLine,line2);
|
|
|
|
|
|
|
|
|
|
|
|
// graph 3
|
|
|
|
|
|
xVtr.clear();
|
|
|
|
|
|
yVtr.clear();
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
xVtr.push_back(point1.x());
|
|
|
|
|
|
yVtr.push_back(point1.y());
|
|
|
|
|
|
|
|
|
|
|
|
xVtr.push_back(point1.x());
|
|
|
|
|
|
yVtr.push_back(point1.y());
|
|
|
|
|
|
#endif
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-21 09:31:38 +00:00
|
|
|
|
#if 1
|
|
|
|
|
|
xVtr.push_back(intersection1.x());
|
|
|
|
|
|
yVtr.push_back(intersection1.y());
|
|
|
|
|
|
|
|
|
|
|
|
xVtr.push_back(intersection2.x());
|
|
|
|
|
|
yVtr.push_back(intersection2.y());
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
QCPGraph *lineGraph3 = _customPlot->addGraph();
|
|
|
|
|
|
lineGraph3->setData(xVtr, yVtr);
|
|
|
|
|
|
lineGraph3->setPen(pen);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
ItemManager::addTemporaryQCPGraph(lineGraph3,objectName);
|
2025-04-21 09:31:38 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
|
|
|
|
|
|
// point value
|
|
|
|
|
|
double averageY = (point1.y() + point2.y()) / 2;
|
|
|
|
|
|
|
|
|
|
|
|
QPointF averagePoint = PointCalculate::getClosestPointByY(point1.x(),point2.x(),averageY);
|
|
|
|
|
|
|
2025-04-22 03:35:39 +00:00
|
|
|
|
QString str = PointCalculate::textFormatGlassTranstion(intersection1.x(),
|
2025-04-21 09:31:38 +00:00
|
|
|
|
averagePoint.x(),
|
2025-04-22 03:35:39 +00:00
|
|
|
|
intersection2.x());
|
2025-06-06 09:17:31 +00:00
|
|
|
|
if(Global::_axisMode == Global::AxisMode::DoubleY){
|
2025-05-23 05:52:14 +00:00
|
|
|
|
Global::ExperimentData intersection1Ed =
|
|
|
|
|
|
PointCalculate::getClosestDataByTemperature(intersection1.x());
|
|
|
|
|
|
Global::ExperimentData averageEd =
|
|
|
|
|
|
PointCalculate::getClosestDataByTemperature(averagePoint.x());
|
|
|
|
|
|
Global::ExperimentData intersection2Ed =
|
|
|
|
|
|
PointCalculate::getClosestDataByTemperature(intersection2.x());
|
|
|
|
|
|
|
|
|
|
|
|
averagePoint = QPointF(averageEd.runTime,averageEd.dsc);
|
|
|
|
|
|
|
|
|
|
|
|
str = PointCalculate::textFormatGlassTranstionWithTime(
|
|
|
|
|
|
intersection1Ed.runTime,
|
|
|
|
|
|
averageEd.runTime,
|
|
|
|
|
|
intersection2Ed.runTime);
|
|
|
|
|
|
}
|
2025-04-21 09:31:38 +00:00
|
|
|
|
|
2025-04-22 03:35:39 +00:00
|
|
|
|
drawText(averagePoint,str);
|
2025-04-21 09:31:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
// 使用最小二乘法计算线性回归
|
|
|
|
|
|
PointCalculate::Line CentralWidget::calculateLinearRegression(const QVector<double>& x, const QVector<double>& y) {
|
|
|
|
|
|
PointCalculate::Line line;
|
|
|
|
|
|
double sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
|
|
|
|
|
|
size_t n = x.size();
|
|
|
|
|
|
|
|
|
|
|
|
// 计算所需的总和
|
|
|
|
|
|
for (size_t i = 0; i < n; ++i) {
|
|
|
|
|
|
sum_x += x[i];
|
|
|
|
|
|
sum_y += y[i];
|
|
|
|
|
|
sum_xy += x[i] * y[i];
|
|
|
|
|
|
sum_xx += x[i] * x[i];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算斜率和截距
|
|
|
|
|
|
double x_mean = sum_x / n;
|
|
|
|
|
|
double y_mean = sum_y / n;
|
|
|
|
|
|
double numerator = n * sum_xy - sum_x * sum_y;
|
|
|
|
|
|
double denominator = n * sum_xx - sum_x * sum_x;
|
|
|
|
|
|
line.slope = numerator / denominator;
|
|
|
|
|
|
line.intercept = y_mean - line.slope * x_mean;
|
|
|
|
|
|
|
|
|
|
|
|
return line;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-26 06:32:01 +00:00
|
|
|
|
QPointF CentralWidget::onsetTemperaturePointHandle(const double x1,const double x2)
|
2025-05-09 09:28:39 +00:00
|
|
|
|
{
|
2025-05-26 06:32:01 +00:00
|
|
|
|
Global::ExperimentData ed = PointCalculate::findOnSetDataByTemperature(x1,x2);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-06-06 09:17:31 +00:00
|
|
|
|
if(Global::_axisMode == Global::AxisMode::SingleY){
|
|
|
|
|
|
return QPointF(ed.sampleTemp,ed.dsc);
|
2025-05-26 06:32:01 +00:00
|
|
|
|
}else{
|
2025-06-06 09:17:31 +00:00
|
|
|
|
return QPointF(ed.runTime,ed.dsc);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
}
|
2025-05-26 06:32:01 +00:00
|
|
|
|
}
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-05-26 06:32:01 +00:00
|
|
|
|
QPointF CentralWidget::endSetTemperaturePointHandle(const double x1, const double x2)
|
|
|
|
|
|
{
|
|
|
|
|
|
Global::ExperimentData ed = PointCalculate::findEndSetDataByTemperature(x1,x2);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-06-06 09:17:31 +00:00
|
|
|
|
if(Global::_axisMode == Global::AxisMode::SingleY){
|
|
|
|
|
|
return QPointF(ed.sampleTemp,ed.dsc);
|
2025-05-26 06:32:01 +00:00
|
|
|
|
}else{
|
2025-06-06 09:17:31 +00:00
|
|
|
|
return QPointF(ed.runTime,ed.dsc);
|
2025-05-26 06:32:01 +00:00
|
|
|
|
}
|
2025-05-09 09:28:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-21 09:31:38 +00:00
|
|
|
|
// 二次多项式拟合函数
|
|
|
|
|
|
void CentralWidget::quadraticFit(const QVector<QPointF>& points, double& a, double& b, double& c) {
|
|
|
|
|
|
int n = points.size();
|
|
|
|
|
|
if (n < 3) {
|
|
|
|
|
|
throw std::invalid_argument("At least three points are required for quadratic fit.");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double sumX = 0, sumY = 0, sumXX = 0, sumXY = 0, sumX2Y = 0;
|
|
|
|
|
|
for (const QPointF& p : points) {
|
|
|
|
|
|
sumX += p.x();
|
|
|
|
|
|
sumY += p.y();
|
|
|
|
|
|
sumXX += p.x() * p.x();
|
|
|
|
|
|
sumXY += p.x() * p.y();
|
|
|
|
|
|
sumX2Y += p.x() * p.x() * p.y();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double det = n * (sumXX * sumY - sumX * sumXY) - sumX * sumX * sumY + sumX * sumX2Y;
|
|
|
|
|
|
a = (sumXX * sumY - sumX * sumXY) / det;
|
|
|
|
|
|
b = (sumX2Y - n * sumXY) / det;
|
|
|
|
|
|
c = (sumY - a * sumX - b * sumX) / n;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算二次多项式拟合曲线的导数(切线斜率)
|
|
|
|
|
|
double CentralWidget::derivativeAt(const double a, const double b, const double x) {
|
|
|
|
|
|
return 2 * a * x + b;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-03-21 09:28:36 +00:00
|
|
|
|
void CentralWidget::setEventHandlerEnable(const bool flag)
|
|
|
|
|
|
{
|
2025-03-27 09:31:19 +00:00
|
|
|
|
logde<<"setEventHandlerEnable..."<<flag;
|
|
|
|
|
|
|
2025-04-03 09:24:29 +00:00
|
|
|
|
// line visiable func
|
|
|
|
|
|
auto lineVisiableFunc = [&](QCPItemStraightLine* line){
|
|
|
|
|
|
line->setSelected(flag);
|
|
|
|
|
|
line->setVisible(flag);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-03-27 09:31:19 +00:00
|
|
|
|
// todo. 当竖线隐藏时,需要设置不可选择模式。
|
2025-04-09 13:25:55 +00:00
|
|
|
|
// _eventHandler->setEnable(flag);
|
2025-03-25 08:45:16 +00:00
|
|
|
|
|
2025-04-03 09:24:29 +00:00
|
|
|
|
#if 1
|
|
|
|
|
|
// move line to suitable position.
|
2025-04-23 09:25:38 +00:00
|
|
|
|
double xMax = _customPlot->xAxis->range().upper;
|
|
|
|
|
|
double xMin = _customPlot->xAxis->range().lower;
|
2025-04-03 09:24:29 +00:00
|
|
|
|
|
2025-04-25 09:20:33 +00:00
|
|
|
|
// logde<<"xMax:"<<xMax;
|
2025-04-03 09:24:29 +00:00
|
|
|
|
|
2025-04-25 09:20:33 +00:00
|
|
|
|
// QVector<double> ticks = _customPlot->xAxis->tickVector();
|
|
|
|
|
|
// int numTicks = ticks.size();
|
|
|
|
|
|
// logde<<"ticks:"<<numTicks;
|
2025-04-23 09:25:38 +00:00
|
|
|
|
|
|
|
|
|
|
double range = xMax - xMin;
|
|
|
|
|
|
double xLeft = xMin + range / 3;
|
|
|
|
|
|
double xRight = xMin + range * 2 / 3;
|
2025-04-03 09:24:29 +00:00
|
|
|
|
|
2025-04-23 09:25:38 +00:00
|
|
|
|
_line1->point1->setCoords(xLeft,_line1->point1->coords().y());
|
|
|
|
|
|
_line1->point2->setCoords(xLeft,_line1->point2->coords().y());
|
|
|
|
|
|
|
|
|
|
|
|
_line2->point1->setCoords(xRight,_line2->point1->coords().y());
|
|
|
|
|
|
_line2->point2->setCoords(xRight,_line2->point2->coords().y());
|
2025-04-03 09:24:29 +00:00
|
|
|
|
#endif
|
2025-05-26 06:32:01 +00:00
|
|
|
|
|
2025-04-03 09:24:29 +00:00
|
|
|
|
lineVisiableFunc(_line1);
|
|
|
|
|
|
if(AnalysisMode::NumericalLabel != _analysisMode){
|
|
|
|
|
|
lineVisiableFunc(_line2);
|
2025-03-20 09:28:22 +00:00
|
|
|
|
}
|
2025-04-03 09:24:29 +00:00
|
|
|
|
//
|
2025-03-21 09:28:36 +00:00
|
|
|
|
_customPlot->replot();
|
2025-03-20 09:28:22 +00:00
|
|
|
|
}
|
2025-03-27 09:31:19 +00:00
|
|
|
|
|
2025-04-23 09:25:38 +00:00
|
|
|
|
QPointF CentralWidget::getTheCoordinatesOfTheTextBox(const QPointF point)
|
|
|
|
|
|
{
|
|
|
|
|
|
double xMax = _customPlot->xAxis->range().upper;
|
|
|
|
|
|
double xMin = _customPlot->xAxis->range().lower;
|
|
|
|
|
|
|
|
|
|
|
|
logde<<"xMax:"<<xMax;
|
|
|
|
|
|
|
|
|
|
|
|
QVector<double> ticks = _customPlot->xAxis->tickVector();
|
|
|
|
|
|
int numTicks = ticks.size();
|
2025-06-06 09:17:31 +00:00
|
|
|
|
// logde<<"ticks:"<<numTicks;
|
2025-04-23 09:25:38 +00:00
|
|
|
|
|
|
|
|
|
|
double distance = (xMax - xMin) / ticks.size();
|
|
|
|
|
|
|
|
|
|
|
|
return QPointF(point.x() + distance,point.y());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
void CentralWidget::drawText(const QPointF point, const QString text,const QString objectName)
|
2025-03-24 09:30:42 +00:00
|
|
|
|
{
|
2025-04-23 09:25:38 +00:00
|
|
|
|
QPointF textBoxPoint = getTheCoordinatesOfTheTextBox(point);
|
2025-04-24 06:35:53 +00:00
|
|
|
|
|
2025-03-26 09:30:02 +00:00
|
|
|
|
// 创建标注文字(QCPItemText)
|
|
|
|
|
|
QCPItemText *textLabel = new QCPItemText(_customPlot);
|
2025-04-25 09:20:33 +00:00
|
|
|
|
textLabel->setPositionAlignment(Qt::AlignCenter); // 对齐方式
|
2025-03-26 09:30:02 +00:00
|
|
|
|
textLabel->position->setType(QCPItemPosition::ptPlotCoords); // 使用数据坐标
|
2025-04-23 09:25:38 +00:00
|
|
|
|
textLabel->position->setCoords(textBoxPoint.x(),textBoxPoint.y()); // 设置文本位置在指定点上方
|
2025-03-26 09:30:02 +00:00
|
|
|
|
|
|
|
|
|
|
textLabel->setText(text); // 设置文本内容
|
2025-04-25 09:20:33 +00:00
|
|
|
|
QFont font(QFont("Arial", 10));
|
|
|
|
|
|
textLabel->setFont(font);
|
|
|
|
|
|
textLabel->setSelectedFont(font);
|
|
|
|
|
|
textLabel->setSelectable(true); // 设置为可选
|
2025-03-26 09:30:02 +00:00
|
|
|
|
|
2025-05-16 09:01:40 +00:00
|
|
|
|
// 设置文本项的位置类型为屏幕坐标比例
|
|
|
|
|
|
textLabel->position->setTypeX(QCPItemPosition::ptAxisRectRatio);
|
|
|
|
|
|
textLabel->position->setTypeY(QCPItemPosition::ptAxisRectRatio);
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
ItemManager::addTemporaryQCPItemText(textLabel,objectName);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-03-26 09:30:02 +00:00
|
|
|
|
// 创建指向点的线段(QCPItemLine)
|
|
|
|
|
|
QCPItemLine *arrow = new QCPItemLine(_customPlot);
|
|
|
|
|
|
arrow->start->setParentAnchor(textLabel->left); // 线段起点绑定到标注文字底部
|
|
|
|
|
|
arrow->end->setCoords(point.x(),point.y()); // 线段终点设置为指定的点
|
|
|
|
|
|
arrow->setHead(QCPLineEnding::esSpikeArrow); // 添加箭头
|
|
|
|
|
|
arrow->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
ItemManager::addTemporaryQCPItemLine(arrow,objectName);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-03-26 09:30:02 +00:00
|
|
|
|
// 重绘图表以显示文本标签和箭头
|
|
|
|
|
|
_customPlot->replot();
|
2025-03-25 08:45:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
void CentralWidget::fillGraph(const double x1, const double x2,const QString objectName)
|
2025-03-25 08:45:16 +00:00
|
|
|
|
{
|
2025-05-23 05:52:14 +00:00
|
|
|
|
#if 0
|
2025-04-03 09:24:29 +00:00
|
|
|
|
double y1 = PointCalculate::getClosestPointByX(x1).y();
|
|
|
|
|
|
double y2 = PointCalculate::getClosestPointByX(x2).y();
|
2025-03-25 08:45:16 +00:00
|
|
|
|
|
|
|
|
|
|
QVector<double> xVtr,yVtr;
|
|
|
|
|
|
xVtr.push_back(x1);
|
|
|
|
|
|
xVtr.push_back(x2);
|
|
|
|
|
|
|
|
|
|
|
|
yVtr.push_back(y1);
|
|
|
|
|
|
yVtr.push_back(y2);
|
2025-05-23 05:52:14 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
Global::ExperimentData x1Ed = PointCalculate::getClosestDataByTemperature(x1);
|
|
|
|
|
|
Global::ExperimentData x2Ed = PointCalculate::getClosestDataByTemperature(x2);
|
|
|
|
|
|
QVector<double> xVtr,yVtr;
|
|
|
|
|
|
xVtr.push_back(x1Ed.sampleTemp);
|
|
|
|
|
|
xVtr.push_back(x2Ed.sampleTemp);
|
|
|
|
|
|
|
|
|
|
|
|
yVtr.push_back(x1Ed.dsc);
|
|
|
|
|
|
yVtr.push_back(x2Ed.dsc);
|
|
|
|
|
|
|
|
|
|
|
|
if(_axisMode == AxisMode::DoubleY){
|
|
|
|
|
|
xVtr.clear();
|
|
|
|
|
|
|
|
|
|
|
|
xVtr.push_back(x1Ed.runTime);
|
|
|
|
|
|
xVtr.push_back(x2Ed.runTime);
|
|
|
|
|
|
}
|
2025-03-25 08:45:16 +00:00
|
|
|
|
|
|
|
|
|
|
QCPGraph *mainGraph = _customPlot->addGraph();
|
|
|
|
|
|
mainGraph->setData(xVtr, yVtr);
|
|
|
|
|
|
mainGraph->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
//
|
2025-04-17 09:31:46 +00:00
|
|
|
|
QVector<Global::ExperimentData> curveDataVtr =
|
|
|
|
|
|
PointCalculate::getDataInXRange(x1,x2);
|
|
|
|
|
|
|
|
|
|
|
|
QCPGraph *fillGraph = _customPlot->addGraph();
|
|
|
|
|
|
QVector<double> fillX, fillY;
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = 0;i < curveDataVtr.size();i++){
|
|
|
|
|
|
Global::ExperimentData &ed = curveDataVtr[i];
|
2025-05-23 05:52:14 +00:00
|
|
|
|
if(_axisMode == AxisMode::DoubleY){
|
|
|
|
|
|
fillX<<ed.runTime;
|
|
|
|
|
|
}else{
|
|
|
|
|
|
fillX<<ed.sampleTemp;
|
|
|
|
|
|
}
|
2025-04-17 09:31:46 +00:00
|
|
|
|
fillY<<ed.dsc;
|
|
|
|
|
|
}
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-04-17 09:31:46 +00:00
|
|
|
|
fillGraph->setData(fillX, fillY);
|
|
|
|
|
|
|
|
|
|
|
|
fillGraph->setBrush(QBrush(Qt::green, Qt::SolidPattern));
|
|
|
|
|
|
fillGraph->setChannelFillGraph(mainGraph);
|
2025-03-25 08:45:16 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
ItemManager::addTemporaryQCPGraph(mainGraph,objectName);
|
|
|
|
|
|
ItemManager::addTemporaryQCPGraph(fillGraph,objectName);
|
2025-05-09 09:28:39 +00:00
|
|
|
|
|
2025-03-25 08:45:16 +00:00
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
void CentralWidget::clearData(const CentralWidget::ClearDataMode mode)
|
2025-03-25 08:45:16 +00:00
|
|
|
|
{
|
2025-05-22 09:31:38 +00:00
|
|
|
|
switch (mode) {
|
|
|
|
|
|
case ClearDataMode::All:
|
2025-05-16 09:01:40 +00:00
|
|
|
|
_analysisFilePathVtr.clear();
|
2025-05-09 09:28:39 +00:00
|
|
|
|
// Clear data.
|
2025-05-16 09:01:40 +00:00
|
|
|
|
logde<<"clearExperimentData...";
|
|
|
|
|
|
Global::clearExperimentData();
|
2025-04-11 05:51:47 +00:00
|
|
|
|
|
2025-05-22 09:31:38 +00:00
|
|
|
|
Global::_curveFileDataVtr.clear();
|
|
|
|
|
|
|
2025-05-30 05:46:40 +00:00
|
|
|
|
AnalysisOperationRecorder::_analysisOperationVtr.clear();
|
|
|
|
|
|
|
2025-05-09 09:28:39 +00:00
|
|
|
|
// Set lines visiable false.
|
|
|
|
|
|
_line1->setVisible(false);
|
|
|
|
|
|
_line2->setVisible(false);
|
|
|
|
|
|
|
|
|
|
|
|
_currentCurve = nullptr;
|
2025-06-06 09:17:31 +00:00
|
|
|
|
|
|
|
|
|
|
Global::_smoothnessFlag = false;
|
2025-05-23 05:52:14 +00:00
|
|
|
|
case ClearDataMode::JustUi:
|
2025-05-09 09:28:39 +00:00
|
|
|
|
//ui
|
2025-05-23 05:52:14 +00:00
|
|
|
|
clearAllUiData();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ClearDataMode::Undo:
|
|
|
|
|
|
{
|
2025-05-09 09:28:39 +00:00
|
|
|
|
// Clear the data of graph.
|
|
|
|
|
|
for (int i = _customPlot->plottableCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPAbstractPlottable* plottable = _customPlot->plottable(i);
|
|
|
|
|
|
if (auto curve = dynamic_cast<QCPCurve*>(plottable)) {
|
|
|
|
|
|
logde<<"clear data,curve object Name:"<<curve->objectName().toStdString();
|
2025-05-26 06:32:01 +00:00
|
|
|
|
if(curve->objectName().contains( ItemManager::TemporaryStr)){
|
2025-05-09 09:28:39 +00:00
|
|
|
|
_customPlot->removePlottable(curve);
|
2025-04-11 05:51:47 +00:00
|
|
|
|
|
2025-05-09 09:28:39 +00:00
|
|
|
|
ItemManager::removeItem(curve);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Clear graph on plot.
|
|
|
|
|
|
for (int i = _customPlot->graphCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPGraph *graph = _customPlot->graph(i);
|
|
|
|
|
|
logde<<"clear data,graph object Name:"<<graph->objectName().toStdString();
|
2025-05-26 06:32:01 +00:00
|
|
|
|
if(graph && graph->objectName().contains(ItemManager::TemporaryStr)){
|
2025-05-09 09:28:39 +00:00
|
|
|
|
_customPlot->removeGraph(graph);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(graph);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Delete items.
|
|
|
|
|
|
QList<QCPAbstractItem *> itemsToKeep;
|
|
|
|
|
|
itemsToKeep << _line1 << _line2;
|
2025-03-27 09:31:19 +00:00
|
|
|
|
|
2025-05-09 09:28:39 +00:00
|
|
|
|
for (int i = _customPlot->itemCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPAbstractItem *item = _customPlot->item(i);
|
|
|
|
|
|
logde<<"item data,graph object Name:"<<item->objectName().toStdString();
|
|
|
|
|
|
if(item && !itemsToKeep.contains(item)
|
2025-05-26 06:32:01 +00:00
|
|
|
|
&& item->objectName().contains(ItemManager::TemporaryStr)){
|
2025-05-09 09:28:39 +00:00
|
|
|
|
_customPlot->removeItem(item);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(item);
|
|
|
|
|
|
}
|
2025-03-27 09:31:19 +00:00
|
|
|
|
}
|
2025-05-16 09:01:40 +00:00
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
AnalysisOperationRecorder::removeTheLastAnalysisOperation();
|
2025-05-23 05:52:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:break;
|
2025-03-27 09:31:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->replot();
|
2025-04-01 09:25:12 +00:00
|
|
|
|
}
|
2025-03-25 08:45:16 +00:00
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
void CentralWidget::clearAllUiData()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Clear the data of graph.
|
|
|
|
|
|
for (int i = _customPlot->plottableCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPAbstractPlottable* plottable = _customPlot->plottable(i);
|
|
|
|
|
|
if (auto curve = dynamic_cast<QCPCurve*>(plottable)) {
|
|
|
|
|
|
_customPlot->removePlottable(curve);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(curve);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Clear graph on plot.
|
|
|
|
|
|
for (int i = _customPlot->graphCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPGraph *graph = _customPlot->graph(i);
|
|
|
|
|
|
_customPlot->removeGraph(graph);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(graph);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Delete items.
|
|
|
|
|
|
QList<QCPAbstractItem *> itemsToKeep;
|
|
|
|
|
|
itemsToKeep << _line1 << _line2;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = _customPlot->itemCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPAbstractItem *item = _customPlot->item(i);
|
|
|
|
|
|
if (!itemsToKeep.contains(item)) {
|
|
|
|
|
|
_customPlot->removeItem(item);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
void CentralWidget::deleteCurve(const QString objectName)
|
|
|
|
|
|
{
|
2025-05-22 09:31:38 +00:00
|
|
|
|
for (int i = _analysisFilePathVtr.size() - 1; i >= 0; --i) {
|
|
|
|
|
|
if (_analysisFilePathVtr[i].startsWith(objectName)) {
|
|
|
|
|
|
_analysisFilePathVtr.removeAt(i); // 从后往前删除避免索引错乱
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-20 09:30:02 +00:00
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItemsByObjectName(objectName);
|
|
|
|
|
|
|
|
|
|
|
|
AnalysisOperationRecorder::removeAnalysisOperationByObjectName(objectName);
|
|
|
|
|
|
|
|
|
|
|
|
// Clear the data of graph.
|
|
|
|
|
|
for (int i = _customPlot->plottableCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPAbstractPlottable* plottable = _customPlot->plottable(i);
|
|
|
|
|
|
if (auto curve = dynamic_cast<QCPCurve*>(plottable)) {
|
|
|
|
|
|
logde<<"clear data,curve object Name:"<<curve->objectName().toStdString();
|
|
|
|
|
|
if(curve->objectName().contains(objectName)){
|
|
|
|
|
|
_customPlot->removePlottable(curve);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(curve);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Clear graph on plot.
|
|
|
|
|
|
for (int i = _customPlot->graphCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPGraph *graph = _customPlot->graph(i);
|
|
|
|
|
|
logde<<"clear data,graph object Name:"<<graph->objectName().toStdString();
|
|
|
|
|
|
if(graph && graph->objectName().contains(objectName)){
|
|
|
|
|
|
_customPlot->removeGraph(graph);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(graph);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Delete items.
|
|
|
|
|
|
QList<QCPAbstractItem *> itemsToKeep;
|
|
|
|
|
|
itemsToKeep << _line1 << _line2;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = _customPlot->itemCount() - 1; i >= 0; --i) {
|
|
|
|
|
|
QCPAbstractItem *item = _customPlot->item(i);
|
|
|
|
|
|
logde<<"item data,graph object Name:"<<item->objectName().toStdString();
|
|
|
|
|
|
if(item && !itemsToKeep.contains(item)
|
|
|
|
|
|
&& item->objectName().contains(objectName)){
|
|
|
|
|
|
_customPlot->removeItem(item);
|
|
|
|
|
|
|
|
|
|
|
|
ItemManager::removeItem(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CentralWidget::loadAnalysisData(
|
|
|
|
|
|
const AnalysisMode mode,const double x1,const double x2,const QString objectName)
|
2025-05-13 09:33:40 +00:00
|
|
|
|
{
|
|
|
|
|
|
switch (mode) {
|
|
|
|
|
|
case AnalysisMode::NumericalLabel:
|
|
|
|
|
|
{
|
2025-05-23 05:52:14 +00:00
|
|
|
|
// QPointF selectPoint = PointCalculate::getClosestPointByX(x1);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
Global::ExperimentData ed = PointCalculate::getClosestDataByTemperature(x1);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
if(Global::isZero(ed.dsc)){
|
2025-05-13 09:33:40 +00:00
|
|
|
|
QMessageBox::warning((QWidget*)this->parent(), "warnning", "曲线选择错误.");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
QPointF selectPoint(ed.sampleTemp,ed.dsc);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
QString str = PointCalculate::textFormatNumbericalLabel(selectPoint);
|
2025-05-23 05:52:14 +00:00
|
|
|
|
if(_axisMode == AxisMode::DoubleY){
|
|
|
|
|
|
selectPoint.setX(ed.runTime);
|
|
|
|
|
|
str = PointCalculate::textFormatNumbericalLabelWithTime(selectPoint);
|
|
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
drawText(selectPoint,str,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case AnalysisMode::StartPoint:
|
|
|
|
|
|
case AnalysisMode::StopPoint:{
|
|
|
|
|
|
PointCalculate::setRegionPointX(x1,x2);
|
|
|
|
|
|
|
2025-05-23 05:52:14 +00:00
|
|
|
|
// QPair<QPointF, QPointF> startEndPointPair =
|
|
|
|
|
|
// PointCalculate::calculateStartAndEndPoint();
|
|
|
|
|
|
|
|
|
|
|
|
QPair<Global::ExperimentData,Global::ExperimentData>
|
|
|
|
|
|
startEndDataPair = PointCalculate::calculateStartAndEndData();
|
|
|
|
|
|
|
2025-05-13 09:33:40 +00:00
|
|
|
|
//
|
|
|
|
|
|
QPointF point;
|
|
|
|
|
|
QString str;
|
|
|
|
|
|
|
2025-05-19 05:58:34 +00:00
|
|
|
|
if(mode == AnalysisMode::StartPoint){
|
2025-05-23 05:52:14 +00:00
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
point = QPointF(startEndDataPair.first.sampleTemp,startEndDataPair.first.dsc);
|
|
|
|
|
|
str = PointCalculate::textFormatStartPoint(point);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
point = QPointF(startEndDataPair.first.runTime,startEndDataPair.first.dsc);
|
|
|
|
|
|
str = PointCalculate::textFormatStartPointWithTime(point);
|
|
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
}else{
|
2025-05-23 05:52:14 +00:00
|
|
|
|
if(_axisMode == AxisMode::SingleY){
|
|
|
|
|
|
point = QPointF(startEndDataPair.second.sampleTemp,startEndDataPair.second.dsc);
|
|
|
|
|
|
str = PointCalculate::textFormatEndPoint(point);
|
|
|
|
|
|
}else{
|
|
|
|
|
|
point = QPointF(startEndDataPair.second.runTime,startEndDataPair.second.dsc);
|
|
|
|
|
|
str = PointCalculate::textFormatEndPointWithTime(point);
|
|
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
drawText(point,str,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case AnalysisMode::PeakSynthesisAnalysis:
|
|
|
|
|
|
{
|
2025-05-20 09:30:02 +00:00
|
|
|
|
fillGraph(x1,x2,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
PointCalculate::setRegionPointX(x1,x2);
|
|
|
|
|
|
|
|
|
|
|
|
//enthalpy
|
2025-05-23 05:52:14 +00:00
|
|
|
|
double sampleWeight = 1.0f;
|
2025-05-13 09:33:40 +00:00
|
|
|
|
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
|
|
|
|
|
|
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
|
2025-06-04 09:29:37 +00:00
|
|
|
|
|
2025-05-21 08:36:47 +00:00
|
|
|
|
#if 0
|
2025-05-13 09:33:40 +00:00
|
|
|
|
if(_currentCurve && _currentCurve == pti.curve){
|
|
|
|
|
|
sampleWeight = cfd.ei.sampleWeight.toDouble();
|
|
|
|
|
|
}
|
2025-05-21 08:36:47 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
if(_currentCurve){
|
|
|
|
|
|
if(_currentCurve == pti.curve){
|
|
|
|
|
|
sampleWeight = cfd.ei.sampleWeight.toDouble();
|
|
|
|
|
|
}else{
|
|
|
|
|
|
}
|
|
|
|
|
|
}else{
|
2025-05-22 09:31:38 +00:00
|
|
|
|
// logde<<"current curve nullptr.";
|
2025-05-21 08:36:47 +00:00
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-05-21 08:36:47 +00:00
|
|
|
|
|
|
|
|
|
|
if(sampleWeight <= 0){
|
|
|
|
|
|
logde<<"sample weight set value 1,"<<sampleWeight;
|
|
|
|
|
|
sampleWeight = 1;
|
|
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
double enthalpyValue = PointCalculate::calculateArea() / sampleWeight;
|
|
|
|
|
|
|
2025-06-04 09:29:37 +00:00
|
|
|
|
logde<<"enthalpyValue:"<<enthalpyValue;
|
2025-05-21 08:36:47 +00:00
|
|
|
|
|
2025-05-13 09:33:40 +00:00
|
|
|
|
// peak
|
|
|
|
|
|
QPointF peakPoint = PointCalculate::getPeakPoint();
|
|
|
|
|
|
|
|
|
|
|
|
// start point and end point
|
|
|
|
|
|
QPair<QPointF, QPointF> startEndPointPair =
|
|
|
|
|
|
PointCalculate::calculateStartAndEndPoint();
|
|
|
|
|
|
|
|
|
|
|
|
logde<<"start,end:"<<startEndPointPair.first.x()<<","
|
|
|
|
|
|
<<startEndPointPair.second.x();
|
|
|
|
|
|
|
|
|
|
|
|
QString str;
|
2025-05-23 05:52:14 +00:00
|
|
|
|
if(_axisMode == AxisMode::DoubleY){
|
|
|
|
|
|
double peakPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(peakPoint.x());
|
|
|
|
|
|
double startPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.first.x());
|
|
|
|
|
|
double endPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.second.x());
|
|
|
|
|
|
|
|
|
|
|
|
str = PointCalculate::textFormatPeakPointWithTime(
|
|
|
|
|
|
enthalpyValue,
|
|
|
|
|
|
peakPointTime,
|
|
|
|
|
|
startPointTime,
|
|
|
|
|
|
endPointTime);
|
|
|
|
|
|
|
|
|
|
|
|
Global::ExperimentData peakPointEd =
|
|
|
|
|
|
PointCalculate::getClosestDataByTemperature(peakPoint.x());
|
|
|
|
|
|
|
|
|
|
|
|
peakPoint = QPointF(peakPointEd.runTime,peakPointEd.dsc);
|
|
|
|
|
|
|
|
|
|
|
|
drawText(peakPoint,str,objectName);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if(Global::_displayTimeValue){
|
2025-05-13 09:33:40 +00:00
|
|
|
|
double peakPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(peakPoint.x());
|
|
|
|
|
|
double startPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.first.x());
|
|
|
|
|
|
double endPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.second.x());
|
|
|
|
|
|
|
|
|
|
|
|
str = PointCalculate::textFormatPeakPointWithTime(
|
|
|
|
|
|
enthalpyValue,
|
|
|
|
|
|
peakPointTime,
|
|
|
|
|
|
startPointTime,
|
|
|
|
|
|
endPointTime);
|
2025-05-29 09:19:11 +00:00
|
|
|
|
|
2025-05-20 09:30:02 +00:00
|
|
|
|
drawText(peakPoint,str,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
}else{
|
|
|
|
|
|
str = PointCalculate::textFormatPeakPoint(enthalpyValue,
|
|
|
|
|
|
peakPoint.x(),
|
|
|
|
|
|
startEndPointPair.first.x(),
|
|
|
|
|
|
startEndPointPair.second.x());
|
2025-05-20 09:30:02 +00:00
|
|
|
|
drawText(peakPoint,str,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case AnalysisMode::GlassTransition:
|
|
|
|
|
|
{
|
2025-05-20 09:30:02 +00:00
|
|
|
|
glassTransitionHandle(x1,x2,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case AnalysisMode::OnsetTemperaturePoint:{
|
2025-05-26 06:32:01 +00:00
|
|
|
|
QPointF point = onsetTemperaturePointHandle(x1,x2);
|
|
|
|
|
|
logde<<"onset point:"<<point.x()<<","<<point.y();
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
QString str = QString::number(point.x(),'f',3);
|
2025-05-20 09:30:02 +00:00
|
|
|
|
drawText(point,str,objectName);
|
2025-05-13 09:33:40 +00:00
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case AnalysisMode::EndsetTemperaturePoint:{
|
2025-05-26 06:32:01 +00:00
|
|
|
|
QPointF point = endSetTemperaturePointHandle(x1,x2);
|
|
|
|
|
|
|
|
|
|
|
|
QString str = QString::number(point.x(),'f',3);
|
|
|
|
|
|
logde<<"object name:"<<objectName.toStdString();
|
|
|
|
|
|
drawText(point,str,objectName);
|
|
|
|
|
|
|
2025-05-13 09:33:40 +00:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-06-12 09:27:45 +00:00
|
|
|
|
case AnalysisMode::OIT:{
|
|
|
|
|
|
logde<<"oit x1,x2:"<<x1<<","<<x2;
|
|
|
|
|
|
|
|
|
|
|
|
Global::ExperimentData ed = PointCalculate::findOnSetDataByTime(x1,x2);
|
|
|
|
|
|
|
|
|
|
|
|
// Global::ExperimentData ed = PointCalculate::findOnSetDataByTemperature(x1,x2);
|
|
|
|
|
|
|
|
|
|
|
|
// PointCalculate::setRegionPointX(x1,x2);
|
|
|
|
|
|
|
|
|
|
|
|
Global::ExperimentData startData = PointCalculate::_dataVtr.first();
|
|
|
|
|
|
|
|
|
|
|
|
// QPair<Global::ExperimentData,Global::ExperimentData>
|
|
|
|
|
|
// startEndDataPair = PointCalculate::calculateStartAndEndData();
|
|
|
|
|
|
|
|
|
|
|
|
logde<<"start data time:"<<startData.runTime;
|
|
|
|
|
|
logde<<"end data time:"<<ed.runTime;
|
|
|
|
|
|
|
|
|
|
|
|
drawOITLine(startData,ed);
|
|
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-05-13 09:33:40 +00:00
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-12 09:27:45 +00:00
|
|
|
|
void CentralWidget::drawOITLine(const Global::ExperimentData startData,const Global::ExperimentData endData)
|
|
|
|
|
|
{
|
|
|
|
|
|
#if 0
|
|
|
|
|
|
// Draw start vertical line.
|
|
|
|
|
|
QVector<double> xVtr,yVtr;
|
|
|
|
|
|
xVtr.push_back(startData.runTime);
|
|
|
|
|
|
xVtr.push_back(startData.runTime);
|
|
|
|
|
|
|
|
|
|
|
|
yVtr.push_back(startData.dsc - 10);
|
|
|
|
|
|
yVtr.push_back(startData.dsc - 20);
|
|
|
|
|
|
|
|
|
|
|
|
QCPGraph *startLine = _customPlot->addGraph();
|
|
|
|
|
|
startLine->setData(xVtr, yVtr);
|
|
|
|
|
|
startLine->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
|
|
|
|
|
|
// Draw end vertical line.
|
|
|
|
|
|
xVtr.clear();
|
|
|
|
|
|
yVtr.clear();
|
|
|
|
|
|
xVtr.push_back(endData.runTime);
|
|
|
|
|
|
xVtr.push_back(endData.runTime);
|
|
|
|
|
|
|
|
|
|
|
|
yVtr.push_back(endData.dsc - 10);
|
|
|
|
|
|
yVtr.push_back(endData.dsc - 20);
|
|
|
|
|
|
|
|
|
|
|
|
QCPGraph *endLine = _customPlot->addGraph();
|
|
|
|
|
|
endLine->setData(xVtr, yVtr);
|
|
|
|
|
|
endLine->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// Draw start line.
|
|
|
|
|
|
QCPItemLine *startLine = new QCPItemLine(_customPlot);
|
|
|
|
|
|
startLine->start->setCoords(startData.runTime,startData.dsc - 10);
|
|
|
|
|
|
startLine->end->setCoords(startData.runTime,startData.dsc - 20);
|
|
|
|
|
|
startLine->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
// Draw end line.
|
|
|
|
|
|
QCPItemLine *endLine = new QCPItemLine(_customPlot);
|
|
|
|
|
|
endLine->start->setCoords(endData.runTime,endData.dsc - 10);
|
|
|
|
|
|
endLine->end->setCoords(endData.runTime,endData.dsc - 20);
|
|
|
|
|
|
endLine->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
|
|
|
|
|
|
// Draw total line.
|
|
|
|
|
|
QCPItemLine *totalLine = new QCPItemLine(_customPlot);
|
|
|
|
|
|
totalLine->start->setCoords(startData.runTime,startData.dsc - 15);
|
|
|
|
|
|
totalLine->end->setCoords(endData.runTime,endData.dsc - 15);
|
|
|
|
|
|
totalLine->setPen(QPen(Qt::red, 1));
|
|
|
|
|
|
|
|
|
|
|
|
// Draw title.
|
|
|
|
|
|
double textX = (endData.runTime - startData.runTime) / 2 + endData.runTime;
|
|
|
|
|
|
|
|
|
|
|
|
QCPItemText *textLabel = new QCPItemText(_customPlot);
|
|
|
|
|
|
textLabel->setPositionAlignment(Qt::AlignCenter); // 对齐方式
|
|
|
|
|
|
textLabel->position->setType(QCPItemPosition::ptPlotCoords); // 使用数据坐标
|
|
|
|
|
|
textLabel->position->setCoords(textX,startData.dsc - 20); // 设置文本位置在指定点上方
|
|
|
|
|
|
|
|
|
|
|
|
textLabel->setText("OIT:123.44"); // 设置文本内容
|
|
|
|
|
|
QFont font(QFont("Arial", 10));
|
|
|
|
|
|
textLabel->setFont(font);
|
|
|
|
|
|
textLabel->setSelectedFont(font);
|
|
|
|
|
|
textLabel->setSelectable(true); // 设置为可选
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-01 09:25:12 +00:00
|
|
|
|
void CentralWidget::clearAllData()
|
|
|
|
|
|
{
|
2025-05-30 05:46:40 +00:00
|
|
|
|
Global::_mode = Global::Mode::Analysis;
|
2025-04-01 09:25:12 +00:00
|
|
|
|
clearData(ClearDataMode::All);
|
2025-03-24 09:30:42 +00:00
|
|
|
|
}
|
2025-04-23 07:33:39 +00:00
|
|
|
|
|
2025-04-25 09:20:33 +00:00
|
|
|
|
QPixmap CentralWidget::getPixMap()
|
|
|
|
|
|
{
|
2025-05-19 09:29:21 +00:00
|
|
|
|
_customPlot->replot();
|
|
|
|
|
|
QApplication::processEvents();
|
2025-04-25 09:20:33 +00:00
|
|
|
|
return _customPlot->toPixmap();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-23 07:33:39 +00:00
|
|
|
|
void CentralWidget::slotAxisModify(const float temp)
|
|
|
|
|
|
{
|
|
|
|
|
|
_customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
|
|
|
|
|
|
|
|
|
|
|
|
float value = temp + 20;
|
|
|
|
|
|
|
|
|
|
|
|
_customPlot->xAxis->setRange(10,value);
|
|
|
|
|
|
_customPlot->yAxis->setRange(-5,5);
|
|
|
|
|
|
}
|
2025-06-06 09:17:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|