236 lines
8.4 KiB
C++
236 lines
8.4 KiB
C++
|
|
#pragma once
|
|||
|
|
#include "vde/mesh/halfedge_mesh.h"
|
|||
|
|
#include "vde/mesh/point_cloud.h"
|
|||
|
|
#include "vde/curves/nurbs_surface.h"
|
|||
|
|
#include <vector>
|
|||
|
|
#include <functional>
|
|||
|
|
|
|||
|
|
namespace vde::mesh {
|
|||
|
|
using core::Point3D;
|
|||
|
|
using core::Vector3D;
|
|||
|
|
using core::AABB3D;
|
|||
|
|
using curves::NurbsSurface;
|
|||
|
|
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
// 参数结构体
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief Poisson 曲面重建参数
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
struct PoissonReconParams {
|
|||
|
|
int max_depth = 8; ///< 八叉树最大深度(越高越精细)
|
|||
|
|
int min_depth = 3; ///< 八叉树最小深度
|
|||
|
|
double point_weight = 4.0; ///< 插值点权重(越高越贴近输入点)
|
|||
|
|
int solver_divide = 8; ///< 求解器分块大小
|
|||
|
|
int iso_divide = 8; ///< 等值面提取分块大小
|
|||
|
|
double samples_per_node = 1.5; ///< 每节点采样数
|
|||
|
|
bool scale_fit = true; ///< 是否缩放到单位立方体
|
|||
|
|
double confidence = 0.0; ///< 点置信度(0=均匀权重)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 四边形重网格化参数
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
struct QuadRemeshParams {
|
|||
|
|
int target_quads = 400; ///< 目标四边形数量
|
|||
|
|
double edge_length = 0.0; ///< 目标边长(0=自动)
|
|||
|
|
double regularity = 0.5; ///< 规则性权重 [0,1]
|
|||
|
|
double sharpness = 0.5; ///< 特征保持权重 [0,1]
|
|||
|
|
int iterations = 10; ///< 迭代次数
|
|||
|
|
bool adaptive_size = false; ///< 自适应边长(曲率区域更密)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief NURBS 拟合参数
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
struct NURBSFitParams {
|
|||
|
|
int degree_u = 3; ///< u 向阶次
|
|||
|
|
int degree_v = 3; ///< v 向阶次
|
|||
|
|
int num_cp_u = 8; ///< u 向控制点数(≥ degree_u+1)
|
|||
|
|
int num_cp_v = 8; ///< v 向控制点数(≥ degree_v+1)
|
|||
|
|
double smoothness = 0.001; ///< 平滑项权重(Tikhonov 正则化)
|
|||
|
|
int max_iterations = 50; ///< 最小二乘迭代上限
|
|||
|
|
double tolerance = 1e-6; ///< 收敛容差
|
|||
|
|
bool use_weights = true; ///< 是否使用有理权重拟合(NURBS vs B-spline)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云→网格综合参数
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
struct PointCloudToMeshParams {
|
|||
|
|
int knn = 10; ///< 法线估计 kNN
|
|||
|
|
double voxel_size = 0.0; ///< 预降采样体素尺寸(0=跳过)
|
|||
|
|
bool remove_outliers = true; ///< 是否先剔除统计离群点
|
|||
|
|
PoissonReconParams poisson; ///< Poisson 重建参数
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 网格→NURBS 综合参数
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
struct MeshToNURBSParams {
|
|||
|
|
QuadRemeshParams quad; ///< 四边形重网格化参数
|
|||
|
|
NURBSFitParams nurbs; ///< NURBS 拟合参数
|
|||
|
|
bool smooth_before_remesh = false; ///< 重网格化前是否平滑
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
// 拟合结果
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/// 平面拟合结果
|
|||
|
|
struct PlaneFitResult {
|
|||
|
|
Point3D origin; ///< 平面上一点(点云质心)
|
|||
|
|
Vector3D normal; ///< 平面法向量(单位向量)
|
|||
|
|
double rms_error; ///< RMS 拟合误差
|
|||
|
|
bool valid; ///< 拟合是否有效
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
/// 曲面片拟合结果
|
|||
|
|
struct PatchFitResult {
|
|||
|
|
NurbsSurface surface; ///< 拟合的 NURBS 曲面
|
|||
|
|
double rms_error; ///< RMS 拟合误差
|
|||
|
|
double max_error; ///< 最大偏差
|
|||
|
|
bool valid; ///< 拟合是否有效
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
// 核心函数声明
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云 → 三角网格(Poisson 曲面重建)
|
|||
|
|
*
|
|||
|
|
* 完整流水线:法线估计 → Poisson 隐式曲面重建 → 等值面提取。
|
|||
|
|
*
|
|||
|
|
* @param cloud 输入点云(可无法线,内部自动估计)
|
|||
|
|
* @param params 控制参数
|
|||
|
|
* @return 重建的三角网格
|
|||
|
|
*
|
|||
|
|
* @code{.cpp}
|
|||
|
|
* PointCloudToMeshParams p;
|
|||
|
|
* p.knn = 10; p.voxel_size = 0.02;
|
|||
|
|
* auto mesh = point_cloud_to_mesh(cloud, p);
|
|||
|
|
* @endcode
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
HalfedgeMesh point_cloud_to_mesh(const PointCloud& cloud,
|
|||
|
|
const PointCloudToMeshParams& params = {});
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 网格 → NURBS 曲面
|
|||
|
|
*
|
|||
|
|
* 流水线:四边形重网格化 → 参数化 → 控制点最小二乘拟合。
|
|||
|
|
*
|
|||
|
|
* @param mesh 输入三角网格
|
|||
|
|
* @param params 控制参数
|
|||
|
|
* @return 拟合的 NURBS 曲面
|
|||
|
|
*
|
|||
|
|
* @code{.cpp}
|
|||
|
|
* MeshToNURBSParams p;
|
|||
|
|
* p.quad.target_quads = 200;
|
|||
|
|
* p.nurbs.num_cp_u = 6; p.nurbs.num_cp_v = 6;
|
|||
|
|
* auto surf = mesh_to_nurbs_surface(mesh, p);
|
|||
|
|
* @endcode
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
NurbsSurface mesh_to_nurbs_surface(const HalfedgeMesh& mesh,
|
|||
|
|
const MeshToNURBSParams& params = {});
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云平面拟合(SVD 最小二乘)
|
|||
|
|
*
|
|||
|
|
* @param points 输入点列表
|
|||
|
|
* @return 平面拟合结果(origin, normal, rms_error)
|
|||
|
|
*
|
|||
|
|
* @code{.cpp}
|
|||
|
|
* auto plane = fit_plane(points);
|
|||
|
|
* // plane.normal 是单位法向量,plane.origin 是质心
|
|||
|
|
* @endcode
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
PlaneFitResult fit_plane(const std::vector<Point3D>& points);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云曲面片 NURBS 拟合
|
|||
|
|
*
|
|||
|
|
* 将点云拟合为指定阶次的 NURBS 曲面片:先将点投影到拟合平面上,
|
|||
|
|
* 在参数域中均匀采样构造控制网格,再用最小二乘优化控制点位置。
|
|||
|
|
*
|
|||
|
|
* @param points 输入点列表
|
|||
|
|
* @param degree_u u 向阶次
|
|||
|
|
* @param degree_v v 向阶次
|
|||
|
|
* @param num_cp_u u 向控制点数
|
|||
|
|
* @param num_cp_v v 向控制点数
|
|||
|
|
* @return 拟合结果(NURBS 曲面 + 误差)
|
|||
|
|
*
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
PatchFitResult fit_patch(const std::vector<Point3D>& points,
|
|||
|
|
int degree_u = 3, int degree_v = 3,
|
|||
|
|
int num_cp_u = 8, int num_cp_v = 8);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云曲率感知采样
|
|||
|
|
*
|
|||
|
|
* 计算局部曲率近似,高曲率区域保留更多点,低曲率区域用较少点表示。
|
|||
|
|
*
|
|||
|
|
* @param points 输入点列表
|
|||
|
|
* @param target_count 目标保留点数
|
|||
|
|
* @return 采样后的点索引数组
|
|||
|
|
*
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
std::vector<size_t> curvature_aware_sampling(const std::vector<Point3D>& points,
|
|||
|
|
size_t target_count);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 网格孔洞填充
|
|||
|
|
*
|
|||
|
|
* 检测边界环,对每个孔洞用 fan 三角化(或最小面积三角化)填充。
|
|||
|
|
*
|
|||
|
|
* @param mesh 输入网格
|
|||
|
|
* @param max_hole_edges 最大孔洞边界边数(超过此数的孔洞不填充,0=无限制)
|
|||
|
|
* @return 填充后的网格
|
|||
|
|
*
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
HalfedgeMesh hole_filling(const HalfedgeMesh& mesh, int max_hole_edges = 0);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云平滑滤波
|
|||
|
|
*
|
|||
|
|
* 对点云位置进行各向同性拉普拉斯 + 双边滤波去噪。
|
|||
|
|
*
|
|||
|
|
* @param points 输入点列表
|
|||
|
|
* @param sigma 高斯核 σ(控制平滑强度)
|
|||
|
|
* @param iterations 迭代次数
|
|||
|
|
* @return 平滑后的点列表
|
|||
|
|
*
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
std::vector<Point3D> smoothing_filter(const std::vector<Point3D>& points,
|
|||
|
|
double sigma = 0.5, int iterations = 3);
|
|||
|
|
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
// 法线估计(独立函数)
|
|||
|
|
// ───────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 点云法线估计(kNN + PCA)
|
|||
|
|
*
|
|||
|
|
* @param points 输入点列表
|
|||
|
|
* @param k 最近邻点数
|
|||
|
|
* @return 估计的法线向量列表
|
|||
|
|
*
|
|||
|
|
* @ingroup mesh
|
|||
|
|
*/
|
|||
|
|
std::vector<Vector3D> estimate_normals(const std::vector<Point3D>& points, int k = 10);
|
|||
|
|
|
|||
|
|
} // namespace vde::mesh
|