81. plugins.nurbs — Using NURBS in pyFormex.

The nurbs module defines functions and classes to manipulate NURBS curves and surfaces in pyFormex. The most important classes and functions for the end user are:

The other classes and functions are mostly intended for internal use.

81.1. Classes defined in module plugins.nurbs

class plugins.nurbs.NurbsCurve(control, degree=None, wts=None, knots=None, blended=True, closed=False, wrap=True, norm_urange=True)[source]

A NURBS curve.

This class can represent a NURBS curve as well as its special case of a non-rational (or simple) B-spline curve. The difference sits only in the weights attributed to the control points: if they are constant, the interpolation functions are simple polynoms and the curve is a B-spline. If variable weights are attributed, the curve becomes a more general Non-Uniform Rational B-Spline or NURBS.

A B-spline is defined by nctrl control points, a degree (>=1) and a sequence of nknots = nctrl+degree+1 parametric values called knots. The knots divide the curve in parametric regions where the mathematical representation of the curve is constant. They form a non-descending sequence , but values may be repeated to model appropriate discontinuities. Given a set of control points and a knot vector, the degree of the curve is obviously degree = nknots-nctrl-1. In literature often the order of a NURBS is used. This is just order = degree+1 = nknots-nctrl. The order is also the minimum number of control points.

To model a NURBS curve, we add a weight wi to each control point and use 4-dimensional coordinates (xi*wi, yi*wi, zi*wi, wi) for each point i. Internally, the NurbsCurve class uses 4-dim points, with default weights set to 1. Before returning, the coordinates are divided At the endInput and output are always 3-dimensional points.

Parameters
  • control (Coords-like (nctrl,3)) – The vertices of the control polygon.

  • degree (int) – The degree of the Nurbs curve. If not specified, it is derived from the length of the knot vector (knots).

  • wts (float array (nctrl)) – Weights to be attributed to the control points. Default is to attribute a weight 1.0 to all points. Using different weights allows for more versatile modeling (like perfect circles and arcs.)

  • knots (KnotVector | list of floats) – The nknots knot values to be used. If a list, the values should be in ascending order. Identical values have to be repeated to their multiplicity. The values are only defined upon a multiplicative constant and will be normalized to set the last value to 1. If degree is specified, default values are constructed automatically by calling genKnotVector(). If no knots are given and no degree is specified, the degree is set to the nctrl-1 if the curve is blended. If not blended, the degree is not set larger than 3.

  • closed (bool, optional) – Determines whether the curve is closed. Default is False. The functionality of closed NurbsCurves is currently limited.

  • blended (bool, optional) – Determines that the curve is blended. Default is True. Set blended==False to define a nonblended curve. A nonblended curve is a chain of independent curves, Bezier curves if the weights are all ones. See also decompose(). The number of control points should be a multiple of the degree, plus one. This parameter is only used if no knots are specified.

class plugins.nurbs.NurbsSurface(control, degree=(None, None), wts=None, knots=(None, None), closed=(False, False), blended=(True, True))[source]

A NURBS surface

The Nurbs surface is defined as a tensor product of NURBS curves in two parametrical directions u and v. The control points form a grid of (nctrlu,nctrlv) points. The other data are like those for a NURBS curve, but need to be specified as a tuple for the (u,v) directions.

The knot values are only defined upon a multiplicative constant, equal to the largest value. Sensible default values are constructed automatically by a call to the genKnotVector() function.

If no knots are given and no degree is specified, the degree is set to the number of control points - 1 if the curve is blended. If not blended, the degree is not set larger than 3.

Warning

This is a class under development!

class plugins.nurbs.Coords4(data=None, w=None, normalize=True, dtyp=<class 'numpy.float32'>, copy=False)[source]

A collection of points represented by their homogeneous coordinates.

While most of the pyFormex implementation is based on the 3D Cartesian coordinates class Coords, some applications may benefit from using 4-dimensional coordinates. The Coords4 class provides some basic functions, including conversion to and from cartesian coordinates. Through the conversion, all pyFormex functions defined on Coords, such as transformations, are possible.

