Free-form Deformation

Utilities for performing Free Form Deformation (FFD).

Theoretical Insight:

Free Form Deformation is a technique for the efficient, smooth and accurate geometrical parametrization. It has been proposed the first time in Sederberg, Thomas W., and Scott R. Parry. “Free-form deformation of solid geometric models.” ACM SIGGRAPH computer graphics 20.4 (1986): 151-160. It consists in three different step:

  • Mapping the physical domain to the reference one with map \(\boldsymbol{\psi}\). In the code it is named transformation.

  • Moving some control points to deform the lattice with \(\hat{T}\). The movement of the control points is basically the weight (or displacement) \(\boldsymbol{\mu}\) we set in the parameters file.

  • Mapping back to the physical domain with map \(\boldsymbol{\psi}^{-1}\). In the code it is named inverse_transformation.

FFD map (\(T\)) is the composition of the three maps, that is

\[T(\cdot, \boldsymbol{\mu}) = (\Psi^{-1} \circ \hat{T} \circ \Psi) (\cdot, \boldsymbol{\mu})\]

In this way, every point inside the FFD box changes it position according to

\[\boldsymbol{P} = \boldsymbol{\psi}^{-1} \left( \sum_{l=0}^L \sum_{m=0}^M \sum_{n=0}^N \mathsf{b}_{lmn}(\boldsymbol{\psi}(\boldsymbol{P}_0)) \boldsymbol{\mu}_{lmn} \right)\]

where \(\mathsf{b}_{lmn}\) are Bernstein polynomials. We improve the traditional version by allowing a rotation of the FFD lattice in order to give more flexibility to the tool.

You can try to add more shapes to the lattice to allow more and more involved transformations.

class FFD(n_control_points=None)[source]

Bases: Deformation

Class that handles the 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].

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.

  • rot_angle (numpy.ndarray) – rotation angle around x, y and z axis 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.

Example:
>>> from pygem import FFD
>>> import numpy as np
>>> ffd = FFD()
>>> ffd.read_parameters(
>>>        'tests/test_datasets/parameters_test_ffd_sphere.prm')
>>> original_mesh_points = np.load(
>>>         'tests/test_datasets/meshpoints_sphere_orig.npy')
>>> new_mesh_points = ffd(original_mesh_points)
property n_control_points

The number of control points in X, Y and Z directions

Return type:

numpy.ndarray

property psi

Return the function that map the physical domain to the reference domain.

Return type:

callable

property inverse_psi

Return the function that map the reference domain to the physical domain.

Return type:

callable

property T

Return the function that deforms the points within the unit cube.

Return type:

callable

property rotation_matrix

The rotation matrix (according to rot_angle_x, rot_angle_y, rot_angle_z).

Return type:

numpy.ndarray

property position_vertices

The position of the vertices of the FFD bounding box.

Return type:

numpy.ndarray

reset_weights()[source]

Set transformation parameters to arrays of zeros.

read_parameters(filename='parameters.prm')[source]

Reads in the parameters file and fill the self structure.

Parameters:

filename (string) – parameters file to be read in.

write_parameters(filename='parameters.prm')[source]

This method writes a parameters file (.prm) called filename and fills it with all the parameters class members.

Parameters:

filename (string) – parameters file to be written out.

control_points(deformed=True)[source]

Method that returns the FFD control points. If the deformed flag is set to True the method returns the deformed lattice, otherwise it returns the original undeformed lattice.

Parameters:

deformed (bool) – flag to select the original or modified FFD control lattice. The default is True.

Returns:

the FFD control points (by row).

Return type:

numpy.ndarray

reflect(axis=0, in_place=True)[source]

Reflect the lattice of control points along the direction defined by axis. In particular the origin point of the lattice is preserved. So, for instance, the reflection along x, is made with respect to the face of the lattice in the yz plane that is opposite to the origin. Same for the other directions. Only the weights (mu) along the chosen axis are reflected, while the others are preserved. The symmetry plane can not present deformations along the chosen axis. After the refletcion there will be 2n-1 control points along axis, witha doubled box length.

Parameters:
  • axis (int) – axis along which the reflection is performed. Default is 0. Possible values are 0, 1, or 2, corresponding to x, y, and z respectively.

  • in_place (bool) – if True, the object attributes are modified in place; if False, a new object is return with the reflected lattice. Default is True.

Returns:

a new object with the same parameters and the reflected lattice if in_place is False, otherwise NoneType.

Example:
>>> ffd.reflect(axis=0, in_place=True) # irreversible
>>> # or ...
>>> refle_ffd = ffd.reflect(axis=0, in_place=False)
__call__(src_pts)[source]

This method performs the FFD to src_pts and return the deformed points.

Parameters:

src_pts (numpy.ndarray) – the array of dimensions (n_points, 3) containing the points to deform. The points have to be arranged by row.

Returns:

the deformed points

Return type:

numpy.ndarray (with shape = (n_points, 3))