前言
塞尔曲线的数学表达式中涉及到伯恩斯坦多项式,而计算伯恩斯坦多项式又依赖于二项式系数。通过将这两个计算过程封装成独立的函数,使得代码结构更加清晰和模块化。这样在计算贝塞尔曲线的过程中,只需要调用这两个函数,而无需重复编写复杂的数学计算逻辑,提高了代码的可读性和可维护性。
测试源码
#include <iostream>
#include <vector>
#include <cmath>
#include "matplotlibcpp.h"
namespace plt = matplotlibcpp;
// 计算二项式系数
int binomialCoefficient(int n, int k) {
if (k > n - k)
k = n - k;
int res = 1;
for (int i = 0; i < k; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
// 计算伯恩斯坦多项式
double bernsteinPoly(int i, int n, double t) {
return binomialCoefficient(n, i) * std::pow(t, i) * std::pow(1 - t, n - i);
}
// 计算三阶贝塞尔曲线点
std::vector<std::pair<double, double>> bezierCurve(const std::vector<std::pair<double, double>>& points, int numPoints) {
std::vector<std::pair<double, double>> curvePoints;
double tStep = 1.0 / (numPoints - 1);
for (int i = 0; i < numPoints; ++i) {
double t = i * tStep;
double x = 0.0, y = 0.0;
for (size_t j = 0; j < points.size(); ++j) {
double b = bernsteinPoly(j, static_cast<int>(points.size()) - 1, t);
x += points[j].first * b;
y += points[j].second * b;
}
curvePoints.emplace_back(x, y);
}
return curvePoints;
}
int main() {
std::vector<std::pair<double, double>> points = { {0, 0}, {1, 2}, {2, 2}, {3, 3}, {4, 5} };
int numPoints = 100;
std::vector<std::pair<double, double>> curvePoints = bezierCurve(points, numPoints);
// 绘制原始点
std::vector<double> xPoints, yPoints;
for (const auto& point : points) {
xPoints.push_back(point.first);
yPoints.push_back(point.second);
}
plt::plot(xPoints, yPoints, "ro");
// 绘制拟合的曲线
std::vector<double> curveX, curveY;
for (const auto& point : curvePoints) {
curveX.push_back(point.first);
curveY.push_back(point.second);
}
plt::plot(curveX, curveY);
plt::show();
return 0;
}
在上述代码中,我们将计算得到的原始点和贝塞尔曲线点分别存储在不同的向量中,然后使用 matplotlibcpp
库的 plot
函数进行绘制,并通过 show
函数显示图形。