Coords4 is implemented as a float type numpy.ndarray whose last axis has a length equal to 4. Each set of 4 values (x,y,z,w) along the last axis represents a single point in 3D space. The cartesian coordinates of the point are obtained by dividing the first three values by the fourth: (x/w, y/w, z/w). A zero w-value represents a point at infinity. Converting such points to Coords will result in Inf or NaN values in the resulting object.

The float datatype is only checked at creation time. It is the responsibility of the user to keep this consistent throughout the lifetime of the object.

Just like Coords, the class Coords4 is derived from numpy.ndarray.

Parameters
  • data (array_like, optional) – An array of floats, with the length of its last axis not larger than 4. If equal to four, each tuple along the last axis represents a single point in homogeneous coordinates. If smaller than four, the last axis is expanded to four by adding zero values in the second and third position and unity values in the last position (the w-coordinate). If no data are given, a single point (0.,0.,0.,1.) is created.

  • w (array_like, optional) – If specified, the w values are used to denormalize the homogeneous data such that the last component becomes w.

  • dtyp (data-type, optional) – The datatype to be used. It not specified, the datatype of data is used, or the default Float (which is equivalent to numpy.float32).

  • copy (bool, optional) – If True, the data are copied. By default, the original data are used if possible, e.g. if a correctly shaped and typed numpy.ndarray is provided.

class plugins.nurbs.Geometry4[source]

This is a preliminary class intended to provide some transforms in 4D

class plugins.nurbs.KnotVector(data=None, val=None, mul=None)[source]

A knot vector.

A knot vector is sequence of float values sorted in ascending order. Values can occur multiple times. In the typical use case (NURBS) most values do indeed occur multiple times, and the multiplicity of the values is an important quantity. Therefore, the knot vector is stored in two arrays of the same length: val and mul.

val

The unique float values, in a strictly ascending sequence.

Type

float array (nval)

mul

The multiplicity of each of the values in val.

Type

int array (nval)

See also

genKnotVector

generate a knot vector for a NURBS curve

Examples

>>> K = KnotVector([0.,0.,0.,0.5,0.5,1.,1.,1.])
>>> print(K.val)
[0.  0.5 1. ]
>>> print(K.mul)
[3 2 3]
>>> print(K)
KnotVector(8): 0*3, 0.5*2, 1*3
>>> print([(v,m) for v,m in zip(K.val,K.mul)])
[(0.0, 3), (0.5, 2), (1.0, 3)]
>>> print(K.values())
[0.  0.  0.  0.5 0.5 1.  1.  1. ]
>>> print(K.nknots())
8
>>> K.index(0.5)
1
>>> K.span(1.0)
5
>>> K.mult(0.5)
2
>>> K.mult(0.7)
0
>>> K[4],K[-1]
(0.5, 1.0)
>>> K[4:6]
array([0.5, 1. ])

81.2. Functions defined in module plugins.nurbs

plugins.nurbs.genKnotVector(nctrl, degree, blended=True, closed=False)[source]

Compute a sensible knot vector for a Nurbs curve.

A knot vector is a sequence of non-decreasing parametric values. These values define the knots, i.e. the points where the analytical expression of the Nurbs curve may change. The knot values are only meaningful upon a multiplicative constant, and they are usually normalized to the range [0.0..1.0].

A Nurbs curve with nctrl points and of given degree needs a knot vector with nknots = nctrl+degree+1 values. A degree curve needs at least nctrl = degree+1 control points, and thus at least nknots = 2*(degree+1) knot values.

By default, the returned knot vector will produce a blended, clamped, open curve. A blended curve uses overlapping basis functions spanning multiple intervals of the knot vector. This gives the highest smoothness. An unblended (or decomposed) curve is like a chain of separate curves, each formed on a sequence of degree+1 control points.

A clamped (open) curve starts and ends exactly at the first and last control points. Unclamped curves are deprecated and therefore genKnotVector only produces knot vectors for clamped curves. To achieve this, the knot vector should have multiplicity degree+1 for its end values.

Thus, for an open blended curve, the policy is to set the knot values at the ends to 0.0, resp. 1.0, both with multiplicity degree+1, and to spread the remaining nctrl-degree-1 values equally over the interval.

