Display slice plane

Hi,
I want to display the slice plane selected by vtkImplicitPlaneWidget2 as a two-dimensional image while synchronizing in another window.

Can you tell me how to display while synchronizing?

The code to reslice was created as follows:

 // Extract a slice in the desired orientation
vtkSmartPointer<vtkImageReslice> reslice =
vtkSmartPointer<vtkImageReslice>::New();
reslice->SetInputConnection(reader->GetOutputPort());
reslice->SetOutputDimensionality(2);
reslice->SetResliceAxes(resliceMatrix);
reslice->SetInterpolationModeToLinear();
reslice->SetOutputOrigin(0.0, 0.0, 0.0);
reslice->SetOutputExtent(0, n-1, 0, n-1, 0, 0);
reslice->SetOutputSpacing(s, s, s);

// Create a greyscale lookup table
vtkSmartPointer<vtkLookupTable> table =
vtkSmartPointer<vtkLookupTable>::New();
table->SetRange(0, 500); // image intensity range
table->SetValueRange(0.0, 1.0); // from black to white
table->SetSaturationRange(0.0, 0.0); // no color saturation
table->SetRampToLinear();
table->Build();

// Map the image through the lookup table
vtkSmartPointer<vtkImageMapToColors> Imagecolor =
vtkSmartPointer<vtkImageMapToColors>::New();
Imagecolor->SetLookupTable(table);
Imagecolor->SetInputConnection(reslice->GetOutputPort());

// Display the image
vtkSmartPointer<vtkImageActor> actor =
vtkSmartPointer<vtkImageActor>::New();
actor->GetMapper()->SetInputConnection(Imagecolor->GetOutputPort());

vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);

vtkSmartPointer<vtkRenderWindow> window =
vtkSmartPointer<vtkRenderWindow>::New();
window->AddRenderer(renderer);

@dgobbi

Use a callback. The TestImplicitPlaneWidget2 example code will give you some ideas.

2 Likes

Thank you for your reply.
I would like to refer to TestImplicitPlaneWidget2.

Does that mean you need to make the callback in vtkImplicitPlaneWidget2 also apply to vtkImageReslice?

@dgobbi

Hi,
After manipulating in the window, I want to know the normal and center and adapt to a 4x4 matrix.
I’ve studied, but I don’t know how to update the normals and origins using callback.

Can you give me a hint if possible?

The code for the callback part is shown below.

class vtkIPWCallback : public vtkCommand
{
public:
static vtkIPWCallback *New()
{ return new vtkIPWCallback; }
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkImplicitPlaneWidget2 *planeWidget =
  reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
vtkImplicitPlaneRepresentation *rep =
  reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
rep->GetPlane(this->Plane);
//this->Actor->VisibilityOn();
}
vtkIPWCallback():Plane(0),Actor(0) {}
vtkPlane *Plane;
vtkActor *Actor;
};

@dgobbi

The callback also needs `vtkImageReslice *Reslice;" as a member.
And the Execute() method must compute the ResliceAxes matrix and call Update().
(The Actor member is not needed, it can be removed).

Of course, the callback must be connected to the widget:

myCallback->Plane = plane;
myCallback->Reslice = reslice;

planeWidget->AddObserver(vtkCommand::InteractionEvent, myCallback);

Thank you for your reply.

 The callback also needs `vtkImageReslice *Reslice;" as a member.

Does this mean creating a new call back (vtkImageReslice * Reslice) in addition to vtkIPWCallback as follow?

 class vtkIPWCallback : public vtkCommand
 {
 public:
static vtkIPWCallback *New()
{ return new vtkIPWCallback; }
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkImplicitPlaneWidget2 *planeWidget =
  reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
vtkImplicitPlaneRepresentation *rep =
  reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
rep->GetPlane(this->Plane);

}
vtkIPWCallback():Plane(0) {}
vtkPlane *Plane;
};

class vtkIRCallback : public vtkCommand
{
public:
static vtkIRCallback *New()
{ return new vtkIRCallback; }
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkImageReslice *reslice =
  reinterpret_cast<vtkImageReslice*>(caller);
}
vtkIRCallback():Reslice(0) {}
vtkImageReslice *Reslice;
};

