# 38. `plugins.curve` — Definition of curves in pyFormex.

This module defines classes and functions specialized for handling one-dimensional geometry in pyFormex. These may be straight lines, polylines, higher order curves and collections thereof. In general, the curves are 3D, but special cases may be created for handling plane curves.

## 38.1. Classes defined in module plugins.curve

class `plugins.curve.``Curve`

  Base class for curve type classes.

  This is a virtual class intended to be subclassed. It defines the common definitions for all curve types. The subclasses should at least define the following attributes and methods or override them if the defaults are not suitable.

  Attributes:

  - coords: coordinates of points defining the curve
  - nparts: number of parts (e.g. straight segments of a polyline)
  - closed: is the curve closed or not
  - range: [min,max], range of the parameter: default 0..1

  Methods:

  - sub_points(t,j): returns points at parameter value t,j
  - sub_directions(t,j): returns direction at parameter value t,j
  - pointsOn(): the defining points placed on the curve
  - pointsOff(): the defining points placeded off the curve (control points)
  - parts(j,k):
  - approx(nseg=None,ndiv=None,chordal=None):

  Furthermore it may define, for efficiency reasons, the following methods:

  - sub_points_2
  - sub_directions_2
  `nelems`()

    Return the number of elements in the Geometry.

    Returns: | int – The number of elements in the Geometry. This is an abstract method that should be reimplemented by the derived class.

  `endPoints`()

    Return start and end points of the curve.

    Returns a Coords with two points, or None if the curve is closed.

  `sub_points`(t, j)

    Return the points at values t in part j

    t can be an array of parameter values, j is a single segment number.

  `sub_points_2`(t, j)

    Return the points at values,parts given by zip(t,j)

    t and j can both be arrays, but should have the same length.

  `sub_directions`(t, j)

    Return the directions at values t in part j

    t can be an array of parameter values, j is a single segment number.

  `sub_directions_2`(t, j)

    Return the directions at values,parts given by zip(t,j)

    t and j can both be arrays, but should have the same length.

  `localParam`(t)

    Split global parameter value in part number and local parameter

    Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.

    Returns a tuple of arrays i,t, where i are the (integer) part numbers and t the local parameter values (between 0 and 1).

  `pointsAt`(t, return_position=False)

    Return the points at parameter values t.

    Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.

    Returns a Coords with the coordinates of the points.

    If return_position is True, also returns the part numbers on which the point are lying and the local parameter values.

  `directionsAt`(t)

    Return the directions at parameter values t.

    Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.

  `subPoints`(div=10, extend=[0.0, 0.0])

    Return a sequence of points on the Curve.

    - div: int or a list of floats (usually in the range [0.,1.]) If div is an integer, a list of floats is constructed by dividing the range [0.,1.] into div equal parts. The list of floats then specifies a set of parameter values for which points at in each part are returned. The points are returned in a single Coords in order of the parts.

    The extend parameter allows to extend the curve beyond the endpoints. The normal parameter space of each part is [0.0 .. 1.0]. The extend parameter will add a curve with parameter space [-extend[0] .. 0.0] for the first part, and a curve with parameter space [1.0 .. 1 + extend[0]] for the last part. The parameter step in the extensions will be adjusted slightly so that the specified extension is a multiple of the step size. If the curve is closed, the extend parameter is disregarded.

  `split`(split=None)

    Split a curve into a list of partial curves

    split is a list of integer values specifying the node numbers where the curve is to be split. As a convenience, a single int may be given if the curve is to be split at a single node, or None to split at all nodes.

    Returns a list of open curves of the same type as the original.

  `length`()

    Return the total length of the curve.

    This is only available for curves that implement the ‘lengths’ method.

  `atApproximate`(nseg=None, ndiv=None, equidistant=False, npre=None)

    Return parameter values for approximating a Curve with a PolyLine.

    Parameters:

    - nseg: number of segments of the resulting PolyLine. The number of returned parameter values is nseg if the curve is closed, else nseg+1. Only used if ndiv is not specified.
    - ndiv: positive integer or a list thereof. If a single integer, it specifies the number of straight segments in each part of the curve, and is thus equivalent with nseg = ndiv * self.nparts. If a list of integers, its length should be equal to the number of parts in the curve and each integer in the list specifies the number of segments the corresponding part.
    - equidistant: bool, only used if ndiv is not specified. If True, the points are spaced almost equidistantly over the curve. If False (default), the points are spread equally over the parameter space.
    - npre: integer: only used when equidistant is True: number of segments per part of the curve used in the pre-approximation. This pre-approximation is currently required to compute curve lengths.
  `atChordal`(chordal, at=None)

    Return parameter values to approximate within given chordal error.

    Parameters:

    - chordal: relative tolerance on the distance of the chord to the curve. The tolerance is relative to the curve’s charLength().
    - at: list of floats: list of parameter values that need to be included in the result. The list should contain increasing values in the curve’s parameter range. If not specified, a default is set assuring that the curve is properly approximated. If you specify this yourself, you may end up with bad approximations due to bad choice of the initial values.

    Returns a list of parameter values that create a PolyLine approximate for the curve, such that the chordal error is everywhere smaller than the give value. The chordal error is defined as the distance from a point of the curve to the chord.

  `approxAt`(at)

    Create a PolyLine approximation with specified parameter values.

    Parameters:

    - at: a list of parameter values in the curve parameter range. The Curve points at these parameter values are connected with straight segments to form a PolyLine approximation.
  `approx`(nseg=None, ndiv=None, chordal=0.02, equidistant=False, npre=None)

    Approximate a Curve with a PolyLine of n segments

    If neither nseg nor ndiv are specified (default), a chordal method is used limiting the chordal distance of the curve to the PolyLine segments.

    Parameters:

    - nseg: integer: number of straight segments of the resulting PolyLine. Only used if ndiv is not specified.
    - ndiv: positive integer or a list thereof. If a single integer, it specifies the number of straight segments in each part of the curve, and is thus equivalent with nseg = ndiv * self.nparts. If a list of integers, its length should be equal to the number of parts in the curve and each integer in the list specifies the number of segments the corresponding part.
    - chordal: float: accuracy of the approximation when using the ‘chordal error’ method. This is the case if neither nseg nor ndiv are specified (the default). The value is relative to the curve’s `charLength()`.
    - equidistant: bool, only used if nseg is specified and ndiv is not. If True the nseg+1 points are spaced almost equidistantly over the curve. If False (default), the points are spread equally over the parameter space.
    - npre: integer, only used if the chordal method is used or if nseg is not None and equidistant is True: the number of segments per part of the curve (like ndiv) used in a pre-approximation. If not specified, it is set to the degree of the curve for the chordal method (1 for PolyLine), and to 100 in the equidistant method (where the pre-approximation is currently used to compute accurate curve lengths).
  `approximate`(nseg=None, ndiv=None, chordal=0.02, equidistant=False, npre=None)

    Approximate a Curve with a PolyLine of n segments

    If neither nseg nor ndiv are specified (default), a chordal method is used limiting the chordal distance of the curve to the PolyLine segments.

    Parameters:

    - nseg: integer: number of straight segments of the resulting PolyLine. Only used if ndiv is not specified.
    - ndiv: positive integer or a list thereof. If a single integer, it specifies the number of straight segments in each part of the curve, and is thus equivalent with nseg = ndiv * self.nparts. If a list of integers, its length should be equal to the number of parts in the curve and each integer in the list specifies the number of segments the corresponding part.
    - chordal: float: accuracy of the approximation when using the ‘chordal error’ method. This is the case if neither nseg nor ndiv are specified (the default). The value is relative to the curve’s `charLength()`.
    - equidistant: bool, only used if nseg is specified and ndiv is not. If True the nseg+1 points are spaced almost equidistantly over the curve. If False (default), the points are spread equally over the parameter space.
    - npre: integer, only used if the chordal method is used or if nseg is not None and equidistant is True: the number of segments per part of the curve (like ndiv) used in a pre-approximation. If not specified, it is set to the degree of the curve for the chordal method (1 for PolyLine), and to 100 in the equidistant method (where the pre-approximation is currently used to compute accurate curve lengths).
  `frenet`(ndiv=None, nseg=None, chordal=0.01, upvector=None, avgdir=True, compensate=False)

    Return points and Frenet frame along the curve.

    A PolyLine approximation for the curve is constructed, using the `Curve.approx()` method with the arguments ndiv, nseg and chordal. Then Frenet frames are constructed with `PolyLine._movingFrenet()` using the remaining arguments. The resulting PolyLine points and Frenet frames are returned.

    Parameters:

    - upvector: (3,) vector: a vector normal to the (tangent,normal) plane at the first point of the curve. It defines the binormal at the first point. If not specified it is set to the shorted distance through the set of 10 first points.

    - avgdir: bool or array. If True (default), the tangential vector is set to the average direction of the two segments ending at a node. If False, the tangent vectors will be those of the line segment starting at the points. The tangential vector can also be set by the user by specifying an array with the matching number of vectors.

    - compensate: bool: If True, adds a compensation algorithm if the curve is closed. For a closed curve the moving Frenet algorithm can be continued back to the first point. If the resulting binormial does not coincide with the starting one, some torsion is added to the end portions of the curve to make the two binormals coincide.

      This feature is off by default because it is currently experimental and is likely to change in future. It may also form the base for setting the starting as well as the ending binormal.

    Returns:

    - X: a Coords with npts points on the curve
    - T: normalized tangent vector to the curve at npts points
    - N: normalized normal vector to the curve at npts points
    - B: normalized binormal vector to the curve at npts points
  `position`(geom, csys=None)

    Position a Geometry object along a path.

    Parameters:

    - geom: Geometry or Coords.
    - csys: CoordSys.

    For each point of the curve, a copy of the Geometry/Coords object is created, and positioned thus that the specified csys (default the global axes) coincides with the curve’s frenet axes at that point.

    Returns a list of Geometry/Coords objects.

  `sweep`(mesh, eltype=None, csys=None)

    Sweep a mesh along the curve, creating an extrusion.

    Parameters:

    - mesh: Mesh-like object. This is usually a planar object that is swept in the direction normal to its plane.
    - eltype: string. Name of the element type on the returned Meshes.

    Returns a Mesh obtained by sweeping the given Mesh over a path. The returned Mesh has double plexitude of the original. If path is a closed Curve connect back to the first.

    Note

    Sweeping nonplanar objects and/or sweeping along very curly curves may result in physically impossible geometries.

    See also

    `sweep2()`

  `sweep2`(coords, origin=(0.0, 0.0, 0.0), scale=None, **kargs)

    Sweep a Coords object along a curve, returning a series of copies.

    At each point of the curve a copy of the coords is created, possibly scaled, and rotated to keep same orientation with respect to the curve.

    Parameters: | coords (Coords object) – The Coords object to be copied, possibly scaled and positioned at each point of the curve. origin (float array-like (3,)) – The local origin in the Coords. This is the point that will be positioned at the curve’s points. It is also the center of scaling if scale is provided. scale (float array-like, optional) – If provided, it should have the shape (npts,3). For each point of the curve, it specifies the three scaling factors to be used in the three coordinate directions on the coords for the copy that is to be plavced at that point. **kargs (optional keyword arguments) – Extra keyword arguments that are passed to `positionCoordsObj()`.
    Returns: | A sequence of the transformed Coords objects.

    See also

    `sweep()`

  `toFormex`(*args, **kargs)

    Convert a curve to a Formex.

    This creates a polyline approximation as a plex-2 Formex. This is mainly used for drawing curves that do not implement their own drawing routines.

    The method can be passed the same arguments as the approx method.

  `toNurbs`()

    Convert a curve to a NurbsCurve.

    This is currently only implemented for BezierSpline and PolyLine

  `setProp`(p=None)

    Create or destroy the property number for the Curve.

    A curve can have a single integer as property number. If it is set, derived curves and approximations will inherit it. Use this method to set or remove the property.

    Parameters:

    - p: integer or None. If a value None is given, the property is removed from the Curve.

