DSCAnalysisTool/src/ui/coefficientselectionform.cpp

340 lines
9.5 KiB
C++
Raw Normal View History

2025-04-18 09:30:35 +00:00
#include <QFileDialog>
#include "coefficientselectionform.h"
#include "ui_coefficientselectionform.h"
#include "confighandler.h"
#include "logger.h"
#include "global.h"
CoefficientSelectionForm::CoefficientSelectionForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::CoefficientSelectionForm)
{
ui->setupUi(this);
setWindowTitle("热焓校正系数选择");
#if 1
ui->LineEditCoefficient->setText(
QString::number(
ConfigHandler::_configMap[ConInstrumentCoefficientStr].toFloat(),
'f',3));
#endif
ui->radioButtonSinglePointCoefficient->setChecked(true);
ui->radioButtonSinglePointCoefficient->setChecked(false);
on_radioButtonSinglePointCoefficient_toggled(true);
on_radioButtonMultiPointCoefficient_toggled(false);
ui->textEditFileContent->setReadOnly(true);
}
CoefficientSelectionForm::~CoefficientSelectionForm()
{
delete ui;
}
2025-04-21 01:32:54 +00:00
void CoefficientSelectionForm::showEvent(QShowEvent *event)
{
}
2025-04-18 09:30:35 +00:00
void CoefficientSelectionForm::on_pushButtonCalculate_clicked()
{
float theory = ui->LineEditTheory->text().toFloat();
float measure = ui->LineEditActualMeasurement->text().toFloat();
_instrumentCoefficient = theory/measure;
ui->LineEditCoefficient->setText(QString::number(_instrumentCoefficient,'f',3));
}
void CoefficientSelectionForm::on_pushButtonConfirm_clicked()
{
if(ui->radioButtonSinglePointCoefficient->isChecked()){
ConfigHandler::_configMap[ConInstrumentCoefficientStr] = _instrumentCoefficient;
ConfigHandler::writer();
Global::_enthalpyCoefficientEnableFlag = false;
}else{
2025-05-07 09:33:03 +00:00
QJsonDocument doc = QJsonDocument::fromJson(_jsonStr.toUtf8());
if (doc.isNull()) {
logde << "Failed to parse JSON data";
return;
}
if (!doc.isObject()) {
logde << "JSON data is not an object";
return ;
}
QJsonObject majorObj = doc.object();
{
QJsonObject subObj = majorObj[Global::AtomsphereData].toObject();
double temperature = subObj[Global::Atmosphere].toDouble();
double heatingRate = subObj[Global::HeatingRate].toDouble();
logde<<"temperatur:"<<temperature;
logde<<"heatingRate:"<<heatingRate;
}
2025-04-18 09:30:35 +00:00
2025-05-07 09:33:03 +00:00
QJsonArray jsonArray = majorObj[Global::SampleData].toArray();
QVector<double> xVtr,yVtr;
2025-04-18 09:30:35 +00:00
for (const QJsonValue &value : jsonArray) {
QJsonObject jsonObj = value.toObject();
2025-05-07 09:33:03 +00:00
xVtr<<jsonObj[Global::TemperatureStr].toDouble();
yVtr<<jsonObj[Global::RateStr].toDouble();
2025-04-18 09:30:35 +00:00
}
double coeff[3] = {0};
2025-05-06 09:26:23 +00:00
quadraticLeastSquaresFit(xVtr.data(),yVtr.data(),xVtr.size(),coeff);
#if 0
std::cout << "Fitted quadratic polynomial: y = "
<< coeff[0] << "x^2 + "
<< coeff[1] << "x + "
<< coeff[2] << std::endl;
#endif
2025-05-07 09:33:03 +00:00
logde<<"y:"<<coeff[0]<<"x2,"
<<coeff[1]<<"x,"
2025-04-18 09:30:35 +00:00
<<coeff[2];
2025-04-21 01:32:54 +00:00
Global::_enthalpyCoefficientEnableFlag = true;
2025-04-18 09:30:35 +00:00
Global::_enthalpyCoefficientVtr.clear();
Global::_enthalpyCoefficientVtr.push_back(coeff[2]);
Global::_enthalpyCoefficientVtr.push_back(coeff[1]);
Global::_enthalpyCoefficientVtr.push_back(coeff[0]);
}
2025-04-21 01:32:54 +00:00
hide();
2025-04-18 09:30:35 +00:00
}
void CoefficientSelectionForm::on_pushButtonExit_clicked()
{
2025-04-21 01:32:54 +00:00
#if 0
2025-04-18 09:30:35 +00:00
ui->LineEditTheory->clear();
ui->LineEditCoefficient->clear();
ui->labelFilePath->clear();
ui->textEditFileContent->clear();
_jsonStr.clear();
2025-04-21 01:32:54 +00:00
#endif
2025-04-18 09:30:35 +00:00
hide();
}
2025-05-07 09:33:03 +00:00
2025-05-06 09:26:23 +00:00
void CoefficientSelectionForm::quadraticLeastSquaresFit(double x[], double y[], int n, double coeff[]) {
if (n < 3) {
2025-05-07 09:33:03 +00:00
throw std::invalid_argument("At least 3 data points are required for quadratic fitting");
2025-05-06 09:26:23 +00:00
}
2025-05-07 09:33:03 +00:00
double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
double sum_y = 0, sum_xy = 0, sum_x2y = 0;
2025-05-06 09:26:23 +00:00
2025-05-07 09:33:03 +00:00
// 计算各项累加和
2025-05-06 09:26:23 +00:00
for (int i = 0; i < n; ++i) {
2025-05-07 09:33:03 +00:00
double xi = x[i];
double xi2 = xi * xi;
double xi3 = xi2 * xi;
double xi4 = xi3 * xi;
double yi = y[i];
sum_x += xi;
sum_x2 += xi2;
sum_x3 += xi3;
sum_x4 += xi4;
sum_y += yi;
sum_xy += xi * yi;
sum_x2y += xi2 * yi;
2025-05-06 09:26:23 +00:00
}
2025-04-18 09:30:35 +00:00
2025-05-07 09:33:03 +00:00
// 构建正规方程组的增广矩阵
double matrix[3][4] = {
{sum_x4, sum_x3, sum_x2, sum_x2y}, // 对应方程: a*Σx⁴ + b*Σx³ + c*Σx² = Σx²y
{sum_x3, sum_x2, sum_x, sum_xy}, // 对应方程: a*Σx³ + b*Σx² + c*Σx = Σxy
{sum_x2, sum_x, static_cast<double>(n), sum_y} // 对应方程: a*Σx² + b*Σx + c*n = Σy
2025-05-06 09:26:23 +00:00
};
2025-05-07 09:33:03 +00:00
// 高斯消元法解方程组
2025-05-06 09:26:23 +00:00
for (int i = 0; i < 3; ++i) {
2025-05-07 09:33:03 +00:00
// 部分主元选择
int maxRow = i;
for (int k = i + 1; k < 3; ++k) {
if (std::abs(matrix[k][i]) > std::abs(matrix[maxRow][i])) {
maxRow = k;
2025-05-06 09:26:23 +00:00
}
}
// 交换行
2025-05-07 09:33:03 +00:00
for (int k = i; k < 4; ++k) {
std::swap(matrix[i][k], matrix[maxRow][k]);
2025-05-06 09:26:23 +00:00
}
// 消元
2025-05-07 09:33:03 +00:00
for (int k = i + 1; k < 3; ++k) {
double factor = matrix[k][i] / matrix[i][i];
for (int j = i; j < 4; ++j) {
matrix[k][j] -= factor * matrix[i][j];
2025-05-06 09:26:23 +00:00
}
}
}
// 回代求解
2025-05-07 09:33:03 +00:00
coeff[2] = matrix[2][3] / matrix[2][2]; // c
coeff[1] = (matrix[1][3] - matrix[1][2] * coeff[2]) / matrix[1][1]; // b
coeff[0] = (matrix[0][3] - matrix[0][2] * coeff[2] - matrix[0][1] * coeff[1]) / matrix[0][0]; // a
2025-05-06 09:26:23 +00:00
}
2025-04-18 09:30:35 +00:00
void CoefficientSelectionForm::on_pushButtonSelectFile_clicked()
{
QString filePath = QFileDialog::getOpenFileName(
nullptr, "选择 JSON 文件", "", "JSON 文件 (*.json);;所有文件 (*.*)");
if (!filePath.isEmpty()) {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
_jsonStr = in.readAll();
file.close();
} else {
qDebug() << "无法打开文件:" << filePath;
return;
}
} else {
qDebug() << "未选择文件";
return;
}
//
ui->labelFilePath->setText(filePath);
2025-05-07 09:33:03 +00:00
ui->labelFilePath->setToolTip(filePath);
2025-04-18 09:30:35 +00:00
ui->textEditFileContent->setText(_jsonStr);
}
void CoefficientSelectionForm::on_radioButtonSinglePointCoefficient_toggled(bool checked)
{
ui->LineEditTheory->setEnabled(checked);
ui->LineEditCoefficient->setEnabled(checked);
ui->LineEditActualMeasurement->setEnabled(checked);
ui->pushButtonCalculate->setEnabled(checked);
#if 0
if(checked){
ui->LineEditTheory->setEnabled(true);
ui->LineEditCoefficient->setEnabled(true);
ui->LineEditActualMeasurement->setEnabled(true);
ui->pushButtonCalculate->setEnabled(true);
}else{
ui->LineEditTheory->setEnabled(false);
ui->LineEditCoefficient->setEnabled(false);
ui->LineEditActualMeasurement->setEnabled(false);
ui->pushButtonCalculate->setEnabled(false);
}
#endif
}
void CoefficientSelectionForm::on_radioButtonMultiPointCoefficient_toggled(bool checked)
{
ui->pushButtonSelectFile->setEnabled(checked);
ui->textEditFileContent->setEnabled(checked);
#if 0
if(checked){
ui->pushButtonSelectFile->setEnabled(true);
ui->textEditFileContent->setEnabled(true);
}else{
ui->pushButtonSelectFile->setEnabled(false);
ui->textEditFileContent->setEnabled(false);
}
#endif
}
void CoefficientSelectionForm::cubicLeastSquaresFit(
double x[], double y[], int n, double coeff[])
{
int i, j, k;
2025-05-06 09:26:23 +00:00
double atemp[3] = {0}; // 存储x^0, x^1, x^2的和
double b[3] = {0}; // 右侧向量
// 计算各次幂的和
for (i = 0; i < n; i++) {
double xi = x[i];
double xi_pow2 = xi * xi; // x^2
// 累加atemp[0]到atemp[2]
atemp[0] += 1; // x^0的和等于数据点个数
atemp[1] += xi;
atemp[2] += xi_pow2;
// 计算右侧向量b
double yi = y[i];
b[0] += yi;
b[1] += yi * xi;
b[2] += yi * xi_pow2;
}
// 构建法方程矩阵
double a[3][3];
a[0][0] = atemp[0];
a[0][1] = atemp[1];
a[0][2] = atemp[2];
a[1][0] = atemp[1];
a[1][1] = atemp[2];
a[1][2] = 0;
a[2][0] = atemp[2];
a[2][1] = 0;
a[2][2] = 0;
// 高斯列主元消元法
for (k = 0; k < 2; k++) { // 消去第k列
// 寻找主元行
int max_row = k;
double max_val = fabs(a[k][k]);
for (i = k + 1; i < 3; i++) {
if (fabs(a[i][k]) > max_val) {
max_val = fabs(a[i][k]);
max_row = i;
}
}
// 交换行
if (max_row != k) {
for (j = k; j < 3; j++) {
double temp = a[k][j];
a[k][j] = a[max_row][j];
a[max_row][j] = temp;
}
double temp_b = b[k];
b[k] = b[max_row];
b[max_row] = temp_b;
}
// 消元
for (i = k + 1; i < 3; i++) {
double factor = a[i][k] / a[k][k];
for (j = k; j < 3; j++) {
a[i][j] -= factor * a[k][j];
}
b[i] -= factor * b[k];
}
}
// 回代求解
coeff[2] = b[2] / a[2][2];
for (i = 1; i >= 0; i--) {
double sum = 0.0;
for (j = i + 1; j < 3; j++) {
sum += a[i][j] * coeff[j];
}
coeff[i] = (b[i] - sum) / a[i][i];
}
2025-04-18 09:30:35 +00:00
}