CE7453: B-splines

22 minute read

Published:

This post serves as a comprehensive exam preparation guide for CE7453, focusing on B-splines and NURBS - fundamental techniques for curve and surface representation in computer graphics and CAD.

B-splines

B-splines (Basis splines) represent a powerful mathematical tool for curve and surface representation in computer graphics, CAD systems, and geometric modeling. This post provides a comprehensive overview of B-splines, including their mathematical foundations, key properties, algorithms for evaluation and manipulation, and practical applications.

Historical Context

B-splines evolved from the need to overcome limitations of Bezier curves:

  • 1946: Schoenberg introduces the concept of B-splines in approximation theory
  • 1960s: Development of the recursive definition by de Boor, Cox, and Mansfield
  • 1970s: Integration into CAD/CAM systems
  • 1980s: Development of NURBS (Non-Uniform Rational B-Splines)
  • Current: Industry standard for curve and surface representation

Key Concepts

1. B-spline Basis Functions

B-spline basis functions $N_{i,p}(t)$ are defined recursively:

Degree 0 (constant): \(N_{i,0}(t) = \begin{cases} 1 & \text{if } t_i \leq t < t_{i+1} \\ 0 & \text{otherwise} \end{cases}\)

Higher degrees: \(N_{i,p}(t) = \frac{t - t_i}{t_{i+p} - t_i} N_{i,p-1}(t) + \frac{t_{i+p+1} - t}{t_{i+p+1} - t_{i+1}} N_{i+1,p-1}(t)\)

where:

  • $t$ is the parameter value
  • $t_i$ are knot values from the knot vector
  • $p$ is the degree of the basis function

Properties of Basis Functions

  1. Local Support: Each $N_{i,p}(t)$ is non-zero only in the interval $[t_i, t_{i+p+1}]$
  2. Partition of Unity: At any parameter value $t$, $\sum_{i=0}^{n} N_{i,p}(t) = 1$
  3. Non-negativity: $N_{i,p}(t) \geq 0$ for all $i$, $p$, and $t$
  4. Continuity: $C^{p-k}$ continuity at a knot with multiplicity $k$

2. Knot Vectors

A knot vector $T = {t_0, t_1, \ldots, t_m}$ is a non-decreasing sequence of parameter values:

  • Uniform: Knots are equally spaced
  • Open (clamped): First and last knots have multiplicity $p+1$
  • Non-uniform: Unequal spacing between knots

Knot Vector Formulation

For a B-spline of degree $p$ with $n+1$ control points, the knot vector has $m+1$ knots where $m = n+p+1$.

Examples:

  • Uniform: $T = {0, 1, 2, 3, 4, 5, 6}$
  • Open uniform: $T = {0, 0, 0, 1, 2, 3, 3, 3}$ (cubic with multiplicity 3 at endpoints)
  • Non-uniform: $T = {0, 0, 0, 1, 2, 2, 3, 3, 3}$ (multiplicity 2 at interior knot $t=2$)

Effect of Knot Multiplicity

  • Single knot: $C^{p-1}$ continuity at that knot
  • Double knot: $C^{p-2}$ continuity
  • Multiplicity $k$: $C^{p-k}$ continuity
  • Multiplicity $p$: $C^0$ continuity (curve passes through control point)
  • Multiplicity $p+1$: Discontinuity at that knot

3. B-spline Curves

A B-spline curve is defined as:

\[P(t) = \sum_{i=0}^{n} P_i N_{i,p}(t)\]

where:

  • $P_i$ are the control points
  • $N_{i,p}(t)$ are the B-spline basis functions of degree $p$
  • $t$ is the parameter value within the domain $[t_p, t_{n+1}]$

Properties of B-spline Curves

  1. Local Control: Moving a control point affects only the curve segment within $p+1$ spans
  2. Convex Hull: Curve lies within the convex hull of $p+1$ consecutive control points
  3. Variation Diminishing: Curve doesn’t oscillate more than its control polygon
  4. Affine Invariance: Affine transformations can be applied to control points
  5. Endpoint Interpolation: With an open knot vector, the curve passes through first and last control points

4. Evaluation Algorithms

Finding the Knot Span

def find_span(t, knots):
    """
    Find the knot span index for parameter t.
    
    Parameters:
    - t: Parameter value
    - knots: Knot vector
    
    Returns:
    - Index of the knot span
    """
    n = len(knots) - 1
    
    # Special cases
    if t >= knots[n]:
        return n - 1
    if t <= knots[0]:
        return 0
    
    # Binary search
    low = 0
    high = n
    mid = (low + high) // 2
    
    while t < knots[mid] or t >= knots[mid+1]:
        if t < knots[mid]:
            high = mid
        else:
            low = mid
        mid = (low + high) // 2
    
    return mid

