NURBS: curves & surfaces¶
Pure-Python port of the NURBS evaluation API from BOSL2’s nurbs.scad: evaluate a NURBS
curve, sample a NURBS surface patch, mesh a patch into a VNF, and elevate a curve’s degree. All
three flavours – "clamped", "open" and "closed" – are supported, with weights
(rational NURBS), knot multiplicities, and explicit knot vectors.
nurbs_curve() returns a Path (2-D control points) or
Path3D (3-D), so the result carries the full path/extrude/stroke API;
nurbs_vnf() returns a VNF. Every case is pinned
point-for-point to the real BOSL2 output in tests/test_bosl2_reorient.py – including the
classic rational-NURBS sphere.
The first argument to any of these may be a NURBS parameter list
[type, degree, control, knots, mult, weights] instead of separate arguments.
Coverage of BOSL2 nurbs.scad¶
BOSL2 function |
Status |
Notes |
|---|---|---|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
ported |
|
|
not ported |
the constrained least-squares interpolation solvers (fit a NURBS through given points with derivative/curvature/corner constraints) – thousands of lines of custom linear algebra; a large follow-up. |
|
not ported |
preview/annotation display modules. |
Examples¶
A cubic clamped NURBS curve, swept into a tube:
ctrl = [[0, 0, 0], [10, 20, 5], [30, -10, 10], [50, 20, 0], [60, 0, 15]]
nurbs_curve(ctrl, 3, splinesteps=12).stroke(width=3).show()
A cubic B-spline surface patch meshed into a sheet:
patch = [
[[-50, 50, 0], [-16, 50, 20], [16, 50, 20], [50, 50, 0]],
[[-50, 16, 20], [-16, 16, 40], [16, 16, 40], [50, 16, 20]],
[[-50, -16, 20], [-16, -16, 40], [16, -16, 40], [50, -16, 20]],
[[-50, -50, 0], [-16, -50, 20], [16, -50, 20], [50, -50, 0]],
]
nurbs_vnf(patch, 3, splinesteps=10).polyhedron().show()
A sphere as a rational NURBS surface (weights + repeated knots):
patch = [[[0, 0, 1]] * 7,
[[2, 0, 1], [2, 4, 1], [-2, 4, 1], [-2, 0, 1], [-2, -4, 1], [2, -4, 1], [2, 0, 1]],
[[2, 0, -1], [2, 4, -1], [-2, 4, -1], [-2, 0, -1], [-2, -4, -1], [2, -4, -1], [2, 0, -1]],
[[0, 0, -1]] * 7]
weights = [[w / 9 for w in row] for row in
[[9, 3, 3, 9, 3, 3, 9], [3, 1, 1, 3, 1, 1, 3], [3, 1, 1, 3, 1, 1, 3], [9, 3, 3, 9, 3, 3, 9]]]
nurbs_vnf(patch, 3, weights=weights, knots=[None, [0, 0.5, 0.5, 0.5, 1]], splinesteps=12).polyhedron().show()
API reference¶
- bosl2.nurbs.nurbs_curve(control, degree=None, splinesteps=None, u=None, mult=None, weights=None, type='clamped', knots=None)[source]¶
Evaluate a NURBS curve, returning its points (BOSL2 nurbs_curve()).
Give either splinesteps (uniform samples between knots, with a sample at every knot) or u (parameter values in
[0, 1]). weights makes it a rational NURBS; mult / knots give knot multiplicities / an explicit knot vector; type is"clamped"(default),"open"or"closed". The first argument may instead be a NURBS parameter list[type, degree, control, knots, mult, weights].- Returns:
A
Path(2-D control points) orPath3D(3-D). A single scalar u returns just that point as a plain list.- Parameters:
degree (int | None)
splinesteps (int | None)
type (str)
Examples
A cubic clamped NURBS curve through five control points, swept into a tube:
ctrl = [[0, 0, 0], [10, 20, 5], [30, -10, 10], [50, 20, 0], [60, 0, 15]] nurbs_curve(ctrl, 3, splinesteps=12).stroke(width=3).show()
- bosl2.nurbs.nurbs_patch_points(patch, degree=None, splinesteps=None, u=None, v=None, weights=None, type=('clamped', 'clamped'), mult=(None, None), knots=(None, None))[source]¶
Sample a NURBS surface patch on a grid of points (BOSL2 nurbs_patch_points()).
patch is a rectangular array of control points (or a NURBS parameter list). degree, splinesteps, type, mult and knots are scalars applied to both directions or 2-lists
[u_dir, v_dir]. Give splinesteps, or u and v parameter lists. weights is a matrix the size of patch.- Returns:
A grid (list of rows) of
[x, y, z]points.- Parameters:
degree (int | None)
splinesteps (int | None)
type (str)
- bosl2.nurbs.nurbs_vnf(patch, degree=None, splinesteps=16, weights=None, type='clamped', mult=None, knots=None, style='default', reverse=False, caps=None, cap1=None, cap2=None)[source]¶
Mesh a NURBS surface patch into a
VNF(BOSL2 nurbs_vnf()).Samples the patch with
nurbs_patch_points()and builds the mesh withvertex_array(), wrapping the rows/columns for"closed"directions.- Parameters:
patch – control-point grid or a NURBS parameter list
degree (int | None) – scalar or
[u, v]degreesplinesteps (int) – scalar or
[u, v]samples per knot span (default 16)weights/type/mult/knots – as for
nurbs_patch_points()style (str) –
vertex_array()triangulation stylereverse (bool) – flip every face normal
caps/cap1/cap2 – cap a
["clamped","closed"]/["closed","clamped"]surfacetype (str)
Examples
A cubic B-spline surface patch meshed into a solid:
patch = [ [[-50, 50, 0], [-16, 50, 20], [16, 50, 20], [50, 50, 0]], [[-50, 16, 20], [-16, 16, 40], [16, 16, 40], [50, 16, 20]], [[-50, -16, 20], [-16, -16, 40], [16, -16, 40], [50, -16, 20]], [[-50, -50, 0], [-16, -50, 20], [16, -50, 20], [50, -50, 0]], ] nurbs_vnf(patch, 3).polyhedron().show()
- bosl2.nurbs.nurbs_elevate_degree(control, degree=None, knots=None, type='clamped', times=1, weights=None, mult=None)[source]¶
Raise a NURBS/B-spline curve’s degree by times, returning a parameter list (BOSL2 nurbs_elevate_degree()).
Returns
[type, new_degree, new_control, new_knots, None, new_weights]. Only"clamped"and"open"splines are supported (as in BOSL2). Rational curves are elevated in homogeneous space and de-homogenised.- Parameters:
degree (int | None)
type (str)
times (int)