Files
ViewDesignEngine/include/vde/mesh/mesh_smooth.h
T
茂之钳 4c9ee4f760
CI / Build & Test (push) Failing after 29s
CI / Release Build (push) Failing after 38s
docs: doxygen annotations for curves + mesh + sketch
2026-07-24 11:04:04 +00:00

140 lines
4.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "vde/mesh/halfedge_mesh.h"
namespace vde::mesh {
using core::Point2D;
using core::Point3D;
using core::Vector3D;
/**
* @brief 网格光顺方法
* @ingroup mesh
*/
enum class SmoothMethod {
Laplacian, ///< 标准拉普拉斯光顺:v ← v + λ·L(v),快速但会收缩
Taubin, ///< Taubin λ|μ 光顺:先正后负步交替,体积保持
HCLaplacian, ///< HC 拉普拉斯(Humphrey's Classes):推拉两步保持形状/体积
Bilateral ///< 双边滤波:法向加权去噪,保持尖锐特征
};
/**
* @brief 网格光顺参数
* @ingroup mesh
*/
struct SmoothOptions {
int iterations = 10; ///< 迭代次数
double lambda = 0.5; ///< 拉普拉斯步长(Standard / Taubin 正步)
/// Taubin 负步系数,典型值 mu = -(lambda + ε),默认 -0.53
/// 必须满足 mu < -lambda 以实现体积保持
double mu = -0.53;
/// HC 拉普拉斯参数
double hc_alpha = 0.0; ///< 回推强度,0 = 自动计算(推荐)
double hc_beta = 0.5; ///< 前推混合系数
/// 双边滤波参数
double bilateral_sigma_c = 0.0; ///< 空间 σ,0 = 自动按平均边长计算
double bilateral_sigma_n = 0.3; ///< 法向 σ(弧度),控制特征保持的敏感度
int bilateral_iters = 5; ///< 双边内部迭代次数
SmoothMethod method = SmoothMethod::Laplacian; ///< 光顺方法选择
};
/**
* @brief 网格光顺(通用分发器)
*
* 根据 opts.method 分派到具体的光顺实现:
* - Laplacian → smooth_laplacian()
* - Taubin → smooth_taubin()
* - HCLaplacian → smooth_hc_laplacian()
* - Bilateral → smooth_bilateral()
*
* @param mesh 输入三角网格
* @param opts 光顺选项
* @return 光顺后的网格(顶点位置更新,拓扑不变)
*
* @code{.cpp}
* SmoothOptions opts;
* opts.method = SmoothMethod::Taubin;
* opts.iterations = 20;
* auto smooth = smooth_mesh(noisy_mesh, opts);
* @endcode
* @ingroup mesh
*/
HalfedgeMesh smooth_mesh(const HalfedgeMesh& mesh, const SmoothOptions& opts = {});
/**
* @brief 标准拉普拉斯光顺
*
* 均匀拉普拉斯:v ← v + λ·(avg(neighbor_positions) - v)
* 最简单但会引入体积收缩,适用于轻度平滑。
*
* @param mesh 输入网格
* @param iterations 迭代次数
* @param lambda 步长系数 (0, 1]
* @return 光顺后的网格
*
* @note 迭代过多会导致网格坍塌;对于体积关键的应用优先选 Taubin 或 HC
* @see smooth_taubin smooth_hc_laplacian
* @ingroup mesh
*/
HalfedgeMesh smooth_laplacian(const HalfedgeMesh& mesh, int iterations, double lambda);
/**
* @brief Taubin λ|μ 光顺(体积保持)
*
* 两阶段交替:
* 1. 正步(收缩滤波):v ← v + λ·L(v)
* 2. 负步(膨胀滤波):v ← v + μ·L(v),其中 μ < 0 且 |μ| > |λ|
*
* 传递函数在低频通带增益 ≈ 1,有效去噪同时保持体积。
*
* @param mesh 输入网格
* @param iterations 完整 λ/μ 循环次数
* @param lambda 正步系数 (0, 1]
* @param mu 负步系数,需满足 mu < 0 且 |mu| > lambda
* @return 光顺后的网格
*
* @note 典型值:λ = 0.5, μ = -0.53;|mu| 过大可能导致不稳定振荡
* @ingroup mesh
*/
HalfedgeMesh smooth_taubin(const HalfedgeMesh& mesh, int iterations, double lambda, double mu);
/**
* @brief HC 拉普拉斯光顺(Humphrey's Classes
*
* 两遍处理以保持原始形状特征:
* 1. 前推:标准拉普拉斯光顺,记录位移 b_i = v_i' - v_i
* 2. 回推:v_i'' = v_i' - (α·b_i + β·avg(neighbor_b))
*
* 相比标准拉普拉斯显著减轻体积收缩,同时比 Taubin 更好地保持尖锐特征。
*
* @param mesh 输入网格
* @param opts 光顺选项(使用 hc_alpha 和 hc_beta 字段)
* @return 光顺后的网格
*
* @ingroup mesh
*/
HalfedgeMesh smooth_hc_laplacian(const HalfedgeMesh& mesh, const SmoothOptions& opts = {});
/**
* @brief 双边网格滤波
*
* 基于法向加权的各向异性去噪,保持尖锐边缘和特征:
* - 空间权重:w_c = exp(-d²/(2·σ_c²)),基于顶点间距
* - 法向权重:w_n = exp(-θ²/(2·σ_n²)),基于法向夹角
* - 更新:v ← v + Σ_j w_c(j)·w_n(j)·(v_j - v) / Σ_j w_c(j)·w_n(j)
*
* 相比于各向同性的拉普拉斯类方法,双边滤波在 CAD/机械零件网格上效果最优。
*
* @param mesh 输入网格
* @param opts 光顺选项(使用 bilateral_ 前缀字段)
* @return 光顺后的网格
*
* @ingroup mesh
*/
HalfedgeMesh smooth_bilateral(const HalfedgeMesh& mesh, const SmoothOptions& opts = {});
} // namespace vde::mesh