TheBB / NURBS.jl

NURBS package for Julia
Other
8 stars 5 forks source link

NURBS

Build Status

This package does not support the latest Julia release version (0.3). You need to use the 0.4 development version.

NURBS.jl is a Julia package for manipulating NURBS objects (curves, surfaces, volumes, etc.) This includes B-Splines, as a special case. It involves no external dependencies.

This is written mostly as a way to teach myself Julia. Other packages provide similar functionality:

NURBS.jl intends to provide a common framework objects of both spline and NURBS types, with no external dependencies.

Status

The package is currently very early in development. See below for what is implemented.

Usage

Creating basis objects

Import NURBS.Bases. The two bases currently implemented are BSplineBasis and NURBSBasis, both subtypes of Basis1D.

Instantiate a BSplineBasis with a knot vector and a given order:

basis = BSplineBasis([0, 1, 3, 4], 4)

Note that the order is one higher than the polynomial degree of the basis functions. An order 4 basis is cubic. The constructor will create repeated knots at the endpoints automatically. Pass extend=false as a keyword argument if you don't want this.

You can also create a uniform basis more easily.

basis = BSplineBasis(lower, upper, nelements, order)
    # Equivalent to
    # basis = BSplineBasis(linspace(lower, upper, nelements+1), order)

Note that, unlike linspace, this constructor expects the number of elements (intervals), not the number of points.

A NURBS basis is instantiated from a B-Spline basis and a vector of weights, one for each basis function.

nbasis = NURBSBasis(bbasis, [1.0, 2.0, ...])

Using basis objects

Evaluating basis functions

NURBS.jl basis and basis function objects make use of Julia's call overloading, which is present in 0.4 but not in earlier version. For this reason, NURBS.jl will not work on Julia 0.3.

Evaluation at a single point (e.g. basis(1)) will return a tuple (vals, idxs), where vals is a vector of basis function values at that point, and idxs is a range denoting which basis functions are supported there. Only the supported basis functions are actually evaluated, although this doesn't mean they cannot be zero there!

You can evaluate a single basis function at a single point, which will return a Float64.

Evaluation at multiple points will return, for a basis, an array of tuples, or for a basis function, an array of floats.

You can also evaluate a basis with coefficients. Coefficients are stored either in a vector of size length(basis) or a matrix of size length(basis) × d, where d is the dimension of the surrounding space. Calls to basis(pt, coeffs) will return a float or a 1×d-dimensional matrix, while calls to basis(pts, coeffs) will return a vector or a matrix.

(This may change when I decide it is more convenient to do something else.)

Example

The unit circle in NURBS form. See the Wikipedia article.

julia> using NURBS.Bases

julia> knots = [0, pi/2, pi/2, pi, pi, 3pi/2, 3pi/2, 2pi];

julia> bsplines = BSplineBasis(knots, 3);

julia> t = sqrt(2) / 2;

julia> weights = [1, t, 1, t, 1, t, 1, t, 1];

julia> nurbs = NURBSBasis(bsplines, weights);

julia> coeffs = [1 0; 1 1; 0 1; -1 1; -1 0; -1 -1; 0 -1; 1 -1; 1 0];

julia> for p in linspace(0, 2pi, 9) @show nurbs(p, coeffs) end
nurbs(p,coeffs) = [1.0 0.0]
nurbs(p,coeffs) = [0.7071067811865476 0.7071067811865476]
nurbs(p,coeffs) = [0.0 1.0]
nurbs(p,coeffs) = [-0.7071067811865476 0.7071067811865476]
nurbs(p,coeffs) = [-1.0 0.0]
nurbs(p,coeffs) = [-0.7071067811865476 -0.7071067811865476]
nurbs(p,coeffs) = [0.0 -1.0]
nurbs(p,coeffs) = [0.7071067811865476 -0.7071067811865476]
nurbs(p,coeffs) = [1.0 0.0]

julia> points = nurbs(linspace(0, 2pi, 1000), coeffs);

julia> (min, max) = extrema(sum(points .^ 2, 2))
(0.9999999999999997,1.0000000000000004)