class `plugins.curve.``PolyLine`(coords=[], control=None, closed=False)

  A class representing a series of straight line segments.

  coords is a (npts,3) shaped array of coordinates of the subsequent vertices of the polyline (or a compatible data object). If closed == True, the polyline is closed by connecting the last point to the first. This does not change the vertex data.

  The control parameter has the same meaning as coords and is added for symmetry with other Curve classes. If specified, it will override the coords argument.

  `close`(atol=0.0)

    Close a PolyLine.

    If the PolyLine is already closed, this does nothing. Else it is closed by one of two methods, depending on the distance between the start and end points of the PolyLine:

    - if the distance is smaller than atol, the last point is removed and the last segment now connects the penultimate point with the first one, leaving the number of segments unchanged and the number of points decreased by one;
    - if the distance is not smaller than atol, a new segment is added connecting the last point with the first, resulting in a curve with one more segment and the number of points unchanged. Since the default value for atol is 0.0, this is the default behavior for all PolyLines.

    Returns True if the PolyLine was closed without adding a segment.

    The return value can be used to reopen the PolyLine while keeping all segments (see `open()`).

    Warning

    This method changes the PolyLine inplace.

  `open`(keep_last=False)

    Open a closed PolyLine.

    If the PolyLine is not closed, this does nothing.

    Else, the PolyLine is opened in one of two ways:

    - if keep_last is True, the PolyLine is opened by adding a last point equal to the first, and keeping the number of segments unchanged;
    - if False, the PolyLine is opened by removing the last segment, keeping the number of points unchanged. This is the default behavior.

    There is no return value.

    If a closed PolyLine is opened with keep_last=True, the first and last point will coincide. In order to close it again, a positive atol value needs to be used in `close()`.

    Warning

    This method changes the PolyLine inplace.

  `nelems`()

    Return the number of elements in the Geometry.

    Returns: | int – The number of elements in the Geometry. This is an abstract method that should be reimplemented by the derived class.

  `toFormex`()

    Return the PolyLine as a Formex.

  `toMesh`()

    Convert the PolyLine to a plex-2 Mesh.

    The returned Mesh is equivalent with the PolyLine.

  `sub_points`(t, j)

    Return the points at values t in part j

  `sub_points_2`(t, j)

    Return the points at value,part pairs (t,j)

  `sub_directions`(t, j)

    Return the unit direction vectors at values t in part j.

  `vectors`()

    Return the vectors of each point to the next one.

    The vectors are returned as a Coords object. If the curve is not closed, the number of vectors returned is one less than the number of points.

  `directions`(return_doubles=False)

    Returns unit vectors in the direction of the next point.

    This directions are returned as a Coords object with the same number of elements as the point set.

    If two subsequent points are identical, the first one gets the direction of the previous segment. If more than two subsequent points are equal, an invalid direction (NaN) will result.

    If the curve is not closed, the last direction is set equal to the penultimate.

    If return_doubles is True, the return value is a tuple of the direction and an index of the points that are identical with their follower.

  `avgDirections`(return_doubles=False)

    Returns the average directions at points.

    For each point the returned direction is the average of the direction from the preceding point to the current, and the direction from the current to the next point.

    If the curve is open, the first and last direction are equal to the direction of the first, resp. last segment.

    Where two subsequent points are identical, the average directions are set equal to those of the segment ending in the first and the segment starting from the last.

  `cosAngles`()

    Return the cosinus of the angles between subsequent segments.

    Returns an array of floats in the range [-1.0..1.0]. The value at index i is the cosinus of the angle between the segment i and the segment i-1. The number of floats is always equal to the number of points.

    If the curve is not closed, the first value is the cosinus of the angle between the last and the first segment, while the last value is always equal to 1.0.

    Where a curve has two subsequent coincident points, the value for the the first point will be 1.0. Where a curve has more than two subsequent coincident points, NAN values will result.

    Examples:

        >>> C1 = PolyLine('01567')
        >>> C2 = PolyLine('01567',closed=True)
        >>> C3 = PolyLine('015674')
        >>> print(C1.cosAngles())
        [-0.71  0.71  0.    0.    1.  ]
        >>> print(C2.cosAngles())
        [ 0.    0.71  0.    0.    0.71]
        >>> print(C3.cosAngles())
        [ 0.    0.71  0.    0.    0.71  1.  ]

  `splitByAngle`(cosangle=0.0, angle=None, angle_spec=0.017453292519943295)

    Split a curve at points with high change of direction.

    Parameters:

    - cosangle: float: threshold value for the cosinus of the angle between subsequent segment vectors. The curve will be split at all points where the value of `cosAngles()` is (algebraicallly) lower than or equal to this threshold value. The default value will split the curve where the direction changes with more than 90 degrees. A value 1.0 will split the curve at all points. A value of -1.0 will only split where the curve direction exactly reverses.
    - angle: float: if specified, cosangle will be computed from cosd(angle,angle_spec)
    - angle_spec: float: units used for the angle. Thiis is the number of radians for 1 unit.

    Returns a list of PolyLines, where each PolyLine has limited direction changes. Major changes in direction occur between the PolyLines.

  `roll`(n)

    Roll the points of a closed PolyLine.

  `lengths`()

    Return the length of the parts of the curve.

  `cumLengths`()

    Return the cumulative length of the curve for all vertices.

  `relLengths`()

    Return the relative length of the curve for all vertices.

  `atLength`(div)

    Returns the parameter values at given relative curve length.

    `div` is a list of relative curve lengths (from 0.0 to 1.0). As a convenience, a single integer value may be specified, in which case the relative curve lengths are found by dividing the interval [0.0,1.0] in the specified number of subintervals.

    The function returns a list with the parameter values for the points at the specified relative lengths.

  `reverse`()

    Return the same curve with the parameter direction reversed.

  `parts`(j, k)

    Return a PolyLine containing only segments j to k (k not included).

    j and k should be in the range [0:nparts]. For an open curve j < k. For a closed curve a value k<=j is allowed, to get parts spanning the point 0 as a single (open) PolyLine.

    The resulting PolyLine is always open.

  `cutWithPlane`(p, n, side='')

    Return the parts of the PolyLine at one or both sides of a plane.

    If side is ‘+’ or ‘-‘, return a list of PolyLines with the parts at the positive or negative side of the plane.

    For any other value, returns a tuple of two lists of PolyLines, the first one being the parts at the positive side.

    p is a point specified by 3 coordinates. n is the normal vector to a plane, specified by 3 components.

  `append`(PL, fuse=True, smart=False, **kargs)

    Concatenate two open PolyLines.

    This combines two open PolyLines into a single one. Closed PolyLines cannot be concatenated.

    Parameters:

    - PL: an open PolyLine, to be appended at the end of the current.
    - fuse: bool. If True, the last point of self and the first point of PL will be fused to a single point if they are close. Extra parameters may be added to tune the fuse operation. See the `Coords.fuse()` method. The ppb parameter is not allowed.
    - smart: bool. If True, PL will be connected to self by the endpoint that is closest to the last point of self, thus possibly reversing the sense of PL.

    The same result (with the default parameter values) can also be achieved using operator syntax: PolyLine1 + PolyLine2.

  static `concatenate`(PLlist, **kargs)

    Concatenate a list of `PolyLine` objects.

    Parameters:

    - PLlist: a list of open PolyLines.
    - Other parameters are like in `append()`

    Returns a PolyLine which is the concatenation of all the PolyLines in PLlist

  `insertPointsAt`(t, return_indices=False)

    Insert new points at parameter values t.

    Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.

    Returns a PolyLine with the new points inserted. Note that the parameter values of the points will have changed. If return_indices is True, also returns the indices of the inserted points in the new PolyLine.

  `splitAt`(t)

    Split a PolyLine at parametric values t

    Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.

    Returns a list of open Polylines.

  `splitAtLength`(L)

    Split a PolyLine at relative lenghts L.

    This is a convenience function equivalent with:

        self.splitAt(self.atLength(L))

  `refine`(maxlen)

    Insert extra points in the PolyLine to reduce the segment length.

    Parameters:

    - maxlen: float: maximum length of the segments. The value is relative to the total curve length.

    Returns a PolyLine which is geometrically equivalent to the input PolyLine.

  `vertexReductionDP`(tol, maxlen=None, keep=[0, -1])

    Douglas-Peucker vertex reduction.

    For any subpart of the PolyLine, if the distance of all its vertices to the line connecting the endpoints is smaller than tol, the internal points are removed.

    Returns a bool array flagging the vertices to be kept in the reduced form.

  `coarsen`(tol=0.01, maxlen=None, keep=[0, -1])

    Reduce the number of points of the PolyLine.

    Parameters:

    - tol: maximum relative distance of vertices to remove from the chord of the segment. The value is relative to the total curve length.
    - keep: list of vertices to keep during the coarsening process. (Not implemented yet).

    Retuns a Polyline with a reduced number of points.

