Skip to content

util ¤

align_edges(src_pts: ndarray, src_edges: ndarray, tgt_pts: ndarray, tgt_edges: ndarray, return_transform: bool = False) -> ndarray ¤

Calulate mean change in angle and position between two curves

Parameters:

Name Type Description Default
src_pts ndarray

(n, 2) source vertex coordinates.

required
tgt_pts ndarray

(n, 2) target vertex coordinates.

required
src_edges ndarray

(n, 2) source edge vectors.

required
tgt_edges ndarray

(n, 2) target edge vectors.

required
return_transform bool

If True, return a 3x3 transformation matrix. Otherwise, return the transformed points.

False
Source code in src\curvey\util.py
def align_edges(
    src_pts: ndarray,
    src_edges: ndarray,
    tgt_pts: ndarray,
    tgt_edges: ndarray,
    return_transform: bool = False,
) -> ndarray:
    """Calulate mean change in angle and position between two curves

    Parameters
    ----------
    src_pts
        `(n, 2)` source vertex coordinates.

    tgt_pts
        `(n, 2)` target vertex coordinates.

    src_edges
        `(n, 2)` source edge vectors.

    tgt_edges
        `(n, 2)` target edge vectors.

    return_transform
        If True, return a 3x3 transformation matrix. Otherwise, return the transformed points.

    """
    # Calculate the mean angle between source and target edge vectors
    # Because these are unnormalized, larger edges are weighted more heavily
    cos_theta = (src_edges * tgt_edges).sum()
    sin_theta = cross(src_edges, tgt_edges).sum()
    theta = arctan2(sin_theta, cos_theta)
    # NB negative sign here bc we're post-multipying, equiv. to transposing the rot matrix
    pts = src_pts @ rotation_matrix(-theta)
    # AFTER applying the rotation, check mean change in vertex position
    offset = (tgt_pts - pts).mean(axis=0, keepdims=True)

    if return_transform:
        transform = eye(3)
        transform[:2, :2] = rotation_matrix(theta)
        transform[:2, 2] = offset
        return transform

    return pts + offset

periodic_interpolator(x: ndarray, f: ndarray, typ: InterpType | str = 'cubic') -> Callable[[ndarray], ndarray] ¤

Construct a periodic interpolator of the function f(x)

Parameters:

Name Type Description Default
x ndarray

(n + 1,) array of independent variable values.

required
f ndarray

(n,) or (n, ndim) array of function values. f(x[-1]) is assumed equal to f(x[0]).

required
typ InterpType | str

The type of interpolator. One of

  • 'linear' for linear interpolation via scipy.interpolate.interp1d
  • cubic for cubic spline interpolation via scipy.interpolate.CubicSpline
  • 'pchip`
    • for piecewise cubic hermite interpolating polynomial via scipy.interpolate.PchipInterpolator.
'cubic'

Returns:

Type Description
interpolator

A function f that returns interpolated values.

Source code in src\curvey\util.py
def periodic_interpolator(
    x: ndarray,
    f: ndarray,
    typ: InterpType | str = "cubic",
) -> Callable[[ndarray], ndarray]:
    """Construct a periodic interpolator of the function f(x)

    Parameters
    ----------
    x
        `(n + 1,)` array of independent variable values.

    f
        `(n,)` or `(n, ndim)` array of function values.
        `f(x[-1])` is assumed equal to `f(x[0])`.

    typ
        The type of interpolator. One of

        - 'linear' for linear interpolation via `scipy.interpolate.interp1d`
        - `cubic` for cubic spline interpolation via `scipy.interpolate.CubicSpline`
        - 'pchip`
            - for piecewise cubic hermite interpolating polynomial via
            `scipy.interpolate.PchipInterpolator`.

    Returns
    -------
    interpolator
        A function `f` that returns interpolated values.
    """

    if typ == "linear":
        return _periodic_interp1d(x, f)

    if typ == "cubic":
        return scipy.interpolate.CubicSpline(x, concatenate([f, f[[0]]]), bc_type="periodic")

    if typ == "pchip":
        return _periodic_pchip(x, f)

    msg = f"Unrecognized interpolator type {typ}"
    raise ValueError(msg)

reflection_matrix(theta: float) -> ndarray ¤

A 2x2 reflection matrix

Source code in src\curvey\util.py
def reflection_matrix(theta: float) -> ndarray:
    """A 2x2 reflection matrix"""
    cos_2theta, sin_2theta = cos(2 * theta), sin(2 * theta)
    return array([[cos_2theta, sin_2theta], [sin_2theta, -cos_2theta]])

rotation_matrix(theta: float) -> ndarray ¤

A 2x2 rotation matrix

Source code in src\curvey\util.py
def rotation_matrix(theta: float) -> ndarray:
    """A 2x2 rotation matrix"""
    cos_theta, sin_theta = cos(theta), sin(theta)
    return array([[cos_theta, -sin_theta], [sin_theta, cos_theta]])