For an open unblended curve, all internal knots get multiplicity degree. This results in a curve that is only one time continuously derivable at the knots, thus the curve is smooth between the knots, but can have crusts at the knots. There is an extra requirement in this case: nctrl should be a multiple of degree plus 1.

For a closed curve, we currently only produce blended curves. The knots are equally spread over the interval, all having a multiplicity 1 for maximum continuity of the curve.

Parameters
  • nctrl (int) – The number of control points. This should be higher than the degree of the curve.

  • degree (int) – The intended degree of the curve. Should be smaller than nctrl.

Returns

KnotVector – A KnotVector to create a NurbsCurve with the specified degree and number of control points.

Examples

>>> nctrl = 5
>>> for i in range(1, nctrl): print(genKnotVector(nctrl, i))
KnotVector(7): 0*2, 0.25*1, 0.5*1, 0.75*1, 1*2
KnotVector(8): 0*3, 0.333333*1, 0.666667*1, 1*3
KnotVector(9): 0*4, 0.5*1, 1*4
KnotVector(10): 0*5, 1*5
>>> print(genKnotVector(7,3))
KnotVector(11): 0*4, 0.25*1, 0.5*1, 0.75*1, 1*4
>>> print(genKnotVector(7,3,blended=False))
KnotVector(11): 0*4, 1*3, 2*4
>>> print(genKnotVector(3,2,closed=True))
KnotVector(6): 0*1, 0.2*1, 0.4*1, 0.6*1, 0.8*1, 1*1
plugins.nurbs.globalInterpolationParameters(Q, exp)[source]

Compute parameters for a global interpolation curve

The global interpolation algorithm computes the control points that produce a NurbsCurve with given points occurring at predefined parameter values. The curve shape depends on the choosen values. This function provides a way to set values that work well under mosr conditions/

Parameters
  • Q (coords_like (npts, 3)) – An ordered set of points through which the curve should pass. Two consecutive points should not coincide.

  • exp (float) – The exponent to be used in the interpolation algorithm. See Notes.

Returns

u (float array (npts, )) – Only returned if return_param=True: the parametric values where the input points are found on the NurbsCurve. Thus, N.pointsAt(u) produces Q.

Notes

The algorithm to set these values uses a variable exponent. Different values produce (slighly) different curves. The smaller the value, the more the two spans get curved. Values above 1 will almost straighten the end spans, but intermediate spans become more curved. Typical values are:

0.0: equally spaced (not recommended) 0.5: centripetal (recommended when data set take sharp turns) 0.7: our prefered default 1.0: chord length (widely used)

plugins.nurbs.globalInterpolationCurve(Q, degree=3, *, t0=None, t1=None, alfa=None, u=None, exp=0.7, return_param=False)[source]

Create a global interpolation NurbsCurve.

An interpolation curve is a curve passing through all the given points.

Parameters
  • Q (coords_like (npts, 3)) – An ordered set of points through which the curve should pass. Two consecutive points should not coincide.

  • degree (int) – The degree of the resulting curve. Usually 2 or 3 is used. For degree 1, the result is a PolyLine through the points Q. For degrees higher than 4, it is better to create a degree 3 curve and then increase the degree.,

  • u (float array_like (npts,), optional) – The parameter values where the points Q should be obtained on the curve. If not provided, a default set of parameter values is computed from globalInterpolationParameters(Q, exp=exp).

  • exp (float, optional) – The exponent to be used in computing the parameter values if no u was provided. The default value 0.7 works well in most cases. See globalInterpolationParameters().

  • return_param (bool) – If True, also returns also parameter values where the given points occur.

Returns

  • N (NurbsCurve) – A NurbsCurve of the specified degree that passes through the given point set. The number of control points is equal to the number of input points plus one for every end tangent set.

  • u (float array (npts, )) – Only returned if return_param=True: the parametric values where the input points are found on the NurbsCurve. Thus, N.pointsAt(u) produces Q.

See also

cubicSplineInterpolate

returns the classical C2 spline interpolate

