Constrained Free-form Deformation

Utilities for performing Constrained Free Form Deformation (CFFD).

Theoretical Insight:

It performs Free Form Deformation while trying to enforce a costraint of the form F(x)=c. The constraint is enforced exactly (up to numerical errors) if and only if the function is linear. For details on Free Form Deformation see the mother class.

class CFFD(fixval, fun, n_control_points=None, ffd_mask=None, fun_mask=None)[source]

Bases: FFD

Class that handles the Constrained Free Form Deformation on the mesh points.

Parameters:
  • n_control_points (list) – number of control points in the x, y, and z direction. Default is [2, 2, 2].

  • mode (string) – it can be affine or triaffine. The first option is for the F that are affine in all the coordinates of the points. The second one is for functions that are F in the coordinates of the points. The first option implies the second, but is optimal for that class of functions.

Variables:
  • box_length (numpy.ndarray) – dimension of the FFD bounding box, in the x, y and z direction (local coordinate system).

  • box_origin (numpy.ndarray) – the x, y and z coordinates of the origin of the FFD bounding box.

  • n_control_points (numpy.ndarray) – the number of control points in the x, y, and z direction.

  • array_mu_x (numpy.ndarray) – collects the displacements (weights) along x, normalized with the box length x.

  • array_mu_y (numpy.ndarray) – collects the displacements (weights) along y, normalized with the box length y.

  • array_mu_z (numpy.ndarray) – collects the displacements (weights) along z, normalized with the box length z.

  • fun (callable) – it defines the F of the constraint F(x)=c. Default is the constant 1 function.

  • fixval (numpy.ndarray) – it defines the c of the constraint F(x)=c. Default is 1.

  • ffd_mask (numpy.ndarray) – a boolean tensor that tells to the class which control points can be moved, and in what direction, to enforce the constraint. The tensor has shape (n_x,n_y,n_z,3), where the last dimension indicates movement on x,y,z respectively. Default is all true.

  • fun_mask (numpy.ndarray) – a boolean tensor that tells to the class on which axis which constraint depends on. The tensor has shape (n_cons,3), where the last dimension indicates dependency on on x,y,z respectively. Default is all true. It used only in the triaffine mode.

Example:
>>> from pygem import CFFD
>>> import numpy as np
>>> original_mesh_points = np.load("tests/test_datasets/test_sphere_cffd.npy")
>>> A = np.random.rand(3, original_mesh_points[:-4].reshape(-1).shape[0])
>>> fun = lambda x: A @ x.reshape(-1)
>>> b = np.random.rand(3)
>>> cffd = CFFD(b, fun, [2, 2, 2])
>>> cffd.read_parameters('tests/test_datasets/parameters_test_cffd.prm')
>>> cffd.adjust_control_points(original_mesh_points[:-4])
>>> assert np.isclose(np.linalg.norm(fun(cffd.ffd(original_mesh_points[:-4])) - b), np.array([0.]), atol = 1e-06)
>>> new_mesh_points = cffd.ffd(original_mesh_points)
adjust_control_points(src_pts)[source]

Adjust the FFD control points such that fun(ffd(src_pts))=fixval

Parameters:

src_pts (np.ndarray) – the points whose deformation we want to be constrained.

Return type:

None.

ffd(src_pts)[source]

Performs Classic Free Form Deformation.

Parameters:

src_pts (np.ndarray) – the points to deform.

Returns:

the deformed points.

Return type:

numpy.ndarray

_save_parameters()[source]

Saves the FFD control points in an array of shape [n_x,ny,nz,3].

Returns:

the FFD control points in an array of shape [n_x,ny,nz,3].

Return type:

numpy.ndarray

_load_parameters(tmp)[source]

Loads the FFD control points from an array of shape [n_x,ny,nz,3].

Parameters:

tmp (np.ndarray) – the array of FFD control points.

Return type:

None

_compute_linear_map(src_pts, saved_parameters, indices)[source]

Computes the coefficient and the intercept of the linear map from the control points to the output.

Parameters:
  • src_pts (np.ndarray) – the points to deform.

  • saved_parameters (np.ndarray) – the array of FFD control points.

Returns:

a tuple containing the coefficient and the intercept.

Return type:

tuple(np.ndarray,np.ndarray)