simkit.rotation_strain_coordinates#

Rotation–strain (RS) coordinates via Jacobian fitting.

Splits a per-element deformation gradient F = I + grad u into a rotation R and a symmetric stretch S. The rotation is taken from the linear field’s axis-angle (the axial vector of the antisymmetric part of grad u) and turned into a finite rotation by the matrix exponential (Rodrigues). The rotation–strain target Y = R @ S - I keeps both the rotation and the strain, and vertex displacements reproducing Y in Jacobian space are fit using a precomputed factorization.

Classes#

RSPrecompute

Precompute for fitting displacements to rotation-only Jacobian targets.

Functions#

rotation_strain_coordinates(→ Union[numpy.ndarray, ...)

Map a displacement field to rotation–strain coordinates.

Module Contents#

class simkit.rotation_strain_coordinates.RSPrecompute(X: numpy.ndarray, T: numpy.ndarray, pinned: numpy.ndarray | None = None)#

Precompute for fitting displacements to rotation-only Jacobian targets.

Builds the deformation Jacobian J, volume-weighted normal equations, and a sparse factorization of J^T Vol J + H_pin.

Parameters:
  • X (np.ndarray (n, dim)) – Rest vertex positions.

  • T (np.ndarray (nt, simplex_size)) – Mesh simplices.

  • pinned (np.ndarray, optional) – Pinned vertex indices. If None, pins vertices near the mesh mean.

X#

Rest positions.

Type:

np.ndarray (n, dim)

T#

Mesh simplices.

Type:

np.ndarray (nt, simplex_size)

J#

Deformation Jacobian (membrane or solid).

Type:

scipy.sparse matrix

K#

Volume-weighted transpose J^T Vol.

Type:

scipy.sparse matrix

factorization#

Sparse solve handle for the penalized normal system.

Type:

callable

X#
T#
J#
K#
factorization#
fit_displacements_to_jacobian(Y: numpy.ndarray) numpy.ndarray#

Solve for vertex displacements whose Jacobian matches Y.

Parameters:

Y (np.ndarray (, dim, dim) or (, 3, 2)) – Per-element rotation targets (flattened internally).

Returns:

u – Fitted displacement vector.

Return type:

np.ndarray (n*dim, 1)

simkit.rotation_strain_coordinates.rotation_strain_coordinates(X: numpy.ndarray, T: numpy.ndarray, u: numpy.ndarray, pinned: numpy.ndarray | None = None, pre: RSPrecompute | None = None, return_pre: bool = True) numpy.ndarray | Tuple[numpy.ndarray, RSPrecompute]#

Map a displacement field to rotation–strain coordinates.

Decomposes F = I + grad u into a rotation R and a symmetric stretch S = I + sym(grad u). R is the matrix exponential of the linear field’s axis-angle (the axial vector of the antisymmetric part of grad u). Sets the rotation–strain target Y = R @ S - I and fits u_rs so J u_rs Y.

Parameters:
  • X (np.ndarray (n, dim)) – Rest vertex positions.

  • T (np.ndarray (nt, simplex_size)) – Mesh simplices. Must be triangles for 2D, or tetrahedra for 3D.

  • u (np.ndarray (n, dim) or (n*dim,)) – Input displacement field.

  • pinned (np.ndarray, optional) – Pinned vertex indices passed to RSPrecompute if pre is None.

  • pre (RSPrecompute, optional) – Reusable precompute. Built from (X, T, pinned) when None.

  • return_pre (bool, optional) – If True, return (u_rs, pre); otherwise only u_rs.

Returns:

  • u_rs (np.ndarray (n, dim)) – Rotation–strain displacement coordinates.

  • pre (RSPrecompute, optional) – Precompute object (only if return_pre is True).