#pragma once #include "vde/core/point.h" #include "vde/curves/bspline_curve.h" #include namespace vde::curves { using core::Point3D; using core::Vector3D; /** * @brief B 样条张量积曲面(非有理) * * 由 (nu+1)×(nv+1) 控制点网格、u/v 向各一个节点向量以及两个阶次定义。 * 参数域 (u,v) ∈ [knots_u[pu], knots_u[nu+1]] × [knots_v[pv], knots_v[nv+1]]。 * * 求值公式:S(u,v) = Σ_i Σ_j P_{ij} · N_{i,pu}(u) · N_{j,pv}(v) * * 具有局部控制性:修改单个控制点仅影响相邻 pu×pv 个节点区间的曲面区域。 * * @ingroup curves */ class BSplineSurface { public: /** * @brief 构造 B 样条曲面 * @param control_grid (nu+1)×(nv+1) 控制点网格 * @param knots_u u 向节点向量,长度 = nu + pu + 1 * @param knots_v v 向节点向量,长度 = nv + pv + 1 * @param degree_u u 向阶次 pu * @param degree_v v 向阶次 pv * @code{.cpp} * BSplineSurface surf(grid, * {0,0,0,0, 0.5, 1,1,1,1}, // u knots (三次,5 个控制点) * {0,0,0, 0.5, 1,1,1}, // v knots (二次,4 个控制点) * 3, 2); * @endcode */ BSplineSurface(std::vector> control_grid, std::vector knots_u, std::vector knots_v, int degree_u, int degree_v); /** * @brief 求曲面点 S(u,v) * @param u u 参数 * @param v v 参数 * @return 曲面上的 3D 点 * @note 张量积分解:先行后列(或先列后行)做两次 B 样条求值 */ [[nodiscard]] Point3D evaluate(double u, double v) const; /** * @brief u 向偏导数 ∂S/∂u * @param u u 参数 * @param v v 参数 * @return u 向切向量 */ [[nodiscard]] Vector3D derivative_u(double u, double v) const; /** * @brief v 向偏导数 ∂S/∂v * @param u u 参数 * @param v v 参数 * @return v 向切向量 */ [[nodiscard]] Vector3D derivative_v(double u, double v) const; /** * @brief 单位法向量 * @param u u 参数 * @param v v 参数 * @return N(u,v) = (∂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 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_; } private: std::vector> cp_; ///< 控制点网格 std::vector knots_u_, knots_v_; ///< u/v 向节点向量 int degree_u_, degree_v_; ///< u/v 向阶次 }; } // namespace vde::curves