No, only one callback (the vtkIPWCallback).

The callback should get the Plane, create the matrix, and put the matrix into vtkImageReslice.

Thank you.
I understand.

Do I need to include code to calculate a 4x4 matrix in Excute()?

Yes. Of course it would be best to write a function that computes the vtkMatrix4x4 from the vtkPlane, and to call that function from Execute.

Thank you for reply.

I created Excute () including 4x4 matrix calculation.
Can you tell me if there are improvements in the code below?

vtkImplicitPlaneWidget2 *planeWidget =
  reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
vtkImplicitPlaneRepresentation *rep =
  reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
rep->GetPlane(this->Plane);

double normal[3];
Plane->GetNormal(normal);
double Origin[3];
Plane->GetOrigin(Origin);

// Set the slice orientation
vtkSmartPointer<vtkMatrix4x4> resliceMatrix =
vtkSmartPointer<vtkMatrix4x4>::New();
 {
 (Compute of the 4x4 matrix)
 }
 vtkIPWCallback():Plane(0) {}
 vtkPlane *Plane;

 vtkImageReslice *Reslice;
 };

@dgobbi

In your example, where does Execute() start and where does it end?

The edited version is shown below.
Can you give me some advice?

virtual void Execute(vtkObject *caller, unsigned long, void*)
{
 vtkImplicitPlaneWidget2 *planeWidget =
 reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
 vtkImplicitPlaneRepresentation *rep =
 reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
 rep->GetPlane(this->Plane);

 double normal[3];
 Plane->GetNormal(normal);
 double Origin[3];
 Plane->GetOrigin(Origin);

 // Set the slice orientation
 vtkSmartPointer<vtkMatrix4x4> resliceMatrix =
 vtkSmartPointer<vtkMatrix4x4>::New();

 (Compute of the 4x4 matrix)

}
 vtkIPWCallback():Plane(0) {}
 vtkPlane *Plane;

 vtkImageReslice *Reslice;
};

Yes, that should be okay.

Does Execute() also call Reslice->SetResliceAxes(matrix)?

 Does Execute() also call Reslice->SetResliceAxes(matrix)?

Does it mean to include Reslice-> SetResliceAxes (matrix) in Execute ()?
I’m sorry, can you tell me a little more?

@dgobbi

Hi,
I want to adapt the computed 4x4 matrix to Reslice.
I am thinking about how to adapt the reslice by calling the calculated 4x4 matrix.
Therefore, the following code was added after the compute of the 4x4 matrix.
Please let me know if you have any improvements.

  virtual void Execute(vtkObject *caller, unsigned long, void*)
 {
 vtkImplicitPlaneWidget2 *planeWidget =
 reinterpret_cast<vtkImplicitPlaneWidget2*>(caller);
 vtkImplicitPlaneRepresentation *rep = reinterpret_cast<vtkImplicitPlaneRepresentation*>(planeWidget->GetRepresentation());
 rep->GetPlane(this->Plane);

 double normal[3];
 Plane->GetNormal(normal);
 double Origin[3];
 Plane->GetOrigin(Origin);

 // Set the slice orientation
 vtkSmartPointer<vtkMatrix4x4> resliceMatrix =
 vtkSmartPointer<vtkMatrix4x4>::New();

(Compute of the 4x4 matrix)

vtkImageReslice *reslice = this->Reslice;
reslice->SetResliceAxes(resliceMatrix);
reslice->Update();
}
vtkIPWCallback():Plane(0) {}
vtkPlane *Plane;
vtkImageReslice *Reslice;
};

The code for Reslice is as follows:

vtkSmartPointer<vtkImageReslice> reslice =
vtkSmartPointer<vtkImageReslice>::New();
reslice->SetInputConnection(reader->GetOutputPort());
reslice->SetOutputDimensionality(2);
reslice->SetResliceAxes(resliceMatrix);
reslice->SetInterpolationModeToLinear();
reslice->SetOutputOrigin(0.0, 0.0, 0.0);
reslice->SetOutputExtent(0, n-1, 0, n-1, 0, 0);
reslice->SetOutputSpacing(s, s, s);

myCallback->Reslice = reslice;