clamped b_spline

#ifndef B_SPLINE_H
#define B_SPLINE_H

#include <vector>

//节点个数 m + 1
//最大次数 p = m
//定义基函数

class BaseFunction {
 public:
  BaseFunction(){};
  ~BaseFunction(){};
  void setKnots(std::vector<double> knots_) {
    knots = knots_;
    m = knots.size() - 1;
    max_p = m - 1;
  };

  // i_:  0 -- m-1
  // p_:  0 -- max_p
  // u_:  knots.front()  --  knots.back()
  // i_ + p_ <= max_p
  double baseN(int i_, int p_, double u_) {
    if (p_ == 0) {
      if (u_ >= knots[i_] && u_ < knots[i_ + 1])
        return 1;
      else
        return 0;
    } else {
      double a = 0;
      if ((knots[i_ + p_] - knots[i_]) != 0)
        a = (u_ - knots[i_]) / (knots[i_ + p_] - knots[i_]);
      double b = 0;
      if ((knots[i_ + p_ + 1] - knots[i_ + 1]) != 0)
        b = (knots[i_ + p_ + 1] - u_) / (knots[i_ + p_ + 1] - knots[i_ + 1]);
      return a * baseN(i_, p_ - 1, u_) + b * baseN(i_ + 1, p_ - 1, u_);
    }
  }

 private:
  std::vector<double> knots;
  int m = 1;
  int max_p = 1;
};

//对一组数据计算BSpline
class BSpline {
 public:
  BSpline(){};
  ~BSpline(){};
  void setP(int p_) {
    p = p_;
    m = n + p + 1;
    generateKnots();
  };
  void addControlPoints(std::vector<double> control_points_) {
    control_points = control_points_;
    n = control_points.size() - 1;
    m = n + p + 1;
    generateKnots();
  };
  void setPointsNum(int points_num_) {
    points_num = points_num_;
    u.clear();
    for (int i = 0; i < points_num; i++) {
      u.emplace_back((double)i / (double)(points_num - 1));
    }
  };

  bool bSplineCal() {
    if (n < 2) {
      return false;
    }
    data_out.clear();
    BaseFunction bf;
    bf.setKnots(knots);
    for (int j = 0; j < u.size(); j++) {
      double c_u = 0;
      for (int i = 0; i <= n; i++) {
        if (j == u.size() - 1 && i == n)
          c_u += control_points[i];
        else
          c_u += (bf.baseN(i, p, u[j]) * control_points[i]);
      }
      data_out.emplace_back(c_u);
    }
    return true;
  }

 public:
  std::vector<double> getDataOut() const { return data_out; };

 private:
  std::vector<double> control_points;  //控制点
  int n = 1;                           //控制点n+1个
  std::vector<double> knots;           //节点0-1范围内
  int m = 1;                           //节点数量m+1个
  int p = 3;                           //曲线阶数

  int points_num = 10;
  std::vector<double> u;         //根据points_num计算采样点的
  std::vector<double> data_out;  //计算完成后的数据

  //生成knots

  void generateKnots() {
    knots.clear();
    for (size_t i = 0; i < m + 1; i++) {
      if (i <= p)
        knots.emplace_back(0);
      else if (i >= m - p)
        knots.emplace_back(1);
      else {
        // p+1 --- m-p-1区间范围内
        int num = m - p - p;
        if (num < 2) return;
        double step = 1.0 / (double)num;
        knots.emplace_back(step * (i - p));
      }
    }
  }
};

class BSpline2D {
 public:
  BSpline2D(){};
  ~BSpline2D(){};

  std::vector<double> getXOut() const { return x_out; };
  std::vector<double> getYOut() const { return y_out; };
  void setP(int p_) { p = p_; };
  void setPointsNum(int points_num_) { points_num = points_num_; };
  void addXControlData(std::vector<double> x_control_data_) {
    x_control_data = x_control_data_;
  };
  void addYControlData(std::vector<double> y_control_data_) {
    y_control_data = y_control_data_;
  };

  bool bSpline2DCal() {
    BSpline bs;
    bs.setP(p);
    bs.setPointsNum(points_num);
    // x方向
    bs.addControlPoints(x_control_data);
    if (!bs.bSplineCal()) {
      return false;
    }
    x_out = bs.getDataOut();
    // y方向
    bs.addControlPoints(y_control_data);
    if (!bs.bSplineCal()) {
      return false;
    }
    y_out = bs.getDataOut();
    return true;
  };

 private:
  std::vector<double> x_control_data, y_control_data;
  std::vector<double> x_out, y_out;
  int p = 3;
  int points_num = 30;
};

#endif

使用方法:

BSpline2D bs2d;

bs2d.setPointsNum(point_num);//设置点数量(默认30个点)

bs2d.setP(3);//设置曲线阶数(默认3阶数)

bs2d.addXControlData(x_control_data);//设置控制点

bs2d.addYControlData(y_control_data);

//进行计算

if (!bs2d.bSpline2DCal()) {

return false;

}

//提取插值点数据

std::vector<double> x_out = bs2d.getXOut();

std::vector<double> y_out = bs2d.getYOut();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值