Files

94 lines
2.9 KiB
C++
Raw Permalink Normal View History

#pragma once
#include "vde/core/point.h"
#include <vector>
namespace vde::curves {
using core::Point3D;
using core::Vector3D;
/**
* @brief 任意阶 Bézier 曲线
*
* 通过 de Casteljau 递推算法定义的参数多项式曲线。
* 控制点 cp_ 的数量 = p+1(p 为次数)。
* 参数域 t ∈ [0, 1],端点插值首末控制点。
*
* @ingroup curves
*/
class BezierCurve {
public:
/**
* @brief 构造 Bézier 曲线
* @param control_points 控制点序列,点数 = degree + 1,最少 2 个
* @note 控制点数量决定了曲线阶次;点数越多,曲线越灵活但计算越昂贵
* @code{.cpp}
* BezierCurve curve({p0, p1, p2, p3}); // 三次 Bézier
* @endcode
*/
explicit BezierCurve(std::vector<Point3D> control_points);
/**
* @brief 在参数 t 处求值曲线点
* @param t 参数值,范围 [0, 1]
* @return 曲线上对应 t 的点坐标
* @note 使用 de Casteljau 递推算法,O(n²) 复杂度
*/
[[nodiscard]] Point3D evaluate(double t) const;
/**
* @brief 在参数 t 处求导数
* @param t 参数值,范围 [0, 1]
* @param order 导数阶数,1 = 一阶(切向量),2 = 二阶(曲率相关)
* @return 导数向量
* @note 高阶导数通过降阶 Bézier 曲线计算:
* P^{(k)}(t) = n(n-1)...(n-k+1) Σ Δ^k P_i · B_i^{n-k}(t)
*/
[[nodiscard]] Vector3D derivative(double t, int order = 1) const;
/**
* @brief 曲线阶次
* @return 阶次 = 控制点数 - 1
*/
[[nodiscard]] int degree() const { return static_cast<int>(cp_.size()) - 1; }
/**
* @brief 参数定义域
* @return 固定为 [0, 1]
*/
[[nodiscard]] std::pair<double, double> domain() const { return {0.0, 1.0}; }
/**
* @brief 控制点访问
* @return 控制点向量的只读引用
*/
[[nodiscard]] const std::vector<Point3D>& control_points() const { return cp_; }
/**
* @brief 在 t 处将曲线一分为二
* @param t 分割参数,范围 [0, 1]
* @return 左段 + 右段两条 Bézier 曲线
* @note 使用 de Casteljau 分割算法,分割点为三角阵的对角线
* @code{.cpp}
* auto [left, right] = curve.split(0.5);
* // left: 控制点 = [P0, b1, b2, P(t)]
* // right: 控制点 = [P(t), b3, b4, P3]
* @endcode
*/
[[nodiscard]] std::pair<BezierCurve, BezierCurve> split(double t) const;
/**
* @brief 升阶操作
* @param times 升阶次数,≥ 1
* @return 升阶后的 Bézier 曲线(控制点数增加 times,形状不变)
* @note 通过反复应用公式 P_i' = i/(n+1) P_{i-1} + (1 - i/(n+1)) P_i
* 升阶不仅增加自由度,也用于不同阶曲线间的兼容操作
* @see split
*/
[[nodiscard]] BezierCurve degree_elevate(int times = 1) const;
private:
std::vector<Point3D> cp_; ///< 控制点序列
};
} // namespace vde::curves