Evaluating Basis Functions

def basis_functions(i, p, t, knots):
    """
    Calculate all B-spline basis functions of degree p at parameter t.
    
    Parameters:
    - i: Knot span index
    - p: Degree of the B-spline
    - t: Parameter value
    - knots: Knot vector
    
    Returns:
    - Array of p+1 basis function values
    """
    N = [0.0] * (p + 1)
    left = [0.0] * (p + 1)
    right = [0.0] * (p + 1)
    
    # Initialize degree 0 basis function
    N[0] = 1.0
    
    # Compute basis functions of increasing degree
    for j in range(1, p + 1):
        left[j] = t - knots[i + 1 - j]
        right[j] = knots[i + j] - t
        saved = 0.0
        
        for r in range(j):
            # Avoid division by zero
            if right[r + 1] + left[j - r] == 0.0:
                temp = 0.0
            else:
                temp = N[r] / (right[r + 1] + left[j - r])
            
            N[r] = saved + right[r + 1] * temp
            saved = left[j - r] * temp
            
        N[j] = saved
    
    return N

Evaluating B-spline Curve Points

def bspline_curve_point(t, control_points, knots, degree):
    """
    Evaluate a B-spline curve at parameter t.
    
    Parameters:
    - t: Parameter value
    - control_points: Array of control points (each can be a multidimensional point)
    - knots: Knot vector
    - degree: Degree of the B-spline
    
    Returns:
    - Point on the B-spline curve
    """
    import numpy as np
    
    # Find knot span
    span = find_span(t, knots)
    
    # Calculate basis functions
    N = basis_functions(span, degree, t, knots)
    
    # Initialize point with zeros matching the dimension of control points
    point = np.zeros_like(control_points[0]).astype(float)
    
    # Compute curve point as weighted sum of control points
    for j in range(degree + 1):
        point += N[j] * control_points[span - degree + j]
    
    return point

Python Implementation: De Boor Algorithm

def de_boor(t, control_points, knots, degree):
    """
    Evaluate B-spline curve at parameter t using De Boor algorithm.
    
    Parameters:
    - t: Parameter value
    - control_points: Array of control points
    - knots: Knot vector
    - degree: Degree of the B-spline
    
    Returns:
    - Point on the B-spline curve
    """
    # Find knot span
    span = find_span(t, knots)
    
    # Special case: t is at a knot
    if t == knots[span]:
        # Handle multiplicity (simplified for this example)
        return control_points[span - degree]
    
    # Initialize d array
    d = [control_points[i] for i in range(span - degree, span + 1)]
    
    # Apply De Boor recursion
    for r in range(1, degree + 1):
        for j in range(degree, r - 1, -1):
            i = span - degree + j
            alpha = (t - knots[i]) / (knots[i + degree - r + 1] - knots[i])
            d[j] = (1.0 - alpha) * d[j - 1] + alpha * d[j]
    
    return d[degree]

2. Knot Insertion

  • Purpose: Add knots without changing curve shape
  • Applications:
    • Refinement for analysis
    • Splitting curves
    • Converting to Bezier representation

Knot Insertion Algorithm

To insert a knot t̄ into knot vector T (between tk and tk+1):

  1. New knot vector: T’ = {t₀, t₁, …, tk, t̄, tk+1, …, tm}
  2. New control points: Pi’ = αᵢPi + (1-αᵢ)Pi-1 for i = k-p+1, …, k where:
    • αᵢ = (t̄ - ti)/(ti+p - ti) if i ∈ [k-p+1, k]
    • αᵢ = 1 if i > k
    • αᵢ = 0 if i < k-p+1
  3. Original control points outside the range [k-p+1, k] remain unchanged
