Skip to main content

nurbspy

Description

nurbspy is a Python package for Non-Uniform Rational Basis Spline (NURBS) curves and surfaces. The classes and methods were inspired by the algorithms presented in The NURBS Book and the code uses vectorized NumPy operations, with optional Numba just-in-time compilation for faster basis-function evaluation.

nurbspy aims to be a simple NURBS library, not a fully fledged CAD kernel. If you need a powerful, open source CAD kernel we recommend you to check out the C++ OpenCascade library. If you feel that OpenCascade is too complex or you are not sure how to start using it, this repository might be useful for you!

📚 Documentation: https://turbo-sim.github.io/nurbspy/

Capabilities

nurbspy represents both curves and surfaces as rational or non-rational Bézier / B-Spline / NURBS geometries, built directly from control points, weights, and knot vectors. For both, it provides:

  • Evaluation of coordinates and arbitrary-order analytical derivatives
  • Curvature (and, for surfaces, mean and Gaussian curvature)
  • Point projection / point inversion
  • Matplotlib-based visualization

Curves additionally offer the tangent, normal, and binormal unit vectors (Frenet-Serret frame), torsion, and arc-length by numerical quadrature. Surfaces additionally offer unit normal vectors, u- and v-isoparametric curves, and constructors for common special surfaces: bilinear, ruled, extruded, revolution, and Coons.

nurbspy also works with real and complex data types natively, so shape derivatives can be computed to machine precision with the complex-step method instead of finite differences. This is useful for shape-optimization problems with many design variables that rely on gradient-based algorithms; nurbspy is, to our knowledge, the only Python NURBS package with native complex-number support.

An optional JAX backend (nurbspy.jax) additionally provides automatic differentiation and JIT compilation, see Installation.

For repeated JAX calculations at fixed knots and parameter locations, prepare_curve and prepare_surface reuse polynomial basis tables while control points and weights vary. prepare_surface_projection reuses the initialization grid for repeated queries onto one fixed surface. See the JAX performance guide for usage, lifetimes, and tradeoffs.

See the documentation for the theory behind these capabilities (Bézier, B-Spline, NURBS, and G² continuity) and the examples gallery, with complete scripts and their numerical and graphical output.

Installation

nurbspy requires Python 3.11 to 3.13. Install the latest release from PyPI:

pip install nurbspy

The default installation uses NumPy and does not require Numba. To add optional acceleration:

pip install "nurbspy[numba]"

Numba is used automatically when it is available. Without it, the same functions run with NumPy; the API and numerical algorithms are unchanged, but evaluation can be slower. If Numba raises an import error (for example, because it does not support the installed NumPy version), nurbspy warns and uses NumPy. Installing the extra still requires versions compatible with Numba's own NumPy constraints.

To also install the optional JAX backend and its supporting libraries:

pip install "nurbspy[jax]"

Use import nurbspy as nrb (or explicitly import nurbspy.numpy as nrb) for the NumPy interface, or import nurbspy.jax as nrb for the JAX interface. The default installation does not install Numba or JAX. The JAX extra does not require Numba; both extras can be installed with pip install "nurbspy[numba,jax]". The JAX backend currently uses the CPU.

Verify the installation:

python -c "import nurbspy; print(nurbspy.__version__)"

If you installed the JAX extra, check it with:

python -c "import nurbspy.jax"

For installing from source, contributing, and running the test suite, see Getting started in the documentation.

Minimal working examples

NURBS curves

nurbspy can be used to create Bézier, B-Spline and NURBS curves. The type of curve depends on the arguments used to initialize the curve class. As an example, the following piece of code can be used to generate a degree four Bézier curve in two dimensions:

# Import packages
import numpy as np
import nurbspy as nrb
import matplotlib.pyplot as plt

# Define the array of control points
P = np.zeros((2,5))
P[:, 0] = [0.20, 0.50]
P[:, 1] = [0.40, 0.70]
P[:, 2] = [0.80, 0.60]
P[:, 3] = [0.80, 0.40]
P[:, 4] = [0.40, 0.20]

# Create and plot the Bezier curve
bezierCurve = nrb.NurbsCurve(control_points=P)
bezierCurve.plot()
plt.show()

