Files
ViewDesignEngine/include/vde/curves/nurbs_surface.h
T

163 lines
5.0 KiB
C++
Raw Normal View History

#pragma once
#include "vde/core/point.h"
#include "vde/curves/bspline_curve.h"
#include "vde/curves/nurbs_curve.h"
#include <vector>
#include <array>
namespace vde::curves {
using core::Point3D;
using core::Vector3D;
/**
* @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
*/
class NurbsSurface {
public:
/**
* @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
*/
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);
/**
* @brief 求曲面点 S(u,v)
* @param u u 参数
* @param v v 参数
* @return 曲面上对应 (u,v) 的 3D 点
*/
[[nodiscard]] Point3D evaluate(double u, double v) const;
/**
* @brief u 向偏导数
* @param u u 参数
* @param v v 参数
* @return ∂S/∂u
*/
[[nodiscard]] Vector3D derivative_u(double u, double v) const;
/**
* @brief v 向偏导数
* @param u u 参数
* @param v v 参数
* @return ∂S/∂v
*/
[[nodiscard]] Vector3D derivative_v(double u, double v) const;
/**
* @brief 单位法向量
* @param u u 参数
* @param v v 参数
* @return N(u,v) = normalize(∂S/∂u × ∂S/∂v)
*/
[[nodiscard]] Vector3D normal(double u, double v) const;
/**
* @brief u 向阶次
* @return pu
*/
[[nodiscard]] int degree_u() const { return degree_u_; }
/**
* @brief v 向阶次
* @return pv
*/
[[nodiscard]] int degree_v() const { return degree_v_; }
/**
* @brief 控制点数量
* @return {nu+1, nv+1},即网格的行数和列数
*/
[[nodiscard]] std::array<int, 2> num_control_points() const {
return {static_cast<int>(cp_.size()), static_cast<int>(cp_.empty()?0:cp_[0].size())};
}
/**
* @brief u 向节点向量
* @return 只读引用
*/
[[nodiscard]] const std::vector<double>& knots_u() const { return knots_u_; }
/**
* @brief v 向节点向量
* @return 只读引用
*/
[[nodiscard]] const std::vector<double>& knots_v() const { return knots_v_; }
/**
* @brief 控制点网格访问
* @return 只读引用
*/
[[nodiscard]] const std::vector<std::vector<Point3D>>& control_points() const { return cp_; }
/**
* @brief 权重网格访问
* @return 只读引用
*/
[[nodiscard]] const std::vector<std::vector<double>>& weights() const { return weights_; }
/**
* @brief 由两条 NURBS 曲线创建直纹面
* @param c1 起始曲线(v=0 边界)
* @param c2 终止曲线(v=1 边界)
* @return 直纹 NURBS 曲面
* @note 两条曲线需具有兼容的阶次和节点结构(内部做升阶和节点精化对齐)
* @see blend_surfaces ruled_surface
*/
static NurbsSurface ruled(const NurbsCurve& c1, const NurbsCurve& c2);
/**
* @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
*/
static NurbsSurface revolve(const NurbsCurve& profile, const Point3D& axis_origin,
const Vector3D& axis_dir, double angle_rad);
/**
* @brief 将 NURBS 曲面三角化
* @param res_u u 方向采样分辨率
* @param res_v v 方向采样分辨率
* @return {顶点数组, 三角形索引数组},每个三角形为 {i0,i1,i2}
* @note 生成 res_u×res_v 均匀网格,每个单元格拆为两个三角形
* @see tessellate
*/
[[nodiscard]] std::pair<std::vector<Point3D>, std::vector<std::array<int,3>>>
tessellate(int res_u, int res_v) const;
private:
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 向阶次
};
} // namespace vde::curves