/* calculates b-spline location */ float b_spline(int k, int m, float t) { float denom1, denom2, sum = 0.0; if (m == 1) return (t >= knot[k] && t < knot[k+1]); denom1 = knot[k+m -1] - knot[k]; if (denom1 != 0.0) sum = (t - knot[k]) * b_spline(k, m - 1, t) / denom1; denom2 = knot[k + m] - knot[k + 1]; if (denom2 != 0.0) sum += (knot[k + m] - t) * b_spline(k + 1, m - 1, t) / denom2; return sum; }
/* Points */ void draw_screen() { int i, m = 4; double t, sum_x, sum_y, x_old, y_old; glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.0, 0.0, 1.0); /* draw points and connecting lines */ for (i = 0; i < num_points; i++) { draw_point(points[i].x, points[i].y); if (i == 0) { x_old = points[i].x; y_old = points[i].y; } glBegin(GL_LINES); glVertex2i(x_old, y_old); glVertex2i(points[i].x, points[i].y); glEnd(); x_old = points[i].x; y_old = points[i].y; } /* exit if no knot vector */ if (!build_knots(m, num_points - 1)) { glutSwapBuffers(); glFlush(); return; } /* reset last point variables */ x_old = points[0].x; y_old = points[0].y; glColor3f(0.0, 1.0, 0.0); /* draw curve */ for (t = knot[m-1] ; t <= knot[num_points]; t += .05) { sum_x = 0; sum_y = 0; for (i = 0; i < num_points; i++) { sum_x += points[i].x * b_spline(i, m, t); sum_y += points[i].y * b_spline(i, m, t); } if (sum_x == 0.0 || sum_y == 0.0) continue; glBegin(GL_LINES); glVertex2i(x_old, y_old); glVertex2i(sum_x, sum_y); glEnd(); x_old = sum_x; y_old = sum_y; } glutSwapBuffers(); glFlush(); }
void smooth_contour (NV_INT32 num_interp, NV_INT32 *num_pts, NV_FLOAT64 *contour_x, NV_FLOAT64 *contour_y) { NV_FLOAT64 *raw_x, *raw_y; NV_FLOAT64 x[4], y[4]; NV_FLOAT64 coef_x[4], coef_y[4]; NV_FLOAT64 dx, dy, dist; NV_INT32 segment; void b_spline(NV_FLOAT64 *, NV_FLOAT64 *, NV_FLOAT64 *, NV_FLOAT64 *); // allocate memory and make copies of the original contour data if ((raw_x = (NV_FLOAT64 *) malloc ((*num_pts + 2) * sizeof (NV_FLOAT64))) == NULL) { perror ("Allocating raw_x in smooth_contour.cpp"); perror (__FILE__); exit (-1); } if ((raw_y = (NV_FLOAT64 *) malloc ((*num_pts + 2) * sizeof (NV_FLOAT64))) == NULL) { perror ("Allocating raw_y in smooth_contour.cpp"); exit (-1); } memcpy (raw_x + 1, contour_x, *num_pts * sizeof (NV_FLOAT64)); memcpy (raw_y + 1, contour_y, *num_pts * sizeof (NV_FLOAT64)); // obtain the distance between the endpoints dx = raw_x[*num_pts] - raw_x[1]; dy = raw_y[*num_pts] - raw_y[1]; dist = sqrt (pow (dx, 2) + pow (dy, 2)); // if contour closes or nearly closes on itself (endpoints closer than // MIN_ENDPOINT_SEPARATION), use real data from the other end of the // contour to populate the endpoints, else linearly extrapolate to obtain // first and last points if (dist < MIN_ENDPOINT_SEPARATION) { raw_x[0] = raw_x[*num_pts-1]; raw_y[0] = raw_y[*num_pts-1]; raw_x[*num_pts+1] = raw_x[2]; raw_y[*num_pts+1] = raw_y[2]; } else { raw_x[0] = (raw_x[1] - raw_x[2]) + raw_x[1]; raw_y[0] = (raw_y[1] - raw_y[2]) + raw_y[1]; raw_x[*num_pts+1] = (raw_x[*num_pts] - raw_x[*num_pts-1]) + raw_x[*num_pts]; raw_y[*num_pts+1] = (raw_y[*num_pts] - raw_y[*num_pts-1]) + raw_y[*num_pts]; } // loop once for each spline segment, interpolate and fill contour arrays for (segment=0; segment < *num_pts - 1; segment++) { x[0] = raw_x[0 + segment]; x[1] = raw_x[1 + segment]; x[2] = raw_x[2 + segment]; x[3] = raw_x[3 + segment]; y[0] = raw_y[0 + segment]; y[1] = raw_y[1 + segment]; y[2] = raw_y[2 + segment]; y[3] = raw_y[3 + segment]; b_spline (x, y, coef_x, coef_y); interpolate (num_interp, segment, coef_x, coef_y, contour_x, contour_y, SPLINE_POINTS); } segment = *num_pts - 2; interpolate (num_interp, segment, coef_x, coef_y, contour_x, contour_y, SPLINE_ENDPOINT); // set the new number of points in the contour arrays (number of // interpolated points times the number of intervals *num_pts = (num_interp * (*num_pts - 1)) + 1; free(raw_x); free(raw_y); }