def knot_insertion(t_bar, control_points, knots, degree):
    """
    Insert a knot into a B-spline curve without changing its shape.
    
    Parameters:
    - t_bar: Parameter value of new knot
    - control_points: Original control points
    - knots: Original knot vector
    - degree: Degree of the B-spline
    
    Returns:
    - New control points
    - New knot vector
    """
    import numpy as np
    
    n = len(control_points) - 1
    
    # Find knot span containing t_bar
    k = find_span(t_bar, knots)
    
    # Create new knot vector
    new_knots = knots.copy()
    new_knots.insert(k + 1, t_bar)
    
    # Create new control points array
    new_control_points = [None] * (n + 2)
    
    # Copy unaffected control points
    for i in range(k - degree + 1):
        new_control_points[i] = control_points[i]
    
    for i in range(k + 1, n + 1):
        new_control_points[i + 1] = control_points[i]
    
    # Calculate affected control points
    for i in range(k - degree + 1, k + 1):
        # Calculate alpha
        if i <= k - degree:
            alpha = 0.0
        elif i >= k + 1:
            alpha = 1.0
        else:
            alpha = (t_bar - knots[i]) / (knots[i + degree] - knots[i])
        
        # Calculate new control point
        new_control_points[i] = (1 - alpha) * control_points[i - 1] + alpha * control_points[i]
    
    return new_control_points, new_knots

Bezier Decomposition

By inserting knots of multiplicity p at each interior knot, a B-spline can be converted into a series of Bezier curves. This is useful for rendering and intersection algorithms.

def bezier_decomposition(control_points, knots, degree):
    """
    Decompose a B-spline curve into a series of Bezier curves.
    
    Parameters:
    - control_points: B-spline control points
    - knots: B-spline knot vector
    - degree: Degree of the B-spline
    
    Returns:
    - List of Bezier control point sets
    """
    # Create deep copies to avoid modifying originals
    cp = control_points.copy()
    kv = knots.copy()
    
    # Get unique internal knots
    unique_internal_knots = []
    for k in kv[degree:-degree]:
        if k not in unique_internal_knots:
            unique_internal_knots.append(k)
    
    # Insert knots to get Bezier segments
    for knot in unique_internal_knots:
        # Determine current multiplicity
        mult = kv.count(knot)
        # Insert knot until multiplicity reaches degree
        for _ in range(degree - mult):
            cp, kv = knot_insertion(knot, cp, kv, degree)
    
    # Extract Bezier segments
    bezier_segments = []
    segment_size = degree + 1
    
    # For each segment
    for i in range(len(cp) - degree):
        if i % degree == 0:
            segment = cp[i:i+segment_size]
            if len(segment) == segment_size:
                bezier_segments.append(segment)
    
    return bezier_segments

3. Degree Elevation

  • Process: Increase degree while preserving shape
  • Application: Compatibility between curves of different degrees

Degree Elevation Algorithm

To increase the degree of a B-spline from p to p+1:

  1. Create a new knot vector by adding duplicates of each knot
  2. Calculate new control points through a linear combination of original points
  3. Preserve the shape of the original curve
def degree_elevate(control_points, knots, degree):
    """
    Elevate the degree of a B-spline curve by 1.
    
    Parameters:
    - control_points: Original control points
    - knots: Original knot vector
    - degree: Original degree
    
    Returns:
    - New control points
    - New knot vector
    """
    n = len(control_points) - 1
    m = len(knots) - 1
    
    # New dimensions
    new_n = n + (n + 1)  # (n+1) new points
    new_degree = degree + 1
    new_m = m + 2  # 2 new knots
    
    # Create new knot vector
    new_knots = [0] * (new_m + 1)
    
    # First degree+1 knots are same
    for i in range(degree + 1):
        new_knots[i] = knots[i]
    
    # Last degree+1 knots are same
    for i in range(1, degree + 2):
        new_knots[new_m - degree - 1 + i] = knots[m - degree + i]
    
    # Interior knots
    for i in range(1, m - 2 * degree):
        # For each original knot, insert it twice
        new_knots[degree + 2*i] = knots[degree + i]
        new_knots[degree + 2*i + 1] = knots[degree + i]
    
    # Calculate new control points
    new_control_points = [None] * (new_n + 1)
    
    # First and last control points remain unchanged
    new_control_points[0] = control_points[0]
    new_control_points[new_n] = control_points[n]
    
    # Calculate intermediate control points
    for i in range(1, n):
        alpha = i / (n + 1)
        new_control_points[2*i] = (1 - alpha) * control_points[i-1] + alpha * control_points[i]
        new_control_points[2*i+1] = (1 - alpha) * control_points[i] + alpha * control_points[i+1]
    
    return new_control_points, new_knots

4. Non-Uniform Rational B-splines (NURBS)

  • Definition: Rational extension of B-splines
  • Equation: P(t) = Σi=0n wiPi Ni,k(t) / Σi=0n wi Ni,k(t)
  • Advantages:
    • Exact representation of conic sections
    • Perspective invariance
    • Extended modeling capabilities

NURBS Formulation

