Rhino's Gallery. lots of cool images made with their NURBS modeller.
Breezy Intro for GEEKS #1 scanned from a world famous PEX book (Hardenbergh)
Breezy Intro for GEEKS #2 CAUTION, some formulas...
The source for the application is twist1.py and it is a terrible mess of a UI, but, it has been useful to me. Perhaps you will find it useful. You will also need Point.py
def C(t, order, points, weights, knots):
c = Point([0,0,0])
rational = 0
i = 0
while i < len(points):
b = B(i, order, t, knots)
p = points[i] * (b * weights[i])
c = c + p
rational = rational + b*weights[i]
i = i + 1
return c * (1.0/rational)
def B(i,k,t,knots):
ret = 0
if k>0:
n1 = (t-knots[i])*B(i,k-1,t,knots)
d1 = knots[i+k] - knots[i]
n2 = (knots[i+k+1] - t) * B(i+1,k-1,t,knots)
d2 = knots[i+k+1] - knots[i+1]
if d1 > 0.0001 or d1 < -0.0001:
a = n1 / d1
else:
a = 0
if d2 > 0.0001 or d2 < -0.0001:
b = n2 / d2
else:
b = 0
ret = a + b
#print "B i = %d, k = %d, ret = %g, a = %g, b = %g\n"%(i,k,ret,a,b)
else:
if knots[i] <= t and t <= knots[i+1]:
ret = 1
else:
ret = 0
return ret
Circle
Example with OpenGL code included below and ancient PEX C
code which takes three XYZ points and put a circle thru them. The example
is taken from the book Mathematical Elements for Computer Graphics,
by David F. Rogers and J Alan Adams.
Here is a little NURBCurve playground using that same example. It evaluates the curve in a very transparent, if very inefficient way. However, if you are trying to build up your understand of how NURBS work, this bit of source if for you.
There is also a good page
based on a talk given to college students by Markus Altmann
/*
* OpenGL code for drawing a circle with a NURBS curve.
*
* Method found on page 374, Mathematical Elements for Computer Graphics,
* 2nd ed. David F. Rogers and J Alan Adams. McGraw Hill, 1990.
* This is the triangle method, using 7 control points at the corners
* and middles of an equilateral triangle, with knot vector
* [ 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 ] 10 knots (nCtrlPoints + order)
* [ 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 1.0] weights, one per ctrlPoint.
* Control points are the corners and midpoints of an equilateral triangle
* 0,0 - 1,0 - 0,sqrt(3)/2 except it has been translated to -.5, -.5
* The first point is repeated as the 7th point.
*
* see picture at http://www.jch.com/NURBS/NURBCirc.gif
* and other notes at http://www.jch.com/NURBS/
* YON - Jan C. Hardenbergh
*/
GLUnurbsObj *pNurb = NULL;
int nCtrlPoints = 7;
GLfloat ctrlPoints[7][4];
GLfloat pointsWeights[7][4] = {
{0,-.5, 0, 1},
{.5,-.5, 0, 0.5},
{0.25, -0.0669873, 0, 1},
{0, 0.3880254, 0, 0.5},
{-.25, -0.0669873, 0, 1},
{-.5,-.5, 0, 0.5},
{0,-.5, 0, 1}};
// Knot vector
int order = 3;
int nKnots = 10;
GLfloat Knots[10] = {0,0,0,1,1,2,2,3,3,3};
#define kStride 4
// Called to draw scene
void RenderScene(void)
{
int i, j;
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Render the NURB
// make sure we are setup
if (!pNurb)
{
// Setup the Nurbs object
pNurb = gluNewNurbsRenderer();
gluNurbsProperty(pNurb, GLU_SAMPLING_TOLERANCE, 5.0f);
//gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
//gluNurbsProperty(pNurb, GLU_DISPLAY_MODE, (GLfloat)GLU_FILL);
// make the NURBS control points from the points & weights
for(i = 0; i < nCtrlPoints; i++)
{
ctrlPoints[i][3] = pointsWeights[i][3];
for (j = 0; j < 3; j++)
{
ctrlPoints[i][j] = pointsWeights[i][j]*ctrlPoints[i][3];
}
}
}
glColor3f(1,0,1);
// Begin the NURB definition
gluBeginCurve(pNurb);
// Send the Non Uniform Rational BSpline
gluNurbsCurve(pNurb, nKnots, Knots, kStride,
&ctrlPoints[0][0], order, GL_MAP1_VERTEX_4);
gluEndCurve(pNurb);
// Draw the control points in red
glPointSize(3.0f);
glColor3f(1,0,0);
glBegin(GL_POINTS);
for(i = 0; i < nCtrlPoints; i++)
glVertex3fv(pointsWeights[i]);
glEnd();
// Flush drawing commands
glFlush();
}
3-DEC-2000 jch - updated 29-MAY-2003