Skip to main content

Python N-Dimensional Bezier, RationalBezier, BSpline and NURBS library with C++ Backend.

Project description

splinepy

workflow PyPI version

splinepy is a python library for splines of arbitrary dimensions and degrees. The library supports Bezier, Rational Bezier, BSpline and NURBS with fast and easy-to-use APIs.

Install guide

splinepy wheels are available for python3.6+ for MacOS, Linux, and Windows:

pip install --upgrade pip
pip install splinepy

It is also possible to install current development version using pip. It requires a compiler that supports C++17 or higher (C++20 for debug mode - tested with gcc-10.3 and clang-12). Here are two variants:

  1. Fast build - minimal and debug mode
SPLINEPY_MINIMAL_DEBUG_BUILD=True pip install git+https://github.com/tataratat/splinepy.git@main -vvv
  1. Same build as in PyPI - full set of splines and optimized build
pip install git+https://github.com/tataratat/splinepy.git@main -vvv

-vvv is not necessary, but we suggest using it, since you can see the build progress. Full build (the second option) may take a while.

Of course, you can install directly from the source. In addition to aforementioned compilers, this requires a cmake3.16+. If you don't have cmake, easiest way to install it would be: pip install cmake.

git clone git@github.com:tataratat/splinepy.git
cd splinepy
git submodule update --init --recursive
python3 setup.py install

For visualization and extended functionalities, please take a look at gustaf!

Quick start

import splinepy
import numpy as np

