B Spline C Implementation
B Spline C Implementation
cpp
//////////////////////////////////////////////////////////////////////////////
// Note:
//
// anyone likes to copy or try it has to take the risk by her or him-self.
//
// Copyright is reserved.
//
//
// Author comment:
// The major purpose of this program is used to demo how to convert any NURBS
//
// Once you finished a NURBS drawing with this program, you can verify it with
//
//
//////////////////////////////////////////////////////////////////////////////
#include <direct.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <crtdbg.h>
#include <freeglut.h>
// key function
//
// ESC quit
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
class BitAry
int _max;
public:
BitAry(int m = 0) { bits.resize(m/32+1); _max = m; }
void SetBit(int k)
void ClearBit(int k)
bool ChkBit(int k)
void SetAll()
int n = bits.size();
void Resize(int m)
bits.clear(); bits.resize(m/32+1);
_max = m;
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
struct Vec2D
double x, y;
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
#define KEY_ESC 27
// window size
int ww = 800;
int wh = 640;
int NDEG;
int pickRadius = 5;
char txtBuf[64];
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
void clearData()
glPushAttrib(GL_ENABLE_BIT);
glLineStipple(1, 0x00FF);
glEnable(GL_LINE_STIPPLE);
glBegin(GL_LINE_STRIP);
glEnd();
glDisable(GL_LINE_STIPPLE);
glPopAttrib();
glBegin(GL_POINTS);
for (int i=0; i<n; i++) glVertex2d(pt[i].x, pt[i].y);
glEnd();
glBegin(GL_POINTS);
else { glColor3f(0.8f,0.5f,0.2f);
glPointSize(5.0); } // gold
glVertex2d(pt[i].x, pt[i].y);
glEnd();
glPushAttrib(GL_ENABLE_BIT); glLineWidth(1.0);
if (! Bits.ChkBit(j)) continue;
glBegin(GL_LINE_STRIP);
glEnd();
glDisable(GL_LINE_STIPPLE);
glPopAttrib();
}
if (state == GLUT_DOWN) {
if (button == GLUT_LEFT_BUTTON) {
dx = CtrlPts[i].x-newX; dy = CtrlPts[i].y-newY;
lIdx = i; break;
if (state == GLUT_UP) {
if (button == GLUT_LEFT_BUTTON) {
if (-1 == lIdx) {
if (bRing) return;
CtrlPts.push_back(Vec2D(newX, newY));
if (bRing) {
RingPts.clear();
lIdx = -1;
}
}
glutPostRedisplay();
if (n > 3) {
if (! bRing) {
if (0 == lIdx) {
dx = newX-CtrlPts[n-1].x; dy = newY-CtrlPts[n-1].y;
dx = newX-CtrlPts[0].x; dy = newY-CtrlPts[0].y;
} else {
RingPts.clear();
glutPostRedisplay();
}
void setKnots()
coreNuts.resize(nNuts);
if (bUnif) {
} else {
srand(GetTickCount());
if (0 == m) {
coreNuts[0] = 0;
if (bRing) {
if (0 == RingPts.size()) {
}
} else {
pNurb = gluNewNurbsRenderer();
gluBeginCurve(pNurb);
gluEndCurve(pNurb);
if (pNurb) gluDeleteNurbsRenderer(pNurb);
void drawBez2Cuv()
glLineWidth(1);
if (! Bits.ChkBit(j)) continue;
B = BezPts[j*2+1]-BezPts[j*2]; A = BezPts[j*2+2]-
BezPts[j*2+1]*2+BezPts[j*2];
glBegin(GL_LINE_STRIP);
glVertex2d(pt.x, pt.y);
glEnd();
void drawBez3Cuv()
glLineWidth(1);
if (! Bits.ChkBit(j)) continue;
A = BezPts[j*3+3]-BezPts[j*3]-(BezPts[j*3+2]-BezPts[j*3+1])*3;
C = BezPts[j*3+1]-BezPts[j*3]; B = BezPts[j*3+2]-
BezPts[j*3+1]*2+BezPts[j*3];
glBegin(GL_LINE_STRIP);
glVertex2d(pt.x, pt.y);
glEnd();
void drawBez4Cuv()
{
glLineWidth(1);
if (! Bits.ChkBit(j)) continue;
A = BezPts[j*4+4]+BezPts[j*4]+BezPts[j*4+2]*6-
(BezPts[j*4+3]+BezPts[j*4+1])*4;
B = BezPts[j*4+3]-BezPts[j*4]-(BezPts[j*4+2]-BezPts[j*4+1])*3;
D = BezPts[j*4+1]-BezPts[j*4]; C = BezPts[j*4+2]-
BezPts[j*4+1]*2+BezPts[j*4];
glBegin(GL_LINE_STRIP);
glVertex2d(pt.x, pt.y);
glEnd();
else {
Bits.ClearBit(i);
if (0 < i) Bits.ClearBit(i-1);
d = nut[mx+3]-nut[mx+1];
else Bits.ClearBit(mx-1);
if (0 != d) { t = (nut[4]-nut[3])/d; tv[0] =
pt[0]*t+pt[1]*(1.0-t); }
if (0 != (d = nut[i+5]-nut[i+2])) {
if (0 == (d = nut[i+4]-nut[i+2])) Bits.ClearBit(i);
} else Bits.ClearBit(i);
if (0 != (d = nut[mx+5]-nut[mx+2])) {
if (0 == (d = nut[mx+4]-nut[mx+2])) Bits.ClearBit(mx-1);
else { t = (nut[mx+3]-nut[mx+2])/d; tv[k] = tv[k+1]*t+tv[k-
1]*(1.0-t); }
} else Bits.ClearBit(mx-1);
double d0, d1, d2, n0, n1, n2, t0, t1, t2, t3; std::vector<Vec2D>
tv(m);
Bits.Resize(mx); Bits.SetAll();
if (0 != d2) {
tv[0] = (pt[0]*t0+pt[1]*(1.0-t0))*t2+(pt[2]*t1+pt[1]*(1.0-t1))*(1.0-t2);
if (0 == d2) Bits.ClearBit(i);
else {
tv[i*4+2] = tp0*(1.0-t2)+(pt[i+3]*t1+pt[i+2]*(1.0-t1))*t2;
tv[i*4+3] = tp0*(1.0-t1-t2)+tp1*t2+pt[i+2]*t1;
t2 = n2/d2; tv[i*4+4] = (pt[i+1]*(1.0-t0)+pt[i+2]*t0)*(1.0-
t2)+tp1*t2;
else Bits.ClearBit(i);
if (0 != d2) {
else Bits.ClearBit(mx-1);
} else Bits.ClearBit(mx-1);
void saveData()
_getcwd(buf, _MAX_PATH);
_ASSERTE(NULL != buf);
strcat_s(buf, file);
if ((NDEG == QUAD && 3 > n) || (NDEG == CUBIC && 4 > n) || (NDEG == QUART && 5 >
n)) {
else p = deg4;
fwrite(buf, m, 1, fp);
o *= L; L = n%L;
if (0 < L) {
fwrite(buf, m, 1, fp);
o *= L; L = k%L;
if (0 < L) {
fwrite(buf, m, 1, fp);
void drawNURBS()
if (0 == n) return;
if (bRing || (QUAD < n && NDEG == QUAD) || (CUBIC < n && NDEG == CUBIC) ||
(QUART < n && NDEG == QUART))
setKnots();
else return;
// set BezPts[]
// draw B-Spline
if (bVerify) {
if (bHull) {
drawHullPts(BezPts.size(), &BezPts[0]);
bHull = false;
void init()
clearData();
void setTitle()
char *p;
else p = deg4;
case '2':
NDEG = QUAD;
break;
case '3':
NDEG = CUBIC;
break;
case '4':
NDEG = QUART;
break;
break;
if (bRing) {
} else return;
break;
if (bUnif) return;
else coreNuts.clear();
break;
bVerify = true;
else return;
break;
else return;
break;
glutPostRedisplay();
void display()
glClear(GL_COLOR_BUFFER_BIT);
drawNURBS();
glutSwapBuffers();
ww = w; wh = h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
void listCommand()
printf("\nkey function:\n\n");
printf("\tESC \tquit\n\n");
printf(" Author: Hunt Chang 20141130\n");
glutInit(&argc, argv);
listCommand();
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(ww, wh);
glutInitWindowPosition(400,50);
setTitle();
glutCreateWindow(txtBuf);
glutDisplayFunc(display);
glutMouseFunc(pickPt);
glutMotionFunc(mouseMove);
glutKeyboardFunc(keyIn);
glutReshapeFunc(reshape);
init();
glutMainLoop();
return 0;
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////