c++计算贝塞尔曲线(折线平滑为曲线)坐标方法

效果可查看上一篇博文:js手动画平滑曲线,贝塞尔曲线拟合【代码】js手动画平滑曲线,贝塞尔曲线拟合。https://blog.csdn.net/qiufeng_xinqing/article/details/131711963?spm=1001.2014.3001.5502

代码如下:

#include 
#include 
#include 
#include 

namespace line {
// 二维坐标点定义:first对应x值,second对应y值
using point_t = std::pair;

/// 
/// 阶乘(递归),即 n! = n * (n-1) * (n-2) * (n-3) * ...* 1
/// 
/// 阶乘的数
/// 阶乘结果数
double factorial(double num)
{
	return (num <= 1) ? 1 : (num * factorial(num - 1));
}

/// 
/// 通过多个控制点计算当前贝塞尔曲线上的点坐标,横坐标为[0,1]
/// 关于 贝塞尔曲线:https://www.cnblogs.com/fangsmile/articles/11642607.html
/// 
/// 控制点集合
/// 横轴的步长,如果为零则使用默认的 0.01 使用为步长
/// 贝塞尔曲线上的点坐标集
/// 贝塞尔曲线上的点坐标集
const std::vector& calcBezierLine(const std::vector& points, double stepTime, std::vector& 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 points({ {115, 53},{392,105},{555,62}, {681, 94} });
	std::vector retPoints(100);
	line::calcBezierLine(points, 0.01, retPoints);

    return 0;
}

你可能感兴趣的:(c++,贝塞尔曲线,折线平滑为曲线)