If the installation was successful, you should be able to see the Bézier curve when you execute the previous code snippet.

Check out the documentation examples directory to see more examples showing the capabilities of the library and how to use them.

NURBS surfaces

Similarly, nurbspy can be used to create Bézier, B-Spline and NURBS surfaces. The type of surface depends on the arguments used to initialize the surface class. As an example, the following code snippet can be used to generate a simple Bézier surface of degree 3 in the u-direction and degree 2 in the v-direction:

# Import packages
import numpy as np
import nurbspy as nrb
import matplotlib.pyplot as plt

# Define the array of control points
n_dim, n, m = 3, 4, 3
P = np.zeros((n_dim, n, m))

# First row
P[:, 0, 0] = [0.00, 0.00, 0.00]
P[:, 1, 0] = [1.00, 0.00, 1.00]
P[:, 2, 0] = [2.00, 0.00, 1.00]
P[:, 3, 0] = [3.00, 0.00, 0.00]

# Second row
P[:, 0, 1] = [0.00, 1.00, 1.00]
P[:, 1, 1] = [1.00, 1.00, 2.00]
P[:, 2, 1] = [2.00, 1.00, 2.00]
P[:, 3, 1] = [3.00, 1.00, 1.00]

# Third row
P[:, 0, 2] = [0.00, 2.00, 0.00]
P[:, 1, 2] = [1.00, 2.00, 1.00]
P[:, 2, 2] = [2.00, 2.00, 1.00]
P[:, 3, 2] = [3.00, 2.00, 0.00]

# Create and plot the Bezier surface
bezierSurface = nrb.NurbsSurface(control_points=P)
bezierSurface.plot(control_points=True, isocurves_u=6, isocurves_v=6)
plt.show()

If the installation was successful, you should be able to see the Bézier surface when you execute the previous script.

Check out the documentation examples directory to see more examples showing the capabilities of the library and how to use them.

Development

The Python package lives under src/nurbspy. Install the checkout in editable mode before running local scripts or tests:

python -m pip install -e . pytest
python -m pytest

To test both optional backends, install -e ".[numba,jax]" instead and run python -m pytest --require-backend=numba --require-backend=jax. poetry install --with dev --all-extras also installs the checkout in editable mode; use poetry run python -m pytest in that environment.

Contact information

nurbspy was originally developed by Roberto Agromayor under the supervision of Associate Professor Lars O. Nord at the Norwegian University of Science and Technology (NTNU) as part of his PhD on turbomachinery shape optimization, and has since been maintained and extended. Please, drop us an email to roberto.agromayor@ntnu.no if you have questions about the code or you have a bug to report!

Metadata

Release files for nurbspy 1.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nurbspy 1.5.0
File Size Uploaded Provenance Actions
nurbspy-1.5.0.tar.gz 73.1 kB Without provenance Details for nurbspy-1.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for nurbspy 1.5.0
File Interpreter ABI Platform Actions
nurbspy-1.5.0-py3-none-any.whl Python 3 none any Details for nurbspy-1.5.0-py3-none-any.whl

Total release size: 157.2 kB

Release files / nurbspy-1.5.0.tar.gz

Download URL nurbspy-1.5.0.tar.gz
Size 73.1 kB
Tags Source
SHA-256 checksum
How to use checksums
2740e04c727ddc4fa38dca462eacac3d0cd61c738a6a536da1b9fc81f7e0a225
BLAKE2b-256 checksum
How to use checksums
c1117285a36947a21b68d6f12749104db9160c25ec9d451a3bad9db669081cbe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.4 CPython/3.12.15 Linux/6.17.0-1022-azure

Release files / nurbspy-1.5.0-py3-none-any.whl

Download URL nurbspy-1.5.0-py3-none-any.whl
Size 84.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c8d959ef65f44e7be6c623eb87e78a87b54d08bd222d42d9eeddf414ba8363b9
BLAKE2b-256 checksum
How to use checksums
011986340a8559c313eb742960a6acd3debd89664d236cdbd35ed0ae12341fc8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.1.4 CPython/3.12.15 Linux/6.17.0-1022-azure

Security for nurbspy 1.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page