# Rotating Slice around Axis of Model

**URL:** <https://discourse.slicer.org/t/rotating-slice-around-axis-of-model/916>\
**Category:** Development\
**Tags:** registration\
**Created:** [August 21, 2017, 9:18pm UTC](https://discourse.slicer.org/t/rotating-slice-around-axis-of-model/916 "2017-08-21T21:18:06Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielbr](https://avatars.discourse-cdn.com/v4/letter/d/c2a13f/32.png) [@danielbr](https://discourse.slicer.org/u/danielbr)\
**Post date:** [August 21, 2017, 9:18pm UTC](https://discourse.slicer.org/t/rotating-slice-around-axis-of-model/916/1 "2017-08-21T21:18:06Z")

</div>

Hi all,  
Having a slight problem and can’t for the life of me figure it out. Was hoping that one of you could help me out. Let me explain the problem.

I have a 3d model loaded into the scene. That model has two transforms applied to it.

RegistrationTransform-\>RotationTransform-\>Model

The registration transform registers the model to image space(offset and rotation). The RotationTransform controls how the model is rotated about its axes. I am trying to make a slider which will rotate the model about the model Y axis and have the axial slice follow this rotation. Currently I have a slider which is connected to the following method and the model rotation is working perfectly by applying a Y rotation to the RotationTransform. See code:

```
void onModelRotationSliderChanged(double value){
     vtkMRMLLinearTransformNode* registrationTransform = this->mrmlScene()->GetNodeByID('vtkMRMLLinearTransformNode1');
     vtkMRMLLinearTransformNode* rotationTransform = this->mrmlScene()->GetNodeByID('vtkMRMLLinearTransformNode2');
     rotationTransform->RotateWXYZ(d->previousRotation - value, 0, 1, 0);
     d->previousRotation = value;
}

```

The above code works perfectly. No matter what RegistrationTransform is used the model always rotates around the model Y axis. The problem I am having is getting the slice to then follow that same rotation. I have the following code which I added to the end of the above function, but it doesn’t rotate the axial slice in the desired manner:

```
vtkSmartPointer<vtkMatrix4x4> currentSliceToRAS = d->redViewer->GetSliceToRAS();
vtkSmartPointer<vtkMatrix4x4> registrationMatrix = registrationTransform->GetMatrixTransformToParent();
vtkSmartPointer<vtkMatrix4x4> newResliceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
newResliceMatrix->Multiply4x4(rotationTransform->GetMatrix(), registrationMatrix, newResliceMatrix);
currentSliceToRAS->SetElement(0, 0, newResliceMatrix->GetElement(0, 0));
currentSliceToRAS->SetElement(0, 1, newResliceMatrix->GetElement(0, 1));
currentSliceToRAS->SetElement(0, 2, newResliceMatrix->GetElement(0, 2));
currentSliceToRAS->SetElement(0, 3, registrationMatrix->GetElement(0, 3));
currentSliceToRAS->SetElement(1, 0, newResliceMatrix->GetElement(1, 0));
currentSliceToRAS->SetElement(1, 1, newResliceMatrix->GetElement(1, 1));
currentSliceToRAS->SetElement(1, 2, newResliceMatrix->GetElement(1, 2));
currentSliceToRAS->SetElement(1, 3, registrationMatrix->GetElement(1, 3));
currentSliceToRAS->SetElement(2, 0, newResliceMatrix->GetElement(2, 0));
currentSliceToRAS->SetElement(2, 1, newResliceMatrix->GetElement(2, 1));
currentSliceToRAS->SetElement(2, 2, newResliceMatrix->GetElement(2, 2));
currentSliceToRAS->SetElement(2, 3, registrationMatrix->GetElement(2, 3));
d->redViewer->UpdateMatrices();

The axial slice lines up perfect with the model in the beginning, but when I start to rotate, the slice does not rotate around the Y axis of the model. Any help would be greatly appreciated. Thanks!
```

---

<div class="post-metadata">

**Author:** ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)\
**Post date:** [August 22, 2017, 2:12am UTC](https://discourse.slicer.org/t/rotating-slice-around-axis-of-model/916/2 "2017-08-22T02:12:28Z")

</div>

Despite compositing matrices is a really simple operation (you just have to get the order of the matrices right and invert them as needed), you may easily spend a couple of days figuring out the correct combination.

We’ve found that a very good way of getting the correct solution quickly is following these steps:

1. Define each coordinate system: what is the unit (mm, pixel, …), where is the origin, what are the coordinate system axis directions. It also helps if you draw a sketch of the origin position and axis directions relative to physical objects. See an [example in Plus toolkit’s user manual](http://perk-software.cs.queensu.ca/plus/doc/nightly/user/CommonCoordinateSystems.html).

2. Name each transformation as a transformation from coordinate system `A` to `B` as AToB (you may add Transform or Matrix suffix to make it even more clear that it is a transform). For example, `SliceToRAS` is a well-defined transformation. `newResliceMatrix` and `registrationMatrix` names are not usable because they don’t specify what coordinate systems they are transforming between and in what order.

3. Create chain of matrices using the following rules:

- AToC = BToC \* AToB
- AToB = inv(BToA)

Alternatively, in some simple cases when you need to place a slice view to a based on a position and a normal vector, you may also find [vtkMRMLSliceNode::SetSliceToRASByNTP](http://apidocs.slicer.org/master/classvtkMRMLSliceNode.html#a0e8251eb55cfb40e316c2e22894b140c) method useful. See how it is used for [rotating slice views in ValveView module](https://github.com/SlicerHeart/SlicerHeart/blob/master/ValveView/ValveView.py).

For real-time positioning of a slice view using a transform, use `VolumeResliceDriver` module of `SlicerIGT` extension.

---

<div class="post-metadata">

**Author:** ![danielbr](https://avatars.discourse-cdn.com/v4/letter/d/c2a13f/32.png) [@danielbr](https://discourse.slicer.org/u/danielbr)\
**Post date:** [August 22, 2017, 1:43pm UTC](https://discourse.slicer.org/t/rotating-slice-around-axis-of-model/916/3 "2017-08-22T13:43:52Z")

</div>

Thanks for the explanation. Turns out it was something extremely simple. Matrix multiplication is not commutative. For my example above I was specifying AToC = AToB \* BToC. Changing the order fixed the problem right away! Thanks!