plugins.nurbs.globalInterpolationCurve2(Q, D, degree=3, *, u=None, exp=0.7, alfa=None, return_param=False)[source]

Create a global interpolation NurbsCurve with given derivatives.

plugins.nurbs.cubicSpline(Q, t0, t1, *, u=None, exp=0.7, alfa=None)[source]

Cubic spline interpolation.

Computes a traditional C2 cubic spline through the points Q with given end tangents.

Parameters
  • Q (float array (nc, 3)) – The nc points where the curve should pass through.

  • t0 (float array (3,)) – The tangent to the curve at the start point Q[0]

  • t1 (float array (3,)) – The tangent to the curve at the end point Q[nc-1]

  • u (float array (nc,), optional) – The parameter values where the points Q should be obtained on the curve. If not provided, a default set of parameter values is computed from globalInterpolationParameters() (Q, exp=exp)``.

  • exp (float, optional) – The exponent to be used in computing the parameter values if no u was provided. The default value 0.7 will work well in most cases. See globalInterpolationParameters().

  • alfa (float, optional) – Multiplication factor for the tangent vectors. If not provided, the tangent vectors are normalized and the multiplication factor is set to the mean segment length of the PolyLine through the given points Q. Note that the length of these vectors influences the resulting curve.

Returns

N (NurbsCurve) – A NurbsCurve of the third degree that passes through the given point set Q and has tangents t0 and t1 at its ends. The number of control points of the curve is nc+2. The parametric values of the input points Q can be got from N.knots[3:-3].

See also

globalInterpolationCurve

global interpolation curve of any degree

plugins.nurbs.NurbsCircle(C=[0.0, 0.0, 0.0], r=1.0, X=[1.0, 0.0, 0.0], Y=[0.0, 1.0, 0.0], ths=0.0, the=360.0)[source]

Create a NurbsCurve representing a perfect circle or arc.

Parameters:

  • C: float (3,): center of the circle

  • r: float: radius

  • X: unit vector in the plane of the circle

  • ‘Y’: unit vector in the plane of the circle and perpendicular to X

  • ths: start angle, measured from the X axis, coungerclockwise in X-Y plane

  • the: end angle, measured from the X axis

Returns a NurbsCurve that is a perfect circle or arc.

plugins.nurbs.toCoords4(x)[source]

Convert cartesian coordinates to homogeneous

x: Coords

Array with cartesian coordinates.

Returns a Coords4 object corresponding to the input cartesian coordinates.

plugins.nurbs.pointsOnBezierCurve(P, u)[source]

Compute points on a Bezier curve

Parameters:

P is an array with n+1 points defining a Bezier curve of degree n. u is a vector with nu parameter values between 0 and 1.

Returns:

An array with the nu points of the Bezier curve corresponding with the specified parametric values. ERROR: currently u is a single paramtric value!

See also: examples BezierCurve, Casteljau

plugins.nurbs.frenet(d1, d2, d3=None)[source]

Compute Frenet vectors, curvature and torsion.

This function computes Frenet vectors, curvature and torsion from the provided first, second, and optional third derivatives of curve. The derivatives can be obtained from NurbsCurve.deriv(). Curvature is computed as abs| d1 x d2 | / |d1|**3

Parameters
  • d1 (float array_like (npts,3)) – First derivative at npts points of a nurbs curve

  • d2 (float array_like (npts,3)) – Second derivative at npts points of a nurbs curve

  • d3 (float array_like (npts,3) , optional) – Third derivative at npts points of a nurbs curve

Returns

  • T (float array(npts,3)) – Normalized tangent vector to the curve at npts points.

  • N (float array(npts,3)) – Normalized normal vector to the curve at npts points.

  • B (float array(npts,3)) – Normalized binormal vector to the curve at npts points.

  • k (float array(npts,3)) – Curvature of the curve at npts points.

  • t (float array(npts,3), optional) – Torsion of the curve at npts points. This value is only returned if d3 was provided.

See also

NurbsCurve.frenet

the corresponding NurbsCurve method

NurbsCurve.deriv

computation of the derivatives of a NurbsCurve