diff --git a/src/data/pointcalculate.cpp b/src/data/pointcalculate.cpp index 5a1437b..d13af3b 100644 --- a/src/data/pointcalculate.cpp +++ b/src/data/pointcalculate.cpp @@ -184,6 +184,7 @@ void PointCalculate::setRegionPointX(const float left, const float right) _rightSelectedPoint = getClosestPointByX(right); _peakPoint = getPeakPoint(); + logde<<"peak point:"<<_peakPoint.x()<<","<<_peakPoint.y(); //根据峰谷重置选择点。 @@ -197,7 +198,8 @@ QVector PointCalculate::getPeakPointGroup() { QVector pointVtr; for(FileManager::ExperimentData& ed:_dataVtr) { - if(ed.sampleTemp >= _leftSelectedPoint.x() && ed.sampleTemp <= _rightSelectedPoint.x()){ + if(ed.sampleTemp >= _leftSelectedPoint.x() && + ed.sampleTemp <= _rightSelectedPoint.x()){ pointVtr.push_back(QPointF(ed.sampleTemp,ed.dsc)); } } @@ -205,7 +207,7 @@ QVector PointCalculate::getPeakPointGroup() return pointVtr; } -double PointCalculate::calculateArea() { +float PointCalculate::calculateArea() { //getPoint group QVector points = getPeakPointGroup(); @@ -218,27 +220,27 @@ double PointCalculate::calculateArea() { } //find a line. - double k = (_leftSelectedPoint.y() - _rightSelectedPoint.y()) / + float k = (_leftSelectedPoint.y() - _rightSelectedPoint.y()) / (_leftSelectedPoint.x() - _rightSelectedPoint.x()); - double b = _leftSelectedPoint.y() - k * _leftSelectedPoint.x(); + float b = _leftSelectedPoint.y() - k * _leftSelectedPoint.x(); for (size_t i = 0; i < n - 1; ++i) { #if 1 - double x1 = points[i].x(); - double y1 = points[i].y(); + float x1 = points[i].x(); + float y1 = points[i].y(); - double x2 = points[i + 1].x(); - double y2 = points[i + 1].y(); + float x2 = points[i + 1].x(); + float y2 = points[i + 1].y(); #endif - double yLine1 = k * x1 + b; - double yLine2 = k * x2 + b; + float yLine1 = k * x1 + b; + float yLine2 = k * x2 + b; - double diff1 = y1 - yLine1; - double diff2 = y2 - yLine2; + float diff1 = y1 - yLine1; + float diff2 = y2 - yLine2; - double dx = x2 - x1; + float dx = x2 - x1; - double cellArea = (diff1 + diff2) * dx /2.0; + float cellArea = (diff1 + diff2) * dx /2.0; integral += std::abs(cellArea); } @@ -289,9 +291,9 @@ void PointCalculate::updateStartEndPoint() } } QString PointCalculate::textFormatPeakPoint(const float enthalpyValue, - const float peakValue, - const float startPoint, - const float endPoint) + const float peakValue, + const float startPoint, + const float endPoint) { return QString("峰的综合信息:\n" "焓值:%1 J/g \n" @@ -306,7 +308,7 @@ QString PointCalculate::textFormatPeakPoint(const float enthalpyValue, // 计算两条直线的交点 QPointF PointCalculate::calculateIntersection(const QPointF p1,const QPointF p2, - const QPointF p3, const QPointF p4){ + const QPointF p3, const QPointF p4){ // 直线的一般式: A1x + B1y + C1 = 0 和 A2x + B2y + C2 = 0 float A1 = p2.y() - p1.y(); float B1 = p1.x() - p2.x(); @@ -328,6 +330,44 @@ QPointF PointCalculate::calculateIntersection(const QPointF p1,const QPointF p2, } } +QPair PointCalculate::getCurveInflectionPointTangent(const float x1,const float x2) +{ + std::vector dataVtr; + for(FileManager::ExperimentData& ed:_dataVtr){ + if(x1 < ed.sampleTemp && ed.sampleTemp < x2){ + dataVtr.push_back(ed.sampleTemp); + } + } + // + std::vector processedVtr = movingAverage(dataVtr,5); + + // find max slope. + float maxSlope = 0.0; + float targetX = 0.0; + for (size_t i = 1; i < processedVtr.size(); ++i) { + float slope = processedVtr[i] - processedVtr[i - 1]; + if(std::abs(slope) > maxSlope){ + maxSlope = slope; + targetX = processedVtr[i]; + } + } + + // calculate line slope and axis Y space number b. + QPointF point = getClosestPointByX(targetX); + + // 使用点斜式方程求y轴截距 + // y = m * x + b + // double b = y - m * x; + float b = point.y() - maxSlope * point.x(); + + return qMakePair(maxSlope,b); +} +QPointF PointCalculate::getIntersectionBySlope(const LineStruct& line1, const LineStruct& line2) { + float x = (line2.intercept - line1.intercept) / (line1.slope - line2.slope); + float y = line1.slope * x + line1.intercept; +// return {x, y}; + return QPointF(x,y); +} QPointF PointCalculate::getClosestPointByX(const float targetX) { #if 0 @@ -362,7 +402,7 @@ QPointF PointCalculate::getClosestPointByX(const float targetX) if(left > 0 && std::abs(resultPointF.x() - targetX) > std::abs(_dataVtr.at(left - 1).sampleTemp - targetX)){ - // + // resultPointF = QPointF(_dataVtr.at(left - 1).sampleTemp, _dataVtr.at(left - 1).dsc); } @@ -381,10 +421,11 @@ QString PointCalculate::textFormatNumbericalLabel(const QPointF point) QPair PointCalculate::getStartAndEndPoint() { if(_dataVtr.empty()){ - return qMakePair(QPointF(), QPointF()); + return qMakePair(QPointF(), QPointF()); } - FileManager::ExperimentData startPoint = _dataVtr.at(0); - FileManager::ExperimentData endPoint = _dataVtr.at(_dataVtr.size() - 1); + + FileManager::ExperimentData startPoint = _dataVtr.at(0); + FileManager::ExperimentData endPoint = _dataVtr.at(_dataVtr.size() - 1); return qMakePair( QPointF(startPoint.sampleTemp,startPoint.dsc), @@ -405,12 +446,16 @@ QString PointCalculate::textFormatEndPoint(const QPointF point) ).arg(QString::number(point.x(), 'f', 3)); } -QPair PointCalculate::getCurveInflectionPointTangent() + +QPointF PointCalculate::getClosestPointByY(const float left,const float right,const float valueY) { - -} - -QVector PointCalculate::getRegionPoints(const float, const float) -{ - + float minValue = 100.0; + for(FileManager::ExperimentData& ed:_dataVtr){ + if(left < ed.sampleTemp && ed.sampleTemp < right){ + if(std::abs(ed.dsc - valueY) < minValue){ + return QPointF(ed.sampleTemp,ed.dsc); + } + } + } + return QPointF(); } diff --git a/src/data/pointcalculate.h b/src/data/pointcalculate.h index 1a4c81d..b409991 100644 --- a/src/data/pointcalculate.h +++ b/src/data/pointcalculate.h @@ -12,7 +12,13 @@ QPair getStartAndEndPoint(); void setRegionPointX(const float,const float); QPointF getClosestPointByX(const float); +QPointF getClosestPointByY(const float left,const float right,const float valueY); QPointF getPeakPoint(); + +QPair calculateStartAndEndPoint(); +float calculateArea(); + +// text format QString textFormatPeakPoint(const float enthalpyValue, const float peakValue, const float startPoint, @@ -21,12 +27,14 @@ QString textFormatNumbericalLabel(const QPointF); QString textFormatStartPoint(const QPointF); QString textFormatEndPoint(const QPointF); -QPair calculateStartAndEndPoint(); -double calculateArea(); +// glass transition +QPair getCurveInflectionPointTangent(const float,const float); +struct LineStruct { + float slope; // + float intercept; // +}; +QPointF getIntersectionBySlope(const LineStruct& line1, const LineStruct& line2); -//​获取曲线拐点处的切线 -QPair getCurveInflectionPointTangent(); -QVector getRegionPoints(const float,const float); //private void updateStartEndPoint(); QPair calculateMaxDiffPointLeft(); diff --git a/src/ui/centralwidget.cpp b/src/ui/centralwidget.cpp index 4bb780a..8859fbd 100644 --- a/src/ui/centralwidget.cpp +++ b/src/ui/centralwidget.cpp @@ -231,9 +231,9 @@ void CentralWidget::slotAnalysisSettingApply() <point1->setCoords(point1.x() - 55,point1.y()); - line1->point2->setCoords(point1.x() + 55,point1.y()); - line1->setPen(QPen(Qt::darkGreen)); + line1->point1->setCoords(point1.x() - 5,point1.y()); + line1->point2->setCoords(point1.x() + 5,point1.y()); + line1->setPen(QPen(Qt::darkRed)); line1->setSelectable(false); line1->setVisible(true); QCPItemStraightLine *line2 = new QCPItemStraightLine(_customPlot); - line2->point1->setCoords(point2.x() - 55,point2.y()); - line2->point2->setCoords(point2.x() + 55,point2.y()); + line2->point1->setCoords(point2.x() - 5,point2.y()); + line2->point2->setCoords(point2.x() + 5,point2.y()); line2->setPen(QPen(Qt::darkGreen)); line2->setSelectable(false); line2->setVisible(true); + _customPlot->replot(); + // + PointCalculate::LineStruct lineStrc1,lineStrc2,tangetLineStrc; + + lineStrc1.slope = 0.0; + lineStrc1.intercept = point1.y(); + + lineStrc2.slope = 0.0; + lineStrc2.intercept = point2.y(); + + QPair tangentLinePair = PointCalculate::getCurveInflectionPointTangent(point1.x(),point2.x()); + tangetLineStrc.slope = tangentLinePair.first; + tangetLineStrc.intercept = tangentLinePair.second; + + QPointF intersection1 = PointCalculate::getIntersectionBySlope(tangetLineStrc,lineStrc1); + QPointF intersection2 = PointCalculate::getIntersectionBySlope(tangetLineStrc,lineStrc2); + + // logde<<"intersection1 x:"<addItem(circle); + + // 设置圆形的位置和大小 + circle->topLeft->setCoords(-5, 5); + circle->bottomRight->setCoords(5, -5); + + // 设置圆形的填充和边框颜色 + circle->setBrush(QBrush(Qt::cyan)); + circle->setPen(QPen(Qt::blue)); +#endif + + QCPItemStraightLine *line3 = new QCPItemStraightLine(_customPlot); + line3->point1->setCoords(averagePoint.x() + 2,averagePoint.y() + 2); + line3->point2->setCoords(averagePoint.x() - 2,averagePoint.y() - 2); + line3->setPen(QPen(Qt::black)); + line3->setSelectable(false); + line3->setVisible(true); + _customPlot->replot(); } diff --git a/src/ui/centralwidget.h b/src/ui/centralwidget.h index dea6348..03bf67b 100644 --- a/src/ui/centralwidget.h +++ b/src/ui/centralwidget.h @@ -50,6 +50,7 @@ private: void setEventHandlerEnable(const bool); void drawText(const QPointF,const QString); void fillGraph(const double x1,const double x2); + enum ClearDataMode{ All, Undo