#pragma once #include "vde/core/point.h" #include namespace vde::curves { using core::Point3D; using core::Vector3D; /** * @brief Bézier 张量积曲面 * * 由 (m+1)×(n+1) 控制点网格定义,m = degree_u,n = degree_v。 * 参数域 (u,v) ∈ [0,1]×[0,1],四个角点插值网格四角。 * * 求值公式:S(u,v) = Σ_i Σ_j P_{ij} · B_i^m(u) · B_j^n(v) * * @ingroup curves */ class BezierSurface { public: /** * @brief 构造 Bézier 曲面 * @param control_grid 控制点网格,grid[i][j] 对应 u 方向第 i 个、v 方向第 j 个控制点 * @note grid 必须矩整(所有行等长);grid.size() = degree_u+1, grid[0].size() = degree_v+1 * @code{.cpp} * // 3x3 控制网格 → 双二次 Bézier 曲面 * BezierSurface surf({{p00,p01,p02}, {p10,p11,p12}, {p20,p21,p22}}); * @endcode */ BezierSurface(std::vector> control_grid); /** * @brief 求曲面点 S(u,v) * @param u u 参数,范围 [0, 1] * @param v v 参数,范围 [0, 1] * @return 曲面上对应 (u,v) 的 3D 坐标 * @note 张量积求值:先按 v 方向对每行做 de Casteljau,再沿 u 方向对结果做一次 */ [[nodiscard]] Point3D evaluate(double u, double v) const; /** * @brief u 方向偏导数 ∂S/∂u * @param u u 参数 * @param v v 参数 * @return u 方向切向量 * @note 通过降阶 Bézier 曲线计算:对 v 求值后沿 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 单位法向量 N(u,v) = (∂S/∂u × ∂S/∂v) / |…| * @param u u 参数 * @param v v 参数 * @return 归一化法向量(指向曲面的特选侧) * @note 当两个偏导数平行时返回零向量(奇异点) */ [[nodiscard]] Vector3D normal(double u, double v) const; /** * @brief u 向阶次 * @return u 方向阶次(控制点行数 - 1) */ [[nodiscard]] int degree_u() const { return static_cast(cp_.size()) - 1; } /** * @brief v 向阶次 * @return v 方向阶次(控制点列数 - 1) */ [[nodiscard]] int degree_v() const { return static_cast(cp_[0].size()) - 1; } private: std::vector> cp_; ///< 控制点网格 [u_idx][v_idx] /** * @brief 一维 de Casteljau 求值(内部辅助) * @param t 参数 * @param pts 一维控制点序列 * @return 求值结果 */ [[nodiscard]] Point3D de_casteljau(double t, const std::vector& pts) const; }; } // namespace vde::curves