class `plugins.curve.``Line`(coords)

  A Line is a PolyLine with exactly two points.

  Parameters:

  - coords: compatible with (2,3) shaped float array

class `plugins.curve.``BezierSpline`(coords=None, deriv=None, curl=0.3333333333333333, control=None, closed=False, degree=3, endzerocurv=False)

  A class representing a Bezier spline curve of degree 1, 2 or 3.

  A Bezier spline of degree d is a continuous curve consisting of nparts successive parts, where each part is a Bezier curve of the same degree. Currently pyFormex can model linear, quadratic and cubic BezierSplines. A linear BezierSpline is equivalent to a PolyLine, which has more specialized methods than the BezierSpline, so it might be more sensible to use a PolyLine instead of the linear BezierSpline.

  A Bezier curve of degree d is determined by d+1 control points, of which the first and the last are on the curve, while the intermediate d-1 points are not. Since the end point of one part is the begin point of the next part, a BezierSpline is described by ncontrol=d*nparts+1 control points if the curve is open, or ncontrol=d*nparts if the curve is closed.

  The constructor provides different ways to initialize the full set of control points. In many cases the off-curve control points can be generated automatically.

  Parameters:

  - coords : array_like (npoints,3) The points that are on the curve. For an open curve, npoints=nparts+1, for a closed curve, npoints = nparts. If not specified, the on-curve points should be included in the control argument.

  - deriv : array_like (npoints,3) or (2,3) or a list of 2 values one of which can be None and the other is a shape(3,) arraylike. If specified, it gives the direction of the curve at all points or at the endpoints only for a shape (2,3) array or only at one of the endpoints for a list of shape(3,) arraylike and a None type. For points where the direction is left unspecified or where the specified direction contains a NaN value, the direction is calculated as the average direction of the two line segments ending in the point. This will also be used for points where the specified direction contains a value NaN. In the two endpoints of an open curve however, this average direction can not be calculated: the two control points in these parts are set coincident.

  - curl : float The curl parameter can be set to influence the curliness of the curve in between two subsequent points. A value curl=0.0 results in straight segments. The higher the value, the more the curve becomes curled.

  - control : array(nparts,d-1,3) or array(ncontrol,3) If coords was specified and d > 1, this should be a (nparts,d-1,3) array with the intermediate control points, d-1 for each part. If coords was not specified, this should be the full array of ncontrol control points for the curve.

    If not specified, the control points are generated automatically from the coords, deriv and curl arguments. If specified, they override these parameters.

  - closed : boolean If True, the curve will be continued from the last point back to the first to create a closed curve.

  - degree: int (1, 2 or 3) Specfies the degree of the curve. Default is 3.

  - endzerocurv : boolean or tuple of two booleans. Specifies the end conditions for an open curve. If True, the end curvature will be forced to zero. The default is to use maximal continuity of the curvature. The value may be set to a tuple of two values to specify different conditions for both ends. This argument is ignored for a closed curve.

  `pointsOn`()

    Return the points on the curve.

    This returns a Coords object of shape [nparts+1]. For a closed curve, the last point will be equal to the first.

  `pointsOff`()

    Return the points off the curve (the control points)

    This returns a Coords object of shape [nparts,ndegree-1], or an empty Coords if degree <= 1.

  `part`(j, k=None)

    Returns the points defining parts [j:k] of the curve.

    If k is None, it is set equal to j+1, resulting in a single part with degree+1 points.

  `sub_points`(t, j)

    Return the points at values t in part j.

  `sub_directions`(t, j)

    Return the unit direction vectors at values t in part j.

  `sub_curvature`(t, j)

    Return the curvature at values t in part j.

  `length_intgrnd`(t, j)

    Return the arc length integrand at value t in part j.

  `lengths`()

    Return the length of the parts of the curve.

  `parts`(j, k)

    Return a curve containing only parts j to k (k not included).

    The resulting curve is always open.

  `atLength`(l, approx=20)

    Returns the parameter values at given relative curve length.

    Parameters:

    - l: list of relative curve lengths (from 0.0 to 1.0). As a convenience, a single integer value may be specified, in which case the relative curve lengths are found by dividing the interval [0.0,1.0] in the specified number of subintervals.
    - approx: int or None. If not None, an approximate result is returned obtained by approximating the curve first by a PolyLine with approx number of line segments per curve segment. This is currently the only implemented method, and specifying None will fail.

    The function returns a list with the parameter values for the points at the specified relative lengths.

  `insertPointsAt`(t, split=False)

    Insert new points on the curve at parameter values t.

    Parameters:

    - t: float: parametric value where the new points will be inserted. Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.
      - Currently there can only be one new point in each segment *
    - split: bool: if True, this method behaves like the `split()` method. Users should use the latter method instead of the split parameter.

    Returns a single BezierSpline (default). The result is equivalent with the input curve, but has more points on the curve (and more control points. If split is True, the behavior is that of the `split()` method.

  `splitAt`(t)

    Split a BezierSpline at parametric values.

    Parameters:

    - t: float: parametric value where the new points will be inserted. Parameter values are floating point values. Their integer part is interpreted as the curve segment number, and the decimal part goes from 0 to 1 over the segment.
      - Currently there can only be one new point in each segment *

    Returns a list of len(t)+1 open BezierSplines of the same degree as the input.

  `toMesh`()

    Convert the BezierSpline to a Mesh.

    For degrees 1 or 2, the returned Mesh is equivalent with the BezierSpline, and will have element type ‘line1’, resp. ‘line2’.

    For degree 3, the returned Mesh will currently be a quadratic approximation with element type ‘line2’.

  `extend`(extend=[1.0, 1.0])

    Extend the curve beyond its endpoints.

    This function will add a Bezier curve before the first part and/or after the last part by applying de Casteljau’s algorithm on this part.

  `reverse`()

    Return the same curve with the parameter direction reversed.

class `plugins.curve.``Contour`(coords, elems)

  A class for storing a contour.

  The contour class stores a continuous (usually closed) curve which consists of a sequence of strokes, each stroke either being a straight segment or a quadratic or cubic Bezier curve. A stroke is thus defined by 2, 3 or 4 points. The contour is defined by a list of points and a Varray of element connectivity. This format is well suited to store contours of scalable fonts. The contours are in that case usually 2D.

  `endPoints`()

    Return start and end points of the curve.

    Returns a Coords with two points, or None if the curve is closed.

  `part`(i)

    Returns the points defining part j of the curve.

  `stroke`(i)

    Return curve for part i

  `sub_points`(t, j)

    Return the points at values t in part j

    t can be an array of parameter values, j is a single segment number.

  `sub_directions`(t, j)

    Return the directions at values t in part j

    t can be an array of parameter values, j is a single segment number.

  `atChordal`(chordal=0.01, at=None)

    Return parameter values to approximate within given chordal error.

    Parameters:

    - chordal: relative tolerance on the distance of the chord to the curve. The tolerance is relative to the curve’s charLength().
    - at: list of floats: list of parameter values that need to be included in the result. The list should contain increasing values in the curve’s parameter range. If not specified, a default is set assuring that the curve is properly approximated. If you specify this yourself, you may end up with bad approximations due to bad choice of the initial values.

    Returns a list of parameter values that create a PolyLine approximate for the curve, such that the chordal error is everywhere smaller than the give value. The chordal error is defined as the distance from a point of the curve to the chord.

  `toMesh`()

    Convert the Contour to a Mesh.

class `plugins.curve.``CardinalSpline`(coords, tension=0.0, closed=False, endzerocurv=False)

  A class representing a cardinal spline.

  Create a natural spline through the given points.

  The Cardinal Spline with given tension is a Bezier Spline with curl :math: curl = ( 1 - tension) / 3 The separate class name is retained for compatibility and convenience. See CardinalSpline2 for a direct implementation (it misses the end intervals of the point set).

class `plugins.curve.``CardinalSpline2`(coords, tension=0.0, closed=False)

  A class representing a cardinal spline.

  `sub_points`(t, j)

    Return the points at values t in part j

    t can be an array of parameter values, j is a single segment number.

class `plugins.curve.``NaturalSpline`(coords, closed=False, endzerocurv=False)

  A class representing a natural spline.

  `sub_points`(t, j)

    Return the points at values t in part j

    t can be an array of parameter values, j is a single segment number.

class `plugins.curve.``Arc3`(coords)

  A class representing a circular arc.

  `sub_points`(t, j)

    Return the points at values t in part j

    t can be an array of parameter values, j is a single segment number.

class `plugins.curve.``Arc`(coords=None, center=None, radius=None, angles=None, angle_spec=0.017453292519943295)

  A class representing a circular arc.

  The arc can be specified by 3 points (begin, center, end) or by center, radius and two angles. In the latter case, the arc lies in a plane parallel to the x,y plane. If specified by 3 colinear points, the plane of the circle will be parallel to the x,y plane if the points are in such plane, else the plane will be parallel to the z-axis.

  `sub_points`(t, j)

    Return the points at values t in part j

    t can be an array of parameter values, j is a single segment number.

  `sub_directions`(t, j)

    Return the directions at values t in part j

    t can be an array of parameter values, j is a single segment number.

  `approx`(ndiv=None, chordal=0.001)

    Return a PolyLine approximation of the Arc.

    Approximates the Arc by a sequence of inscribed straight line segments.

    If ndiv is specified, the arc is divided in precisely ndiv segments.

    If ndiv is not given, the number of segments is determined from the chordal distance tolerance. It will guarantee that the distance of any point of the arc to the chordal approximation is less or equal than chordal times the radius of the arc.

class `plugins.curve.``Spiral`(turns=2.0, nparts=100, rfunc=None)

  A class representing a spiral curve.

## 38.2. Functions defined in module plugins.curve

`plugins.curve.``circle`()

  Create a spline approximation of a circle.

  The returned circle lies in the x,y plane, has its center at (0,0,0) and has a radius 1.

  In the current implementation it is approximated by a bezier spline with curl 0.375058 through 8 points.

`plugins.curve.``arc2points`(x0, x1, R, pos='-')

  Create an arc between two points

  Given two points x0 and x1, this constructs an arc with radius R through these points. The two points should have the same z-value. The arc will be in a plane parallel with the x-y plane and wind positively around the z-axis when moving along the arc from x0 to x1.

  If pos == ‘-‘, the center of the arc will be at the left when going along the chord from x0 to x1, creating an arc smaller than a half-circle. If pos == ‘+’, the center of the arc will be at the right when going along the chord from x0 to x1, creating an arc larger than a half-circle.

  If R is too small, an exception is raised.

`plugins.curve.``binomial`(n, k)

  Compute the binomial coefficient Cn,k.

  This computes the binomial coefficient Cn,k = fac(n) // fac(k) // fac(n-k).

  Example:

      >>> print([ binomial(3,i) for i in range(4) ])
      [1, 3, 3, 1]

`plugins.curve.``binomialCoeffs`(p)

  Compute all binomial coefficients for a given degree p.

  Returns an array of p+1 values.

  For efficiency reasons, the computed values are stored in the module, in a dict with p as key. This allows easy and fast lookup of already computed values.

  Example:

      >>> print(binomialCoeffs(4))
      [1 4 6 4 1]

`plugins.curve.``bezierPowerMatrix`(p)

  Compute the Bezier to power curve transformation matrix for degree p.

  Bezier curve representations can be converted to power curve representations using the coefficients in this matrix.

  Returns a (p+1,p+1) shaped array with a zero upper triangular part.

  For efficiency reasons, the computed values are stored in the module, in a dict with p as key. This allows easy and fast lookup of already computed values.

  Example:

      >>> print(bezierPowerMatrix(4))
      [[  1.   0.   0.   0.   0.]
       [ -4.   4.   0.   0.   0.]
       [  6. -12.   6.   0.   0.]
       [ -4.  12. -12.   4.   0.]
       [  1.  -4.   6.  -4.   1.]]

      >>> 4 in _bezier_power_matrix
      True

`plugins.curve.``convertFormexToCurve`(self, closed=False)

  Convert a Formex to a Curve.

  The following Formices can be converted to a Curve: - plex 2 : to PolyLine - plex 3 : to BezierSpline with degree=2 - plex 4 : to BezierSpline

`plugins.curve.``positionCoordsObj`(objects, path, normal=0, upvector=2, avgdir=False, enddir=None)

  Position a sequence of Coords objects along a path.

  At each point of the curve, a copy of the Coords object is created, with its origin in the curve’s point, and its normal along the curve’s direction. In case of a PolyLine, directions are pointing to the next point by default. If avgdir==True, average directions are taken at the intermediate points avgdir can also be an array like sequence of shape (N,3) to explicitely set the directions for ALL the points of the path

  Missing end directions can explicitely be set by enddir, and are by default taken along the last segment. enddir is a list of 2 array like values of shape (3). one of the two can also be an empty list. If the curve is closed, endpoints are treated as any intermediate point, and the user should normally not specify enddir.

  The return value is a sequence of the repositioned Coords objects.