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);
}
float points[8] = {0,0,0.3,0.1,0.3,0.1,1,1};
std::vector<std::pair<float, float>> coords;
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::pair<float, float> point(px, py);
return point;
}
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 << std::setiosflags(std::ios::fixed) << std::setprecision(3);
}
coords = result;
return result;
}
float getY(float x)
{
if (x >= 1) return 1;
if (x <= 0) return 0;
int startX = 0;
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);
std::cout << "Bezier: ";
for (int i = 0; i < 8; i++)
{
std::cout << Bezier.points[i] << " ";
}
std::cout << 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;
}