#include #include "peakpoint.h" QVectorPeakPoint:: _dataVtr; float PeakPoint::_leftPointX,PeakPoint::_rightPointX; QPointF PeakPoint::_peakPoint; QPointF PeakPoint::_leftSelectedPoint,PeakPoint::_rightSelectedPoint; void PeakPoint::setExperimentData(const QVector &dataVtr) { _dataVtr = dataVtr; } QPointF PeakPoint::findPeakPoint(){ int n = _dataVtr.size(); if (n < 3) { return QPointF(); // 至少需要三个点才能找到波峰 } QPointF uniquePeak; // 初始化为 float 类型能表示的最小负数,确保能处理负数 y 值 float maxY = 0.0; bool findFlag = false; // 直接在遍历过程中找出最大波峰 for (int i = 1; i < n - 1; ++i) { const float currentX = _dataVtr.at(i).sampleTemp; const float currentY = _dataVtr.at(i).dsc; if(currentX < _leftPointX){ continue; } if(currentX > _rightPointX){ break; } const float preY = _dataVtr.at(i - 1).dsc; const float lastY = _dataVtr.at(i + 1).dsc; findFlag = false; if(currentY >= preY && currentY >= lastY){ findFlag = true; }else if(currentY <= preY && currentY <= lastY){ findFlag = true; } if(findFlag){ float absY = std::abs(currentY); if(absY >= maxY){ maxY = absY; uniquePeak = QPointF(currentX,currentY); } } } _peakPoint = uniquePeak; return uniquePeak; } QPair PeakPoint::calculateMaxDiffPointDetail( const PeakPoint::MaxDiffPointDetailType type) { #if 1 float maxDiff = std::numeric_limits::min(); QPointF currentPoint,lastPoint; for (int i = 0; i < _dataVtr.size() - 1; ++i) { const float currentX = _dataVtr.at(i).sampleTemp; const float currentY = _dataVtr.at(i).dsc; if(type == MaxDiffPointDetailType::Left){ if(currentX <= _leftPointX){ continue; } if(currentX >= _peakPoint.x()){ break; } }else{ if(currentX <= _peakPoint.x()){ continue; } if(currentX >= _rightPointX){ break; } } // const float lastX = _dataVtr.at(i + 1).sampleTemp; const float lastY = _dataVtr.at(i + 1).dsc; float diff = std::abs(currentY - lastY); if(diff > maxDiff){ maxDiff = diff; currentPoint.setX(currentX); currentPoint.setY(currentY); lastPoint.setX(lastX); lastPoint.setY(lastY); } } #endif return qMakePair(currentPoint,lastPoint); } QPair PeakPoint::calculateMaxDiffPointLeft() { return calculateMaxDiffPointDetail(MaxDiffPointDetailType::Left); } QPair PeakPoint::calculateMaxDiffPointRight() { return calculateMaxDiffPointDetail(MaxDiffPointDetailType::Right); } float PeakPoint::findClosestY(float targetX) { float minDiff = std::numeric_limits::max(); float closestY = 0.0; for(FileManager::ExperimentData &ed:_dataVtr){ // 计算当前 x 与目标 x 的差值的绝对值 float diff = std::abs(ed.sampleTemp - targetX); // 更新最小差值和对应的 y 值 if (diff < minDiff) { minDiff = diff; closestY = ed.dsc; } } return closestY; } QPointF PeakPoint::findClosestPointByX(float x) { int left = 0; int right = _dataVtr.size() - 1; QPointF targetPoint; targetPoint.setX(_dataVtr.value(0).sampleTemp); targetPoint.setY(_dataVtr.value(0).dsc); while (left <= right) { int mid = left + (right - left) / 2; FileManager::ExperimentData& ed = _dataVtr[mid]; if (std::abs(ed.sampleTemp - x) < std::abs(targetPoint.x() - x)) { targetPoint.setX(ed.sampleTemp); targetPoint.setY(ed.dsc); } if(ed.sampleTemp < x){ left = mid + 1; } else { right = mid - 1; } } return targetPoint; } void PeakPoint::setRegionPointX(const float left, const float right) { _leftPointX = left; _rightPointX = right; _leftSelectedPoint = findClosestPointByX(_leftPointX); _rightSelectedPoint = findClosestPointByX(_rightPointX); findPeakPoint(); updateStartEndPoint(); qDebug()<<"left,right point:"<<_leftSelectedPoint <<","<<_rightSelectedPoint; } QVector PeakPoint::getPeakPointGroup() { QVector pointVtr; for(FileManager::ExperimentData& ed:_dataVtr) { if(ed.sampleTemp >= _leftSelectedPoint.x() && ed.sampleTemp <= _rightSelectedPoint.x()){ pointVtr.push_back(QPointF(ed.sampleTemp,ed.dsc)); } } return pointVtr; } double PeakPoint::calculateArea() { //getPoint group QVector points = getPeakPointGroup(); #if 0 for(QPointF point:points){ qDebug()<<"x,y:"< PeakPoint::calculateStartAndEndPoint() { QPair leftMaxDiffPointPair = PeakPoint::calculateMaxDiffPointLeft(); QPair rightMaxDiffPointPair = PeakPoint::calculateMaxDiffPointRight(); QPointF startPoint = calculateIntersection(_leftSelectedPoint,_rightSelectedPoint, leftMaxDiffPointPair.first,leftMaxDiffPointPair.second); QPointF endPoint = calculateIntersection(_leftSelectedPoint,_rightSelectedPoint, rightMaxDiffPointPair.first,rightMaxDiffPointPair.second); return qMakePair(startPoint,endPoint); } void PeakPoint::updateStartEndPoint() { //需要在a1和a2之间查询是否有高于a1和a2之间的点,若存在,则重新给a1、a2赋值 for(FileManager::ExperimentData& ed:_dataVtr){ if(ed.sampleTemp > _leftSelectedPoint.x() && ed.sampleTemp < _peakPoint.x()){ if(ed.dsc > _leftSelectedPoint.y()){ _leftSelectedPoint.setX(ed.sampleTemp); _leftSelectedPoint.setY(ed.dsc); } } if(ed.sampleTemp < _rightSelectedPoint.x() && ed.sampleTemp > _peakPoint.x()){ if(ed.dsc > _rightSelectedPoint.y()){ _rightSelectedPoint.setX(ed.sampleTemp); _rightSelectedPoint.setY(ed.dsc); } } } } QString PeakPoint::textFormat(const float enthalpyValue, const float peakValue, const float startPoint, const float endPoint) { return QString("峰的综合信息:\n" "焓值:%1 J/g \n" "峰值:%2℃ \n" "起始点:%3℃ \n" "终止点:%4℃" ).arg(QString::number(enthalpyValue, 'f', 2)) .arg(QString::number(peakValue, 'f', 2)) .arg(QString::number(startPoint, 'f', 2)) .arg(QString::number(endPoint, 'f', 2)); } // 计算两条直线的交点 QPointF PeakPoint::calculateIntersection(const QPointF p1,const QPointF p2, 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(); float C1 = A1 * p1.x() + B1 * p1.y(); float A2 = p4.y() - p3.y(); float B2 = p3.x() - p4.x(); float C2 = A2 * p3.x() + B2 * p3.y(); float determinant = A1 * B2 - A2 * B1; if (determinant == 0) { // 两条直线平行或重合,无交点或无限交点 return {0, 0}; } else { float x = (B2 * C1 - B1 * C2) / determinant; float y = (A1 * C2 - A2 * C1) / determinant; return {x, y}; } }