DSCAnalysisTool/src/ui/centralwidget.cpp

1275 lines
38 KiB
C++
Raw Normal View History

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-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-04-28 09:31:29 +00:00
,_axisMode(AxisMode::SingleY)
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-04-10 07:20:57 +00:00
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
// 设置坐标轴标签
_customPlot->xAxis->setLabel("Temp/℃");
_customPlot->yAxis->setLabel("DSC/mW");
// 设置坐标轴范围,以便我们可以看到全部数据
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;
_customPlot->yAxis2->setVisible(true);
_customPlot->yAxis2->setLabel("Time/min");
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
QVector<Global::ExperimentData> dataVtr;
QVector<double> tVtr,xVtr, yVtr;
int index = 0;
for (Global::ExperimentData &ed : pti.dataVtr)
{
tVtr.push_back(index++);
xVtr.push_back(ed.sampleTemp);
yVtr.push_back(ed.runTime);
}
double yMin = yVtr.first();
double yMax = yVtr.last();
double tick = (yMax - yMin) / 4;
double axisMin = yMin - tick;
double axisMax = yMax + tick;
_customPlot->yAxis2->setRange(axisMin,axisMax);
QCPCurve* curve = new QCPCurve(_customPlot->xAxis, _customPlot->yAxis2);
curve->setData(tVtr, xVtr, yVtr);
2025-04-29 09:29:14 +00:00
curve->setPen(QPen(QColor(Qt::red)));
2025-04-28 09:31:29 +00:00
curve->setObjectName(Global::CurveOfTimeTypeObjectName);
2025-04-29 09:29:14 +00:00
// logde<<"plottableCount count:"<<_customPlot->plottableCount();
2025-04-28 09:31:29 +00:00
}
}
}else{
_axisMode = AxisMode::SingleY;
_customPlot->yAxis2->setVisible(false);
2025-04-29 09:29:14 +00:00
// logde<<"graph count:"<<_customPlot->plottableCount();
for (int i = _customPlot->plottableCount() - 1; i >= 0; --i) {
QCPAbstractPlottable* plottable = _customPlot->plottable(i);
if (auto curve = dynamic_cast<QCPCurve*>(plottable)) {
if(curve && curve->objectName() == Global::CurveOfTimeTypeObjectName){
_customPlot->removePlottable(curve);
}
2025-04-28 09:31:29 +00:00
}
}
}
_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-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-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-23 07:33:39 +00:00
// logde<<"slotRecvCommonData...";
2025-03-21 09:28:36 +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-04-15 08:03:00 +00:00
}
2025-04-22 09:33:03 +00:00
2025-04-25 09:20:33 +00:00
// logde<<"temp:"<<cd.sample_temp<<",dsc:"<<cd.dsc;
2025-04-22 09:33:03 +00:00
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-04-23 07:33:39 +00:00
// _customPlot->rescaleAxes();
_customPlot->replot();
2025-04-14 09:11:01 +00:00
2025-04-23 07:33:39 +00:00
// return;
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-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-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-04-11 05:51:47 +00:00
2025-04-25 09:20:33 +00:00
QFileInfo fileInfo(filePath);
cfd.fileName = fileInfo.fileName();
2025-04-15 08:03:00 +00:00
for(int i = 0;i < cfd.phaseTotalVtr.size();i++){
Global::PhaseTotalInfo& pti = cfd.phaseTotalVtr[i];
2025-03-19 07:19:45 +00:00
2025-05-14 09:30:52 +00:00
// logde<<"data Vtr size:"<<pti.dataVtr.size();
2025-04-16 09:10:35 +00:00
2025-04-15 08:03:00 +00:00
PointCalculate::setExperimentData(pti.dataVtr);
2025-04-16 07:38:25 +00:00
2025-04-15 08:03:00 +00:00
QPair<QPointF,QPointF>startEndPointPair = PointCalculate::getStartAndEndPoint();
2025-03-21 09:28:36 +00:00
2025-04-15 08:03:00 +00:00
QPointF endPoint = startEndPointPair.second;
_customPlot->xAxis->setRange(0, endPoint.x() / 3 * 4);
2025-04-03 09:24:29 +00:00
2025-04-16 09:10:35 +00:00
//QPointF peakPoint = PointCalculate::getPeakPoint();
QPair<float, float> maxMinPair = PointCalculate::getMaxMinValue();
float absY = std::abs(maxMinPair.first - maxMinPair.second);
2025-04-15 08:03:00 +00:00
_customPlot->yAxis->setRange(- absY * 2,absY *2);
2025-03-26 09:30:02 +00:00
2025-04-15 08:03:00 +00:00
_customPlot->yAxis->setLabel("DSC/mW");
_customPlot->xAxis->setLabel("Temp/℃");
2025-04-03 09:24:29 +00:00
2025-04-16 07:38:25 +00:00
QVector<Global::ExperimentData> dataVtr;
2025-04-15 08:03:00 +00:00
QVector<double> tVtr,xVtr, yVtr;
int index = 0;
for (Global::ExperimentData &ed : pti.dataVtr)
{
tVtr.push_back(index++);
xVtr.push_back(ed.sampleTemp);
yVtr.push_back(ed.dsc);
}
2025-03-19 07:19:45 +00:00
2025-04-15 08:03:00 +00:00
_currentCurve = new QCPCurve(_customPlot->xAxis, _customPlot->yAxis);
_currentCurve->setData(tVtr, xVtr, yVtr);
_currentCurve->setSelectable(QCP::stWhole); // 设置曲线可选
2025-05-07 09:33:03 +00:00
_currentCurve->setLineStyle(QCPCurve::lsLine); // 线性连接
2025-04-10 09:33:38 +00:00
2025-04-24 08:41:20 +00:00
pti.curve = _currentCurve;
2025-04-15 08:03:00 +00:00
}
2025-04-09 09:30:32 +00:00
2025-05-13 09:33:40 +00:00
// Add analysis operation data.
2025-05-14 09:30:52 +00:00
if(AnalysisOperationRecorder::_ananlysisOperationVtr.size() > 0){
for(AnaOpRecorder::AnalysisOperation& ao
:AnalysisOperationRecorder::_ananlysisOperationVtr){
loadAnalysisData(ao.mode,ao.x1,ao.x2);
}
2025-05-13 09:33:40 +00:00
}
// Refresh ui.
2025-04-23 09:25:38 +00:00
_customPlot->rescaleAxes();
2025-03-19 07:19:45 +00:00
_customPlot->replot();
2025-05-13 09:33:40 +00:00
// Add data to global parameter.
Global::_curveFileDataVtr.push_back(cfd);
2025-03-19 07:19:45 +00:00
}
2025-03-21 09:28:36 +00:00
void CentralWidget::slotAnalysisSettingApply()
{
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
//
loadAnalysisData(_analysisMode,x1,x2);
2025-05-09 09:28:39 +00:00
//
2025-05-13 09:33:40 +00:00
#if 0
2025-04-03 09:24:29 +00:00
switch (_analysisMode) {
2025-03-25 08:45:16 +00:00
case AnalysisMode::NumericalLabel:
{
2025-05-09 09:28:39 +00:00
QPointF selectPoint = PointCalculate::getClosestPointByX(x1);
2025-04-01 09:25:12 +00:00
2025-05-12 09:29:59 +00:00
// logde<<"lin1 x:"<<x1;
2025-04-16 07:38:25 +00:00
2025-04-24 06:35:53 +00:00
if(selectPoint.isNull()){
QMessageBox::warning((QWidget*)this->parent(), "warnning", "曲线选择错误.");
return;
}
2025-05-12 09:29:59 +00:00
QString str = PointCalculate::textFormatNumbericalLabel(selectPoint);
drawText(selectPoint,str);
2025-04-03 09:24:29 +00:00
2025-05-12 09:29:59 +00:00
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnaOpRecorder::NumericalLabel;
ao.x1 = x1;
AnaOpRecorder::addAnalysisOperation(ao);
//
2025-04-03 09:24:29 +00:00
break;
}
case AnalysisMode::StartPoint:
case AnalysisMode::StopPoint:{
PointCalculate::setRegionPointX(x1,x2);
QPair<QPointF, QPointF> startEndPointPair =
PointCalculate::calculateStartAndEndPoint();
2025-05-12 09:29:59 +00:00
//
QPointF point;
QString str;
AnaOpRecorder::AnalysisOperation ao;
2025-04-03 09:24:29 +00:00
if(_analysisMode == AnalysisMode::StartPoint){
2025-05-12 09:29:59 +00:00
point = startEndPointPair.first;
str = PointCalculate::textFormatStartPoint(point);
ao.mode = AnaOpRecorder::StartPoint;
2025-04-03 09:24:29 +00:00
}else{
2025-05-12 09:29:59 +00:00
point = startEndPointPair.second;
str = PointCalculate::textFormatEndPoint(point);
ao.mode = AnaOpRecorder::StopPoint;
2025-04-03 09:24:29 +00:00
}
2025-04-01 09:25:12 +00:00
2025-05-12 09:29:59 +00:00
drawText(point,str);
//
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
2025-03-25 08:45:16 +00:00
break;
}
case AnalysisMode::PeakSynthesisAnalysis:
{
fillGraph(x1,x2);
2025-03-26 09:30:02 +00:00
2025-04-03 09:24:29 +00:00
PointCalculate::setRegionPointX(x1,x2);
2025-03-26 09:30:02 +00:00
2025-03-27 09:31:19 +00:00
//enthalpy
2025-04-24 08:41:20 +00:00
double sampleWeight = 0.0f;
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
if(_currentCurve && _currentCurve == pti.curve){
sampleWeight = cfd.ei.sampleWeight.toDouble();
}
}
}
2025-05-09 09:28:39 +00:00
// logde<<"sample weight:"<<sampleWeight;
2025-04-24 08:41:20 +00:00
double enthalpyValue = PointCalculate::calculateArea() / sampleWeight;
2025-05-09 09:28:39 +00:00
// peak
2025-04-03 09:24:29 +00:00
QPointF peakPoint = PointCalculate::getPeakPoint();
2025-05-09 09:28:39 +00:00
// start point and end point
2025-04-01 09:25:12 +00:00
QPair<QPointF, QPointF> startEndPointPair =
2025-04-03 09:24:29 +00:00
PointCalculate::calculateStartAndEndPoint();
2025-03-27 09:31:19 +00:00
2025-04-03 09:24:29 +00:00
logde<<"start,end:"<<startEndPointPair.first.x()<<","
<<startEndPointPair.second.x();
2025-05-12 09:29:59 +00:00
QString str;
2025-04-30 02:59:08 +00:00
if(Global::_displayTimeValue){
double peakPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(peakPoint.x());
double startPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.first.x());
double endPointTime = PointCalculate::obtainTimeValueBasedOnTemperatureValue(startEndPointPair.second.x());
2025-05-12 09:29:59 +00:00
str = PointCalculate::textFormatPeakPointWithTime(
enthalpyValue,
peakPointTime,
startPointTime,
endPointTime);
drawText(peakPoint,str);
2025-04-30 02:59:08 +00:00
}else{
2025-05-12 09:29:59 +00:00
str = PointCalculate::textFormatPeakPoint(enthalpyValue,
2025-04-30 02:59:08 +00:00
peakPoint.x(),
startEndPointPair.first.x(),
2025-05-12 09:29:59 +00:00
startEndPointPair.second.x());
drawText(peakPoint,str);
2025-04-30 02:59:08 +00:00
}
2025-03-27 09:31:19 +00:00
//
2025-05-12 09:29:59 +00:00
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnaOpRecorder::PeakSynthesisAnalysis;
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
2025-03-27 09:31:19 +00:00
break;
2025-03-25 08:45:16 +00:00
}
2025-04-03 09:24:29 +00:00
case AnalysisMode::GlassTransition:
{
2025-05-09 09:28:39 +00:00
glassTransitionHandle(x1,x2);
2025-05-13 09:33:40 +00:00
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnaOpRecorder::GlassTransition;
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
2025-04-03 09:24:29 +00:00
break;
}
2025-05-07 09:33:03 +00:00
case AnalysisMode::OnsetTemperaturePoint:{
2025-05-09 09:28:39 +00:00
#if 0
QPointF point = OnsetTemperaturePointHandle(x1,x2);
2025-05-07 09:33:03 +00:00
QString str = QString::number(point.y(),'f',3);
drawText(point,str);
2025-05-09 09:28:39 +00:00
#endif
2025-05-07 09:33:03 +00:00
2025-05-09 09:28:39 +00:00
QPointF point = OnsetTemperaturePointHandle(x1,x2);
QString str = QString::number(point.x(),'f',3);
drawText(point,str);
2025-05-07 09:33:03 +00:00
2025-05-12 09:29:59 +00:00
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnaOpRecorder::OnsetTemperaturePoint;
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
2025-05-07 09:33:03 +00:00
break;
}
case AnalysisMode::EndsetTemperaturePoint:{
break;
}
2025-03-25 08:45:16 +00:00
default:
break;
}
2025-05-13 09:33:40 +00:00
#endif
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-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-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-03-20 09:28:22 +00:00
2025-05-09 09:28:39 +00:00
void CentralWidget::glassTransitionHandle(const double x1,const double x2)
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
ItemManager::addTemporaryQCPGraph(lineGraph1);
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-09 09:28:39 +00:00
ItemManager::addTemporaryQCPGraph(lineGraph2);
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
ItemManager::addTemporaryQCPGraph(lineGraph3);
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-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
2025-05-12 09:29:59 +00:00
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-09 09:28:39 +00:00
QPointF CentralWidget::OnsetTemperaturePointHandle(const double x1,const double x2)
{
QVector<QPointF> rowPointVtr = PointCalculate::getPointVtrInXRange(x1,x2);
QVector<QPointF> pointVtr = PointCalculate::movingAveragePoint(rowPointVtr,5);
QVector<double> xVtr,yVtr;
for (QPointF &point : pointVtr) {
xVtr.push_back(point.x());
yVtr.push_back(point.y());
}
double coeff[3] = {0};
Global::quadraticLeastSquaresFit(xVtr.data(),yVtr.data(),xVtr.size(),coeff);
// derivative
double a = coeff[0] * 2;
double b = coeff[1];
double targetX = Global::findNegativeStartPoint(a,b,pointVtr.first().x(),pointVtr.last().x());
logde<<"traget x:"<<targetX;
// QPointF targetPoint = PointCalculate::getClosestPointByX(targetX);
return PointCalculate::getClosestPointByX(targetX);
}
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
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();
logde<<"ticks:"<<numTicks;
double distance = (xMax - xMin) / ticks.size();
return QPointF(point.x() + distance,point.y());
}
2025-03-26 09:30:02 +00:00
void CentralWidget::drawText(const QPointF point, const QString text)
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-09 09:28:39 +00:00
ItemManager::addTemporaryQCPItemText(textLabel);
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-09 09:28:39 +00:00
ItemManager::addTemporaryQCPItemLine(arrow);
2025-03-26 09:30:02 +00:00
// 重绘图表以显示文本标签和箭头
_customPlot->replot();
2025-03-25 08:45:16 +00:00
}
void CentralWidget::fillGraph(const double x1, const double x2)
{
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);
QCPGraph *mainGraph = _customPlot->addGraph();
mainGraph->setData(xVtr, yVtr);
mainGraph->setPen(QPen(Qt::red, 1));
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];
fillX<<ed.sampleTemp;
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-09 09:28:39 +00:00
ItemManager::addTemporaryQCPGraph(mainGraph);
ItemManager::addTemporaryQCPGraph(fillGraph);
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-04-01 09:25:12 +00:00
if(mode == ClearDataMode::All){
2025-05-09 09:28:39 +00:00
// Clear data.
Global::_curveExperimentDataVtr.clear();
2025-04-11 05:51:47 +00:00
2025-05-09 09:28:39 +00:00
// Set lines visiable false.
_line1->setVisible(false);
_line2->setVisible(false);
_currentCurve = nullptr;
//ui
// Clear the data of graph.
2025-04-11 05:51:47 +00:00
for (int i = _customPlot->plottableCount() - 1; i >= 0; --i) {
QCPAbstractPlottable* plottable = _customPlot->plottable(i);
if (auto curve = dynamic_cast<QCPCurve*>(plottable)) {
_customPlot->removePlottable(curve);
2025-05-09 09:28:39 +00:00
ItemManager::removeItem(curve);
2025-04-11 05:51:47 +00:00
}
2025-04-01 09:25:12 +00:00
}
2025-04-11 05:51:47 +00:00
2025-05-09 09:28:39 +00:00
// Clear graph on plot.
for (int i = _customPlot->graphCount() - 1; i >= 0; --i) {
QCPGraph *graph = _customPlot->graph(i);
_customPlot->removeGraph(graph);
2025-03-27 09:31:19 +00:00
2025-05-09 09:28:39 +00:00
ItemManager::removeItem(graph);
}
2025-04-01 09:25:12 +00:00
2025-05-09 09:28:39 +00:00
// 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);
}
}
}else if(mode == ClearDataMode::Undo){
// 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() == ItemManager::TemporaryStr){
_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();
if(graph && graph->objectName() == ItemManager::TemporaryStr){
_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)
&& item->objectName() == ItemManager::TemporaryStr){
_customPlot->removeItem(item);
ItemManager::removeItem(item);
}
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-13 09:33:40 +00:00
void CentralWidget::loadAnalysisData(const CentralWidget::AnalysisMode mode, const double x1, const double x2)
{
switch (mode) {
case AnalysisMode::NumericalLabel:
{
QPointF selectPoint = PointCalculate::getClosestPointByX(x1);
// logde<<"lin1 x:"<<x1;
if(selectPoint.isNull()){
QMessageBox::warning((QWidget*)this->parent(), "warnning", "曲线选择错误.");
return;
}
QString str = PointCalculate::textFormatNumbericalLabel(selectPoint);
drawText(selectPoint,str);
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnalysisMode::NumericalLabel;
ao.x1 = x1;
AnaOpRecorder::addAnalysisOperation(ao);
//
break;
}
case AnalysisMode::StartPoint:
case AnalysisMode::StopPoint:{
PointCalculate::setRegionPointX(x1,x2);
QPair<QPointF, QPointF> startEndPointPair =
PointCalculate::calculateStartAndEndPoint();
//
QPointF point;
QString str;
AnaOpRecorder::AnalysisOperation ao;
if(_analysisMode == AnalysisMode::StartPoint){
point = startEndPointPair.first;
str = PointCalculate::textFormatStartPoint(point);
2025-05-14 09:30:52 +00:00
ao.mode = Global::AnalysisMode::StartPoint;
2025-05-13 09:33:40 +00:00
}else{
point = startEndPointPair.second;
str = PointCalculate::textFormatEndPoint(point);
2025-05-14 09:30:52 +00:00
ao.mode = Global::AnalysisMode::StopPoint;
2025-05-13 09:33:40 +00:00
}
drawText(point,str);
//
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
break;
}
case AnalysisMode::PeakSynthesisAnalysis:
{
fillGraph(x1,x2);
PointCalculate::setRegionPointX(x1,x2);
//enthalpy
double sampleWeight = 0.0f;
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
if(_currentCurve && _currentCurve == pti.curve){
sampleWeight = cfd.ei.sampleWeight.toDouble();
}
}
}
// logde<<"sample weight:"<<sampleWeight;
double enthalpyValue = PointCalculate::calculateArea() / sampleWeight;
// 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;
if(Global::_displayTimeValue){
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);
drawText(peakPoint,str);
}else{
str = PointCalculate::textFormatPeakPoint(enthalpyValue,
peakPoint.x(),
startEndPointPair.first.x(),
startEndPointPair.second.x());
drawText(peakPoint,str);
}
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnalysisMode::PeakSynthesisAnalysis;
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
break;
}
case AnalysisMode::GlassTransition:
{
glassTransitionHandle(x1,x2);
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnalysisMode::GlassTransition;
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
break;
}
case AnalysisMode::OnsetTemperaturePoint:{
#if 0
QPointF point = OnsetTemperaturePointHandle(x1,x2);
QString str = QString::number(point.y(),'f',3);
drawText(point,str);
#endif
QPointF point = OnsetTemperaturePointHandle(x1,x2);
QString str = QString::number(point.x(),'f',3);
drawText(point,str);
//
AnaOpRecorder::AnalysisOperation ao;
ao.mode = AnalysisMode::OnsetTemperaturePoint;
ao.x1 = x1;
ao.x2 = x2;
AnaOpRecorder::addAnalysisOperation(ao);
//
break;
}
case AnalysisMode::EndsetTemperaturePoint:{
break;
}
default:
break;
}
}
2025-04-01 09:25:12 +00:00
void CentralWidget::clearAllData()
{
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()
{
return _customPlot->toPixmap();
}
2025-04-28 09:31:29 +00:00
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);
}