# Initialize bspline with any array-like input
bspline = splinepy.BSpline(
    degrees=[2, 1],
    knot_vectors=[
        [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
        [0.0, 0.0, 1.0, 1.0],
    ],
    control_points=[
        [0.0, 0.0],  # [0, 0] (control grid index)
        [0.5, 0.0],  # [1, 0]
        [1.0, 0.0],  # [2, 0]
        [0.0, 1.0],  # [0, 1]
        [0.5, 1.0],  # [1, 1]
        [1.0, 1.0],  # [2, 1]
    ],
)

# We always store control points in 2D arrays with shape
# (total_number_of_control_points, physical_dimension).
# The indexing of the control grid is defined by iterating
# lower-indexed dimensions first. But if you prefer a
# grid-like structure, try
multi_index = bspline.multi_index
grid_cps = np.empty(bspline.control_points.shape)
grid_cps[multi_index[0, 0]] = [0.0, 0.0]
grid_cps[multi_index[1, 0]] = [0.5, 0.0]
grid_cps[multi_index[2, 0], 0] = 1.0
# which also supports ranges
grid_cps[multi_index[:, 0], 1] = 0.0
grid_cps[multi_index[:, 1], 1] = 1.0
grid_cps[multi_index[:, 1], 0] = [0.0, 0.5, 1.0]

assert np.allclose(bspline.control_points, grid_cps)

# Evaluate spline mapping.
# First, let's form parametric coordinate queries
queries = [
    [0.1, 0.2],        # first query
    [0.4, 0.5],        # second query
    [0.1156, 0.9091],  # third query
]
physical_coords = bspline.evaluate(queries)

# we can also execute this in parallel using multithread
# executions on c++ side (for heavy multi-queries scenarios)
physical_coords_parallel = bspline.evaluate(queries, nthreads=2)

# this holds
assert np.allclose(physical_coords, physical_coords_parallel)

Feature Summary

For details, please take a look at the documentation. Most of the functions are vectorized and capable of multithread executions.

Common features

Method Description
evaluate() Given parametric coordinates, returns physical (i.e., mapped / evaluated) coordinate
derivative() Given parametric cooridnates and order of partial derivatives, returns physical derivatives
jacobian() Given a number of query points, returns the jacobian of the geometry or field
sample() Given number of sampling points per parametric dimension, returns evaluated physical coordinates, which are equally distributed in parametric space.
basis_and_support() Given parametric coordinates, returns basis function values and their support. Satisfies partition of unity.
basis_derivative_and_support() Given parametric coordinates and order of partial derivatives, returns basis function derivative values.
proximities() Given physical coordinates, returns parametric coordinates that maps to the nearest physical coordinate. Often referred as "point inversion".
elevate_degrees() Elevates Spline degrees along specified parametric dimensions
extract_boundaries() Given boundary ids, returns extracted boundary splines.

BSpline, NURBS

Method Description
reduce_degrees() Reduces spline degrees along specified parametric dimensionans, as long as the spline stays under given tolerance
insert_knots() Insert knots at given locations
remove_knots() Removes knots at given locations, as long as the spline stays under given tolerance
extract_bezier_patches() Extracts each knot spans as a Bezier spline

Bezier, Rational Bezier

Method Description
multiply (*) Given two Beziers a and b, returns a Bezier c that satisfies: c.evaluate(query) = a.evalute(query) * b.evaluate(query)
add (+) Given two Beziers a and b, returns a Bezier c that satisfies: c.evaluate(query) = a.evaluate(query) + b.evaluate(query)
derivative_spline() Given order or partial derivatives, returns a bezier c that satisfies: c.derivative(query, orders) = a.derivative_spline(orders).evaluate(query)
split() Splits Bezier into multiple patches at defined locations
extract_dim() Extract a single physical dimension
compose() Given an inner function spline a and an outer function spline b, it returns their functional composition that satisfies c.evaluate(query) = b.evaluate(a.evaluate(query))
composition_derivative() Given an outer function a, an inner function b and its derivative b' with respect to some variable s, it returns the derivative with respect to the same variable s of the composition a(b) by applying the chain-rule

Multipatch

Splinepy offers a common interface for multipatch geometries, i.e., geometries consisting of multiple, individual splines of arbitrary types. This concept is both used for complex geometries as for Isogeometric Analysis. Multipatch objects have the following functionalities:

  • determine patch-interfaces automatically
  • identification of boundary faces
  • boundary assignement using different techniques, relying either on the boundary position or on the continuity inbetween patches
  • Boundary extraction

IO

Available in splinepy.io.

Formats Description
iges Loads/Exports splines from an IGES file
irit IRIT compatible format
json (Custom) easy-to-read format, supports base64 encoding
mfem MFEM compatible .mesh format. Supports structured multi-patch splines in controlpoints_cartesian and 2D single-patch splines
gismo GISMO compatible .xml format
npz Based on np.savez()
xml RWTH CATS spline format

BSpline fitting

Implements fitting routines from the The NURBS Book. Available as BSpline's classmethod.

  • interpolate_curve()
  • approximate_curve()
  • interpolate_surface()
  • approximate_surface()

Dependencies

Followings are direct dependencies for splinepy. Please feel free to check out the repositories linked in the following.

Dependency Usage
C++
pybind11 Binding between C++ Backend and Python frontend
SplineLib Backend for BSplines and NURBS
bezman Backend for (rational) Beziers
napf Used for KD-Trees, wrapper for nanoflann
Python
numpy Used for data storage and data manipulation
scipy (optional) Used for sparse matrices, where applicable
Build process
cmake Platform independent build system for Backend
setuptools
wheel

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

splinepy-0.0.24.tar.gz (4.2 MB view hashes)

Uploaded Source

Built Distributions

splinepy-0.0.24-cp311-cp311-win_amd64.whl (1.0 MB view hashes)

Uploaded CPython 3.11 Windows x86-64

splinepy-0.0.24-cp311-cp311-win32.whl (904.5 kB view hashes)

Uploaded CPython 3.11 Windows x86

splinepy-0.0.24-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

splinepy-0.0.24-cp311-cp311-macosx_11_0_arm64.whl (8.8 MB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

splinepy-0.0.24-cp311-cp311-macosx_10_9_x86_64.whl (10.7 MB view hashes)

Uploaded CPython 3.11 macOS 10.9+ x86-64

splinepy-0.0.24-cp310-cp310-win_amd64.whl (1.0 MB view hashes)

Uploaded CPython 3.10 Windows x86-64

splinepy-0.0.24-cp310-cp310-win32.whl (904.6 kB view hashes)

Uploaded CPython 3.10 Windows x86

splinepy-0.0.24-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

splinepy-0.0.24-cp310-cp310-macosx_11_0_arm64.whl (8.8 MB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

splinepy-0.0.24-cp310-cp310-macosx_10_9_x86_64.whl (10.7 MB view hashes)

Uploaded CPython 3.10 macOS 10.9+ x86-64

splinepy-0.0.24-cp39-cp39-win_amd64.whl (1.0 MB view hashes)

Uploaded CPython 3.9 Windows x86-64

splinepy-0.0.24-cp39-cp39-win32.whl (904.6 kB view hashes)

Uploaded CPython 3.9 Windows x86

splinepy-0.0.24-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

splinepy-0.0.24-cp39-cp39-macosx_11_0_arm64.whl (8.8 MB view hashes)

Uploaded CPython 3.9 macOS 11.0+ ARM64

splinepy-0.0.24-cp39-cp39-macosx_10_9_x86_64.whl (10.7 MB view hashes)

Uploaded CPython 3.9 macOS 10.9+ x86-64

splinepy-0.0.24-cp38-cp38-win_amd64.whl (1.0 MB view hashes)

Uploaded CPython 3.8 Windows x86-64

splinepy-0.0.24-cp38-cp38-win32.whl (904.6 kB view hashes)

Uploaded CPython 3.8 Windows x86

splinepy-0.0.24-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

splinepy-0.0.24-cp38-cp38-macosx_11_0_arm64.whl (8.8 MB view hashes)

Uploaded CPython 3.8 macOS 11.0+ ARM64

splinepy-0.0.24-cp38-cp38-macosx_10_9_x86_64.whl (10.7 MB view hashes)

Uploaded CPython 3.8 macOS 10.9+ x86-64

splinepy-0.0.24-cp37-cp37m-win_amd64.whl (1.0 MB view hashes)

Uploaded CPython 3.7m Windows x86-64

splinepy-0.0.24-cp37-cp37m-win32.whl (907.7 kB view hashes)

Uploaded CPython 3.7m Windows x86

splinepy-0.0.24-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.6 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

splinepy-0.0.24-cp37-cp37m-macosx_10_9_x86_64.whl (10.7 MB view hashes)

Uploaded CPython 3.7m macOS 10.9+ x86-64

splinepy-0.0.24-cp36-cp36m-win_amd64.whl (1.0 MB view hashes)

Uploaded CPython 3.6m Windows x86-64

splinepy-0.0.24-cp36-cp36m-win32.whl (907.7 kB view hashes)

Uploaded CPython 3.6m Windows x86

splinepy-0.0.24-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (12.6 MB view hashes)

Uploaded CPython 3.6m manylinux: glibc 2.17+ x86-64

splinepy-0.0.24-cp36-cp36m-macosx_10_9_x86_64.whl (10.7 MB view hashes)

Uploaded CPython 3.6m macOS 10.9+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page