I am have a set of control points, and I am trying to draw a cubic B-spline (degree 3) based on these control points. The issue I'm experiencing is that my curve does not connect to the final control point, but instead it draws the curve to some other point that is in a different area all together. The curve points approach (0, 0)
after a certain time.
Image of just the control points
The code I'm working with:
float Stroke::calculate_N(float t, int i, int j, vector<float> knots){
float t_1 = knots[i];
float t_2 = knots[(i + j)];
float t_3 = knots[(i + 1)];
float t_4 = knots[(i + j + 1)];
// Base case of basis function
if (j == 0){
if (t_1 <= t && t < t_3) return 1;
else return 0;
}
float temp1 = (t_2 - t_1 == 0) ? 0 : ((t - t_1) / (t_2 - t_1)) * calculate_N(t, i, j-1, knots);
float temp2 = (t_4 - t_3 == 0) ? 0 : ((t_4 - t) / (t_4 - t_3)) * calculate_N(t, i+1, j-1, knots);
return temp1 + temp2;
}
vector<float> make_knot_vector(int m, int p, int n){
vector<float> knots;
for (int i = 0; i <= p; i++){
knots.push_back(0.0);
}
for (int i = 1; i <= n - p; i++){
knots.push_back((float)i/(float)(n-p+1));
}
for (int i = 0; i <= p; i++){
knots.push_back(1.0);
}
return knots;
}
int main(){
// Init control points
s = Spline();
s.add_control_point(100,100);
s.add_control_point(232,71);
s.add_control_point(148,294);
s.add_control_point(310,115);
s.add_control_point(375,280);
// Get the number of knots based on the number of control points and degree
int num_ctrl_pts = s.get_control_points().size();
float NUM_KNOTS = (float)(num_ctrl_pts + 3 + 1);
// Draw each control point in red
for (auto pt : s.get_control_points()){
int x = pt->get_x();
int y = pt->get_y();
int r = s.get_radius();
vector<vector<float>> circle_points = calc_circ(y, x, r);
int si = circle_points.size();
for (auto circ_point : circle_points){
c->setColor(circ_point[0], circ_point[1], Color(1.0, 0.0, 0.0));
}
}
// Draw the curve
vector<float> knots = make_knot_vector(NUM_KNOTS, 3, num_ctrl_pts);
for (float t = 0.0; t < 1.0; t+= 1.0/1000.0){
Vector sum = Vector(0.0, 0.0);
for (int i = 0;i < num_ctrl_pts; i++){
Vector next = *(s.get_control_points()[i]);
float n = s.calculate_N(t, i, 3, knots);
next = next * n;
sum = sum + next;
}
cout<<"("<<(int)sum.get_x()<<", "<<(int)sum.get_y()<<")"<<endl;
// Draw the curve point in green
vector<vector<float>> circle_points = calc_circ((int)sum.get_y(), (int)sum.get_x(), s.get_radius());
for (auto circ_point : circle_points){
c->setColor(circ_point[0], circ_point[1], Color(0.0, 1.0, 0.0));
}
}
c->writeImage(path + "spline.ppm");
// delete canvas;
return 0;
}