#pragma once #include "vde/core/point.h" #include "vde/curves/bspline_curve.h" #include "vde/curves/nurbs_curve.h" #include #include 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() : degree_u_(0), degree_v_(0) {} // degenerate empty surface NurbsSurface(std::vector> control_grid, std::vector knots_u, std::vector knots_v, std::vector> 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 num_control_points() const { return {static_cast(cp_.size()), static_cast(cp_.empty()?0:cp_[0].size())}; } /** * @brief u 向节点向量 * @return 只读引用 */ [[nodiscard]] const std::vector& knots_u() const { return knots_u_; } /** * @brief v 向节点向量 * @return 只读引用 */ [[nodiscard]] const std::vector& knots_v() const { return knots_v_; } /** * @brief 控制点网格访问 * @return 只读引用 */ [[nodiscard]] const std::vector>& control_points() const { return cp_; } /** * @brief 权重网格访问 * @return 只读引用 */ [[nodiscard]] const std::vector>& 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>> tessellate(int res_u, int res_v) const; private: std::vector> cp_; ///< 控制点网格 std::vector knots_u_, knots_v_; ///< u/v 向节点向量 std::vector> weights_; ///< 权重网格 int degree_u_, degree_v_; ///< u/v 向阶次 }; } // namespace vde::curves