Hello everyone. I have a task - to record the displacement of fragments in all planes when they move. I use the transforms module. But I encountered the following problem: all values in the “rotation” field are reset to zero as soon as I click somewhere. This problem does not arise with the “translation”: all values in this field are saved. How can I make the values in the “ratation” field be saved (like in video guides)?
That’s normal and expected. The rotation sliders don’t uniquely define the transform so they are applied incrementally.
That’s an older version of Slicer.
The behavior has be clarified as described here:
- Note: Linear transform edit sliders only show relative translation and rotation because a transformation can be achieved using many different series of transforms. To make this clear to users, only one transform slider can be non-zero at a time (all previously modified sliders are reset to 0 when a slider is moved). The only exception is translation sliders in “translate first” mode (i.e., when translation in global/local coordinate system button is not depressed): in this case there is a only one way how a specific translation can be achieved, therefore transform sliders are not reset to 0. An rotating dial widget would be a more appropriate visual representation of the behavior than sliders, but slider is chosen because it is a standard widget and users are already familiar with it.
Thanks for the detailed answer. As far as I know, the widget does not show the displacement values in degrees (as, for example, it happens in Autodesk Netfabb).
If you really want to get the angles for a single linear transform, you can use this python snippet
import numpy as np
def rotationMatrixToEulerZYX(R):
if R[2,0] < 1:
if R[2,0] > -1:
pitch = np.arcsin(-R[2,0])
roll = np.arctan2(R[2,1], R[2,2])
yaw = np.arctan2(R[1,0], R[0,0])
else:
# R[2,0] = -1
pitch = np.pi / 2
roll = -np.arctan2(-R[1,2], R[1,1])
yaw = 0
else:
# R[2,0] = +1
pitch = -np.pi / 2
roll = np.arctan2(-R[1,2], R[1,1])
yaw = 0
return np.degrees([roll, pitch, yaw])
m = slicer.util.arrayFromTransformMatrix(tn)
tn = getNode('Transform')
rotationMatrixToEulerZYX(m)
The output is an array with the angles, e.g. array([10., 20., 30.])
Thank you very much.
If you want to avoid Python scripting, you can also use Characterize transform matrix module (in Sandbox extension). It decomposes the transformation into a few rotations and other operations and provides a detailed description. Decompositions are always arbitrary (there are infinite ways a transform can be put together from elementary operations), but it might happen to be suitable for what you want to achieve.