2026-07-23 05:27:51 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "vde/mesh/halfedge_mesh.h"
|
|
|
|
|
|
#include <cmath>
|
2026-07-23 12:36:39 +00:00
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <string>
|
2026-07-24 11:04:04 +00:00
|
|
|
|
#include <array>
|
2026-07-23 05:27:51 +00:00
|
|
|
|
|
|
|
|
|
|
namespace vde::mesh {
|
2026-07-23 08:19:24 +00:00
|
|
|
|
using core::Point2D;
|
|
|
|
|
|
using core::Point3D;
|
|
|
|
|
|
using core::Vector3D;
|
2026-07-23 05:27:51 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
// Triangle quality
|
|
|
|
|
|
// ════════════════════════════════════════════════════════
|
2026-07-23 12:36:39 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 三角网格质量指标
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
struct MeshQuality {
|
2026-07-24 11:04:04 +00:00
|
|
|
|
double min_angle_deg = 0; ///< 最小三角形内角(度),≥ 0
|
|
|
|
|
|
double max_angle_deg = 0; ///< 最大三角形内角(度),≤ 180
|
|
|
|
|
|
double avg_aspect_ratio = 0; ///< 平均长宽比(外接圆半径 / 最短边)
|
|
|
|
|
|
double max_aspect_ratio = 0; ///< 最大长宽比
|
|
|
|
|
|
size_t degenerate_faces = 0; ///< 退化面数(面积 ≈ 0)
|
2026-07-23 05:27:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 评估三角网格质量
|
|
|
|
|
|
*
|
|
|
|
|
|
* 对网格中每个三角面计算内角、长宽比,统计全局最值及平均值。
|
|
|
|
|
|
* 质量好的三角网格应有:
|
|
|
|
|
|
* - min_angle > 20°(CFD 模拟要求 > 25°)
|
|
|
|
|
|
* - max_angle < 120°(避免狭长退化)
|
|
|
|
|
|
* - avg_aspect_ratio 接近 1
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mesh 输入三角网格
|
|
|
|
|
|
* @return MeshQuality 质量指标汇总
|
|
|
|
|
|
*
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* auto q = evaluate_mesh_quality(mesh);
|
|
|
|
|
|
* if (q.min_angle_deg < 15.0) {
|
|
|
|
|
|
* // 需要 remesh 或优化
|
|
|
|
|
|
* }
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
MeshQuality evaluate_mesh_quality(const HalfedgeMesh& mesh);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
// Tetrahedron quality
|
|
|
|
|
|
// ════════════════════════════════════════════════════════
|
2026-07-23 12:36:39 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 四面体网格质量指标
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
struct TetQuality {
|
2026-07-24 11:04:04 +00:00
|
|
|
|
double min_jacobian = 0.0; ///< 最小归一化 Jacobian [0, 1],0=退化 1=正四面体
|
|
|
|
|
|
double max_jacobian = 0.0; ///< 最大归一化 Jacobian
|
|
|
|
|
|
double avg_jacobian = 0.0; ///< 平均归一化 Jacobian
|
|
|
|
|
|
double min_dihedral_deg = 0.0; ///< 最小二面角(度),太小会导致刚度矩阵病态
|
|
|
|
|
|
double max_dihedral_deg = 0.0; ///< 最大二面角(度),接近 180° 表示退化
|
|
|
|
|
|
double max_aspect_ratio = 0.0; ///< 最大长宽比(外接球半径 / 最短边)
|
|
|
|
|
|
size_t degenerate_tets = 0; ///< 退化四面体数(体积 ≈ 0 或 Jacobian ≈ 0)
|
|
|
|
|
|
size_t total_tets = 0; ///< 四面体总数
|
2026-07-23 12:36:39 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 评估三角网格作为四面体边界的质量
|
|
|
|
|
|
*
|
|
|
|
|
|
* 将每个三角面与其面重心构造虚拟四面体,评估这些四面体的质量。
|
|
|
|
|
|
* 适用于将封闭三角表面解释为体积边界时的质量检测。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mesh 封闭三角网格(volume boundary)
|
|
|
|
|
|
* @return TetQuality 四面体质量指标
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note 这不是真正的四面体网格质量评估——仅用于表面网格的代理指标
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
TetQuality evaluate_tet_quality(const HalfedgeMesh& mesh);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
// Generic element quality
|
|
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 单元类型枚举
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
|
|
|
|
|
enum class ElementType {
|
|
|
|
|
|
Tri, ///< 三角形
|
|
|
|
|
|
Quad, ///< 四边形(Stub)
|
|
|
|
|
|
Tet, ///< 四面体
|
|
|
|
|
|
Hex ///< 六面体(Stub)
|
|
|
|
|
|
};
|
2026-07-23 12:36:39 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 通用单元质量指标
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
struct ElemQuality {
|
2026-07-24 11:04:04 +00:00
|
|
|
|
double min_jacobian = 0.0; ///< 最小归一化 Jacobian
|
|
|
|
|
|
double max_jacobian = 0.0; ///< 最大归一化 Jacobian
|
|
|
|
|
|
double avg_jacobian = 0.0; ///< 平均归一化 Jacobian
|
|
|
|
|
|
size_t total_elements = 0; ///< 单元总数
|
|
|
|
|
|
size_t degenerate = 0; ///< 退化单元数
|
2026-07-23 12:36:39 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 按单元类型分派的网格质量评估
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mesh 输入网格
|
|
|
|
|
|
* @param type 单元类型
|
|
|
|
|
|
* @return ElemQuality 质量指标
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note 目前仅 Tri 和 Tet 完整实现;Quad / Hex 返回 stub(全零)
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
ElemQuality evaluate_element_quality(const HalfedgeMesh& mesh, ElementType type);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
// Quality report
|
|
|
|
|
|
// ════════════════════════════════════════════════════════
|
2026-07-23 12:36:39 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 详细质量报告
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
struct QualityReport {
|
2026-07-24 11:04:04 +00:00
|
|
|
|
std::string element_type; ///< "triangle" 或 "tetrahedron"
|
2026-07-23 12:36:39 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
size_t total = 0; ///< 单元总数
|
|
|
|
|
|
size_t degenerate = 0; ///< 退化单元数
|
|
|
|
|
|
|
|
|
|
|
|
/// 质量直方图(k=10 个区间,[0,0.1), [0.1,0.2), ..., [0.9,1.0])
|
2026-07-23 12:36:39 +00:00
|
|
|
|
static constexpr int kBins = 10;
|
|
|
|
|
|
std::array<size_t, kBins> histogram{};
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/// 分级计数(A=优秀 B=良好 C=合格 D=差 F=不合格)
|
2026-07-23 12:36:39 +00:00
|
|
|
|
size_t grade_A = 0, grade_B = 0, grade_C = 0, grade_D = 0, grade_F = 0;
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
double min_quality = 0.0; ///< 最低质量值
|
|
|
|
|
|
double max_quality = 0.0; ///< 最高质量值
|
|
|
|
|
|
double avg_quality = 0.0; ///< 平均质量值
|
|
|
|
|
|
double stddev_quality = 0.0; ///< 质量标准差
|
2026-07-23 12:36:39 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 生成三角网格的完整质量报告
|
|
|
|
|
|
*
|
|
|
|
|
|
* 包含直方图、分级统计及基本统计量。
|
|
|
|
|
|
* 分级标准(按归一化 Jacobian):
|
|
|
|
|
|
* - A: [0.9, 1.0] — 优秀
|
|
|
|
|
|
* - B: [0.7, 0.9) — 良好
|
|
|
|
|
|
* - C: [0.5, 0.7) — 合格
|
|
|
|
|
|
* - D: [0.3, 0.5) — 差
|
|
|
|
|
|
* - F: [0.0, 0.3) — 不合格
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mesh 输入三角网格
|
|
|
|
|
|
* @return QualityReport 完整质量报告
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
QualityReport mesh_quality_report(const HalfedgeMesh& mesh);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 生成四面体网格的完整质量报告
|
|
|
|
|
|
*
|
|
|
|
|
|
* 将表面网格的面解释为四面体单元的边界(面 + 面心 = 虚拟四面体)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mesh 封闭三角网格
|
|
|
|
|
|
* @return QualityReport 完整质量报告
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
QualityReport mesh_quality_report_tet(const HalfedgeMesh& mesh);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
// Utility
|
|
|
|
|
|
// ════════════════════════════════════════════════════════
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 三角形归一化 Jacobian
|
|
|
|
|
|
*
|
|
|
|
|
|
* 计算三角形 (a,b,c) 的带符号面积,归一化到 [-1, 1]。
|
|
|
|
|
|
* 值 1 = 等边三角形(最优),0 = 退化(共线),-1 = 翻转(法向反了)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 公式:J = det([b-a, c-a, n]) / (|b-a|·|c-a|·|b-c|? or area-based?)
|
|
|
|
|
|
* 实际实现使用面积与理想等边三角形面积之比。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param a,b,c 三角形三个顶点
|
|
|
|
|
|
* @return 归一化 Jacobian [-1, 1]
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
double tri_scaled_jacobian(const Point3D& a, const Point3D& b, const Point3D& c);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 四面体归一化 Jacobian
|
|
|
|
|
|
*
|
|
|
|
|
|
* 计算四面体 (a,b,c,d) 的体积 Jacobian,归一化到 [0, 1]。
|
|
|
|
|
|
* 值 1 = 正四面体(最优),0 = 退化(共面)。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 公式:J = det([b-a, c-a, d-a]) / (归一化因子)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param a,b,c,d 四面体四个顶点
|
|
|
|
|
|
* @return 归一化 Jacobian [0, 1]
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
double tet_scaled_jacobian(const Point3D& a, const Point3D& b,
|
|
|
|
|
|
const Point3D& c, const Point3D& d);
|
|
|
|
|
|
|
2026-07-23 05:27:51 +00:00
|
|
|
|
} // namespace vde::mesh
|