Frames in CamiTK

What is a frame and how it can help you in relatively positioning and orienting your components.

CamiTK components provide a service called Frame. This means that each component can be manipulated as a Frame. In this documentation you will learn about frames, what they are, and how to use them in CamiTK.

What is a CamiTK frame?

Two mesh components represented in the CamiTK 3D viewer according to their frames. (Two mesh components represented in the CamiTK 3D viewer according to their frames.)

A CamiTK frame represents a space transformation from a component to another one.

A frame is characterized by two things:

  • a 3D space landmark which stands for a referential.
  • a 3D space transform, composed of a translation and rotation, represented as a 4x4 matrix computed regarding this referential.

Each component in CamiTK has a frame, a 4x4 matrix that represents its position and orientation relatively to a specific 3D landmark.

On the figure above, there are two mesh components (from the female.vtk and male.vtk files provided with the test data of CamiTK Community Edition). The mesh representing the male has a frame composed of a 3D space transform containing a translation vector and a rotation matrix. This frame is expressed relatively to the female mesh component. The 2 components frames’ landmarks are shown at the bottom right feet of the of meshes.

In this example, if we modify the female frame’s 3D space transform (e.g., if we displace the mesh in the x direction), it will change its landmark’s position. As the male’s frame is expressed relatively to the female frame, the male’s frame would also change accordingly and automatically.

By default a component frame is initialized like this:

  • its 3D space landmark is the world landmark.
  • its 3D space transform is characterized by the identity 4x4 matrix.

