C++三阶贝塞尔曲线

1. 贝塞尔曲线

  • 贝塞尔曲线阶数等于控制点个数n-1
  • 将控制点首尾相连并且取每段连线上一点P,再将每个线段上的P点连接
  • 设第一个控制点为P1,第二个为P2,则参数 t = P 1 P / P 1 P 2 t=P_1P/P_1P_2 t=P1P/P1P2,以此类推
  • 其中t∈[0,1],t由0->1变化的过程,P点也随之移动最终生成贝塞尔曲线
  • 这个博主的博客讲得很清晰,这个c++代码也是根据他写的CSS代码修改的

2. 示意图

  • 一阶贝塞尔曲线
    在这里插入图片描述
  • 二阶贝塞尔曲线
    在这里插入图片描述
  • 三阶贝塞尔曲线
    在这里插入图片描述
  • 四阶贝塞尔曲线
    在这里插入图片描述
  • 五阶贝塞尔曲线
    在这里插入图片描述

3. c++代码实现

#include <stdio.h>
#include <math.h>
#include <vector>
#include <string.h>
#include <Windows.h>
#include <iostream>
#include <iomanip>

class CubicBezier
{
public:
	CubicBezier(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
	{
		const int precision = 100;
		points[0] = x1;
		points[1] = y1;
		points[2] = x2;
		points[3] = y2;
		points[4] = x3;
		points[5] = y3;
		points[6] = x4;
		points[7] = y4;
		coords = getCoordsArray(precision);
	}

	//~CubicBezier()
	//{
	//	std::cout << "CubicBezier的析构函数" << std::endl;
	//}

	float points[8] = {0,0,0.3,0.1,0.3,0.1,1,1};
	std::vector<std::pair<float, float>> coords;

	//定义三阶贝塞尔公式 当t变化时计算曲线上对应的点坐标
	std::pair<float, float> getCoord(float t)
	{
		if (t < 0 || t>1)
		{
			return std::pair<float, float>(0, 0);
		}
		const float t1 = 1 - t;
		const float coefficient1 = pow(t1, 3);
		const float coefficient2 = 3 * t * pow(t1, 2);
		const float coefficient3 = 3 * t1 * pow(t, 2);
		const float coefficient4 = pow(t, 3);
		const float px = coefficient1 * points[0] + coefficient2 * points[2] + coefficient3 * points[4] + coefficient4 * points[6];
		const float py = coefficient1 * points[1] + coefficient2 * points[3] + coefficient3 * points[5] + coefficient4 * points[7];
		std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3);
		//std::cout << "point:(" << px<<"," << py<<")" <<std::endl;
		std::pair<float, float> point(px, py);
		//std::cout << "point:(" << point.first << "," << point.second << ")" << std::endl;
		return point;

	}

	//设置一定的步长 将每次生成的点记录到vector里
	std::vector<std::pair<float, float>> getCoordsArray(int precision)
	{
		const float step = 1.0 / (precision + 1);
		std::vector<std::pair<float, float>> result;
		for (int t = 0; t <= precision +1; t++) {
			float a = t * step;
			result.push_back(std::make_pair<float, float>((getCoord(a)).first, (getCoord(a)).second));
			//std::cout << "1:" << (getCoord(a)).first << "," << (getCoord(a)).second << std::endl;
			std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3);
			//std::cout << "2 (" << result[t].first<<","<< result[t].second<<")" << std::endl;
		}
		coords = result;
		return result;
	}

	//通过近似处点的直线方程利用x来确定y的取值
	float getY(float x)
	{
		if (x >= 1) return 1;
		if (x <= 0) return 0;
		int startX = 0;
		//std::cout << "点数:" << coords.size() << std::endl;
		for (int i = 0; i < coords.size(); i++)
		{
			if (coords[i].first >= x)
			{
				startX = i;
				break;
			}
		}
		const std::pair<float, float> axis1 = coords[startX];
		const std::pair<float, float> axis2 = coords[startX - 1];
		const float k = (axis2.second - axis1.second) / (axis2.first - axis1.first);
		const float b = axis1.second - k * axis1.first;
		return k * x + b;
	}
};
void test()
{
	CubicBezier Bezier(0,0,0.3, 0.1, 0.3, 0.1,1,1);
	//CubicBezier &Bezier = new CubicBezier(0.3, 0.1, 0.3, 0.1);
	std::cout << "Bezier: ";
	for (int i = 0; i < 8; i++)
	{
		std::cout << Bezier.points[i] << " ";
	}
	std::cout << std::endl;
	//std::cout << "Bezier: " << Bezier.points << std::endl;

	//std::pair<float, float> point1 = Bezier.getCoord(0.3);
	//std::cout << "point: (" << point1.first<<","<< point1.second<<")"<< std::endl;

	std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(3);
	std::cout << "Y: " << Bezier.getY(0.7) << std::endl;

}

int main()
{
	test();
	system("pause");
	return 0;
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值