102 lines
3.1 KiB
C++
102 lines
3.1 KiB
C++
#pragma once
|
||
#include "vde/core/point.h"
|
||
#include "vde/curves/bspline_curve.h"
|
||
#include <vector>
|
||
|
||
namespace vde::curves {
|
||
using core::Point3D;
|
||
using core::Vector3D;
|
||
|
||
/**
|
||
* @brief NURBS 曲线(Non-Uniform Rational B-Spline)
|
||
*
|
||
* B 样条的有理推广,引入权重 w_i 使每个控制点的影响可调。
|
||
* 通过投影变换将齐次坐标中的 B 样条映射到 3D 空间。
|
||
*
|
||
* 求值公式:C(t) = Σ N_{i,p}(t) · w_i · P_i / Σ N_{i,p}(t) · w_i
|
||
*
|
||
* 关键性质:
|
||
* - 可精确表示圆锥曲线(圆、椭圆)——Bézier/B 样条无法做到
|
||
* - 权重 w_i 越大,曲线越靠近控制点 P_i
|
||
* - 所有权重 = 1 时退化为 B 样条
|
||
* - 所有权重 > 0 时在凸包内
|
||
*
|
||
* @ingroup curves
|
||
*/
|
||
class NurbsCurve {
|
||
public:
|
||
/**
|
||
* @brief 构造 NURBS 曲线
|
||
* @param control_points 控制点序列
|
||
* @param knots 节点向量
|
||
* @param weights 权重序列,必须与 control_points 等长,各分量 > 0
|
||
* @param degree 阶次 p
|
||
* @note 所有权重必须 > 0 以保证分母不为零(非退化)
|
||
* @code{.cpp}
|
||
* // 用 NURBS 表示四分之一圆(7 个控制点,三次)
|
||
* NurbsCurve arc(cps, {0,0,0,0, 0.5, 1,1,1,1},
|
||
* {1, sqrt2/2, 1, sqrt2/2, 1, sqrt2/2, 1}, 3);
|
||
* @endcode
|
||
*/
|
||
NurbsCurve() : degree_(0) {} // degenerate empty curve
|
||
NurbsCurve(std::vector<Point3D> control_points, std::vector<double> knots,
|
||
std::vector<double> weights, int degree);
|
||
|
||
/**
|
||
* @brief 在参数 t 处求值
|
||
* @param t 参数值
|
||
* @return 曲线上对应 t 的点坐标
|
||
* @note 内部将 (w·P, w) 提升为齐次坐标的 B 样条,求值后投影回 3D
|
||
*/
|
||
[[nodiscard]] Point3D evaluate(double t) const;
|
||
|
||
/**
|
||
* @brief 在参数 t 处求导数
|
||
* @param t 参数值
|
||
* @param order 导数阶数
|
||
* @return 导数向量
|
||
* @note 有理导数公式:
|
||
* C^{(k)} = (A^{(k)} - Σ_{j=1}^{k} C(k,j) · w^{(j)} · C^{(k-j)}) / w
|
||
* 其中 A(t) = Σ N_i(t)·w_i·P_i,w(t) = Σ N_i(t)·w_i
|
||
*/
|
||
[[nodiscard]] Vector3D derivative(double t, int order = 1) const;
|
||
|
||
/**
|
||
* @brief 曲线阶次
|
||
* @return p
|
||
*/
|
||
[[nodiscard]] int degree() const { return degree_; }
|
||
|
||
/**
|
||
* @brief 参数定义域
|
||
* @return [knots[degree], knots[n+1]]
|
||
*/
|
||
[[nodiscard]] std::pair<double, double> domain() const;
|
||
|
||
/**
|
||
* @brief 控制点访问
|
||
* @return 只读引用
|
||
*/
|
||
[[nodiscard]] const std::vector<Point3D>& control_points() const { return cp_; }
|
||
|
||
/**
|
||
* @brief 权重访问
|
||
* @return 只读引用
|
||
*/
|
||
[[nodiscard]] const std::vector<double>& weights() const { return weights_; }
|
||
|
||
/**
|
||
* @brief 节点向量访问
|
||
* @return 只读引用
|
||
*/
|
||
[[nodiscard]] const std::vector<double>& knots() const { return knots_; }
|
||
|
||
private:
|
||
std::vector<Point3D> cp_; ///< 控制点
|
||
std::vector<double> knots_; ///< 节点向量
|
||
std::vector<double> weights_; ///< 权重,w_i > 0
|
||
int degree_; ///< 阶次
|
||
};
|
||
|
||
} // namespace vde::curves
|