这次是实现 de Casteljau 算法,以及绘制 Bezier 曲线,比上次简单
核心思想就是递归,原理忘了就去看第十一节课,从15:00开始的
GAMES101-现代计算机图形学入门-闫令琪
代码
先实现贝塞尔曲线
cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t)
{
// 基线条件:当只剩一个控制点时,返回该点
if(control_points.size() == 1) return control_points[0];
// 创建下一级递归的控制点集合
std::vector<cv::Point2f> next_control_points = {};
// 对每对相邻控制点进行线性插值
for(int i = 0; i < control_points.size() - 1; ++i)
{
auto &a = control_points[i]; // 当前控制点
auto &b = control_points[i + 1]; // 下一个控制点
// 线性插值:a + t*(b - a) = (1-t)*a + t*b
auto p = a + t * (b - a);
// 将插值结果加入下一级控制点集合
next_control_points.emplace_back(p);
}
// 递归调用,处理下一级控制点
return recursive_bezier(next_control_points, t);
}
绘制 Bezier 曲线
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window)
{
// TODO: Iterate through all t = 0 to t = 1 with small steps, and call de Casteljau's
// recursive Bezier algorithm.
// 遍历 t 从 0.0 到 1.0,每次增加 0.001
for (double t = 0.0; t <= 1.0; t += 0.001)
{
// 调用递归贝塞尔算法计算当前 t 对应的曲线点
cv::Point2f point = recursive_bezier(control_points, t);
// 在图像窗口的 (point.y, point.x) 位置设置绿色通道为255
// OpenCV 中 Mat 的 at 方法是 (row, col) 即 (y, x)
window.at<cv::Vec3b>(point.y, point.x)[1] = 255;
}
}
效果
随便在窗口上点四个点生成相应贝塞尔曲线