效果可查看上一篇博文:js手动画平滑曲线,贝塞尔曲线拟合【代码】js手动画平滑曲线,贝塞尔曲线拟合。https://blog.csdn.net/qiufeng_xinqing/article/details/131711963?spm=1001.2014.3001.5502
代码如下:
#include <cmath>
#include <cstdint>
#include <exception>
#include <vector>namespace line {
// 二维坐标点定义:first对应x值,second对应y值
using point_t = std::pair<double, double>;/// <summary>
/// 阶乘(递归),即 n! = n * (n-1) * (n-2) * (n-3) * ...* 1
/// </summary>
/// <param name="num">阶乘的数</param>
/// <returns>阶乘结果数</returns>
double factorial(double num)
{return (num <= 1) ? 1 : (num * factorial(num - 1));
}/// <summary>
/// 通过多个控制点计算当前贝塞尔曲线上的点坐标,横坐标为[0,1]
/// 关于 贝塞尔曲线:https://www.cnblogs.com/fangsmile/articles/11642607.html
/// </summary>
/// <param name="points">控制点集合</param>
/// <param name="stepTime">横轴的步长,如果为零则使用默认的 0.01 使用为步长</param>
/// <param name="retLine">贝塞尔曲线上的点坐标集</param>
/// <returns>贝塞尔曲线上的点坐标集</returns>
const std::vector<point_t>& calcBezierLine(const std::vector<point_t>& points, double stepTime, std::vector<point_t>& retLine)
{if (points.size() < 2){retLine.resize(1);retLine[0] = points[0];return retLine;}int32_t pointsn = points.size() - 1;int64_t pointsFact = factorial(pointsn);int32_t retCount = 0;stepTime = stepTime == 0 ? 0.01 : stepTime;retLine.resize((1 / stepTime) + 1);for (double xt = 0; xt <= 1; xt += stepTime){double x = 0.0;double y = 0.0;for (int32_t n = 0; n < points.size(); n++){const auto& p = points[n];if (!n){double fact = std::pow((1 - xt), pointsn - n) * std::pow(xt, n);x += p.first * fact;y += p.second * fact;}else{double fact = pointsFact / factorial(n) / factorial((int64_t)pointsn - n)* std::pow((1 - xt), (int64_t)pointsn - n) * std::pow(xt, n);x += fact * p.first;y += fact * p.second;}}retLine[retCount++] = std::make_pair(x, y);}return retLine;
}
}int main()
{std::vector<line::point_t> points({ {115, 53},{392,105},{555,62}, {681, 94} });std::vector<line::point_t> retPoints(100);line::calcBezierLine(points, 0.01, retPoints);return 0;
}