When displaying for the first time, we want to set the orientation of the Anatomical plane

Hello, thank you for reading my topic.

In the sample project I made, I want the screen to be displayed when DICOM is first loaded like the 3D Slicer.

  • 3D Slicer

  • My sample project

DICOM Laterality and Patient Position were handled correctly, but what am I missing?

Below is the sample code.

Blockquote
vtkSmartPointer importer = vtkSmartPointer::New();
importer->SetDataSpacing(reader->m_dPixelSpacing[0], reader->m_dPixelSpacing[1], reader->m_dPixelSpacing[2]);
importer->SetDataOrigin(0, 0, 0);
importer->SetWholeExtent(0, reader->m_DicomImageInfo.nWidth - 1, 0, reader->m_DicomImageInfo.nHeight - 1, 0, reader->m_nImgCnt - 1);
importer->SetDataExtentToWholeExtent();
importer->SetDataScalarType(reader->m_nScalarType);
importer->SetNumberOfScalarComponents(reader->m_DicomImageInfo.nSamplesPerPixel);
importer->SetImportVoidPointer(reader->GetOutputBuffer());
importer->Update();

vtkSmartPointer<vtkMatrix4x4> pm = vtkSmartPointer<vtkMatrix4x4>::New();
pm->DeepCopy(reader->pm);
pm->Invert();

reslice = vtkSmartPointer<vtkImageReslice>::New();
reslice->SetInputData(importer->GetOutput());
reslice->SetResliceAxes(pm);
reslice->SetInterpolationModeToLinear();
reslice->AutoCropOutputOn();
reslice->Update();

int imageDims[3] = { 0, };
reslice->GetOutput()->GetDimensions(imageDims);

for (int i = 0; i < 3; i++)
{
	vtkMFCWindow[i] = make_shared<vtkMFCWindowEx>(GetDlgItem(nWndResourceID[i]));

	riv[i] = vtkSmartPointer<vtkResliceImageViewer>::New();

	riv[i]->SetRenderWindow(vtkMFCWindow[i]->GetRenderWindow());
	vtkMFCWindow[i]->GetRenderWindow()->AddRenderer(riv[i]->GetRenderer());
	riv[i]->SetupInteractor(vtkMFCWindow[i]->GetInteractor());

	vtkResliceCursorLineRepresentation *rep = vtkResliceCursorLineRepresentation::SafeDownCast(riv[i]->GetResliceCursorWidget()->GetRepresentation());
	riv[i]->SetResliceCursor(riv[0]->GetResliceCursor());

	rep->GetResliceCursorActor()->GetCursorAlgorithm()->SetReslicePlaneNormal(i);

	riv[i]->SetInputData(reslice->GetOutput());

	riv[i]->SetSlice(imageDims[i] / 2);

	riv[i]->SetSliceOrientation(i);
	riv[i]->SetResliceModeToOblique();

	riv[i]->Reset();
}

vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();
picker->SetTolerance(0.005);

vtkSmartPointer<vtkProperty> ipwProp = vtkSmartPointer<vtkProperty>::New();
ipwProp->LightingOff();

vtkMFCWindow[3] = make_shared<vtkMFCWindowEx>(GetDlgItem(nWndResourceID[3]));
vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
vtkWin32OpenGLRenderWindow *renWin = vtkMFCWindow[3]->GetRenderWindow();
renWin->AddRenderer(ren);

vtkRenderWindowInteractor *iren = vtkMFCWindow[3]->GetInteractor();

for (int i = 0; i < 3; i++)
{
	planeWidget[i] = vtkSmartPointer<vtkImagePlaneWidget>::New();
	planeWidget[i]->SetInteractor(iren);
	planeWidget[i]->SetPicker(picker);
	planeWidget[i]->RestrictPlaneToVolumeOn();
	double color[3] = { 0, 0, 0 };
	//color[i] = 1 / 4.0;
	planeWidget[i]->GetPlaneProperty()->SetColor(color);

	riv[i]->GetRenderer()->SetBackground(color);

	planeWidget[i]->SetTexturePlaneProperty(ipwProp);
	planeWidget[i]->TextureInterpolateOff();
	planeWidget[i]->SetResliceInterpolateToLinear();

	planeWidget[i]->SetInputConnection(reslice->GetOutputPort());

	planeWidget[i]->SetPlaneOrientation(i);
	planeWidget[i]->SetSliceIndex(imageDims[i] / 2);
	planeWidget[i]->DisplayTextOn();
	planeWidget[i]->SetDefaultRenderer(ren);
	planeWidget[i]->On();
	planeWidget[i]->InteractionOff();
}

auto resliceCbk = vtkSmartPointer<vtkResliceCursorCallback>::New();

for (int i = 0; i < 3; i++)
{
	resliceCbk->IPW[i] = planeWidget[i];
	resliceCbk->RCW[i] = riv[i]->GetResliceCursorWidget();

	riv[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceAxesChangedEvent, resliceCbk);
	riv[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::WindowLevelEvent, resliceCbk);
	riv[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResliceThicknessChangedEvent, resliceCbk);
	riv[i]->GetResliceCursorWidget()->AddObserver(vtkResliceCursorWidget::ResetCursorEvent, resliceCbk);
	riv[i]->GetInteractorStyle()->AddObserver(vtkCommand::WindowLevelEvent, resliceCbk);

	riv[i]->AddObserver(vtkResliceImageViewer::SliceChangedEvent, resliceCbk);

//	// Make them all share the same color map.
	riv[i]->SetLookupTable(riv[0]->GetLookupTable());
	planeWidget[i]->GetColorMap()->SetLookupTable(riv[0]->GetLookupTable());
	planeWidget[i]->SetColorMap(riv[i]->GetResliceCursorWidget()->GetResliceCursorRepresentation()->GetColorMap());
}

ren->SetBackground(0, 0, 255);
ren->SetBackground(100, 100, 255);
ren->SetGradientBackground(true);

ren->GetActiveCamera()->SetViewUp(0, 0, 1);
ren->GetActiveCamera()->SetPosition(0, 1, 0);
ren->GetActiveCamera()->SetFocalPoint(0, 0, 0);
ren->GetActiveCamera()->ComputeViewPlaneNormal();

ren->ResetCamera();
ren->ResetCameraClippingRange();

delete reader;
reader = nullptr;

Blockquote

thank you.

You’ll realize that you need more features of Slicer than just setting the orientation of slice views. Instead of copying features from Slicer one by one, I would recommend to create a custom Slicer application.