# 1. `coords` — A structured collection of 3D coordinates.

The `coords` module defines the `Coords` class, which is the basic data structure in pyFormex to store the coordinates of points in a 3D space.

This module implements a data class for storing large sets of 3D coordinates and provides an extensive set of methods for transforming these coordinates. Most of pyFormex’s classes which represent geometry (e.g. `Formex`, `Mesh`, `TriSurface`, `Curve`) use a `Coords` object to store their coordinates, and thus inherit all the transformation methods of this class.

While the user will mostly use the higher level classes, he might occasionally find good reason to use the `Coords` class directly as well.

class `coords.``Coords`(data=None, dtyp=Float, copy=False)

  A structured collection of points in a 3D cartesian space.

  The `Coords` class is the basic data structure used throughout pyFormex to store the coordinates of points in a 3D space. It is used by other classes, such as `Formex`, `Mesh`, `TriSurface`, `Curve`, which thus inherit the same transformation capabilities. Applications will mostly use the higher level classes, which have more elaborated consistency checking and error handling.

  `Coords` is implemented as a subclass of `numpy.ndarray`, and thus inherits all its methods and atttributes. The last axis of the `Coords` however always has a length equal to 3. Each set of 3 values along the last axis are the coordinates (in a global 3D cartesian coordinate system) of a single point in space. The full Coords array thus is a collection of points. It the array is 2-dimensional, the Coords is a flat list of points. But if the array has more dimensions, the collection of points itself becomes structured.

  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.

  Note

  Methods that transform a Coords object, like `scale()`, `translate()`, `rotate()`, … do not change the original Coords object, but return a new object. Some methods however have an inplace option that allows the user to force coordinates to be changed in place. This option is seldom used however: rather we conveniently use statements like:

      X = X.some_transform()

  and Python can immediately free and recollect the memory used for the old object X.

  Parameters: | data (float array-like, or string) – Data to initialize the Coords. The last axis should have a length of 1, 2 or 3, but will be expanded to 3 if it is less, filling the missing coordinates with zeros. Thus, if you only specify two coordinates, all points are lying in the z=0 plane. Specifying only one coordinate creates points along the x-axis. As a convenience, data may also be entered as a string, which will be passed to the `pattern()` function to create the actual coordinates of the points. If no data are provided, an empty Coords with shape (0,3) is created. dtyp (float datatype, optional) – It not provided, the datatype of `data` is used, or the default `Float` (which is equivalent to `numpy.float32`). copy (bool) – If True, the data are copied. The default setting will try to use the original data if possible, e.g. if data is a correctly shaped and typed `numpy.ndarray`.
  Returns: | Coords – An instance of the Coords class, which is basically an ndarray of floats, with the last axis having a length of 3.

  The Coords instance has a number of attributes that provide views on (part of) the data. They are a notational convenience over using indexing. These attributes can be used to set all or some of the coordinates by direct assignment. The assigned data should however be broadcast compatible with the assigned shape: the shape of the Coords can not be changed.

  `xyz`

    The full coordinate array as an ndarray.

    Type: | float array

  `x`

    The X coordinates of the points as an ndarray with shape `pshape()`.

    Type: | float array

  `y`

    The Y coordinates of the points as an ndarray with shape `pshape()`.

    Type: | float array

  `z`

    The Z coordinates of the points as an ndarray with shape `pshape()`.

    Type: | float array

  `xy`

    The X and Y coordinates of the points as an ndarray with shape `pshape()` + (2,).

    Type: | float array

  `xz`

    The X and Z coordinates of the points as an ndarray with shape `pshape()` + (2,).

    Type: | float array

  `yz`

    The Y and Z coordinates of the points as an ndarray with shape `pshape()` + (2,).

    Type: | float array

  Examples

      >>> Coords([1.,2.])
      Coords([ 1., 2., 0.])
      >>> X = Coords(arange(6).reshape(2,3))
      >>> print(X)
      [[ 0. 1. 2.]
       [ 3. 4. 5.]]
      >>> print(X.y)
      [ 1. 4.]
      >>> X.z[1] = 9.
      >>> print(X)
      [[ 0. 1. 2.]
       [ 3. 4. 9.]]
      >>> print(X.xz)
      [[ 0. 2.]
       [ 3. 9.]]
      >>> X.x = 0.
      >>> print(X)
      [[ 0. 1. 2.]
       [ 0. 4. 9.]]

      >>> Y = Coords(X)             # Y shares its data with X
      >>> Z = Coords(X, copy=True)  # Z is independent
      >>> Y.y = 5
      >>> Z.z = 6
      >>> print(X)
      [[ 0.  5.  2.]
       [ 0.  5.  9.]]
      >>> print(Y)
      [[ 0.  5.  2.]
       [ 0.  5.  9.]]
      >>> print(Z)
      [[ 0.  1.  6.]
       [ 0.  4.  6.]]
      >>> X.coords is X
      True
      >>> Z.xyz = [1,2,3]
      >>> print(Z)
      [[ 1.  2.  3.]
       [ 1.  2.  3.]]

      >>> print(Coords('0123'))  # initialize with string
      [[ 0. 0. 0.]
       [ 1. 0. 0.]
       [ 1. 1. 0.]
       [ 0. 1. 0.]]

  `swapaxes`(axis1, axis2)

    Return a view of the array with axis1 and axis2 interchanged.

    Refer to numpy.swapaxes for full documentation.

    See also

    `numpy.swapaxes()`
      equivalent function
  `xyz`

    Returns the coordinates of the points as an ndarray.

    Returns an ndarray with shape self.shape except last axis is reduced to 2, providing a view on all the coordinates of all the points.

  `x`

    Returns the X-coordinates of all points.

    Returns an ndarray with shape self.pshape(), providing a view on the X-coordinates of all the points.

  `y`

    Returns the Y-coordinates of all points.

    Returns an ndarray with shape self.pshape(), providing a view on the Y-coordinates of all the points.

  `z`

    Returns the Z-coordinates of all points.

    Returns an ndarray with shape self.pshape(), providing a view on the Z-coordinates of all the points.

  `xy`

    Returns the X- and Y-coordinates of all points.

    Returns an ndarray with shape self.shape except last axis is reduced to 2, providing a view on the X- and Y-coordinates of all the points.

  `xz`

    Returns the X- and Y-coordinates of all points.

    Returns an ndarray with shape self.shape except last axis is reduced to 2, providing a view on the X- and Z-coordinates of all the points.

  `yz`

    Returns the X- and Y-coordinates of all points.

    Returns an ndarray with shape self.shape except last axis is reduced to 2, providing a view on the Y- and Z-coordinates of all the points.

  `coords`

    Returns the Coords object .

    This exists only for consistency with other classes.

  `fprint`(fmt='%10.3e %10.3e %10.3e')

    Formatted printing of the points of a `Coords` object.

    Parameters: | fmt (string) – Format to be used to print a single point. The supplied format should contain exactly 3 formatting sequences, ome for each of the three coordinates.

    Examples

        >>> x = Coords([[[0.,0.],[1.,0.]],[[0.,1.],[0.,2.]]])
        >>> x.fprint()
        0.000e+00  0.000e+00  0.000e+00
        1.000e+00  0.000e+00  0.000e+00
        0.000e+00  1.000e+00  0.000e+00
        0.000e+00  2.000e+00  0.000e+00
        >>> x.fprint("%5.2f"*3)
        0.00 0.00 0.00
        1.00 0.00 0.00
        0.00 1.00 0.00
        0.00 2.00 0.00

  `pshape`()

    Return the points shape of the `Coords` object.

    This is the shape of the `numpy.ndarray` with the last axis removed.

    Note

    The full shape of the Coords array can be obtained from the inherited (NumPy) shape attribute.

    Examples

        >>> X = Coords(arange(12).reshape(2,1,2,3))
        >>> X.shape
        (2, 1, 2, 3)
        >>> X.pshape()
        (2, 1, 2)

  `points`()

    Return the `Coords` object as a flat set of points.

    Returns: | Coords – The Coords reshaped to a 2-dimensional array, flattening the structure of the points.

    Examples

        >>> X = Coords(arange(12).reshape(2,1,2,3))
        >>> X.shape
        (2, 1, 2, 3)
        >>> X.points().shape
        (4, 3)

  `npoints`()

    Return the total number of points in the Coords.

    Notes

    npoints and ncoords are equivalent. The latter exists to provide a common interface with other geometry classes.

    Examples

        >>> Coords(arange(12).reshape(2,1,2,3)).npoints()
        4

  `ncoords`()

    Return the total number of points in the Coords.

    Notes

    npoints and ncoords are equivalent. The latter exists to provide a common interface with other geometry classes.

    Examples

        >>> Coords(arange(12).reshape(2,1,2,3)).npoints()
        4

  `bbox`()

    Return the bounding box of a set of points.

    The bounding box is the smallest rectangular volume in the global coordinates, such that no points of the `Coords` are outside that volume.

    Returns: | Coords (2,3) – Coords array with two points: the first point contains the minimal coordinates, the second has the maximal ones.

    See also

    `center()`
      return the center of the bounding box
    `bboxPoint()`
      return a corner or middle point of the bounding box
    `bboxPoints()`
      return all corners of the bounding box

    Examples

        >>> X = Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]])
        >>> print(X.bbox())
        [[ 0. 0. 0.]
         [ 3. 3. 0.]]

  `center`()

    Return the center of the `Coords`.

    The center of a Coords is the center of its bbox(). The return value is a (3,) shaped `Coords` object.

    See also

    `bbox()`
      return the bounding box of the Coords
    `centroid()`
      return the average coordinates of the points

    Examples

        >>> X = Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]])
        >>> print(X.center())
        [ 1.5 1.5 0. ]

  `bboxPoint`(position)

    Return a bounding box point of a Coords.

    Bounding box points are points whose coordinates are either the minimal value, the maximal value or the middle value for the Coords. Combining the three values in three dimensions results in 3**3 = 27 alignment points. The corner points of the bounding box are a subset of these.

    Parameters: | position (str) – String of three characters, one for each direction 0, 1, 2. Each character should be one of the following ’-‘: use the minimal value for that coordinate, ’+’: use the minimal value for that coordinate, ‘0’: use the middle value for that coordinate. Any other character will set the corresponding coordinate to zero.

    Notes

    A string ‘000’ is equivalent with center(). The values ‘—’ and ‘+++’ give the points of the bounding box.

    See also

    `Coords.align()`
      translate Coords by bboxPoint

    Examples

        >>> X = Coords([[0.,0.,0.],[1.,1.,1.]])
        >>> print(X.bboxPoint('-0+'))
        [ 0.  0.5 1. ]

  `bboxPoints`()

    Return all the corners of the bounding box point of a Coords.

    Returns: | Coords (8,3) – A Coords with the eight corners of the bounding box, in the order of a `elements.Hex8`.

    See also

    `bbox()`
      return only two points, with the minimum and maximum coordinates

    Examples

        >>> X = Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]])
        >>> print(X.bboxPoints())
        [[ 0.  0.  0.]
         [ 3.  0.  0.]
         [ 3.  3.  0.]
         [ 0.  3.  0.]
         [ 0.  0.  0.]
         [ 3.  0.  0.]
         [ 3.  3.  0.]
         [ 0.  3.  0.]]

  `average`(wts=None, axis=None)

    Returns a (weighted) average of the `Coords`.

    The average of a Coords is a Coords that is obtained by averaging the points along some or all axes. Weights can be specified to get a weighted average.

    Parameters: | wts (float array-like, optional) – Weight to be attributed to the points. If provided, and axis is an int, wts should be 1-dim with the same length as the specified axis. Else, it has a shape equal to self.shape or self.shape[:-1]. axis (int or tuple of ints, optional) – If provided, the average is computed along the specified axis/axes only. Else, the average is taken over all the points, thus over all the axes of the array except the last.

    Notes

    Averaging over the -1 axis does not make much sense.

    Examples

        >>> X = Coords([[[0.,0.,0.],[1.,0.,0.],[2.,0.,0.]],                 [[4.,0.,0.],[5.,0.,0.],[6.,0.,0.]]])
        >>> X = Coords(arange(6).reshape(3,2,1))
        >>> X
        Coords([[[ 0.,  0.,  0.],
                 [ 1.,  0.,  0.]],
        <BLANKLINE>
                [[ 2.,  0.,  0.],
                 [ 3.,  0.,  0.]],
        <BLANKLINE>
                [[ 4.,  0.,  0.],
                 [ 5.,  0.,  0.]]])
        >>> print(X.average())
        [ 2.5  0.   0. ]
        >>> print(X.average(axis=0))
        [[ 2. 0. 0.]
         [ 3. 0. 0.]]
        >>> print(X.average(axis=1))
        [[ 0.5  0.   0. ]
         [ 2.5  0.   0. ]
         [ 4.5  0.   0. ]]
        >>> print(X.average(wts=[0.5,0.25,0.25],axis=0))
        [[ 1.5  0.   0. ]
         [ 2.5  0.   0. ]]
        >>> print(X.average(wts=[3,1],axis=1))
        [[ 0.25  0.    0.  ]
         [ 2.25  0.    0.  ]
         [ 4.25  0.    0.  ]]
        >>> print(X.average(wts=multiplex([3,1],3,0)))
        [ 2.25  0.    0.  ]

  `centroid`()

    Return the centroid of the `Coords`.

    The centroid of Coords is the point whose coordinates are the mean values of all points.

    Returns: | Coords (3,) – A single point that is the centroid of the Coords.

    See also

    `center()`
      return the center of the bounding box.

    Examples

        >>> print(Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]).centroid())
        [ 1. 1. 0.]

  `centroids`()

    Return the Coords itself.

    Notes

    This method exists only to have a common interface with other geometry classes.

  `sizes`()

    Return the bounding box sizes of the `Coords`.

    Returns: | array (3,) – The length of the bounding box along the three global axes.

    See also

    `dsize()`
      The diagonal size of the bounding box.
    `principalSizes()`
      the sizes of the bounding box along the principal axes

    Examples

        >>> print(Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]).sizes())
        [ 3. 3. 0.]

  `maxsize`()

    Return the maximum size of a Coords in any coordinate direction.

    Returns: | float – The maximum length of any edge of the bounding box.

    Notes

    This is a convenient shorthand for self.sizes().max().

    See also

    `sizes()`
      return the length of the bounding box along global axes
    `bbox()`
      return the bounding box

    Examples

        >>> print(Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]).maxsize())
        3.0

  `dsize`()

    Return the diagonal size of the bounding box of the `Coords`.

    Returns: | float – The length of the diagonal of the bounding box.

    Notes

    All the points of the Coords are inside a sphere with the `center()` as center and the `dsize()` as length of the diameter (though it is not necessarily the smallest bouding sphere). `dsize()` is in general a good estimate for the maximum size of the cross section to be expected when the object can be rotated freely around its center. It is conveniently used to zoom the camera on an object, while guaranteeing that the full object remains visible during rotations.

    See also

    `bsphere()`
      return radius of smallest sphere encompassing all points
    `sizes()`
      return the length of the bounding box along global axes
    `bbox()`
      return the bounding box

    Examples

        >>> print(Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]).dsize())
        4.24264

  `bsphere`()

    Return the radius of the bounding sphere of the `Coords`.

    The bounding sphere used here is the smallest sphere with center in the center() of the `Coords`, and such that no points of the Coords are lying outside the sphere.

    Returns: | float – The maximum distance of any point to the Coords.center.

    Notes

    This is not necessarily the absolute smallest bounding sphere, because we use the center from lookin only in the global axes directions.

    Examples

        >>> X = Coords([[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]])
        >>> print(X.dsize(), X.bsphere())
        4.24264 2.12132
        >>> X = Coords([[0.5,0.],[1.,0.5],[0.5,1.0],[0.0,0.5]])
        >>> print(X.dsize(), X.bsphere())
        1.41421 0.5

  `bboxes`()

    Return the bboxes of all subsets of points in the Coords.

    Subsets of points are 2-dim subarrays of the Coords, taken along the two last axes. If the Coords has ndim==2, there is only one subset: the full Coords.

    Returns: | float array – Array with shape (…,2,3). The elements along the penultimate axis are the minimal and maximal values of the Coords along that axis.

    Examples

        >>> X = Coords(arange(18).reshape(2,3,3))
        >>> print(X)
         [[[  0.   1.   2.]
          [  3.   4.   5.]
          [  6.   7.   8.]]
        <BLANKLINE>
         [[  9.  10.  11.]
          [ 12.  13.  14.]
          [ 15.  16.  17.]]]
        >>> print(X.bboxes())
        [[[  0.   1.   2.]
          [  6.   7.   8.]]
        <BLANKLINE>
         [[  9.  10.  11.]
          [ 15.  16.  17.]]]

  `inertia`(**_kargs)

    Return inertia related quantities of the `Coords`.

    Parameters: | mass (float array, optional) – If provided, it is a 1-dim array with `npoints()` weight values for the points, in the order of the `points()`. The default is to attribute a weight 1.0 to each point.
    Returns: | `Inertia` – The Inertia object has the following attributes: `mass`: the total mass (float) `ctr`: the center of mass: float (3,) `tensor`: the inertia tensor in the central axes: shape (3,3)

    See also

    `principalCS()`
      Return the principal axes of the inertia tensor

    Examples

        >>> from pyformex.elements import Tet4
        >>> I = Tet4.vertices.inertia()
        >>> print(I.tensor)
        [[ 1.5  0.25 0.25]
         [ 0.25 1.5  0.25]
         [ 0.25 0.25 1.5 ]]
        >>> print(I.ctr)
        [ 0.25 0.25 0.25]
        >>> print(I.mass)
        4.0

  `principalCS`(mass=None)

    Return a CoordSys formed by the principal axes of inertia.

    Parameters: | mass (1-dim float array (`points()`,), optional) – The mass to be attributed to each of the points, in the order of `npoints()`. If not provided, a mass 1.0 will be attributed to each point.
    Returns: | `CoordSys` object. – Coordinate system aligned along the principal axes of the inertia, for the specified point masses. The origin of the CoordSys is the center of mass of the Coords.

    See also

    `centralCS()`
      CoordSys at the center of mass, but axes along global directions

    Examples

        >>> from pyformex.elements import Tet4
        >>> print(Tet4.vertices.principalCS())
        CoordSys: trl=[ 0.25  0.25  0.25]; rot=[[ 0.58  0.58  0.58]
                                                [ 0.34 -0.81  0.47]
                                                [ 0.82 -0.41 -0.41]]

  `principalSizes`()

    Return the sizes in the principal directions of the `Coords`.

    Returns: | float array (3,) – Array with the size of the bounding box along the 3 principal axes.

    Notes

    This is a convenient shorthand for: `self.toCS(self.principalCS()).sizes()`

    Examples

        >>> print(Coords([[[0.,0.,0.],[3.,0.,0.]]]).rotate(30,2).principalSizes())
        [ 0. 0. 3.]

  `centralCS`(mass=None)

    Returns the central coordinate system of the Coords.

    Parameters: | mass (1-dim float array (`points()`,), optional) – The mass to be attributed to each of the points, in the order of `npoints()`. If not provided, a mass 1.0 will be attributed to each point.
    Returns: | `CoordSys` object. – Coordinate system with origin at the center of mass of the Coords and axes parallel to the global axes.

    See also

    `principalCS()`
      CoordSys aligned with principa axes of inertia tensor

    Examples

        >>> from pyformex.elements import Tet4
        >>> print(Tet4.vertices.centralCS())
        CoordSys: trl=[ 0.25  0.25  0.25]; rot=[[ 1.  0.  0.]
                                                [ 0.  1.  0.]
                                                [ 0.  0.  1.]]

  `distanceFromPoint`(p)

    Returns the distance of all points from the point p.

    Parameters: | p (float array-like with shape (3,) or (1,3)) – Coordinates of a single point in space
    Returns: | float array – Array with shape `pshape()` holding the distance of each point to point p. All values are positive or zero.

    See also

    `closestPoint()`
      return the point of Coords closest to given point

    Examples

        >>> X = Coords([[0.,0.,0.],[2.,0.,0.],[1.,3.,0.],[-1.,0.,0.]])
        >>> print(X.distanceFromPoint([0.,0.,0.]))
        [ 0.    2.    3.16  1.  ]

  `distanceFromLine`(p, n)

    Returns the distance of all points from the line (p,n).

    Parameters: | p (float array-like with shape (3,) or (1,3)) – Coordinates of some point on the line. n (float array-like with shape (3,) or (1,3)) – Vector specifying the direction of the line.
    Returns: | float array – Array with shape `pshape()` holding the distance of each point to the line through p and having direction n. All values are positive or zero.

    Examples

        >>> X = Coords([[0.,0.,0.],[2.,0.,0.],[1.,3.,0.],[-1.,0.,0.]])
        >>> print(X.distanceFromLine([0.,0.,0.],[1.,1.,0.]))
        [ 0.   1.41 1.41 0.71]

  `distanceFromPlane`(p, n)

    Return the distance of all points from the plane (p,n).

    Parameters: | p (float array-like with shape (3,) or (1,3)) – Coordinates of some point in the plane. n (float array-like with shape (3,) or (1,3)) – The normal vector to the plane.
    Returns: | float array – Array with shape `pshape()` holding the distance of each point to the plane through p and having normal n. The values are positive if the point is on the side of the plane indicated by the positive normal.

    See also

    `directionalSize()`
      find the most distant points at both sides of plane

    Examples

        >>> X = Coords([[0.,0.,0.],[2.,0.,0.],[1.,3.,0.],[-1.,0.,0.]])
        >>> print(X.distanceFromPlane([0.,0.,0.],[1.,0.,0.]))
        [ 0.  2.  1. -1.]

  `closestToPoint`(p, return_dist=False)

    Returns the point closest to a given point p.

    Parameters: | p (array-like (3,)) – Coordinates of a single point in space
    Returns: | int – Index of the point in the Coords that has the minimal Euclidean distance to the point p. Use this index with self.points() to get the coordinates of that point.

    Examples

        >>> X = Coords([[[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]])
        >>> X.closestToPoint([2.,0.,0.])
        1
        >>> X.closestToPoint([2.,0.,0.],True)
        (1, 1.0)

  `directionalSize`(n, p=None, return_points=False)

    Returns the extreme distances from the plane p,n.

    Parameters: | n (a single int or a float array-like (3,)) – The direction of the normal to the plane. If an int, it is the number of a global axis. Else it is a vector with 3 components. p (array-like (3,), optional) – Coordinates of a point in the plane. If not provided, the `center()` of the Coords is used. return_points (bool) – If True, also return a Coords with two points along the line (p,n) and at the extreme distances from the plane(p,n).
    Returns: | dmin (float) – The minimal (signed) distance of a point of the Coords to the plane (p,n). The value can be negative or positive. dmax (float) – The maximal (signed) distance of a point of the Coords to the plane (p,n). The value can be negative or positive. points (Coords (2,3), optional) – If return_points=True is provided, also returns a Coords holding two points on the line (p,n) with minimal and maximal distance from the plane (p,n). These two points together with the normal n define two parallel planes such that all points of self are between or on the planes.

    Notes

    The maximal size of self in the direction n is found from the difference dmax - dmin`. See also `directionalWidth()`.

    See also

    `directionalExtremes()`
      return two points in the extreme planes
    `directionalWidth()`
      return the distance between the extreme planes
    `distanceFromPlane()`
      return distance of all points to a plane

    Examples

        >>> X = Coords([[[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]])
        >>> X.directionalSize([1,0,0])
        (-1.5, 1.5)
        >>> X.directionalSize([1,0,0],[1.,0.,0.])
        (-1.0, 2.0)
        >>> X.directionalSize([1,0,0],return_points=True)
        (-1.5, 1.5, Coords([[ 0. ,  1.5,  0. ],
                [ 3. ,  1.5,  0. ]]))

  `directionalExtremes`(n, p=None)

    Returns extremal planes in the direction n.

    Parameters: see `directionalSize()`.

    Returns: | Coords (2,3) – A Coords holding the two points on the line (p,n) with minimal and maximal distance from the plane (p,n). These two points together with the normal n define two parallel planes such that all points of self are between or on the planes.

    See also

    `directionalSize()`
      return minimal and maximal distance from plane

    Notes

    This is like directionalSize with the return_points options, but only returns the extreme points.

    Examples

        >>> X = Coords([[[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]])
        >>> X.directionalExtremes([1,0,0])
        Coords([[ 0. ,  1.5,  0. ],
                [ 3. ,  1.5,  0. ]])

  `directionalWidth`(n)

    Returns the width of a Coords in the given direction.

    Parameters: see `directionalSize()`.

    Returns: | float – The size of the Coords in the direction n. This is the distance between the extreme planes with normal n touching the Coords.

    See also

    `directionalSize()`
      return minimal and maximal distance from plane

    Notes

    This is like directionalSize but only returns the difference between dmax and dmin.

    Examples

        >>> X = Coords([[[0.,0.,0.],[3.,0.,0.],[0.,3.,0.]]])
        >>> print(X.directionalWidth([1,0,0]))
        3.0

  `test`(dir=0, min=None, max=None, atol=0.0)

    Flag points having coordinates between min and max.

    Test the position of the points of the `Coords` with respect to one or two parallel planes. This method is very convenient in clipping a Coords in a specified direction. In most cases the clipping direction is one of the global coordinate axes, but a general direction may be used as well.

    Testing along global axis directions is highly efficient. It tests whether the corresponding coordinate is above or equal to the min value and/or below or equal to the max value. Testing in a general direction tests whether the distance to the min plane is positive or zero and/or the distance to the max plane is negative or zero.

    Parameters: | dir (a single int or a float array-like (3,)) – The direction in which to measure distances. If an int, it is one of the global axes (0,1,2). Else it is a vector with 3 components. The default direction is the global x-axis. min (float or point-like, optional) – Position of the minimal clipping plane. If dir is an int, this is a single float giving the coordinate along the specified global axis. If dir is a vector, this must be a point and the minimal clipping plane is defined by this point and the normal vector dir. If not provided, there is no clipping at the minimal side. max (float or point-like.) – Position of the maximal clipping plane. If dir is an int, this is a single float giving the coordinate along the specified global axis. If dir is a vector, this must be a point and the maximal clipping plane is defined by this point and the normal vector dir. If not provided, there is no clipping at the maximal side. atol (float) – Tolerance value added to the tests to account for accuracy and rounding errors. A min test will be ok if the point’s distance from the min clipping plane is > -atol and/or the distance from the max clipping plane is < atol. Thus a positive atol widens the clipping planes.
    Returns: | bool array with shape `pshape()` – Array flagging whether the points for the Coords pass the test(s) or not. The return value can directly be used as an index to self to obtain a `Coords` with the points satisfying the test (or not).
    Raises: | ValueError: At least one of min or max have to be specified – If neither min nor max are provided.

    Examples

        >>> x = Coords([[[0.,0.],[1.,0.]],[[0.,1.],[0.,2.]]])
        >>> print(x.test(min=0.5))
        [[False  True]
         [False False]]
        >>> t = x.test(dir=1,min=0.5,max=1.5)
        >>> print(x[t])
        [[ 0. 1. 0.]]
        >>> print(x[~t])
        [[ 0. 0. 0.]
         [ 1. 0. 0.]
         [ 0. 2. 0.]]

  `set`(f)

    Set the coordinates from those in the given array.

    Parameters: | f (float array-like, broadcastable to self.shape.) – The coordinates to replace the current ones. This can not be used to chage the shape of the Coords.
    Raises: | ValueError: – If the shape of f does not allow broadcasting to self.shape.

    Examples

        >>> x = Coords([[0],[1],[2]])
        >>> print(x)
        [[ 0.  0.  0.]
         [ 1.  0.  0.]
         [ 2.  0.  0.]]
        >>> x.set([0.,1.,0.])
        >>> print(x)
        [[ 0.  1.  0.]
         [ 0.  1.  0.]
         [ 0.  1.  0.]]

  `scale`(scale, dir=None, center=None, inplace=False)

    Return a scaled copy of the `Coords` object.

    Parameters: | scale (float or tuple of 3 floats) – Scaling factor(s). If it is a single value, and no dir is provided, scaling is uniformly applied to all axes; if dir is provided, only to the specified directions. If it is a tuple, the three scaling factors are applied to the respective global axes. dir (int or tuple of ints, optional) – One or more global axis numbers (0,1,2), indicating the direction(s) that should be scaled with the (single) value scale. center (point-like, optional) – If provided, use this point as the center of the scaling. The default is the global origin. inplace (bool,optional) – If True, the coordinates are change in-place.
    Returns: | Coords – The Coords scaled as specified.

    Notes

    If a center is provided,the operation is equivalent with `self.translate(-center).scale(scale,dir).translate(center)`

    Examples

        >>> X = Coords([1.,1.,1.])
        >>> print(X.scale(2))
        [ 2. 2. 2.]
        >>> print(X.scale([2,3,4]))
        [ 2. 3. 4.]
        >>> print(X.scale(2,dir=(1,2)).scale(4,dir=0))
        [ 4. 2. 2.]
        >>> print(X.scale(2,center=[1.,0.5,0.]))
        [ 1.   1.5  2. ]

  `translate`(dir, step=1.0, inplace=False)

    Return a translated copy of the `Coords` object.

    Translate the Coords in the direction dir over a distance step * length(dir).

    Parameters: | dir (int (0,1,2) or float array-like (..,3)) – The translation vector. If an int, it specifies a global axis and the translation is in the direction of that axis. If an array-like, it specifies one or more translation vectors. If more than one, the array should be broadcastable to the Coords shape: this allows to translate different parts of the Coords over different vectors, all in one operation. step (float) – If `dir` is an int, this is the length of the translation. Else, it is a multiplying factor applied to `dir` prior to applying the translation.
    Returns: | Coords – The Coords translated over the specified vector(s).

    Note

    `trl()` is a convenient shorthand for `translate()`.

    See also

    `centered()`
      translate to center around origin
    `Coords.align()`
      translate to align bounding box

    Examples

        >>> x = Coords([1.,1.,1.])
        >>> print(x.translate(1))
        [ 1. 2. 1.]
        >>> print(x.translate(1,1.))
        [ 1. 2. 1.]
        >>> print(x.translate([0,1,0]))
        [ 1. 2. 1.]
        >>> print(x.translate([0,2,0],0.5))
        [ 1. 2. 1.]
        >>> x = Coords(arange(4).reshape(2,2,1))
        >>> x
        Coords([[[ 0.,  0.,  0.],
                [ 1.,  0.,  0.]],
        <BLANKLINE>
               [[ 2.,  0.,  0.],
                [ 3.,  0.,  0.]]])
        >>> x.translate([[10.,-5.,0.],[20.,4.,0.]]) # translate with broadcasting
        Coords([[[ 10.,  -5.,   0.],
                [ 21.,   4.,   0.]],
        <BLANKLINE>
               [[ 12.,  -5.,   0.],
                [ 23.,   4.,   0.]]])

  `centered`()

    Return a centered copy of the Coords.

    Returns: | Coords – The Coords translated over tus that its `center()` coincides with the origin of the global axes.

    Notes

    This is equivalent with `self.translate(-self.center())`

    Examples

        >>> X = Coords('0123')
        >>> print(X)
        [[ 0.  0.  0.]
         [ 1.  0.  0.]
         [ 1.  1.  0.]
         [ 0.  1.  0.]]
        >>> print(X.centered())
        [[-0.5 -0.5  0. ]
         [ 0.5 -0.5  0. ]
         [ 0.5  0.5  0. ]
         [-0.5  0.5  0. ]]

  `align`(alignment='---', point=[0.0, 0.0, 0.0])

    Align a `Coords` object on a given point.

    Alignment involves a translation such that the bounding box of the Coords object becomes aligned with a given point. The bounding box alignment is done by the translation of a to the target point.

    Parameters: | alignment (str) – The requested alignment is a string of three characters, one for each of the coordinate axes. The character determines how the structure is aligned in the corresponding direction: ’-‘: aligned on the minimal value of the bounding box, ’+’: aligned on the maximal value of the bounding box, ‘0’: aligned on the middle value of the bounding box. Any other value will make the alignment in that direction unchanged. point (point-like) – The target point of the alignment.
    Returns: | Coords – The Coords translated thus that the alignment `bboxPoint()` is at point.

    Notes

    The default parameters translate the Coords thus that all points are in the octant with all positive coordinate values.

    `Coords.align(alignment = '000')` will center the object around the origin, just like the `centered()` (which is slightly faster). This can however be used for centering around any point.

    See also

    `align()`
      aligning multiple objects with respect to each other.
  `rotate`(angle, axis=2, around=None, angle_spec=0.017453292519943295)

    Return a copy rotated over angle around axis.

    Parameters: | angle (float or float array-like (3,3)) – If a float, it is the rotation angle, by default in degrees, and the parameters (angle, axis, angel_spec) are passed to `rotationMatrix()` to produce a (3,3) rotation matrix. Alternatively, the rotation matrix may be directly provided in the angle parameter. The axis and angle_spec are then ignored. axis (int (0,1,2) or float array-like (3,)) – Only used if angle is a float. If provided, it specifies the direction of the rotation axis: either one of 0,1,2 for a global axis, or a vector with 3 components for a general direction. The default (axis 2) is convenient for working with 2D-structures in the x-y plane. around (float array-like (3,)) – If provided, it species a point on the rotation axis. If not, the rotation axis goes through the origin of the global axes. angle_spec (float, DEG or RAD, optional) – Only used if angle is a float. The default (DEG) interpretes the angle in degrees. Use RAD to specify the angle in radians.
    Returns: | Coords – The Coords rotated as specified by the parameters.

    Note

    `rot()` is a convenient shorthand for `rotate()`.

    See also

    `translate()`
      translate a Coords
    `affine()`
      rotate and translate a Coords
    `arraytools.rotationMatrix()`
      create a rotation matrix for use in `rotate()`

    Examples

        >>> X = Coords('0123')
        >>> print(X.rotate(30))
        [[ 0.    0.    0.  ]
         [ 0.87  0.5   0.  ]
         [ 0.37  1.37  0.  ]
         [-0.5   0.87  0.  ]]
        >>> print(X.rotate(30,axis=0))
        [[ 0.    0.    0.  ]
         [ 1.    0.    0.  ]
         [ 1.    0.87  0.5 ]
         [ 0.    0.87  0.5 ]]
        >>> print(X.rotate(30,axis=0,around=[0.,0.5,0.]))
        [[ 0.    0.07 -0.25]
         [ 1.    0.07 -0.25]
         [ 1.    0.93  0.25]
         [ 0.    0.93  0.25]]
        >>> m = rotationMatrix(30,axis=0)
        >>> print(X.rotate(m))
        [[ 0.    0.    0.  ]
         [ 1.    0.    0.  ]
         [ 1.    0.87  0.5 ]
         [ 0.    0.87  0.5 ]]

  `shear`(dir, dir1, skew, inplace=False)

    Return a copy skewed in the direction of a global axis.

    This translates points in the direction of a global axis, over a distance dependent on the coordinates along another axis.

    Parameters: | dir (int (0,1,2)) – Global axis in which direction the points are translated. dir1 (int (0,1,2)) – Global axis whose coordinates determine the length of the translation. skew (float) – Multiplication factor to the coordinates dir1 defining the translation distance. inplace (bool, optional) – If True, the coordinates are translated in-place.

    Notes

    This replaces the coordinate `dir` with `(dir + skew * dir1)`. If dir and dir1 are different, rectangular shapes in the plane (dir,dir1) are thus skewed along the direction dir into parallellogram shapes. If dir and dir1 are the same direction, the effect is that of scaling in the dir direction.

    Examples

        >>> X = Coords('0123')
        >>> print(X.shear(0,1,0.5))
        [[ 0.   0.   0. ]
         [ 1.   0.   0. ]
         [ 1.5  1.   0. ]
         [ 0.5  1.   0. ]]

  `reflect`(dir=0, pos=0.0, inplace=False)

    Reflect the coordinates in the direction of a global axis.

    Parameters: | dir (int (0,1,2)) – Global axis direction of the reflection (default 0 or x-axis). pos (float) – Offset of the mirror plane from origin (default 0.0) inplace (bool, optional) – If True, the coordinates are translated in-place.
    Returns: | Coords – A mirror copy with respect to the plane perpendicular to axis dir and placed at coordinate pos along the dir axis.

    Examples

        >>> X = Coords('012')
        >>> print(X)
        [[ 0.  0.  0.]
         [ 1.  0.  0.]
         [ 1.  1.  0.]]
        >>> print(X.reflect(0))
        [[ 0.  0.  0.]
         [-1.  0.  0.]
         [-1.  1.  0.]]
        >>> print(X.reflect(1,0.5))
        [[ 0.  1.  0.]
         [ 1.  1.  0.]
         [ 1.  0.  0.]]
        >>> print(X.reflect([0,1],[0.5,0.]))
        [[ 1.  0.  0.]
         [ 0.  0.  0.]
         [ 0. -1.  0.]]

  `affine`(mat, vec=None)

    Perform a general affine transformation.

    Parameters: | mat (float array-like (3,3)) – Matrix used in post-multiplication on a row vector to produce a new vector. The matrix can express scaling and/or rotation or a more general (affine) transformation. vec (float array-like (3,)) – Translation vector to add after the transformation with mat.
    Returns: | Coords – A Coords with same shape as self, but with coordinates given by `self * mat + vec`. If mat is a rotation matrix or a uniform scaling plus rotation, the full operation performs a rigid rotation plus translation of the object.

    Examples

        >>> X = Coords('0123')
        >>> S = array([[2.,0.,0.],[0.,3.,0.],[0.,0.,4.]]) # non-uniform scaling
        >>> R = rotationMatrix(90.,2) # rotation matrix
        >>> T = [20., 0., 2.] # translation
        >>> M = dot(S,R)  # combined scaling and rotation
        >>> print(X.affine(M,T))
        [[ 20.   0.   2.]
         [ 20.   2.   2.]
         [ 17.   2.   2.]
         [ 17.   0.   2.]]

  `toCS`(cs)

    Transform the coordinates to another CoordSys.

    Parameters: | cs (`CoordSys` object) – Cartesian coordinate system in which to take the coordinates of the current Coords object.
    Returns: | Coords – A Coords object identical to self but having global coordinates equal to the coordinates of self in the cs CoordSys axes.

    Note

    This returns the coordinates of the original points in another CoordSys. If you use these coordinates as points in the global axes, the transformation of the original points to these new ones is the inverse transformation of the transformation of the global axes to the cs coordinate system.

    See also

    `fromCS()`
      the inverse transformation

    Examples

        >>> X = Coords('01')
        >>> print(X)
        [[ 0.  0.  0.]
         [ 1.  0.  0.]]
        >>> from pyformex.coordsys import CoordSys
        >>> CS = CoordSys(oab=[[0.5,0.,0.],[1.,0.5,0.],[0.,1.,0.]])
        >>> print(CS)
        CoordSys: trl=[ 0.5  0.   0. ]; rot=[[ 0.71  0.71  0.  ]
                                             [-0.71  0.71  0.  ]
                                             [ 0.   -0.    1.  ]]
        >>> print(X.toCS(CS))
        [[-0.35  0.35  0.  ]
         [ 0.35 -0.35  0.  ]]
        >>> print(X.toCS(CS).fromCS(CS))
        [[ 0.  0.  0.]
         [ 1. -0.  0.]]

  `fromCS`(cs)

    Transform the coordinates from another CoordSys to global axes.

    Parameters: | cs (`CoordSys` object) – Cartesian coordinate system in which the current coordinate values are taken.
    Returns: | Coords – A Coords object with the global coordinates of the same points as the input coordinates represented in the cs CoordSys axes.

    See also

    `toCS()`
      the inverse transformation

    Examples: see `toCS()`

  `transformCS`(cs, cs0=None)

    Perform a coordinate system transformation on the Coords.

    This method transforms the Coords object by the transformation that turns one coordinate system into a another.

    Parameters: | cs (`CoordSys`) – The final coordinate system. cs0 (`CoordSys`, optional) – The initial coordinate system. If not provided, the global coordinate system is used.
    Returns: | Coords – The input Coords transformed by the same affine transformation that turns the axes of the coordinate system cs0 into those of the system cs.

    Notes

    For example, with the default cs0 and a cs CoordSys created with the points

         0. 1. 0.
        -1. 0. 0.
         0. 0. 1.
         0. 0. 0.

    the transformCS results in a rotation of 90 degrees around the z-axis.

    See also

    `toCS()`
      transform coordinates to another CS
    `fromCS()`
      transfrom coordinates from another CS
  `position`(x, y)

    Position a `Coords` so that 3 points x are aligned with y.

    Aligning 3 points x with 3 points y is done by a rotation and translation in such way that

    - point x0 coincides with point y0,
    - line x0,x1 coincides with line y0,y1
    - plane x0,x1,x2 coincides with plane y0,y1,y2

    Parameters: | x (float array-like (3,3)) – Original coordinates of three non-collinear points. These points can be be part of the Coords or not. y (float array-like (3,3)) – Final coordinates of the three points.
    Returns: | Coords – The input Coords rotated and translated thus that the points x are aligned with y.

    Notes

    This is a convenient shorthand for `self.affine(*trfmat(x, y))`.

    See also

    `arraytools.trfmat()`
      compute the transformation matrices from points x to y
    `affine()`
      general transform using rotation and translation

    Examples

        >>> X = Coords([[0,0,0],[1,0,0],[1,1,0]])
        >>> Y = Coords([[1,1,1],[1,10,1],[1,1,100]])
        >>> print(X.position(X,Y))
        [[ 1.  1.  1.]
         [ 1.  2.  1.]
         [ 1.  2.  2.]]

  `cylindrical`(dir=(0, 1, 2), scale=(1.0, 1.0, 1.0), angle_spec=0.017453292519943295)

    Convert from cylindrical coordinates to cartesian.

    A cylindrical coordinate system is defined by a longitudinal axis axis (z) and a radial axis (r). The cylindrical coordinates of a point are:

    - r: the radial distance from the z-axis,
    - theta: the circumferential angle measured positively around the z-axis starting from zero at the (r-z) halfplane,
    - z: the axial distance along the z-axis,

    This function interpretes the 3 coordinates of the points as (r,theta,z) values and computes the corresponding global cartesian coordinates (x,y,z).

    Parameters: | dir (tuple of 3 ints, optional) – If provided, it is a permutation of (0,1,2) and specifies which of the current coordinates are interpreted as resp. distance(r), angle(theta) and height(z). Default order is (r,theta,z). Beware that if the permutation is not conserving the order of the axes, a left-handed system results, and the Coords will appear mirrored in the right-handed systems exclusively used by pyFormex scale (tuple of 3 floats, optional) – Scaling factors that are applied on the values prior to make the conversion from cylindrical to cartesian coordinates. These factors are always given in the order (r,theta,z), irrespective of the permutation by dir. angle_spec (float, DEG or RAD, optional) – Multiplication factor for angle coordinates. The default (DEG) interpretes the angle in degrees. Use RAD to specify the angle in radians.
    Returns: | Coords – The global coordinates of the points that were specified with cylindrical coordinates as input.

    Notes

    The scaling can also be applied independently prior to transforming. `X.cylindrical(scale=s)` is equivalent with `X.scale(s).cylindrical()`. The scale option is provided here because in many cases you need at least to scale the theta direction to have proper angle values.

    See also

    `hyperCylindrical()`
      similar but allowing scaling as function of angle
    `toCylindrical()`
      inverse transformation (cartesian to cylindrical)

    Examples

    We want to create six points on a circle with radius 2. We start by creating the points in cylindrical coordinates with unit distances.

        >>> X = Coords('1'+'2'*5)
        >>> print(X)
        [[ 1.  0.  0.]
         [ 1.  1.  0.]
         [ 1.  2.  0.]
         [ 1.  3.  0.]
         [ 1.  4.  0.]
         [ 1.  5.  0.]]

    Remember these are (r,theta,z) coordinates of the points. So we will scale the r-direction with 2 (the target radius) and the angular direction theta with 360/6 = 60. Then we get the cartesian coordinates of the points from

        >>> Y = X.cylindrical(scale=(2.,60.,1.))
        >>> print(Y)
        [[ 2.    0.    0.  ]
         [ 1.    1.73  0.  ]
         [-1.    1.73  0.  ]
         [-2.   -0.    0.  ]
         [-1.   -1.73  0.  ]
         [ 1.   -1.73  0.  ]]

    Going back to cylindrical coordinates yields

        >>> print(Y.toCylindrical())
        [[   2.    0.    0.]
         [   2.   60.    0.]
         [   2.  120.    0.]
         [   2. -180.    0.]
         [   2. -120.    0.]
         [   2.  -60.    0.]]

    This differs from the original input X because of the scaling factors, and the wrapping around angles are reported in the range [-180,180].

  `hyperCylindrical`(dir=(0, 1, 2), scale=(1.0, 1.0, 1.0), rfunc=None, zfunc=None, angle_spec=0.017453292519943295)

    Convert cylindrical coordinates to cartesian with advanced scaling.

    This is similar to `cylindrical()` but allows the specification of two functions defining extra scaling factors for the r and z directions that are dependent on the theta value.

    Parameters: | scale, angle_spec) ((dir,) – rfunc (callable, optional) – Function r(theta) taking one, float parameter and returning a float. Like scale[0] it is multiplied with the provided r values before converting them to cartesian coordinates. zfunc (callable, optional) – Function z(theta) taking one float parameter and returning a float. Like scale[2] it is multiplied with the provided z values before converting them to cartesian coordinates.

    See also

    `cylindrical()`
      similar but without the rfunc and zfunc options.
  `toCylindrical`(dir=(0, 1, 2), angle_spec=0.017453292519943295)

    Converts from cartesian to cylindrical coordinates.

    Returns a Coords where the values are the coordinates of the input points in a cylindrical coordinate system. The three axes of the Coords then correspond to (r, theta, z).

    Parameters: | dir (tuple of ints) – A permutation of (0,1,2) specifying which of the global axes are the radial, circumferential and axial direction of the cylindrical coordinate system. Make sure to keep the axes ordering in order to get a right-handed system. angle_spec (float, DEG or RAD, optional) – Multiplication factor for angle coordinates. The default (DEG) returns angles in degrees. Use RAD to return angles in radians.
    Returns: | Coords – The cylindrical coordinates of the input points.

    See also

    `cylindrical()`
      conversion from cylindrical to cartesian coordinates

    Examples

    see `cylindrical()`

  `spherical`(dir=(0, 1, 2), scale=(1.0, 1.0, 1.0), angle_spec=0.017453292519943295, colat=False)

    Convert spherical coordinates to cartesian coordinates.

    Consider a spherical coordinate system with the global xy-plane as its equatorial plane and the z-axis as axis. The zero meridional halfplane is taken along th positive x-axis. The spherical coordinates of a point are:

    - the longitude (theta): the circumferential angle, measured around the z-axis from the zero-meridional halfplane to the meridional plane containing the point: this angle normally ranges from -180 to +180 degrees (or from 0 to 360);
    - the latitude (phi): the elevation angle of the point’s position vector, measured from the equatorial plane, positive when the point is at the positive side of the plane: this angle is normally restricted to the range from -90 (south pole) to +90 (north pole);
    - the distance (r): the radial distance of the point from the origin: this is normally positive.

    This function interpretes the 3 coordinates of the points as (theta,phi,r) values and computes the corresponding global cartesian coordinates (x,y,z).

    Parameters: | dir (tuple of 3 ints, optional) – If provided, it is a permutation of (0,1,2) and specifies which of the current coordinates are interpreted as resp. longitude(theta), latitude(phi) and distance(r). This allows the axis to be aligned with any of the global axes. Default order is (0,1,2), with (0,1) the equatorial plane and 2 the axis. Beware that using a permutation that is not conserving the order of the globale axes (0,1,2), may lead to a confusing left-handed system. scale (tuple of 3 floats, optional) – Scaling factors that are applied on the coordinate values prior to making the conversion from spherical to cartesian coordinates. These factors are always given in the order (theta,phi,rz), irrespective of the permutation by dir. angle_spec (float, DEG or RAD, optional) – Multiplication factor for angle coordinates. The default (DEG) interpretes the angles in degrees. Use RAD to specify the angles in radians. colat (bool) – If True, the second coordinate is the colatitude instead. The colatitude is the angle measured from the north pole towards the south. In degrees, it is equal to `90 - latitude` and ranges from 0 to 180. Applications that deal with regions around the pole may benefit from using this option.
    Returns: | Coords – The global coordinates of the points that were specified with spherical coordinates as input.

    See also

    `toSpherical()`
      the inverse transformation (cartesian to spherical)
    `cylindrical()`
      similar function for spherical coordinates

    Examples

        >>> X = Coords('0123').scale(90).trl(2,1.)
        >>> X
        Coords([[  0.,   0.,   1.],
                [ 90.,   0.,   1.],
                [ 90.,  90.,   1.],
                [  0.,  90.,   1.]])
        >>> X.spherical()
        Coords([[ 1.,  0.,  0.],
                [-0.,  1.,  0.],
                [ 0., -0.,  1.],
                [-0., -0.,  1.]])

    Note that the last two points, though having different spherical coordinates, are coinciding at the north pole.

  `superSpherical`(n=1.0, e=1.0, k=0.0, dir=(0, 1, 2), scale=(1.0, 1.0, 1.0), angle_spec=0.017453292519943295, colat=False)

    Performs a superspherical transformation.

    superSpherical is much like `spherical()`, but adds some extra parameters to enable the quick creation of a wide range of complicated shapes. Again, the input coordinates are interpreted as the longitude, latitude and distance in a spherical coordinate system.

    Parameters: | n (float, >=0) – Exponent defining the variation of the distance in nort-south (latitude) direction. The default value 1 turns constant r-values into circular meridians. See notes. e (float, >=0) – Exponent defining the variation of the distance in nort-south (latitude) direction. The default value 1 turns constant r-values into a circular latitude lines. See notes. k (float, -1 < k < 1) – Eggness factor. If nonzero, creates asymmetric northern and southern hemisheres. Values > 0 enlarge the southern hemisphere and shrink the northern, while negative values yield the opposite. dir (tuple of 3 ints, optional) – If provided, it is a permutation of (0,1,2) and specifies which of the current coordinates are interpreted as resp. longitude(theta), latitude(phi) and distance(r). This allows the axis to be aligned with any of the global axes. Default order is (0,1,2), with (0,1) the equatorial plane and 2 the axis. Beware that using a permutation that is not conserving the order of the globale axes (0,1,2), may lead to a confusing left-handed system. scale (tuple of 3 floats, optional) – Scaling factors that are applied on the coordinate values prior to making the conversion from spherical to cartesian coordinates. These factors are always given in the order (theta,phi,rz), irrespective of the permutation by dir. angle_spec (float, DEG or RAD, optional) – Multiplication factor for angle coordinates. The default (DEG) interpretes the angles in degrees. Use RAD to specify the angles in radians. colat (bool) – If True, the second coordinate is the colatitude instead. The colatitude is the angle measured from the north pole towards the south. In degrees, it is equal to `90 - latitude` and ranges from 0 to 180. Applications that deal with regions around the pole may benefit from using this option.
    Raises: | `ValueError` – If one of n, e or k is out of the acceptable range.

    Notes

    Values of n and e should not be negative. Values equal to 1 create a circular shape. Other values keep the radius at angles corresponding to mmultiples of 90 degrees, while the radius at the intermediate 45 degree angles will be maximally changed. Values larger than 1 shrink at 45 degrees directions, while lower values increase it. A value 2 creates a straight line between the 90 degrees points (the radius at 45 degrees being reduced to 1/sqrt(2).

    See also example SuperShape.

    Examples

        >>> X = Coords('02222').scale(22.5).trl(2,1.)
        >>> X
        Coords([[  0. ,   0. ,   1. ],
                [  0. ,  22.5,   1. ],
                [  0. ,  45. ,   1. ],
                [  0. ,  67.5,   1. ],
                [  0. ,  90. ,   1. ]])
        >>> X.superSpherical(n=3).toSpherical()
        Coords([[ 90.  ,   0.  ,   1.  ],
                [ 85.93,   0.  ,   0.79],
                [ 45.  ,   0.  ,   0.5 ],
                [  4.07,   0.  ,   0.79],
                [ -0.  ,  -0.  ,   1.  ]])

    The result is smaller radius at angle 45.

  `toSpherical`(dir=[0, 1, 2], angle_spec=0.017453292519943295)

    Converts from cartesian to spherical coordinates.

    Returns a Coords where the values are the coordinates of the input points in a spherical coordinate system. The three axes of the Coords then correspond to (theta, phi, r).

    Parameters: | dir (tuple of ints) – A permutation of (0,1,2) specifying how the spherical coordinate system is oriented in the global axes. The last value is the axis of the system; the first two values are the equatorial plane; the first and last value define the meridional zero plane. Make sure to preserve the axes ordering in order to get a right-handed system. angle_spec (float, DEG or RAD, optional) – Multiplication factor for angle coordinates. The default (DEG) returns angles in degrees. Use RAD to return angles in radians.
    Returns: | Coords – The spherical coordinates of the input points.

    See also

    `spherical()`
      conversion from spherical to cartesian coordinates

    Examples

    See `superSpherical()`

  `circulize`(n)

    Transform sectors of a regular polygon into circular sectors.

    Parameters: | n (int) – Number of edges of the regular polygon.
    Returns: | Coords – A Coords where the points inside each sector of a n-sided regular polygon around the origin are reposition to fill a circular sector. The polygon is in the x-y-plane and has a vertex on the x-axis.

    Notes

    Points on the x-axis and on radii at i * 360 / n degrees are not moved. Points on the bisector lines between these radii are move maximally outward. Points on a regular polygon will become points on a circle if circulized with parameter n equal to the number of sides of the polygon.

    Examples

        >>> Coords([[1.,0.],[0.5,0.5],[0.,1.]]).circulize(4)
        Coords([[ 1.  ,  0.  ,  0.  ],
               [ 0.71,  0.71,  0.  ],
               [-0.  ,  1.  ,  0.  ]])

  `bump`(dir, a, func=None, dist=None, xb=1.0)

    Create a 1-, 2-, or 3-dimensional bump in a Coords.

    A bump is a local modification of the coordinates of a collection of points. The bump can be 1-, 2- or 3-dimensional, meaning that the intensity of the coordinate modification varies in 1, 2 or 3 axis directions. In all cases, the bump only changes one coordinate of the points. This method can produce various effects, but one of the most common uses is to force a surface to be indented at some point.

    Parameters: | dir (int, one of (0,1,2)) – The axis of the coordinates to be modified. a (point (3,)) – The point that sets the bump location and intensity. func (callable, optional) – A function that returns the bump intensity in function of the distance from the bump point a. The distance is the Euclidean distance over all directions except dir. The function takes a single (positive) float value and returns a float (the bump intensity). Its value should not be zero at the origin. The function may include constants, which can be specified as xb. If no function is specified, the default function will be used: `lambda x: where(x<xb,1.-(x/3)**2,0)` This makes the bump quadratically die out over a distance xb. dist (int or tuple of ints, optional) – Specifies how the distance from points to the bump point a is measured. It can be a single axis number (0,1,2) or a tuple of two or three axis numbers. If a single axis, the bump will vary only in one direction and distance is measured along that direction and is signed. The bump will only vary in that direction. If two or three axes, distance is the (always positive) euclidean distance over these directions and the bump will vary in these directions. Default value is the set of 3 axes minus the direction of modification dir. xb (float or list of floats) – Constant(s) to be used in func. Often, this includes the distance over which the bump will extend. The default bump function will reach zero at this distance.
    Returns: | Coords – A Coords with same shape as input, but having a localized change of coordinates as specified by the parameters.

    Notes

    This function replaces the bump1 and bump2 functions in older pyFormex versions. The default value of dist makes it work like bump2. Specifyin a single axis for dist makes it work like bump1.

    See also examples BaumKuchen, Circle, Clip, Novation

    Examples

    One-dimensional bump in a linear set of points.

        >>> X = Coords(arange(6).reshape(-1,1))
        >>> X.bump1(1,[3.,5.,0.],dist=0)
        Coords([[ 0.,  0.,  0.],
                [ 1.,  0.,  0.],
                [ 2.,  0.,  0.],
                [ 3.,  5.,  0.],
                [ 4.,  0.,  0.],
                [ 5.,  0.,  0.]])
        >>> X.bump(1,[3.,5.,0.],dist=0,xb=3.)
        Coords([[ 0.  ,  0.  ,  0.  ],
                [ 1.  ,  2.78,  0.  ],
                [ 2.  ,  4.44,  0.  ],
                [ 3.  ,  5.  ,  0.  ],
                [ 4.  ,  4.44,  0.  ],
                [ 5.  ,  2.78,  0.  ]])

    Create a grid a points in xz-plane, with a bump in direction y with a maximum 5 at x=1.5, z=0., extending over a distance 2.5.

        >>> X = Coords(arange(4).reshape(-1,1)).replicate(4,dir=2)
        >>> X.bump(1,[1.5,5.,0.],xb=2.5)
        Coords([[[ 0.  ,  3.75,  0.  ],
                 [ 1.  ,  4.86,  0.  ],
                 [ 2.  ,  4.86,  0.  ],
                 [ 3.  ,  3.75,  0.  ]],
        <BLANKLINE>
                [[ 0.  ,  3.19,  1.  ],
                 [ 1.  ,  4.31,  1.  ],
                 [ 2.  ,  4.31,  1.  ],
                 [ 3.  ,  3.19,  1.  ]],
        <BLANKLINE>
                [[ 0.  ,  0.  ,  2.  ],
                 [ 1.  ,  2.64,  2.  ],
                 [ 2.  ,  2.64,  2.  ],
                 [ 3.  ,  0.  ,  2.  ]],
        <BLANKLINE>
                [[ 0.  ,  0.  ,  3.  ],
                 [ 1.  ,  0.  ,  3.  ],
                 [ 2.  ,  0.  ,  3.  ],
                 [ 3.  ,  0.  ,  3.  ]]])

  `flare`(xf, f, dir=(0, 2), end=0, exp=1.0)

    Create a flare at the end of a `Coords` block.

    A flare is a local change of geometry (widening, narrowing) at the end of a structure.

    Parameters: | xf (float) – Length over which the local change occurs, measured along `dir[0]`. f (float) – Maximum amplitude of the flare, in the direction `dir[1]`. dir (tuple of two ints (0,1,2)) – Two axis designations. The first axis defines the direction along which the flare decays. The second is the direction of the coordinate modification. end (0 or 1) – With end=0, the flare exists at the end with the smallest coordinates in `dir[0]]` direction; with end=1, at the end with the highest coordinates. exp (float) – Exponent setting the speed of decay of the flare. The default makes the flare change linearly over the length f.
    Returns: | Coords – A Coords with same shape as the input, but having a localized change of coordinates at one end of the point set.

    Examples

        >>> Coords(arange(6).reshape(-1,1)).flare(3.,1.6,(0,1),0)
        Coords([[ 0.  ,  1.6 ,  0.  ],
                [ 1.  ,  1.07,  0.  ],
                [ 2.  ,  0.53,  0.  ],
                [ 3.  ,  0.  ,  0.  ],
                [ 4.  ,  0.  ,  0.  ],
                [ 5.  ,  0.  ,  0.  ]])

  `map`(func)

    Map a `Coords` by a 3-D function.

    This allows any mathematical transformation being applied to the coordinates of the Coords.

    Parameters: | func (callable) – A function taking three float arguments (x,y,z coordinates of a point) and returning a tuple of three float values: the new coordinate values to replace (x,y,z). The function must be applicable to NumPy arrays, so it should only include numerical operations and functions understood by the numpy module. Often an inline lambda function is used, but a normally defined function will work as well.
    Returns: | Coords object – The input Coords mapped through the specified function

    See also

    `map1()`
      apply a 1-dimensional mapping to one coordinate direction
    `mapd()`
      map one coordinate by a function of the distance to a point

    Notes

    See also examples Cones, Connect, HorseTorse, Manantiales, Mobius, ScallopDome

    Examples

        >>> print(Coords([[1.,1.,1.]]).map(lambda x,y,z: [2*x,3*y,4*z]))
        [[ 2. 3. 4.]]

  `map1`(dir, func, x=None)

    Map one coordinate by a 1-D function of one coordinate.

    Parameters: | dir (int (0,1 or 2)) – The coordinate axis to be modified. func (callable) – Function taking a single float argument (the coordinate x) and returning a float value: the new coordinate to replace the dir coordinate. The function must be applicable to NumPy arrays, so it should only include numerical operations and functions understood by the numpy module. Often an inline lambda function is used, but a normally defined function will work as well. x (int(0,1,2), optional) – If provided, specifies the coordinate that is used as argument in func. Default is to use the same as dir.
    Returns: | Coords object – The input Coords where the dir coordinate has been mapped through the specified function.

    See also

    `map()`
      apply a general 3-dimensional mapping function
    `mapd()`
      map one coordinate by a function of the distance to a point

    Notes

    See also example SplineSurface

    Examples

        >>> Coords(arange(4).reshape(-1,1)).map1(1,lambda x:0.1*x,0)
        Coords([[ 0. ,  0. ,  0. ],
                [ 1. ,  0.1,  0. ],
                [ 2. ,  0.2,  0. ],
                [ 3. ,  0.3,  0. ]])

  `mapd`(dir, func, point=(0.0, 0.0, 0.0), dist=None)

    Map one coordinate by a function of the distance to a point.

    Parameters: | dir (int (0, 1 or 2)) – The coordinate that will be replaced with `func(d)`, where d is calculated as the distance to point. func (callable) – Function taking one float argument (distance to point) and returning a float: the new value for the dist coordinate. dir coordinate. The function must be applicable to NumPy arrays, so it should only include numerical operations and functions understood by the numpy module. Often an inline lambda function is used, but a normally defined function will work as well. point (float array-like (3,)) – The point to where the distance is computed. dist (int or tuple of ints (0, 1, 2)) – The coordinate directions that are used to compute the distance to point. The default is to use 3-D distances.

    Examples

    Map a regular 4x4 point grid in the xy-plane onto a sphere with radius 1.5 and center at the corner of the grid.

        >>> from .simple import regularGrid
        >>> X = Coords(regularGrid([0.,0.],[1.,1.],[3,3]))
        >>> X.mapd(2,lambda d:sqrt(1.5**2-d**2),X[0,0],[0,1])
        Coords([[[ 0.  ,  0.  ,  1.5 ],
                 [ 0.33,  0.  ,  1.46],
                 [ 0.67,  0.  ,  1.34],
                 [ 1.  ,  0.  ,  1.12]],
        <BLANKLINE>
                [[ 0.  ,  0.33,  1.46],
                 [ 0.33,  0.33,  1.42],
                 [ 0.67,  0.33,  1.3 ],
                 [ 1.  ,  0.33,  1.07]],
        <BLANKLINE>
                [[ 0.  ,  0.67,  1.34],
                 [ 0.33,  0.67,  1.3 ],
                 [ 0.67,  0.67,  1.17],
                 [ 1.  ,  0.67,  0.9 ]],
        <BLANKLINE>
                [[ 0.  ,  1.  ,  1.12],
                 [ 0.33,  1.  ,  1.07],
                 [ 0.67,  1.  ,  0.9 ],
                 [ 1.  ,  1.  ,  0.5 ]]])

  `copyAxes`(i, j, other=None)

    Copy the coordinates along the axes j to the axes i.

    Parameters: | i (int (0,1 2) or tuple of ints (0,1,2)) – One or more coordinate axes that should have replaced their coordinates by those along the axes j. j (int (0,1 2) or tuple of ints (0,1,2)) – One or more axes whose coordinates should be copied along the axes i. j should have the same type and length as i. other (Coords object, optional) – If provided, this is the source Coords for the coordinates. It should have the same shape as self. The default is to take the coords from self.
    Returns: | Coords object – A Coords where the coordinates along axes i have been replaced by those along axes j.

    Examples

        >>> X = Coords([[1],[2]]).trl(2,5)
        >>> X
        Coords([[ 1.,  0.,  5.],
                [ 2.,  0.,  5.]])
        >>> X.copyAxes(1,0)
        Coords([[ 1.,  1.,  5.],
                [ 2.,  2.,  5.]])
        >>> X.copyAxes((0,1),(1,0))
        Coords([[ 0.,  1.,  5.],
                [ 0.,  2.,  5.]])
        >>> X.copyAxes((0,1,2),(1,2,0))
        Coords([[ 0.,  5.,  1.],
                [ 0.,  5.,  2.]])

  `swapAxes`(i, j)

    Swap two coordinate axes.

    Parameters: | i (int (0,1,2)) – First coordinate axis j (int (0,1,2)) – Second coordinate axis
    Returns: | Coords – A Coords with interchanged i and j coordinates.

    Warning

    Coords.swapAxes merely changes the order of the elements along the last axis of the ndarray. This is quite different from `numpy.ndarray.swapaxes()`, which is inherited by the Coords class. The latter method interchanges the array axes of the ndarray, and will not yield a valid Coords object if the interchange involves the last axis.

    Notes

    This is equivalent with `self.copyAxes((i,j),(j,i))`

    Swapping two coordinate axes has the same effect as mirroring against the bisector plane between the two axes.

    Examples

        >>> X = Coords(arange(6).reshape(-1,3))
        >>> X
        Coords([[ 0.,  1.,  2.],
               [ 3.,  4.,  5.]])
        >>> X.swapAxes(2,0)
        Coords([[ 2.,  1.,  0.],
               [ 5.,  4.,  3.]])
        >>> X.swapaxes(1,0)
        array([[ 0.,  3.],
               [ 1.,  4.],
               [ 2.,  5.]], dtype=float32)

  `rollAxes`(n=1)

    Roll the coordinate axes over the given amount.

    Parameters: | n (int) – Number of positions to roll the axes. With the default (1), the old axes (0,1,2) become the new axes (2,0,1).
    Returns: | Coords – A Coords where the coordinate axes of the points have been rolled over n positions.

    Notes

    `X.rollAxes(1)` can also be obtained by `X.copyAxes((0,1,2),(2,0,1))`. It is also equivalent with a rotation over -120 degrees around the trisectrice of the first quadrant.

    Examples

        >>> X = Coords('0123')
        >>> X
        Coords([[ 0.,  0.,  0.],
                [ 1.,  0.,  0.],
                [ 1.,  1.,  0.],
                [ 0.,  1.,  0.]])
        >>> X.rollAxes(1)
        Coords([[ 0.,  0.,  0.],
                [ 0.,  1.,  0.],
                [ 0.,  1.,  1.],
                [ 0.,  0.,  1.]])
        >>> X.rotate(120,axis=[1.,1.,1.])
        Coords([[ 0.,  0.,  0.],
                [-0.,  1., -0.],
                [-0.,  1.,  1.],
                [-0., -0.,  1.]])

  `projectOnPlane`(n=2, P=(0.0, 0.0, 0.0))

    Project a `Coords` on a plane.

    Creates a parallel projection of the Coords on a plane.

    Parameters: | n (int (0,1,2) or float array-like (3,)) – The normal direction to the plane on which to project the Coords. If an int, it is a global axis. P (float array-like (3,)) – A point in the projection plane, by default the global origin.
    Returns: | Coords – The points of the Coords projected on the specified plane.

    Notes

    For projection on a plane parallel to a coordinate plane, it is far more efficient to specify the normal by an axis number rather than by a three component vector.

    This method will also work if any or both of P and n have the same shape as self, or can be reshaped to the same shape. This will project each point on its individual plane.

    See also example BorderExtension

    Examples

        >>> X = Coords(arange(6).reshape(2,3))
        >>> X.projectOnPlane(0,P=[2.5,0.,0.])
        Coords([[ 2.5,  1. ,  2. ],
                [ 2.5,  4. ,  5. ]])
        >>> X.projectOnPlane([1.,1.,0.])
        Coords([[-0.5,  0.5,  2. ],
                [-0.5,  0.5,  5. ]])

  `projectOnSphere`(radius=1.0, center=(0.0, 0.0, 0.0))

    Project a `Coords` on a sphere.

    Creates a central projection of a Coords on a sphere.

    Parameters: | radius (float, optional) – The radius of the sphere, default 1. center (float array-like (3,), optional) – The center of the sphere. This point should not be part the the Coords. The default is the origin of the global axes.
    Returns: | Coords – A Coords with the input points projected on the specified sphere.

    Notes

    This is a central projection from the center of the sphere. If you want a parallel projection on a spherical surface, you can use `map()`. See the Examples there.

    Examples

        >>> X = Coords([[x,x,1.] for x in range(1,4)])
        >>> X
        Coords([[ 1.,  1.,  1.],
               [ 2.,  2.,  1.],
               [ 3.,  3.,  1.]])
        >>> X.projectOnSphere()
        Coords([[ 0.58,  0.58,  0.58],
               [ 0.67,  0.67,  0.33],
               [ 0.69,  0.69,  0.23]])

  `projectOnCylinder`(radius=1.0, dir=0, center=[0.0, 0.0, 0.0])

    Project the Coords on a cylinder with axis parallel to a global axis.

    Given a cylinder with axis parallel to a global axis, the points of the Coords are projected from the axis onto the surface of the cylinder. The default cylinder has its axis along the x-axis and a unit radius. No points of the `Coords` should belong to the axis.

    Parameters: | radius (float, optional) – The radius of the sphere, default 1. dir (int (0,1,2), optional) – The global axis parallel to the cylinder’s axis. center (float array-like (3,), optional) – A point on the axis of the cylinder. Default is the origin of the global axes.
    Returns: | Coords – A Coords with the input points projected on the specified cylinder.

    Notes

    This is a projection from the axis of the cylinder. If you want a parallel projection on a cylindrical surface, you can use `map()`.

    Examples

        >>> X = Coords([[x,x,1.] for x in range(1,4)])
        >>> X
        Coords([[ 1.,  1.,  1.],
               [ 2.,  2.,  1.],
               [ 3.,  3.,  1.]])
        >>> X.projectOnCylinder()
        Coords([[ 1.  ,  0.71,  0.71],
               [ 2.  ,  0.89,  0.45],
               [ 3.  ,  0.95,  0.32]])

  `projectOnSurface`(S, dir=0, missing='e', return_indices=False)

    Project a `Coords` on a triangulated surface.

    The points of the Coords are projected in the specified direction dir onto the surface S. If a point has multiple projecions in the direction, the one nearest to the original is returned.

    Parameters: | S (`TriSurface`) – A triangulated surface dir (int (0,1,2) or float array-like (3,)) – The direction of the projection, either a global axis direction or specified as a vector with three components. missing ('o', 'r' or 'e') – Specifies how to treat cases where the projective line does not intersect the surface: ’o’: return the original point, ’r’: remove the point from the result. Use return_indices = True to find out which original points correspond with the projections. ’e’: raise an exception (default). return_indices (bool, optional) – If True, also returns the indices of the points that have a projection on the surface.
    Returns: | x (Coords) – A Coords with the projections of the input points on the surface. With missing=’o’, this will have the same shape as the input, but some points might not actually lie on the surface. With missing=’r’, the shape will be (npoints,3) and the number of points may be less than the input. ind (int array, optional) – Only returned if return_indices is True: an index in the input Coords of the points that have a projection on the surface. With missing=’r’, this gives the indices of the orginal points corresponding with the projections. With missing=’o’, this can be used to check which points are located on the surface. The index is sequential, no matter what the shape of the input Coords is.

    Examples

        >>> from pyformex import simple
        >>> S = simple.sphere().scale(2).trl([0.,0.,0.2])
        >>> x = pattern('0123')
        >>> print(x)
        [[ 0. 0. 0.]
         [ 1. 0. 0.]
         [ 1. 1. 0.]
         [ 0. 1. 0.]]
        >>> xp = x.projectOnSurface(S,[0.,0.,1.])
        >>> print(xp)
        [[ 0.    0.   -1.8 ]
         [ 1.    0.   -1.52]
         [ 1.    1.   -1.2 ]
         [ 0.    1.   -1.53]]

  `isopar`(eltype, coords, oldcoords)

    Perform an isoparametric transformation on a Coords.

    This creates an isoparametric transformation `plugins.isopar.Isopar` object and uses it to transform the input Coords. It is equivalent to:

        Isopar(eltype,coords,oldcoords).transform(self)

    See `Isopar` for parameters.

  `addNoise`(rsize=0.05, asize=0.0)

    Add random noise to a Coords.

    A random amount is added to each individual coordinate of the Coords. The maximum difference of the coordinates from their original value is controled by two parameters rsize and asize and will not exceed `asize+rsize*self.maxsize()`.

    Parameters: | rsize (float) – Relative size of the noise compared with the maximum size of the input Coords. asize (float) – Absolute size of the noise

    Examples

        >>> X = Coords(arange(6).reshape(2,3))
        >>> print((abs(X.addNoise(0.1) - X) < 0.1 * X.sizes()).all())
        True

  `replicate`(n, dir=0, step=1.0)

    Replicate a Coords n times with a fixed translation step.

    Parameters: | n (int) – Number of times to replicate the Coords. dir (int (0,1,2) or float array-like (3,)) – The translation vector. If an int, it specifies a global axis and the translation is in the direction of that axis. step (float) – If `dir` is an int, this is the length of the translation. Else, it is a multiplying factor applied to the translation vector.
    Returns: | Coords – A Coords with an extra first axis with length n. The new shape thus becomes `(n,) + self.shape`. The first component along the axis 0 is identical to the original Coords. Each following component is equal to the previous translated over (dir,step), where dir and step are interpreted just like in the `translate()` method.

    Notes

    `rep()` is a convenient shorthand for `replicate()`.

    Examples

        >>> Coords([0.,0.,0.]).replicate(4,1,1.2)
        Coords([[ 0. ,  0. ,  0. ],
                [ 0. ,  1.2,  0. ],
                [ 0. ,  2.4,  0. ],
                [ 0. ,  3.6,  0. ]])
        >>> Coords([0.]).replicate(3,0).replicate(2,1)
        Coords([[[ 0.,  0.,  0.],
                 [ 1.,  0.,  0.],
                 [ 2.,  0.,  0.]],
        <BLANKLINE>
                [[ 0.,  1.,  0.],
                 [ 1.,  1.,  0.],
                 [ 2.,  1.,  0.]]])

  `split`()

    Split the Coords in blocks along first axis.

    Returns: | list of Coords objects – A list of Coords objects being the subarrays takeb along the axis 0. The number of objects in the list is `self.shape[0]` and each Coords has the shape `self.shape[1:]`.
    Raises: | `ValueError` – If `self.ndim < 2`.

    Examples

        >>> Coords(arange(6).reshape(2,3)).split()
        [Coords([ 0.,  1.,  2.]), Coords([ 3.,  4.,  5.])]

  `sort`(order=(0, 1, 2))

    Sort points in the specified order of their coordinates.

    Parameters: | order (int (0,1,2) or tuple of ints (0,1,2)) – The order in which the coordinates have to be taken into account during the sorting operation.
    Returns: | int array – An index into the sequential point list `self.points()` thus that the points are sorted in order of the specified coordinates.

    Examples

        >>> X = Coords([[5,3,0],[2,4,3],[2,3,3],[5,6,2]])
        >>> X.sort()
        array([2, 1, 0, 3])
        >>> X.sort((2,1,0))
        array([0, 3, 2, 1])
        >>> X.sort(1)
        array([0, 2, 1, 3])

  `boxes`(ppb=1, shift=0.5, minsize=1e-05)

    Create a grid of equally sized boxes spanning the `Coords`.

    A regular 3D grid of equally sized boxes is created enclosing all the points of the Coords. The size, position and number of boxes are determined from the specified parameters.

    Parameters: | ppb (int) – Average number of points per box. The box sizes and number of boxes will be determined to approximate this number. shift (float (0.0 .. 1.0)) – Relative shift value for the grid. Applying a shift of 0.5 will make the lowest coordinate values fall at the center of the outer boxes. minsize (float) – Absolute minimal size of the boxes, in each coordinate direction.
    Returns: | ox (float array (3,)) – The minimal coordinates of the box grid. dx (float array (3,)) – The box size in the three global axis directions. nx (int array (3,)) – Number of boxes in each of the coordinate directions.

    Notes

    The primary purpose of this method is its use in the `fuse()` method. The boxes allow to quickly label the points inside each box with an integer value (the box number), so that it becomes easy to find close points by their same label.

    Because of the possibility that two very close points fall in different boxes (if they happen to be close to a box border), procedures based on these boxes are often repeated twice, with a different shift value.

    Examples

        >>> X = Coords([[5,3,0],[2,4,3],[2,3,3],[5,6,2]])
        >>> print(*X.boxes())
        [ 0.5  1.5 -1.5] [ 3.  3.  3.] [2 2 2]
        >>> print(* X.boxes(shift=0.1))
        [ 1.7  2.7 -0.3] [ 3.  3.  3.] [2 2 2]
        >>> X = Coords([[1.,1.,0.],[1.001,1.,0.],[1.1,1.,0.]])
        >>> print(*X.boxes())
        [ 0.98  0.98 -0.02] [ 0.03  0.03  0.03] [4 1 1]

  `fuse`(ppb=1, shift=0.5, rtol=1e-05, atol=1e-08, repeat=True)

    Find (almost) coinciding points and return a compressed set.

    This method finds the points that are very close to each other and replaces them with a single point. See Notes below for explanation about the method being used and the parameters being used. In most cases, atol and rtol are probably the only ones you want to change from the defaults. Two points are considered the same if all their coordinates differ less than the maximum of atol and rtol * self.maxsize().

    Parameters: | ppb (int, optional) – Average number of points per box. The box sizes and number of boxes will be determined to approximate this number. shift (float (0.0 .. 1.0), optional) – Relative shift value for the box grid. Applying a shift of 0.5 will make the lowest coordinate values fall at the center of the outer boxes. rtol (float, optional) – Relative tolerance used when considering two points for fusing. atol (float, optional) – Absolute tolerance used when considering two points for fusing. repeat (bool, optional) – If True, repeat the procedure with a second shift value.
    Returns: | coords (Coords object (npts,3)) – The unique points obtained from merging the very close points of a Coords. index (int array) – An index in the unique coordinates array coords for each of the original points. The shape of the index array is equal to the point shape of the input Coords (`self.pshape()`). All the values are in the range 0..npts.

    Note

    From the return values `coords[index]` will restore the original Coords (with accuracy equal to the tolerance used in the fuse operation)

    Notes

    The procedure works by first dividing the 3D space in a number of equally sized boxes, with a average population of ppb points. The arguments pbb and shift are passed to `boxes()` for this purpose. The boxes are identified by 3 integer coordinates, from which a unique integer scalar is computed, which is then used to sort the points. Finally only the points inside the same box need to be compared. Two points are considered equal if all their coordinates differ less than the maximum of atol and rtol * self.maxsize(). Points considered very close are replaced by a single one, and an index is kept from the original points to the new list of points.

    Running the procedure once does not guarantee finding all close nodes: two close nodes might be in adjacent boxes. The performance hit for testing adjacent boxes is rather high, and the probability of separating two close nodes with the computed box limits is very small. Therefore, the most sensible way is to run the procedure twice, with a different shift value (they should differ more than the tolerance). Specifying repeat=True will automatically do this with a second shift value equal to shift+0.25.

    Because fusing points is a very important and frequent step in many geometrical modeling and conversion procedures, the core part of this function is available in a C as well as a Python version, in the module pyformex.lib.misc. The much faster C version will be used if available.

    Examples

        >>> X = Coords([[1.,1.,0.],[1.001,1.,0.],[1.1,1.,0.]])
        >>> x,e = X.fuse(atol=0.01)
        >>> print(x)
        [[ 1.  1.  0. ]
         [ 1.1 1.  0. ]]
        >>> print(e)
        [0 0 1]
        >>> allclose(X,x[e],atol=0.01)
        True

  `unique`(**kargs)

    Returns the unique points after fusing.

    This is just like `fuse()` and takes the same arguments, but only returns the first argument: the unique points in the Coords.

  `adjust`(**kargs)

    Find (almost) identical nodes and adjust them to be identical.

    This is like the `fuse()` operation, but it does not fuse the close neigbours to a single point. Instead it adjust the coordinates of the points to be identical.

    The parameters are the same as for the `fuse()` method.

    Returns: | Coords – A Coords with the same shape as the input, but where close points now have identical coordinates.

    Examples

        >>> X = Coords([[1.,1.,0.],[1.001,1.,0.],[1.1,1.,0.]])
        >>> print(X.adjust(atol=0.01))
        [[ 1.  1.  0. ]
         [ 1.  1.  0. ]
         [ 1.1 1.  0. ]]

  `match`(coords, **kargs)

    Match points in another `Coords` object.

    Find the points from another Coords object that coincide with (or are very close to) points of `self`. This method works by concatenating the serialized point sets of both Coords and then fusing them.

    Parameters: | coords (Coords) – The Coords object to compare the points with. **kargs (keyword arguments) – Keyword arguments passed to the `fuse()` method.
    Returns: | 1-dim int array – The array has a length of coords.npoints(). For each point in coords it holds the index of a point in self coinciding with it, or a value -1 if there is no matching point. If there are multiple matching points in self, it is undefined which one will be returned. To avoid this ambiguity, you can first fuse the points of self.

    See also

    `hasMatch()`, `fuse()`

    Examples

        >>> X = Coords([[1.],[2.],[3.],[1.]])
        >>> Y = Coords([[1.],[4.],[2.00001]])
        >>> print(X.match(Y))
        [ 0 -1  1]

  `hasMatch`(coords, **kargs)

    Find out which points are also in another Coords object.

    Find the points from self that coincide with (or are very close to) some point of coords. This method is very similar to `match()`, but does not give information about which point of self matches which point of coords.

    Parameters: | coords (Coords) – The Coords object to compare the points with. **kargs (keyword arguments) – Keyword arguments passed to the `fuse()` method.
    Returns: | int array – A 1-dim int array with the unique sorted indices of the points in self that have a (nearly) matching point in coords.

    Warning

    If multiple points in self coincide with the same point in coords, only one index will be returned for this case. To avoid this, you can fuse self before using this method.

    See also

    `match()`

    Examples

        >>> X = Coords([[1.],[2.],[3.],[1.]])
        >>> Y = Coords([[1.],[4.],[2.00001]])
        >>> print(X.hasMatch(Y))
        [0 1]

  `append`(coords)

    Append more coords to a Coords object.

    The appended coords should have matching dimensions in all but the first axis.

    Parameters: | coords (Coords object) – A Coords having a shape with `shape[1:]` equal to `self.shape[1:]`.
    Returns: | Coords – The concatenated Coords object (self,coords).

    Notes

    This is comparable to `numpy.append()`, but the result is a `Coords` object, the default axis is the first one instead of the last, and it is a method rather than a function.

    See also

    `concatenate()`
      concatenate a list of Coords

    Examples

        >>> X = Coords([[1],[2]])
        >>> Y = Coords([[3],[4]])
        >>> X.append(Y)
        Coords([[ 1.,  0.,  0.],
               [ 2.,  0.,  0.],
               [ 3.,  0.,  0.],
               [ 4.,  0.,  0.]])

  classmethod `concatenate`(L, axis=0)

    Concatenate a list of `Coords` objects.

    Class method to concatenate a list of Coords along the given axis.

    Parameters: | L (list of Coords objects) – The Coords objects to be concatenated. All should have the same shape except for the length of the specified axis.
    Returns: | Coords – A Coords with at least two dimensions, even when the list contains only a single Coords with a single point, or is empty.
    Raises: | `ValueError` – If the shape of the Coords in the list do not match or if concatenation along the last axis is attempted.

    Notes

    This is a class method. It is commonly invoked as `Coords.concatenate`, and if used as a method on a Coords object, that object will not be included in the list.

    It is like `numpy.concatenate()` (which it uses internally), but makes sure to return `Coords` object, and sets the first axis as default instead of the last (which would not make sense).

    See also

    `append()`
      append a Coords to self

    Examples

        >>> X = Coords([1.,1.,0.])
        >>> Y = Coords([[2.,2.,0.],[3.,3.,0.]])
        >>> print(Coords.concatenate([X,Y]))
        [[ 1. 1. 0.]
         [ 2. 2. 0.]
         [ 3. 3. 0.]]
        >>> print(Coords.concatenate([X,X]))
        [[ 1. 1. 0.]
         [ 1. 1. 0.]]
        >>> print(Coords.concatenate([X]))
        [[ 1. 1. 0.]]
        >>> print(Coords.concatenate([Y]))
        [[ 2. 2. 0.]
         [ 3. 3. 0.]]
        >>> print(X.concatenate([Y]))
        [[ 2. 2. 0.]
         [ 3. 3. 0.]]
        >>> Coords.concatenate([])
        Coords([], shape=(0, 3))
        >>> Coords.concatenate([[Y],[Y]],axis=1)
        Coords([[[ 2.,  2.,  0.],
                [ 3.,  3.,  0.],
                [ 2.,  2.,  0.],
                [ 3.,  3.,  0.]]])

  classmethod `fromstring`(s, sep=' ', ndim=3, count=-1)

    Create a `Coords` object with data from a string.

    This uses `numpy.fromstring()` to read coordinates from a string and creates a Coords object from them.

    Parameters: | s (str) – A string containing a single sequence of float numbers separated by whitespace and a possible separator string. sep (str) – The separator used between the coordinates. If not a space, all extra whitespace is ignored. ndim (int,) – Number of coordinates per point. Should be 1, 2 or 3 (default). If 1, resp. 2, the coordinate string only holds x, resp. x,y values. count (int, optional) – Total number of coordinates to read. This should be a multiple of ndim. The default is to read all the coordinates in the string.
    Returns: | Coords – A Coords object with the coordinates read from the string.
    Raises: | `ValueError` – If count was provided and the string does not contain that exact number of coordinates.

    Notes

    For writing the coordinates to a string, `numpy.tostring()` can be used.

    Examples

        >>> Coords.fromstring('4 0 0 3 1 2 6 5 7')
        Coords([[ 4.,  0.,  0.],
               [ 3.,  1.,  2.],
               [ 6.,  5.,  7.]])
        >>> Coords.fromstring('1 2 3 4 5 6',ndim=2)
        Coords([[ 1.,  2.,  0.],
               [ 3.,  4.,  0.],
               [ 5.,  6.,  0.]])

  classmethod `fromfile`(fil, **kargs)

    Read a `Coords` from file.

    This uses `numpy.fromfile()` to read coordinates from a file and create a Coords. Coordinates X, Y and Z for subsequent points are read from the file. The total number of coordinates on the file should be a multiple of 3.

    Parameters: | fil (str or file) – If str, it is a file name. An open file object can also be passed **kargs – Arguments to be passed to `numpy.fromfile()`.
    Returns: | Coords – A Coords formed by reading all coordinates from the specified file.
    Raises: | `ValueError` – If the number of coordinates read is not a multiple of 3.

    See also

    `numpy.fromfile()`
      read an array to file
    `numpy.tofile()`
      write an array to file
  `interpolate`(X, div)

    Create linear interpolations between two Coords.

    A linear interpolation of two equally shaped Coords X and Y at parameter value t is a Coords with the same shape as X and Y and with coordinates given by `X * (1.0-t) + Y * t`.

    Parameters: | X (Coords object) – A Coords object with same shape as self. div (int or list of floats) – The list of parameter values for which to compute the interpolation. Usually, they are in the range 0.0 (self) to 1.0 (X). Values outside the range can be used however and result in linear extrapolations. If an int is provided, a list with `(div+1)` parameter values is used, obtained by dividing the interval [0..1] into div equal segments. This `F.interpolate(G,n)` is equivalent with `F.interpolate(G,arange(0,n+1)/float(n))`.
    Returns: | Coords – A Coords object with an extra (first) axis, containing the concatenation of the interpolations of self and X at all parameter values in div. Its shape is (n,) + self.shape, where n is the number of values in div.

    Examples

        >>> X = Coords([0])
        >>> Y = Coords([1])
        >>> X.interpolate(Y,4)
        Coords([[ 0.  ,  0.  ,  0.  ],
               [ 0.25,  0.  ,  0.  ],
               [ 0.5 ,  0.  ,  0.  ],
               [ 0.75,  0.  ,  0.  ],
               [ 1.  ,  0.  ,  0.  ]])
        >>> X.interpolate(Y,[-0.1, 0.5, 1.25])
        Coords([[-0.1 ,  0.  ,  0.  ],
                [ 0.5 ,  0.  ,  0.  ],
                [ 1.25,  0.  ,  0.  ]])

  `convexHull`(dir=None, return_mesh=False)

    Return the 2D or 3D convex hull of a `Coords`.

    Parameters: | dir (int (0,1,2), optional) – If provided, it is one if the global axes and the 2D convex hull in the specified viewing direction will be computed. The default is to compute the 3D convex hull. return_mesh (bool, optional) – If True, returns the convex hull as a `Mesh` object instead of a `Connectivity`.
    Returns: | `Connectivity` or `Mesh` – The default is to return a Connectivity table containing the indices of the points that constitute the convex hull of the Coords. For a 3D hull, the Connectivity has plexitude 3, and eltype ‘tri3’; for a 2D hull these are respectively 2 and ‘line2’. The values in the Connectivity refer to the flat points list as obtained from `points()`. If return_mesh is True, a compacted Mesh is returned instead of the Connectivity. For a 3D hull, the Mesh will be a `TriSurface`, otherwise it is a Mesh of ‘line2’ elements. The returned Connectivity or Mesh will be empty if all the points are in a plane for the 3D version, or an a line in the viewing direction for the 2D version.

    Notes

    This uses SciPy to compute the convex hull. You need to have SciPy version 0.12.0 or higher.

    See also example ConvexHull.

  `rot`(angle, axis=2, around=None, angle_spec=0.017453292519943295)

    Return a copy rotated over angle around axis.

    Parameters: | angle (float or float array-like (3,3)) – If a float, it is the rotation angle, by default in degrees, and the parameters (angle, axis, angel_spec) are passed to `rotationMatrix()` to produce a (3,3) rotation matrix. Alternatively, the rotation matrix may be directly provided in the angle parameter. The axis and angle_spec are then ignored. axis (int (0,1,2) or float array-like (3,)) – Only used if angle is a float. If provided, it specifies the direction of the rotation axis: either one of 0,1,2 for a global axis, or a vector with 3 components for a general direction. The default (axis 2) is convenient for working with 2D-structures in the x-y plane. around (float array-like (3,)) – If provided, it species a point on the rotation axis. If not, the rotation axis goes through the origin of the global axes. angle_spec (float, DEG or RAD, optional) – Only used if angle is a float. The default (DEG) interpretes the angle in degrees. Use RAD to specify the angle in radians.
    Returns: | Coords – The Coords rotated as specified by the parameters.

    Note

    `rot()` is a convenient shorthand for `rotate()`.

    See also

    `translate()`
      translate a Coords
    `affine()`
      rotate and translate a Coords
    `arraytools.rotationMatrix()`
      create a rotation matrix for use in `rotate()`

    Examples

        >>> X = Coords('0123')
        >>> print(X.rotate(30))
        [[ 0.    0.    0.  ]
         [ 0.87  0.5   0.  ]
         [ 0.37  1.37  0.  ]
         [-0.5   0.87  0.  ]]
        >>> print(X.rotate(30,axis=0))
        [[ 0.    0.    0.  ]
         [ 1.    0.    0.  ]
         [ 1.    0.87  0.5 ]
         [ 0.    0.87  0.5 ]]
        >>> print(X.rotate(30,axis=0,around=[0.,0.5,0.]))
        [[ 0.    0.07 -0.25]
         [ 1.    0.07 -0.25]
         [ 1.    0.93  0.25]
         [ 0.    0.93  0.25]]
        >>> m = rotationMatrix(30,axis=0)
        >>> print(X.rotate(m))
        [[ 0.    0.    0.  ]
         [ 1.    0.    0.  ]
         [ 1.    0.87  0.5 ]
         [ 0.    0.87  0.5 ]]

  `trl`(dir, step=1.0, inplace=False)

    Return a translated copy of the `Coords` object.

    Translate the Coords in the direction dir over a distance step * length(dir).

    Parameters: | dir (int (0,1,2) or float array-like (..,3)) – The translation vector. If an int, it specifies a global axis and the translation is in the direction of that axis. If an array-like, it specifies one or more translation vectors. If more than one, the array should be broadcastable to the Coords shape: this allows to translate different parts of the Coords over different vectors, all in one operation. step (float) – If `dir` is an int, this is the length of the translation. Else, it is a multiplying factor applied to `dir` prior to applying the translation.
    Returns: | Coords – The Coords translated over the specified vector(s).

    Note

    `trl()` is a convenient shorthand for `translate()`.

    See also

    `centered()`
      translate to center around origin
    `Coords.align()`
      translate to align bounding box

    Examples

        >>> x = Coords([1.,1.,1.])
        >>> print(x.translate(1))
        [ 1. 2. 1.]
        >>> print(x.translate(1,1.))
        [ 1. 2. 1.]
        >>> print(x.translate([0,1,0]))
        [ 1. 2. 1.]
        >>> print(x.translate([0,2,0],0.5))
        [ 1. 2. 1.]
        >>> x = Coords(arange(4).reshape(2,2,1))
        >>> x
        Coords([[[ 0.,  0.,  0.],
                [ 1.,  0.,  0.]],
        <BLANKLINE>
               [[ 2.,  0.,  0.],
                [ 3.,  0.,  0.]]])
        >>> x.translate([[10.,-5.,0.],[20.,4.,0.]]) # translate with broadcasting
        Coords([[[ 10.,  -5.,   0.],
                [ 21.,   4.,   0.]],
        <BLANKLINE>
               [[ 12.,  -5.,   0.],
                [ 23.,   4.,   0.]]])

  `rep`(n, dir=0, step=1.0)

    Replicate a Coords n times with a fixed translation step.

    Parameters: | n (int) – Number of times to replicate the Coords. dir (int (0,1,2) or float array-like (3,)) – The translation vector. If an int, it specifies a global axis and the translation is in the direction of that axis. step (float) – If `dir` is an int, this is the length of the translation. Else, it is a multiplying factor applied to the translation vector.
    Returns: | Coords – A Coords with an extra first axis with length n. The new shape thus becomes `(n,) + self.shape`. The first component along the axis 0 is identical to the original Coords. Each following component is equal to the previous translated over (dir,step), where dir and step are interpreted just like in the `translate()` method.

    Notes

    `rep()` is a convenient shorthand for `replicate()`.

    Examples

        >>> Coords([0.,0.,0.]).replicate(4,1,1.2)
        Coords([[ 0. ,  0. ,  0. ],
                [ 0. ,  1.2,  0. ],
                [ 0. ,  2.4,  0. ],
                [ 0. ,  3.6,  0. ]])
        >>> Coords([0.]).replicate(3,0).replicate(2,1)
        Coords([[[ 0.,  0.,  0.],
                 [ 1.,  0.,  0.],
                 [ 2.,  0.,  0.]],
        <BLANKLINE>
                [[ 0.,  1.,  0.],
                 [ 1.,  1.,  0.],
                 [ 2.,  1.,  0.]]])

## 1.1. Functions defined in module coords

`coords.``otherAxes`(i)

  Return all global axes except the specified one

  Parameters: | i (int (0,1,2)) – One of the global axes.
  Returns: | tuple of ints – Two ints (j,k) identifying the other global axes in such order that (i,j,k) is a right-handed coordinate system.

`coords.``bbox`(objects)

  Compute the bounding box of a list of objects.

  The bounding box of an object is the smallest rectangular cuboid in the global Cartesian coordinates, such that no points of the objects lie outside that cuboid. The resulting bounding box of the list of objects is the smallest bounding box that encloses all the objects in the list.

  Parameters: | objects (object or list of objects) – One or more (list or tuple) objects that have a method `bbox()` returning the object’s bounding box as a Coords with two points.
  Returns: | Coords – A Coords object with two points: the first contains the minimal coordinate values, the second has the maximal ones of the overall bounding box encompassing all objects.

  Notes

  Objects that do not have a `bbox()` method or whose `bbox()` method returns invalid values, are silently ignored.

  See also

  `Coords.bbox()`
    compute the bounding box of a `Coords` object.

  Examples

      >>> bbox((Coords([-1.,1.,0.]),Coords([2,-3])))
      Coords([[-1., -3.,  0.],
              [ 2.,  1.,  0.]])

`coords.``bboxIntersection`(A, B)

  Compute the intersection of the bounding box of two objects.

  Parameters: | A (first object) – An object having a bbox method returning its boundary box. B (second object) – Another object having a bbox method returning its boundary box.
  Returns: | Coords (2,3) – A Coords specifying the intersection of the bounding boxes of the two objects. This again has the format of a bounding box: a coords with two points: one with the minimal and one with the maximal coordinates. If the two bounding boxes do not intersect, an empty Coords is returned.

  Notes

  Since bounding boxes are Coords objects, it is possible to pass computed bounding boxes as arguments. The bounding boxes are indeed their own bounding box.

  Examples

      >>> A = Coords([[-1.,1.],[2,-3]])
      >>> B = Coords([[0.,1.],[4,2]])
      >>> C = Coords([[0.,2.],[4,2]])
      >>> bbox((A,B))
      Coords([[-1., -3.,  0.],
              [ 4.,  2.,  0.]])

  The intersection of the bounding boxes of A and B degenerates into a line segment parallel to the x-axis:

      >>> bboxIntersection(A,B)
      Coords([[ 0.,  1.,  0.],
              [ 2.,  1.,  0.]])

  The bounding boxes of A and C do not intersect:

      >>> bboxIntersection(A,C)
      Coords([], shape=(0, 3))

`coords.``origin`()

  ReturnCreate a Coords holding the origin of the global coordinate system.

  Returns: | Coords (3,) – A Coords holding a single point with coordinates (0.,0.,0.). Exmaples ——– >>> origin() Coords([ 0., 0., 0.])

`coords.``pattern`(s, aslist=False)

  Generate a sequence of points on a regular grid.

  This function creates a sequence of points that are on a regular grid with unit step. These points are created from a simple string input, interpreting each character as a code specifying how to move from the last to the next point. The start position is always the origin (0.,0.,0.).

  Currently the following codes are defined:

  - 0 or +: goto origin (0.,0.,0.)
  - 1..8: move in the x,y plane
  - 9 or .: remain at the same place (i.e. duplicate the last point)
  - A..I: same as 1..9 plus step +1. in z-direction
  - a..i: same as 1..9 plus step -1. in z-direction
  - /: do not insert the next point

  Any other character raises an error.

  When looking at the x,y-plane with the x-axis to the right and the y-axis up, we have the following basic moves: 1 = East, 2 = North, 3 = West, 4 = South, 5 = NE, 6 = NW, 7 = SW, 8 = SE.

  Adding 16 to the ordinal of the character causes an extra move of +1. in the z-direction. Adding 48 causes an extra move of -1. This means that ‘ABCDEFGHI’, resp. ‘abcdefghi’, correspond with ‘123456789’ with an extra z +/-= 1. This gives the following schema:

          z+=1             z unchanged            z -= 1

      F    B    E          6    2    5         f    b    e
           |                    |                   |
           |                    |                   |
      C----I----A          3----9----1         c----i----a
           |                    |                   |
           |                    |                   |
      G    D    H          7    4    8         g    d    h

  The special character ‘/’ can be put before any character to make the move without inserting the new point. The string should start with a ‘0’ or ‘9’ to include the starting point (the origin) in the output.

  Parameters: | s (str) – A string with characters generating subsequent points. aslist (bool, optional) – If True, the points are returned as lists of integer coordinates instead of a `Coords` object.
  Returns: | Coords or list of ints – The default is to return the generated points as a Coords. With `aslist=True` however, the points are returned as a list of tuples holding 3 integer grid coordinates.

  See also

  `xpattern()`

  Examples

      >>> pattern('0123')
      Coords([[ 0.,  0.,  0.],
              [ 1.,  0.,  0.],
              [ 1.,  1.,  0.],
              [ 0.,  1.,  0.]])
      >>> pattern('2'*4)
      Coords([[ 0.,  1.,  0.],
              [ 0.,  2.,  0.],
              [ 0.,  3.,  0.],
              [ 0.,  4.,  0.]])

`coords.``xpattern`(s, nplex=1)

  Create a Coords object from a string pattern.

  Create a sequence of points using `pattern()`, and groups the points by `nplex` to create a Coords with shape `(-1,nplex,3)`.

  Parameters: | s (str) – The string to pass to `pattern()` to produce the sequence of points. nplex (int) – The number of subsequent points to group together to create the structured Coords.
  Returns: | Coords – A Coords with shape (-1,nplex,3).
  Raises: | `ValueError` – If the number of points produced by the input string s is not a multiple of nplex.

  Examples

      >>> print(xpattern('.12.34',3))
      [[[ 0. 0. 0.]
        [ 1. 0. 0.]
        [ 1. 1. 0.]]
      <BLANKLINE>
       [[ 1. 1. 0.]
        [ 0. 1. 0.]
        [ 0. 0. 0.]]]

`coords.``align`(L, align, offset=(0.0, 0.0, 0.0))

  Align a list of geometrical objects.

  Parameters: | L (list of Coords or Geometry objects) – A list of objects that have an appropriate `align` method, like the `Coords` and `Geometry` (and its subclasses). align (str) – A string of three characters, one for each coordinate direction, that define how the subsequent objects have to be aligned in each of the global axis directions: ’-‘ : align on the minimal coordinate value ’+’ : align on the maximal coordinate value ‘0’ : align on the middle coordinate value ’|’ : align the minimum value on the maximal value of the previous item Thus the string `'|--'` will juxtapose the objects in the x-direction, while aligning them on their minimal coordinates in the y- and z- direction. offset (float array-like (3,), optional) – An extra translation to be given to each subsequent object. This can be used to create a space between the objects, instead of juxtaposing them.
  Returns: | list of objects – A list with the aligned objects.

  Notes

  See also example Align.

  See also

  `Coords.align()`
    align a single object with respect to a point.