The world landmark is the default reference frame. It is fixed and define an absolute and direct reference frame at position and is equals to the world reference of VTK 3D graphics scene (i.e., the position \((0,0,0)\) and axis \( \vec{x},\vec{y},\vec{z} \) are the same as the 3D graphics scene.

If the 3D space landmark of component B is equal to the component A frame specific landmark, we say that component A is the parent frame of component B.

In the above example, the female mesh component is the parent frame of the male mesh component.

A component that has a parent frame pointer equal to nullptr has no specific parent frame, i.e. the component is expressed relatively to the world landmark.

About the space landmarks

The space landmark is the referential from which the 3D space transform is expressed. It is also representing the parent frame of a component: having a custom 3D space landmark (different from the world landmark) is the same as having a parent frame. The parent frame is the one that holds this 3D space landmark in its frame.

By default, for instance when creating a new component, the parent frame is equal to nullptr. This means that by default a component is expressed directly in the world landmark.

In the above example, the female mesh component is expressed in the world landmark.

About the 3D space transform

The 3D space transform of a frame represents the space transformation of the component regarding its frame’s landmark. This transformation is characterized by a 4x4 matrix, expressed in homogeneous coordinates1. We can separate this matrix into several parts:

  • its 3x3 rotation matrix, which stands for the rotation part of the transformation around the X, Y and Z axes of the 3D space landmark.
  • its (X, Y, Z) translation vector regarding the 3D space landmark, after the rotation has been performed.
  • the last line of the matrix stands for the projection components, which we consider equal to (0, 0, 0, 1). Therefore, no projection is done, the component scale is kept to 100% during the transformation.

First rotation then translation

Given a component’s frame, we got a 3D space transformation, characterized by a translation vector and a rotation matrix. One should consider the transformations order:

  • First, the rotation is performed regarding the component’s frame 3D landmark
  • Then, the translation is performed.

The translation vector is expressed in the 3D space landmark rotated by the rotation matrix of the frame. You should remember that the translation vector’s values are not expressed directly in the 3D space landmark, but in the this rotated frame.

Different rotation orders

The rotation itself can be decomposed into 3 rotations: one around each axis (X, Y and Z) of the 3D parent frame’s landmark. The order we perform the rotations in (for instance first around X, then around Y, and finally around Z) has an incidence. CamiTK considers these two cases:

  1. the alphabetical order: X, Y and Z
  2. the VTK order

Alphabetical order

The alphabetical order: X, Y and Z. This is a standard order for considering the rotations. You may use the method

virtual void Component::setTransformTranslation(double x, double y, double z);

and

virtual void Component::setTransformRotation(double x, double y, double z);

to set the translation and the rotation of the component’s frame considering the alphabetical order for rotation.

VTK order

The VTK order : Z, X and Y. This is a non-standard but VTK order of considering rotations. You may use this method:

virtual void Component::setTransformTranslationVTK(double x, double y, double z);

and

virtual void Component::setTransformRotationVTK(double x, double y, double z);

to set the translation and the rotation of the component’s frame considering the VTK order for rotation.

The rotation order is important, and we recommend you to choose the VTK order: Z, X and Y. Even if this seems less logical, CamiTK remains essentially on VTK for the 3D visualization. VTK uses this order to compute rotation angles given a specific rotation matrix. If the rotation matrix has been built using a different order than the VTK one (Z, X, Y) then, the retrieved angles are wrong. This could have some significant drawbacks in your code.

We still propose the X, Y, Z alphabetical order through two methods of the InterfaceFrame for retrocompatibily reasons. Since some old CamiTK code with frames uses this convention for the rotation, we kept the non-VTK convention.

Frame hierarchy

Two mesh components’ frames hierarchy (Two mesh components’ frames hierarchy)

Considering several components opened in CamiTK, they all have a dedicated frame. If some components are the parent frames of other ones, this leads to a frame hierarchy:

  • the top level frame is the world 3D landmark
  • components that have a given component as a parent frame are considered its children frame component.

On the figure above we can see the two male and female mesh components of the previous example. The male mesh component has the female mesh component as a parent frame. This is represented like a hierarchy in the Frame explorer: the male mesh component’s frame is a child of the female mesh component’s one.

Component’s frame hierarchy is completely different from the classic components hierarchy. In this example, the male component is NOT a child component of the female’s one.

Here are three useful tips:

  • You may switch from the Frame explorer to the classic component explorer using the bottom tabs (as seen in the picture).
  • You will notice that there are two types of hierarchies between components:
    • the classic components hierarchy, one component being the child of another one.
    • the frame components hierarchy, one component’s frame being a child of another component frame’s one.
  • You can use the specific Edit Frame action to check and modify the value of the frame matrix (see the dedicated section below).

Why should I consider using the frame service?

In CamiTK, regarding volume images, frames are used to correctly represent them, such as DICOM, to display a correct image orientation.

More generally, components’ frames are helpful to characterize component’s position and orientation relatively to another one. We can imagine a complex 3D structure composed of several smaller ones. In this structure, we want sub-structures to have their positions and orientations dependent to another structure’s ones. This is where frames are helpful: each substructure can have a parent frame component, which represents the position and orientation dependance between the components.

How the frame functionality is implemented in the CamiTK C++ code?

The CamiTK frame functionality is provided as a service to CamiTK components. Meaning, we provide a C++ “interface”, called InterfaceFrame which describes all the methods any class providing the frame service should implement. This interface is implemented by the Component and the Frame classes. Following the delegation pattern, the Component class delegates all the implementation of the InterfaceFrame interface to the Frame instance.

You might take a look at the CamiTK API documentation to look at the InterfaceFrame methods.

How do I edit my component’s frame?

Basically there are two ways of editing your component’s frame. At runtime and interactively, using the Edit Frame action, or directly in your component or action’s code.

The Edit Frame Action

The Edit Frame action widget (The Edit Frame action widget.)

The Edit Frame action is provided with the CamiTK Community Edition source code. To run it, right click on a component and select Frame → Edit Frame action.

This action allows you to:

  • Change the parent frame of your component.
  • Edit the translation vector of your component’s frame 3D space transform.
  • Edit the rotation matrix of your component’s frame 3D space transform, by modifying the 3 rotations angles, around the X, Y and Z axis.
  • Save and Load a transform matrix to / from a .frame file.

The picture above shows you the Edit Frame action’s widget. The component’s position and orientation is updated automatically after moving the different sliders of the widget (translation / rotation).

The Edit Frame action allows you to save and load a component’s frame to / from a file. This functionality is useful if your component does not directly store its information when saving it (such as 3D-image like MHA).

Edit your frame in your code

As any component provides the service of the InterfaceFrame interface, you may call any methods described in this interface to modify your component’s frame. Refer to the InterfaceFrame service in the API documentation to see the available methods and how to use them.