I get trouble in using vtkImageSlabReslice

Dear all,
I`m using vtkImageSlabReslice to create an oblique MPR.The result is right,but there is a rotate angle in output, how to fix it ?
thanks
double res[3] = { 0 }, center[3] = { 0 };
center[0] = mPoints[index].x;
center[1] = mPoints[index].y;
center[2] = mPoints[index].z;
GetPlaneMainPoint(center, m_imgLength, m_imgLength, m_YAxis, m_ZAxis, m_XAxis, res);//Calculate origin point
vtkSmartPointer r = vtkSmartPointer::New();
r->SetResliceAxesOrigin(res);
r->SetInputData(ipt);
r->SetOutputExtentToDefault();
r->SetResliceAxesDirectionCosines(m_XAxis, m_YAxis, m_ZAxis);
r->SetBackgroundColor(0, 0, 0, 0);
r->SetOutputDimensionality(2);
r->SetSlabThickness(ui.sbThickness->value());
r->Update();

The rotation is given by the (m_Axis, y_Axis, z_Axis) values that you have supplied. In order to avoid in-plane rotation, you must constrain these values. How are you computing them?

Hi David,
I want get oblique MPR in a specific angle,the operation interface is shown in the figure below.It also base on a oblique MPR.The red frame circles the operation view:


I got m_YAxis by this way
vtkResliceCursor* myResliceCursor->GetPlane(2)->GetNormal(m_YAxis);//myResliceCursor is a part of red&green cross
m_ZAxis is a vector composed of the world coordinates of the red and blue points
m_XAxis is obtained by vector cross product: vtkMath::Cross(m_ZAxis, m_YAxis, m_XAxis);
It works well when the work interface is orthogonal.But once I start to rotate the remaining two views, the situation in question will appear.
thanks

In addition,the reslice figure is shown by vtkImageViewer2

I’m going to state what I think you are doing, please let me know if this is accurate: At the beginning, you have XAxis, YAxis, and ZAxis from the original image. Then the user places red and blue points to define the angle for an oblique MPR. Finally, you compute a new XAxis, YAxis, and ZAxis. Is this correct?


Below are the constraints. Your method uses two of these constraints, but not the third constraint.

  1. The new ZAxis is defined by the red and blue points.
  2. The XAxis, YAxis, and ZAxis are all perpendicular to each other.
  3. The XAxis and YAxis must be computed so that there is no rotation around ZAxis.

To satisfy the 3rd constraint, a different method is needed. Are you familiar with the Angle and Axis method of doing rotations? As in RotateWXYZ(angle,x,y,z)? This method can be used to solve the problem.

To satisfy the 1st constraint, the rotation must rotate the original z axis, which is probably (0, 0, 1), to the position of the new z axis (as defined by the red and blue points). In order to satisfy the 3rd constraint, the rotation axis must be perpendicular to the original z axis. The 2nd constraint is satisfied automatically because the transformation is a rotation.

Computing the rotation axis is easy. The rotation axis is the cross product of the original z axis and the new z axis. Do not use the y axis in the cross product! Computing the rotation angle is easy, too. You can use vtkMath::AngleBetweenVectors() to compute the rotation angle between the old z axis and the new z axis.

Then you can use vtkTransform and RotateWXYZ() to create a rotation transformation. Apply this transformation to the old y axis to get the new y axis, and apply it to the old x axis to get the new x axis. RotateWXYZ() uses degrees for the angle, so you will have to convert from radians to degrees.

1 Like

Hi David,
I have almost fixed this problem with SetResliceTransform() ,but the image still has slight rotation.Is this a problem of calculation error or choice of angle requires further experiments to verify.
now ,I ran into another problem.I can only get red& blue points display coordinate from the program,I tried to convert it to world coordinates,below is the conversion program. But when I move this point, it`s Z coordinate keeps decreasing until it stabilizes at around -1400, which is obviously not a correct result.How should I get the correct world coordinates with display coordinate?
thanks
vtkSmartPointer< vtkCoordinate > pCoorPress = vtkSmartPointer< vtkCoordinate >::New();
pCoorPress->SetCoordinateSystemToDisplay();
pCoorPress->SetValue(e[0],e[1], 0.0);
worldpos = pCoorPress->GetComputedWorldValue(this->OpView->GetRenderer());

When you set display coordinates you need to give three values: x, y, depth. Using depth=0.0 to set the coordinate is not correct. There are different ways to find the depth, one way is to use a VTK picker.

Why did you decide to use SetResliceTransform()? SetResliceAxes() and SetResliceTransform() do almost exactly the same thing, so I am curious why you made this choice.

When you have a plane, another way to get the world coordinate from the display coordinate (without using a picker) is this:

First, do a display-to-world coordinate transformation for display point (x, y, 0.0). Using depth=0.0 gives a world point at the near clipping plane.

Next, do a display-to-world coordinate transformation for display point (x, y, 1.0). Using depth=1.0 gives a world point at the far clipping plane.

This gives world points at the near and far clipping planes. Together, these points define a line segment, where the direction of the line segment is the direction of the camera. So, the line segment points directly into the computer screen.

If you intersect the image slice plane with this line segment, you can get the world coordinate of a point on the plane. The vtkPlane::IntersectWithLine() method can be used to do this.

This is my favorite method for computing the world coordinates of a point on a plane, if I only know the (x,y) display coordinates.