NURBS extend B-splines by associating a weight wi with each control point Pi. The rational basis functions are:

Ri,p(t) = wiNi,p(t) / Σj=0n wjNj,p(t)

The NURBS curve is then: P(t) = Σi=0n PiRi,p(t)

Representing Conic Sections

NURBS can exactly represent circles, ellipses, and other conic sections:

Circle: With degree p=2, n+1=9 control points, and weights:

  • P₀, P₂, P₄, P₆, P₈ on the circle with w=1
  • P₁, P₃, P₅, P₇ at intersections of tangent lines with w=cos(π/4) = 1/√2 ≈ 0.7071
def create_circle_nurbs():
    """
    Create a NURBS representation of a circle.
    
    Returns:
    - Control points
    - Weights
    - Knot vector
    """
    import numpy as np
    
    # Degree
    p = 2
    
    # Control points for circle of radius 1 centered at origin
    control_points = [
        [1, 0],    # P0
        [1, 1],    # P1
        [0, 1],    # P2
        [-1, 1],   # P3
        [-1, 0],   # P4
        [-1, -1],  # P5
        [0, -1],   # P6
        [1, -1],   # P7
        [1, 0]     # P8 (same as P0 to close the circle)
    ]
    
    # Weights: 1 for points on circle, 1/√2 for corner points
    weights = [
        1.0,               # P0
        1.0/np.sqrt(2),    # P1
        1.0,               # P2
        1.0/np.sqrt(2),    # P3
        1.0,               # P4
        1.0/np.sqrt(2),    # P5
        1.0,               # P6
        1.0/np.sqrt(2),    # P7
        1.0                # P8
    ]
    
    # Knot vector: open uniform
    knots = [0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4]
    
    return control_points, weights, knots

Python Implementation: NURBS Curve

def nurbs_curve_point(t, control_points, weights, knots, degree):
    """
    Evaluate a NURBS curve at parameter t.
    
    Parameters:
    - t: Parameter value
    - control_points: Array of control points
    - weights: Array of weights
    - knots: Knot vector
    - degree: Degree of the NURBS
    
    Returns:
    - Point on the NURBS curve
    """
    import numpy as np
    
    n = len(control_points) - 1
    
    num = np.zeros_like(control_points[0]).astype(float)
    den = 0.0
    
    # Find the span and calculate basis functions
    span = find_span(t, knots)
    basis = basis_functions(span, degree, t, knots)
    
    # Calculate the point
    for j in range(degree + 1):
        i = span - degree + j
        if 0 <= i <= n:
            weight_basis = weights[i] * basis[j]
            num += control_points[i] * weight_basis
            den += weight_basis
    
    return num / den if den != 0 else num

Visualization Example

Here’s a complete example to visualize B-spline curves with interactive control:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
from matplotlib.path import Path
import matplotlib.patches as patches

def plot_bspline(control_points, knots, degree, num_points=100):
    """
    Plot a B-spline curve with its control polygon.
    """
    # Extract x and y coordinates
    x_points = [p[0] for p in control_points]
    y_points = [p[1] for p in control_points]
    
    # Parameter range
    t_min = knots[degree]
    t_max = knots[len(knots) - degree - 1]
    t_range = np.linspace(t_min, t_max, num_points)
    
    # Calculate curve points
    curve_points = []
    for t in t_range:
        point = bspline_curve_point(t, control_points, knots, degree)
        curve_points.append(point)
    
    # Extract curve coordinates
    curve_x = [p[0] for p in curve_points]
    curve_y = [p[1] for p in curve_points]
    
    # Create plot
    fig, ax = plt.subplots(figsize=(10, 8))
    plt.subplots_adjust(bottom=0.25)
    
    # Plot control polygon
    control_line, = ax.plot(x_points, y_points, 'o-', color='gray', alpha=0.5, label='Control Polygon')
    
    # Plot B-spline curve
    curve_line, = ax.plot(curve_x, curve_y, 'r-', linewidth=2, label='B-spline Curve')
    
    # Add legend and grid
    ax.legend()
    ax.grid(True)
    ax.set_title(f'B-spline Curve (Degree {degree})')
    ax.axis('equal')
    
    plt.show()
    
# Example usage
if __name__ == "__main__":
    # Control points for an S-shaped curve
    control_points = [
        [0, 0],
        [1, 2],
        [3, -1],
        [5, 3],
        [7, 0]
    ]
    
    # Knot vector for cubic B-spline (degree 3)
    knots = [0, 0, 0, 0, 0.5, 1, 1, 1, 1]
    
    # Plot cubic B-spline
    plot_bspline(control_points, knots, 3)

