#include "nmCalculationUtils.h" #include #include #include #include #include #include #include #include "pch.h" namespace { QString krigingText(const char* sourceText) { return QCoreApplication::translate("nmCalculationUtils", sourceText); } bool isFiniteValue(double value) { #ifdef _MSC_VER return _finite(value) != 0; #else return std::isfinite(value); #endif } void setKrigingError(QString* errorMessage, const QString& message) { if(errorMessage != NULL) { *errorMessage = message; } } } nmCalculationUtils::nmCalculationUtils() { } bool nmCalculationUtils::copyFileToDir(QString filePath, QString destDir) { // 如果文件不存在,则退出 if(!QFile::exists(filePath)) { return false; } // 如果目标目录不存在,则创建 if(!QDir(destDir).exists()) { if(!QDir().mkdir(destDir)) { qWarning() << "cannot mkdir:" << destDir; return false; } } // 获取源文件的文件名 QString fileName = QFileInfo(filePath).fileName(); // 构造目标文件的完整路径 QString destinationFilePath = QDir(destDir).filePath(fileName); // 如果目标文件已存在,则删除 if(QFile::exists(destinationFilePath)) { QFile destinationFile(destinationFilePath); if(!destinationFile.remove()) { qWarning() << "cannot delete file:" << destinationFilePath; return false; } } // 拷贝文件 if(QFile::copy(filePath, destinationFilePath)) { qDebug() << "file copy success:" << destinationFilePath; return true; } else { qWarning() << "file copy failed:" << destinationFilePath; return false; } return true; } bool nmCalculationUtils::createDirectoryIfNotExists(QString directoryPath) { QDir dir(directoryPath); // 检查目录是否存在 if(dir.exists()) { // 目录已存在 return true; } // 尝试创建目录 if(dir.mkpath(directoryPath)) { // 创建成功 return true; } // 创建失败 qDebug() << "创建目录失败,错误代码。"; return false; } bool nmCalculationUtils::copyFile(const std::string& sourcePath, const std::string& destinationPath) { std::ifstream src(sourcePath, std::ios::binary); // 以二进制模式打开源文件 std::ofstream dst(destinationPath, std::ios::binary); // 以二进制模式打开目标文件 if(!src || !dst) { std::cerr << "文件打开失败" << std::endl; return false; } dst << src.rdbuf(); // 拷贝文件内容 return true; } bool nmCalculationUtils::removeDirectory(const QString &dirPath) { QDir dir(dirPath); if(!dir.exists()) { qDebug() << "Directory does not exist."; return true; } // 获取目录中的所有文件和目录 QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden); foreach(QFileInfo fileInfo, fileList) { if(fileInfo.isDir()) { // 递归删除子目录 if(!removeDirectory(fileInfo.absoluteFilePath())) { return false; } } else { // 删除文件 if(!QFile::remove(fileInfo.absoluteFilePath())) { qDebug() << "Failed to remove file:" << fileInfo.absoluteFilePath(); return false; } } } // 删除目录自身 if(!dir.rmdir(dirPath)) { qDebug() << "Failed to remove directory:" << dirPath; return false; } return true; } bool nmCalculationUtils::writeFile(const QStringList& content, const QString &filePath) { QFile file(filePath); //检查 if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qWarning("Cannot open file for writing: %s", qPrintable(file.errorString())); return false; } QTextStream out(&file); out << content.join("\n"); file.close(); return true; } QStringList nmCalculationUtils::readFile(const QString &filePath) { QStringList content; // 打开文件 QFile file(filePath); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "Failed to open file:" << filePath; return content; } // 使用QTextStream读取文件 QTextStream in(&file); while(!in.atEnd()) { // 读取一行 QString line = in.readLine(); // 将行内容放入QStringList content.append(line); } // 关闭文件 file.close(); return content; } bool nmCalculationUtils::calculateKriging( const QVector& targetPoints, const QVector& measurementPoints, const QVector& measurementValues, double nugget, double sill, double range, int model, const QString& licensePath, QVector& outputValues, QString* errorMessage) { outputValues.clear(); setKrigingError(errorMessage, QString()); if(targetPoints.isEmpty()) { setKrigingError(errorMessage, krigingText("No interpolation points are available.")); return false; } if(measurementPoints.size() < 2) { setKrigingError(errorMessage, krigingText("At least two measurement points are required.")); return false; } if(measurementPoints.size() != measurementValues.size()) { setKrigingError(errorMessage, krigingText("Measurement point coordinates and values do not match.")); return false; } if(!isFiniteValue(nugget) || !isFiniteValue(sill) || !isFiniteValue(range) || nugget < 0.0 || sill <= 0.0 || range <= 0.0) { setKrigingError(errorMessage, krigingText("Kriging parameters are invalid.")); return false; } if(model < 0 || model > 2) { setKrigingError(errorMessage, krigingText("The Kriging model is invalid.")); return false; } for(int i = 0; i < targetPoints.size(); ++i) { if(!isFiniteValue(targetPoints[i].x()) || !isFiniteValue(targetPoints[i].y())) { setKrigingError(errorMessage, krigingText("An interpolation point contains an invalid coordinate.")); return false; } } for(int i = 0; i < measurementPoints.size(); ++i) { if(!isFiniteValue(measurementPoints[i].x()) || !isFiniteValue(measurementPoints[i].y()) || !isFiniteValue(measurementValues[i])) { setKrigingError(errorMessage, krigingText("A measurement point contains invalid data.")); return false; } for(int j = 0; j < i; ++j) { if(measurementPoints[i] == measurementPoints[j]) { setKrigingError(errorMessage, krigingText("Measurement point coordinates cannot be duplicated.")); return false; } } } if(licensePath.isEmpty() || !QFileInfo(licensePath).exists()) { setKrigingError(errorMessage, krigingText("The solver license file was not found.")); return false; } HMODULE dll = LoadLibrary(L"HX_NWTM.dll"); if(dll == NULL) { setKrigingError(errorMessage, krigingText("Failed to load HX_NWTM.dll.")); return false; } typedef void (*HX_NWTM_KRINGING_Func)(HX_KRING_OUTPUT&, const HX_KRING_INPUT, std::string); HX_NWTM_KRINGING_Func krigingFunction = (HX_NWTM_KRINGING_Func)GetProcAddress(dll, "HX_NWTM_KRINGING"); if(krigingFunction == NULL) { FreeLibrary(dll); setKrigingError(errorMessage, krigingText("The Kriging interface was not found in HX_NWTM.dll.")); return false; } // 求解器p参数每行保存{x, y},并保持targetPoints的原始顺序. dVec2 targetData; targetData.reserve(targetPoints.size()); for(int i = 0; i < targetPoints.size(); ++i) { dVec1 point(2, 0.0); point[0] = targetPoints[i].x(); point[1] = targetPoints[i].y(); targetData.push_back(point); } // 求解器v参数每行保存{x, y, value},坐标和值按相同下标配对. dVec2 measurementData; measurementData.reserve(measurementPoints.size()); for(int i = 0; i < measurementPoints.size(); ++i) { dVec1 point(3, 0.0); point[0] = measurementPoints[i].x(); point[1] = measurementPoints[i].y(); point[2] = measurementValues[i]; measurementData.push_back(point); } bool calculationSucceeded = true; QString calculationError; // 局部作用域保证求解器输入、输出对象在FreeLibrary前析构. { HX_KRING_INPUT input(nugget, sill, range, model, targetData, measurementData); HX_KRING_OUTPUT output; try { krigingFunction(output, input, licensePath.toStdString()); } catch(const std::exception& exception) { calculationSucceeded = false; calculationError = krigingText("Kriging calculation failed: %1") .arg(QString::fromLocal8Bit(exception.what())); } catch(...) { calculationSucceeded = false; calculationError = krigingText("Kriging calculation failed."); } if(calculationSucceeded && output.v.size() != static_cast(targetPoints.size())) { calculationSucceeded = false; calculationError = krigingText( "The Kriging result count does not match the interpolation points."); } if(calculationSucceeded) { outputValues.reserve(targetPoints.size()); for(size_t i = 0; i < output.v.size(); ++i) { if(!isFiniteValue(output.v[i])) { calculationSucceeded = false; calculationError = krigingText( "The Kriging result contains an invalid value."); break; } outputValues.append(output.v[i]); } } } FreeLibrary(dll); if(!calculationSucceeded) { outputValues.clear(); setKrigingError(errorMessage, calculationError); } return calculationSucceeded; }