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

102 lines
3.1 KiB
C++
Raw Normal View History

#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_iw(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