Applications

  • CAD/CAM: Industry standard for representing curves and surfaces
  • Animation: Control of smooth motion paths
  • Font Design: TrueType fonts use B-splines
  • Image Processing: Representing contours and geometric features
  • FEA: Isogeometric analysis based on NURBS

B-splines in CAD/CAM

Modern CAD systems like CATIA, SolidWorks, and AutoCAD use NURBS as their underlying representation for curves and surfaces. This provides:

  • Precise control over complex geometries
  • Compact mathematical representation
  • Efficient evaluation for rendering and analysis
  • Preservation of design intent during editing

B-splines in Animation

Animation systems use B-splines for:

  • Character motion paths
  • Camera paths
  • Interpolation between keyframes
  • Deformations of character models
def create_animation_path(keyframes, frames_per_segment=30):
    """
    Create a smooth animation path from keyframes using a B-spline.
    
    Parameters:
    - keyframes: List of key positions [[x0,y0], [x1,y1], ...]
    - frames_per_segment: Number of frames between keyframes
    
    Returns:
    - List of path positions for each frame
    """
    # Create a cubic B-spline
    degree = 3
    
    # Add duplicate end points for clamped B-spline
    control_points = []
    control_points.append(keyframes[0])  # Duplicate first
    control_points.extend(keyframes)
    control_points.append(keyframes[-1])  # Duplicate last
    
    # Create open uniform knot vector
    n = len(control_points) - 1
    knots = []
    
    # Add degree+1 zeros at start
    for i in range(degree+1):
        knots.append(0)
    
    # Add middle knots
    middle_knots = n - degree
    for i in range(1, middle_knots):
        knots.append(i/middle_knots)
    
    # Add degree+1 ones at end
    for i in range(degree+1):
        knots.append(1)
    
    # Generate path points
    path = []
    total_frames = frames_per_segment * (len(keyframes) - 1)
    
    for frame in range(total_frames):
        t = frame / total_frames
        point = bspline_curve_point(t, control_points, knots, degree)
        path.append(point)
    
    return path

Isogeometric Analysis

This advanced technique unifies CAD and finite element analysis by using the same NURBS basis functions for both geometry representation and analysis, eliminating the need for geometry approximation through meshing.

def calculate_isogeometric_basis(t, knots, degree, derivative=0):
    """
    Calculate NURBS basis functions for isogeometric analysis.
    
    Parameters:
    - t: Parameter value
    - knots: Knot vector
    - degree: Degree of basis functions
    - derivative: Order of derivative (0=function, 1=first derivative)
    
    Returns:
    - Array of basis function values or derivatives
    """
    # Basis function derivatives calculation
    # Implementation depends on specific IGA approach
    # This is a simplified example
    
    span = find_span(t, knots)
    
    if derivative == 0:
        # Just return the basis functions
        return basis_functions(span, degree, t, knots)
    else:
        # Calculate derivatives using finite differences
        # Real implementations would use analytical derivatives
        epsilon = 1e-6
        basis_at_t = basis_functions(span, degree, t, knots)
        basis_at_t_plus_e = basis_functions(span, degree, t + epsilon, knots)
        
        # First derivative approximation
        derivatives = [(b2 - b1) / epsilon for b1, b2 in zip(basis_at_t, basis_at_t_plus_e)]
        return derivatives

Comparison with Bezier Curves

  • Local Control: B-splines offer local control
  • Continuity: Automatic higher-order continuity between segments
  • Flexibility: Variable degree and knot placement
  • Complexity: More parameters to control (knot vector, weights)

Side-by-Side Comparison

FeatureBezier CurvesB-splines
Local ControlNoYes
Number of Control PointsFixed by degreeIndependent of degree
Continuity Between SegmentsRequires constraintsAutomatic
Exact Representation of CircleNoYes (with NURBS)
Implementation ComplexitySimplerMore complex
DegreeSame as number of control points - 1Independent parameter

Exam Focus Areas

  1. Basis Function Calculation: Recursive calculation of basis functions
  2. Knot Vector Design: Understand effects of different knot vectors
  3. De Boor Algorithm: Implementation and application
  4. Continuity Analysis: Determining continuity at knots
  5. NURBS Understanding: Basic principles and advantages

Sample Exam Questions

  1. Calculate the non-zero basis functions at a specific parameter value.
  2. Determine the minimum degree required for specific continuity conditions.
  3. Explain how knot multiplicity affects the curve’s continuity.
  4. Convert a B-spline representation to a Bezier representation.
  5. Design a B-spline to interpolate a set of points with specific continuity.

