2025-06-26T17:30:00

This commit is contained in:
yuntang 2025-06-26 17:30:01 +08:00
parent 3551a87337
commit ca1186c9b1
7 changed files with 211 additions and 53 deletions

Binary file not shown.

View File

@ -9,7 +9,7 @@ CONFIG+=precompile_header
PRECOMPILED_HEADER=stable.h
#
VERSION = 1.0.8
VERSION = 1.1.0
# 设置目标文件名,包含版本号
TARGET = DSCAnalysisTool_$${VERSION}

View File

@ -619,16 +619,22 @@ QVector<QPointF> PointCalculate::getNearbyPointGroupByX(const float targetX)
if (diff < minDiff) {
minDiff = diff;
if(tmpPointVtr.size() > conCount){
targetPointVtr = QVector<QPointF>(tmpPointVtr.end() - conCount, tmpPointVtr.end());
}else{
targetPointVtr = tmpPointVtr;
}
}
}
return targetPointVtr;
}
// 计算两点之间的斜率
double PointCalculate::calculateSlope(double x1, double y1, double x2, double y2) {
if(x1 == x2){
return 0.0;
}
return (y2 - y1) / (x2 - x1);
}
@ -659,6 +665,9 @@ QMap<double, PointCalculate::Line> PointCalculate::calculateTangentLine(
for (double xInflection : inflectionPointsX) {
int i = std::distance(x.begin(), std::find(x.begin(), x.end(), xInflection));
double slope = calculateSlope(x[i - 1], y[i - 1], x[i + 1], y[i + 1]);
if(slope == 0.0){
continue;
}
double yInflection = y[i];
double intercept = yInflection - slope * xInflection;
tangentLines[xInflection] = {slope, intercept};
@ -1137,3 +1146,8 @@ std::pair<bool, Global::ExperimentData> PointCalculate::calculateMedianOIT(){
return std::make_pair(true, sortedData[n/2]);
}
}
double PointCalculate::calculateDistance(const QPointF& p1, const QPointF& p2) {
return std::sqrt(std::pow(p2.x() - p1.x(), 2) + std::pow(p2.y() - p1.y(), 2));
}

View File

@ -85,6 +85,7 @@ QPointF getIntersection(const Line& line1, const Line& line2);
double calculateSlope(double x1, double y1, double x2, double y2) ;
QVector<double> findInflectionPoints(const QVector<double>& x, const QVector<double>& y) ;
QMap<double, Line> calculateTangentLine(const QVector<double>& x, const QVector<double>& y) ;
double calculateDistance(const QPointF& p1, const QPointF& p2);
//private
void updateStartEndPoint();
@ -104,6 +105,7 @@ QVector<QPointF> getPeakPointGroup();
std::vector<float> movingAverage(const std::vector<float>& data, int windowSize);
QVector<QPointF> movingAveragePoint(const QVector<QPointF>& data, int windowSize);
extern QVector<Global::ExperimentData> _dataVtr;
extern QPointF _peakPoint;
extern QPointF _leftSelectedPoint,_rightSelectedPoint;

View File

@ -127,6 +127,8 @@ private:
void smoothness(const int level);
QVector<Global::ExperimentData> smoothnessDetail(const int level,const QVector<Global::ExperimentData>&);
void smoothnessExperimentData(const int level);
private:
bool _manuallyStopTheExperimentFlag;
Ui::MainWindow *ui;

View File

@ -617,7 +617,7 @@ void CentralWidget::slotSelectionChangedByUser()
void CentralWidget::uiLoadXlsxFileData()
{
#if 0
#if 1
// Set axis.
_customPlot->yAxis->setVisible(true);
_customPlot->yAxis->setLabel(AxisDSC);
@ -632,6 +632,8 @@ void CentralWidget::uiLoadXlsxFileData()
_customPlot->yAxis2->setVisible(true);
_customPlot->yAxis2->setLabel(AxisTemperature);
}
_customPlot->replot();
#endif
#if 1
@ -759,12 +761,19 @@ void CentralWidget::uiLoadXlsxFileData()
void CentralWidget::glassTransitionHandle(const double x1,const double x2,const QString objectName)
{
QVector<double> tickPositions = _customPlot->xAxis->tickVector();
double step = tickPositions.at(1) - tickPositions.at(0);
logde<<"glassTransitionHandle step:"<<step;
double extendedLineStep = step / 2;
QPointF point1 = PointCalculate::getClosestPointByX(x1);
QPointF point2 = PointCalculate::getClosestPointByX(x2);
logde<<"point1:"<<point1.x()<<","<<point1.y();
logde<<"point2:"<<point2.x()<<","<<point2.y();
//获取与选择点接近的10个点
QVector<QPointF> point1Vtr = PointCalculate::getNearbyPointGroupByX(point1.x());
QVector<QPointF> point2Vtr = PointCalculate::getNearbyPointGroupByX(point2.x());
@ -777,16 +786,15 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
PointCalculate::Line line1 = calculateLinearRegression(xVtr,yVtr);
#if 1
///line1
// QVector<double> xVtr,yVtr;
//line1
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;
xVtr.push_back(point1.x() + extendedLineStep);
double y1 = line1.slope * (point1.x() + extendedLineStep) + line1.intercept;
yVtr.push_back(y1);
QCPGraph *lineGraph1 = _customPlot->addGraph();
@ -797,9 +805,9 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
QPen pen;
pen.setColor(Qt::darkGreen);
lineGraph1->setPen(pen);
#endif
//line2
xVtr.clear();
yVtr.clear();
for(QPointF &p:point2Vtr){
@ -809,8 +817,7 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
PointCalculate::Line line2 = calculateLinearRegression(xVtr,yVtr);
#if 1
///line2
#if 0
QVector<double> xVtr2,yVtr2;
xVtr2.push_back(point2.x());
yVtr2.push_back(point2.y());
@ -846,18 +853,7 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
PointCalculate::Line targetLine;
double maxSlopeAbs = 0.0; // 初始化最大斜率绝对值为0
#if 0
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();
}
}
#endif
// new method
//
for (auto it = tangentLines.begin(); it != tangentLines.end(); ++it) {
if (std::fabs(it.value().slope) > maxSlopeAbs) {
maxSlopeAbs = std::fabs(it.value().slope); // 更新最大斜率绝对值
@ -881,26 +877,17 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
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();
//
#if 1
QPointF intersection1 = PointCalculate::getIntersection(targetLine,line1);
QPointF intersection2 = PointCalculate::getIntersection(targetLine,line2);
// graph 3
// line 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
#if 1
xVtr.push_back(intersection1.x());
yVtr.push_back(intersection1.y());
@ -914,12 +901,50 @@ void CentralWidget::glassTransitionHandle(const double x1,const double x2,const
lineGraph3->setPen(pen);
ItemManager::addTemporaryQCPGraph(lineGraph3,objectName);
_customPlot->replot();
// draw line 2
QVector<double> xVtr2,yVtr2;
xVtr2.push_back(point2.x());
yVtr2.push_back(point2.y());
#if 0
xVtr2.push_back(point2.x() - 10);
double y2 = line2.slope * (point2.x() - 10) + line2.intercept;
yVtr2.push_back(y2);
#endif
double minDistance = PointCalculate::calculateDistance(point2,intersection2);
// 计算延长线另一个端点使线长度超过minDistance.
double halfOfExtendedLineStep = extendedLineStep /2;
double distance = 0.0;
int power = 0;
QPointF line2Endpoint;
while(distance < minDistance){
power++;
line2Endpoint.setX(point2.x() - halfOfExtendedLineStep * power);
line2Endpoint.setY(line2.slope * (point2.x() - halfOfExtendedLineStep * power)
+ line2.intercept);
distance = PointCalculate::calculateDistance(
point2,line2Endpoint);
}
xVtr2.push_back(line2Endpoint.x());
yVtr2.push_back(line2Endpoint.y());
QCPGraph *lineGraph2 = _customPlot->addGraph();
lineGraph2->setData(xVtr2, yVtr2);
lineGraph2->setPen(pen);
ItemManager::addTemporaryQCPGraph(lineGraph2,objectName);
_customPlot->replot();
// point value
double averageY = (point1.y() + point2.y()) / 2;
double averageY = (intersection1.y() + intersection2.y()) / 2;
QPointF averagePoint = PointCalculate::getClosestPointByY(point1.x(),point2.x(),averageY);
@ -1137,6 +1162,9 @@ void CentralWidget::fillGraph(const double x1, const double x2,const QString obj
yVtr.push_back(x2Ed.dsc);
if(_axisMode == AxisMode::DoubleY){
x1Ed = PointCalculate::getClosestDataByTime(x1);
x2Ed = PointCalculate::getClosestDataByTime(x2);
xVtr.clear();
xVtr.push_back(x1Ed.runTime);
@ -1343,11 +1371,14 @@ void CentralWidget::calculateAnalysisResult(
{
logde<<"calculateAnalysisResult...";
logde<<"x1,x2:"<<x1<<","<<x2;
switch (mode) {
case AnalysisMode::NumericalLabel:
{
// QPointF selectPoint = PointCalculate::getClosestPointByX(x1);
QPointF selectPoint;
QString str;
if(_axisMode == AxisMode::SingleY){
Global::ExperimentData ed = PointCalculate::getClosestDataByTemperature(x1);
if(Global::isZero(ed.dsc)){
@ -1355,10 +1386,16 @@ void CentralWidget::calculateAnalysisResult(
return;
}
QPointF selectPoint(ed.sampleTemp,ed.dsc);
QString str = PointCalculate::textFormatNumbericalLabel(selectPoint);
if(_axisMode == AxisMode::DoubleY){
selectPoint.setX(ed.runTime);
selectPoint = QPointF(ed.sampleTemp,ed.dsc);
str = PointCalculate::textFormatNumbericalLabel(selectPoint);
}else{
Global::ExperimentData ed = PointCalculate::getClosestDataByTime(x1);
if(Global::isZero(ed.dsc)){
QMessageBox::warning((QWidget*)this->parent(), "warnning", "曲线选择错误.");
return;
}
selectPoint = QPointF(ed.runTime,ed.dsc);
str = PointCalculate::textFormatNumbericalLabelWithTime(selectPoint);
}
@ -1405,7 +1442,9 @@ void CentralWidget::calculateAnalysisResult(
}
case AnalysisMode::PeakSynthesisAnalysis:
{
fillGraph(x1,x2,objectName);
return;
PointCalculate::setRegionPointX(x1,x2);
@ -1501,7 +1540,6 @@ void CentralWidget::calculateAnalysisResult(
{
glassTransitionHandle(x1,x2,objectName);
//
break;
}
case AnalysisMode::OnsetTemperaturePoint:{
@ -1644,6 +1682,7 @@ void CentralWidget::setAxisMode(AxisMode mode)
if(_axisMode != mode){
_axisMode = mode;
#if 0
// Set axis.
_customPlot->yAxis->setVisible(true);
_customPlot->yAxis->setLabel(AxisDSC);
@ -1660,11 +1699,109 @@ void CentralWidget::setAxisMode(AxisMode mode)
}
_customPlot->replot();
#endif
uiLoadXlsxFileData();
}
}
void CentralWidget::peakSynthesisDoubleAxisY(const double, const double,const QString objectName)
{
}
void CentralWidget::peakSynthesisSingleAxisY(const double x1, const double x2,const QString objectName)
{
fillGraph(x1,x2,objectName);
PointCalculate::setRegionPointX(x1,x2);
//enthalpy
double sampleWeight = 1.0f;
if(Global::_curveFileDataVtr.empty()){
sampleWeight = Global::converStrToDouble(Global::_experimentInfo.sampleWeight);
}else{
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
#if 0
if(_currentCurve && _currentCurve == pti.curve){
sampleWeight = cfd.ei.sampleWeight.toDouble();
}
#endif
if(_currentCurve){
if(_currentCurve == pti.curve){
sampleWeight = cfd.ei.sampleWeight.toDouble();
}else{
}
}else{
// logde<<"current curve nullptr.";
}
}
}
}
if(sampleWeight <= 0){
logde<<"sample weight set value 1,"<<sampleWeight;
sampleWeight = 1;
}
double enthalpyValue = PointCalculate::calculateArea() / sampleWeight;
logde<<"enthalpyValue:"<<enthalpyValue;
// 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(_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){
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,objectName);
}else{
str = PointCalculate::textFormatPeakPoint(
enthalpyValue,
peakPoint.x(),
startEndPointPair.first.x(),
startEndPointPair.second.x());
drawText(peakPoint,str,objectName);
}
}
void CentralWidget::clearAllData()
{
Global::_mode = Global::Mode::Analysis;

View File

@ -123,6 +123,9 @@ private:
const int step,const QString objectName);
void setAxisMode(Global::AxisMode mode);
void peakSynthesisDoubleAxisY(const double,const double,const QString objectName);
void peakSynthesisSingleAxisY(const double,const double,const QString objectName);
private:
AnalysisOperationRecorder::AnalysisMode _analysisMode;
LocalCustomPlot *_customPlot;