#include #include "peakpoint.h" QVectorPeakPoint:: _dataVtr; double 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; // 初始化为 double 类型能表示的最小负数,确保能处理负数 y 值 double maxY = 0.0; bool findFlag = false; // 直接在遍历过程中找出最大波峰 for (int i = 1; i < n - 1; ++i) { const double currentX = _dataVtr.at(i).sampleTemp; const double currentY = _dataVtr.at(i).dsc; if(currentX < _leftPointX){ continue; } if(currentX > _rightPointX){ break; } const double preY = _dataVtr.at(i - 1).dsc; const double 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){ double 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 double maxDiff = std::numeric_limits::min(); QPointF currentPoint,lastPoint; for (int i = 0; i < _dataVtr.size() - 1; ++i) { const double currentX = _dataVtr.at(i).sampleTemp; const double 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 double lastX = _dataVtr.at(i + 1).sampleTemp; const double lastY = _dataVtr.at(i + 1).dsc; double 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); } double PeakPoint::findClosestY(double targetX) { double minDiff = std::numeric_limits::max(); double closestY = 0.0; for(FileManager::ExperimentData &ed:_dataVtr){ // 计算当前 x 与目标 x 的差值的绝对值 double diff = std::abs(ed.sampleTemp - targetX); // 更新最小差值和对应的 y 值 if (diff < minDiff) { minDiff = diff; closestY = ed.dsc; } } return closestY; } QPointF PeakPoint::findClosestPointByX(double 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 double left, const double right) { _leftPointX = left; _rightPointX = right; _leftSelectedPoint = findClosestPointByX(_leftPointX); _rightSelectedPoint = findClosestPointByX(_rightPointX); qDebug()<<"left,right point:"<<_leftSelectedPoint <<","<<_rightSelectedPoint; } QString PeakPoint::textFormat(const double enthalpyValue, const double peakValue, const double startPoint, const double 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 double A1 = p2.y() - p1.y(); double B1 = p1.x() - p2.x(); double C1 = A1 * p1.x() + B1 * p1.y(); double A2 = p4.y() - p3.y(); double B2 = p3.x() - p4.x(); double C2 = A2 * p3.x() + B2 * p3.y(); double determinant = A1 * B2 - A2 * B1; if (determinant == 0) { // 两条直线平行或重合,无交点或无限交点 return {0, 0}; } else { double x = (B2 * C1 - B1 * C2) / determinant; double y = (A1 * C2 - A2 * C1) / determinant; return {x, y}; } } double PeakPoint::calculateArea(const std::vector &points) { double integral = 0.0; size_t n = points.size(); if (n < 2) { return integral; // 至少需要两个点才能计算积分 } for (size_t i = 1; i < n; ++i) { double dx = points[i].x() - points[i - 1].x(); double avg_y = (points[i].y() + points[i - 1].y()) / 2.0; integral += dx * avg_y; } return integral; }