2026-07-23 07:04:11 +00:00
|
|
|
|
#pragma once
|
2026-07-23 08:19:24 +00:00
|
|
|
|
#include "vde/core/point.h"
|
2026-07-23 07:04:11 +00:00
|
|
|
|
#include "vde/curves/bspline_curve.h"
|
2026-07-23 15:40:47 +00:00
|
|
|
|
#include "vde/curves/nurbs_curve.h"
|
2026-07-23 07:04:11 +00:00
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <array>
|
|
|
|
|
|
|
|
|
|
|
|
namespace vde::curves {
|
2026-07-23 08:19:24 +00:00
|
|
|
|
using core::Point3D;
|
|
|
|
|
|
using core::Vector3D;
|
2026-07-23 07:04:11 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief NURBS 张量积曲面
|
|
|
|
|
|
*
|
|
|
|
|
|
* 由 (nu+1)×(nv+1) 控制点网格、权重网格、u/v 节点向量及阶次定义。
|
|
|
|
|
|
* 求值公式:
|
|
|
|
|
|
* S(u,v) = Σ_i Σ_j N_{i,pu}(u)·N_{j,pv}(v)·w_{ij}·P_{ij}
|
|
|
|
|
|
* / Σ_i Σ_j N_{i,pu}(u)·N_{j,pv}(v)·w_{ij}
|
|
|
|
|
|
*
|
|
|
|
|
|
* 可精确表示球面、圆柱面、锥面等二次曲面。广泛应用于 CAD 数据交换。
|
|
|
|
|
|
*
|
|
|
|
|
|
* @ingroup curves
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
class NurbsSurface {
|
|
|
|
|
|
public:
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 构造 NURBS 曲面
|
|
|
|
|
|
* @param control_grid 控制点网格
|
|
|
|
|
|
* @param knots_u u 向节点向量
|
|
|
|
|
|
* @param knots_v v 向节点向量
|
|
|
|
|
|
* @param weights 权重网格,维度与 control_grid 一致,所有值 > 0
|
|
|
|
|
|
* @param degree_u u 向阶次
|
|
|
|
|
|
* @param degree_v v 向阶次
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* NurbsSurface sphere(grid, u_knots, v_knots, weights, 3, 3);
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
NurbsSurface(std::vector<std::vector<Point3D>> control_grid,
|
|
|
|
|
|
std::vector<double> knots_u, std::vector<double> knots_v,
|
|
|
|
|
|
std::vector<std::vector<double>> weights,
|
|
|
|
|
|
int degree_u, int degree_v);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 求曲面点 S(u,v)
|
|
|
|
|
|
* @param u u 参数
|
|
|
|
|
|
* @param v v 参数
|
|
|
|
|
|
* @return 曲面上对应 (u,v) 的 3D 点
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] Point3D evaluate(double u, double v) const;
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief u 向偏导数
|
|
|
|
|
|
* @param u u 参数
|
|
|
|
|
|
* @param v v 参数
|
|
|
|
|
|
* @return ∂S/∂u
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] Vector3D derivative_u(double u, double v) const;
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief v 向偏导数
|
|
|
|
|
|
* @param u u 参数
|
|
|
|
|
|
* @param v v 参数
|
|
|
|
|
|
* @return ∂S/∂v
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] Vector3D derivative_v(double u, double v) const;
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 单位法向量
|
|
|
|
|
|
* @param u u 参数
|
|
|
|
|
|
* @param v v 参数
|
|
|
|
|
|
* @return N(u,v) = normalize(∂S/∂u × ∂S/∂v)
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] Vector3D normal(double u, double v) const;
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief u 向阶次
|
|
|
|
|
|
* @return pu
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] int degree_u() const { return degree_u_; }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief v 向阶次
|
|
|
|
|
|
* @return pv
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] int degree_v() const { return degree_v_; }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 控制点数量
|
|
|
|
|
|
* @return {nu+1, nv+1},即网格的行数和列数
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] std::array<int, 2> num_control_points() const {
|
|
|
|
|
|
return {static_cast<int>(cp_.size()), static_cast<int>(cp_.empty()?0:cp_[0].size())};
|
|
|
|
|
|
}
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief u 向节点向量
|
|
|
|
|
|
* @return 只读引用
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] const std::vector<double>& knots_u() const { return knots_u_; }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief v 向节点向量
|
|
|
|
|
|
* @return 只读引用
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] const std::vector<double>& knots_v() const { return knots_v_; }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 控制点网格访问
|
|
|
|
|
|
* @return 只读引用
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] const std::vector<std::vector<Point3D>>& control_points() const { return cp_; }
|
2026-07-24 11:04:04 +00:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 权重网格访问
|
|
|
|
|
|
* @return 只读引用
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] const std::vector<std::vector<double>>& weights() const { return weights_; }
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 由两条 NURBS 曲线创建直纹面
|
|
|
|
|
|
* @param c1 起始曲线(v=0 边界)
|
|
|
|
|
|
* @param c2 终止曲线(v=1 边界)
|
|
|
|
|
|
* @return 直纹 NURBS 曲面
|
|
|
|
|
|
* @note 两条曲线需具有兼容的阶次和节点结构(内部做升阶和节点精化对齐)
|
|
|
|
|
|
* @see blend_surfaces ruled_surface
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
static NurbsSurface ruled(const NurbsCurve& c1, const NurbsCurve& c2);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 由截面曲线旋转生成旋转曲面
|
|
|
|
|
|
* @param profile 截面 NURBS 曲线
|
|
|
|
|
|
* @param axis_origin 旋转轴上一点
|
|
|
|
|
|
* @param axis_dir 旋转轴方向
|
|
|
|
|
|
* @param angle_rad 旋转角度(弧度),≤ 2π
|
|
|
|
|
|
* @return 旋转 NURBS 曲面
|
|
|
|
|
|
* @note 使用 NURBS 表示圆弧的权重方案;完整旋转生成闭曲面
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* auto rev = NurbsSurface::revolve(profile, origin, {0,0,1}, M_PI);
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
static NurbsSurface revolve(const NurbsCurve& profile, const Point3D& axis_origin,
|
|
|
|
|
|
const Vector3D& axis_dir, double angle_rad);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 将 NURBS 曲面三角化
|
|
|
|
|
|
* @param res_u u 方向采样分辨率
|
|
|
|
|
|
* @param res_v v 方向采样分辨率
|
|
|
|
|
|
* @return {顶点数组, 三角形索引数组},每个三角形为 {i0,i1,i2}
|
|
|
|
|
|
* @note 生成 res_u×res_v 均匀网格,每个单元格拆为两个三角形
|
|
|
|
|
|
* @see tessellate
|
|
|
|
|
|
*/
|
2026-07-23 07:04:11 +00:00
|
|
|
|
[[nodiscard]] std::pair<std::vector<Point3D>, std::vector<std::array<int,3>>>
|
|
|
|
|
|
tessellate(int res_u, int res_v) const;
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
2026-07-24 11:04:04 +00:00
|
|
|
|
std::vector<std::vector<Point3D>> cp_; ///< 控制点网格
|
|
|
|
|
|
std::vector<double> knots_u_, knots_v_; ///< u/v 向节点向量
|
|
|
|
|
|
std::vector<std::vector<double>> weights_; ///< 权重网格
|
|
|
|
|
|
int degree_u_, degree_v_; ///< u/v 向阶次
|
2026-07-23 07:04:11 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace vde::curves
|