Practice Problems

  1. Calculate B-spline basis functions for a given knot vector
  2. Implement the De Boor algorithm for curve evaluation
  3. Determine the effect of knot insertion on a B-spline curve
  4. Convert a B-spline curve to a set of Bezier curves

Challenge Problem

Design a cubic B-spline curve that interpolates the points (0,0), (2,4), (5,1), and (8,3) with C² continuity everywhere. Determine the appropriate knot vector and control points.

Solution Approach:

  1. Set up an interpolation matrix using the B-spline basis functions
  2. Solve the linear system to find control points
  3. Verify continuity conditions at the interpolation points
def solve_interpolation_problem():
    """
    Solve the challenge problem: Interpolate points with C² continuity.
    """
    import numpy as np
    
    # Points to interpolate
    points = np.array([
        [0, 0],
        [2, 4],
        [5, 1],
        [8, 3]
    ])
    
    # For cubic B-spline with C² continuity
    degree = 3
    
    # Number of points
    n = len(points)
    
    # We need n+2 control points for interpolation with C² continuity
    # Create an open uniform knot vector with appropriate multiplicity
    # For cubic curve: [0,0,0,0, ..., 1,1,1,1]
    knots = [0] * (degree + 1) + list(np.linspace(0, 1, n-2)[1:-1]) + [1] * (degree + 1)
    
    # Parameter values for interpolation (chord length parameterization)
    chord_lengths = [0]
    total_length = 0
    
    for i in range(1, n):
        # Calculate Euclidean distance
        dist = np.linalg.norm(points[i] - points[i-1])
        total_length += dist
        chord_lengths.append(total_length)
    
    # Normalize parameters to [0,1]
    params = [t / chord_lengths[-1] for t in chord_lengths]
    
    # Set up interpolation system: A*x = b
    A = np.zeros((n, n+2))
    
    # First and last rows for C² end conditions
    A[0, 0:3] = [1, -2, 1]  # Second derivative at start = 0
    A[n-1, n-1:n+2] = [1, -2, 1]  # Second derivative at end = 0
    
    # Middle rows for interpolation conditions
    for i in range(1, n-1):
        # For each parameter value, calculate basis functions
        param = params[i]
        span = find_span(param, knots)
        basis = basis_functions(span, degree, param, knots)
        
        # Fill row with basis function values
        for j in range(degree + 1):
            if span - degree + j < n+2:
                A[i, span - degree + j] = basis[j]
    
    # Set up right-hand side
    b = np.zeros((n, 2))
    b[1:n-1] = points[1:n-1]  # Interior points
    # End derivatives constraints remain zero
    
    # Solve the system
    control_points = np.linalg.solve(A, b)
    
    return control_points, knots, degree, points

Beyond Basic B-splines: Advanced Topics

1. Tensor Product Surfaces

B-spline surfaces are formed using tensor products, with bidirectional control points and two knot vectors:

\[S(u,v) = \sum_{i=0}^{n} \sum_{j=0}^{m} P_{i,j} N_{i,p}(u) N_{j,q}(v)\]

2. T-splines

T-splines extend NURBS by allowing T-junctions in the control mesh, enabling adaptive refinement without propagating control points.

3. Subdivision Surfaces

An alternative to NURBS that combines faceted modeling with smooth surface generation through recursive subdivision.

Conclusion

B-splines provide a powerful and flexible framework for representing curves and surfaces in computer graphics and CAD. Their mathematical properties, efficient evaluation algorithms, and intuitive geometric interpretation make them an essential tool for geometric modeling. Understanding B-splines and their extensions (NURBS) is crucial for anyone working in computer graphics, CAD/CAM, animation, and related fields.

References and Further Reading

  1. Piegl, L., & Tiller, W. (1997). The NURBS Book. Springer.
  2. Rogers, D. F. (2000). An Introduction to NURBS: With Historical Perspective. Morgan Kaufmann.
  3. Farin, G. (2002). Curves and Surfaces for CAGD: A Practical Guide. Morgan Kaufmann.
  4. de Boor, C. (1978). A Practical Guide to Splines. Springer-Verlag.
  5. Hughes, T. J. R., Cottrell, J. A., & Bazilevs, Y. (2005). Isogeometric analysis: CAD, finite elements, NURBS, exact geometry and mesh refinement. Computer Methods in Applied Mechanics and Engineering.