You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Include/nmNum/nmCalculation/nmPebiGridDiagnostics.h

76 lines
4.4 KiB
C

#ifndef NM_PEBI_GRID_DIAGNOSTICS_H
#define NM_PEBI_GRID_DIAGNOSTICS_H
#include "pch.h"
#include <QCoreApplication>
#include <QString>
#include <QtCore/qnumeric.h>
// 网格失败提示辅助函数:检查输入并生成可翻译的简短原因,不修改输入、不写日志。
// 调用方负责将返回的原因交给框架日志或界面显示。
namespace nmPebiGridDiagnostics {
// 翻译用户可见提示;原文仍保留翻译标记,便于更新中英文语言文件。
inline QString text(const char* source)
{
// 本文件不是 QObject 类,用固定翻译上下文与界面的 tr() 保持相同翻译机制。
// 调用处用 QT_TRANSLATE_NOOP 标记原文,供 Qt 4.8 的 lupdate 提取;本函数负责运行时翻译。
return QCoreApplication::translate("nmPebiGridDiagnostics", source);
}
// 保留双精度数值的有效信息,避免很小的井半径在提示中被格式化成零。
inline QString number(double value)
{
return QString::number(value, 'g', 17);
}
// 只拦截可以确定无效的输入,不人为规定“井半径必须大于 0.1 m”。
// 同一真实井径可能因坐标量级、网格尺度不同而成功或失败,不能擅自修改物理参数。
// 返回首个发现的问题;空字符串仅表示通过这些基础检查,不保证算法一定成功。
inline QString validate(const HX_NWTM_GRID_INPUT& input)
{
// 先检查网格维数和尺度,避免将不支持的维数或无效步长传给算法库。
if(input.D != 2)
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Only two-dimensional grid input is supported."));
if(!qIsFinite(input.GridControl) || input.GridControl <= 0.0)
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Grid spacing must be finite and greater than zero (current value: %1)."))
.arg(number(input.GridControl));
if(input.Boundary.size() < 3)
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "The boundary must contain at least three edges."));
// 每条边至少包含起点和终点的平面坐标;这里不检查整个边界是否闭合或自交。
for(size_t i = 0; i < input.Boundary.size(); ++i) {
const dVec1& edge = input.Boundary[i];
if(edge.size() < 4 || !qIsFinite(edge[0]) || !qIsFinite(edge[1]) ||
!qIsFinite(edge[2]) || !qIsFinite(edge[3]))
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Boundary edge %1 has missing or non-finite coordinates.")).arg(i + 1);
// 捕获边界时当前程序会对坐标取整,原本相邻的点也可能因此重合。
if(edge[0] == edge[2] && edge[1] == edge[3])
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Boundary edge %1 has zero length. Check coincident points and coordinate rounding.")).arg(i + 1);
}
// 直井数据前三项依次为横坐标、纵坐标、井半径;与算法库约定一致,单位为米。
for(size_t i = 0; i < input.VerticalWell.size(); ++i) {
const dVec1& well = input.VerticalWell[i];
if(well.size() < 3 || !qIsFinite(well[0]) || !qIsFinite(well[1]) || !qIsFinite(well[2]))
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Vertical well %1 has missing or non-finite coordinates/radius.")).arg(i + 1);
if(well[2] <= 0.0)
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Vertical well %1 has invalid radius %2 m; it must be greater than zero."))
.arg(i + 1).arg(number(well[2]));
// 这里判断实际浮点分辨能力:加上半径仍得到同一坐标,才能确定半径无法表达。
// 普通正井径即使偏小也允许提交 DLL,避免把算法敏感性误判为输入错误。
if(well[0] + well[2] == well[0] || well[1] + well[2] == well[1])
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Vertical well %1: radius %2 m is too small to represent at coordinates (%3, %4) m."))
.arg(i + 1).arg(number(well[2])).arg(number(well[0])).arg(number(well[1]));
}
return QString();
}
// 算法失败且无法确定根因时附加通用建议,不把建议当成已经确认的失败原因。
inline QString failureHint()
{
// DLL 没有给出具体原因时,只提供排查方向,不将小井径直接判定为错误。
return text(QT_TRANSLATE_NOOP("nmPebiGridDiagnostics", "Check whether the well radius is too small, and check grid spacing and geometry positions."));
}
}
#endif