Files
2026-01-05 23:14:04 +01:00

498 lines
14 KiB
C++

#include "gRen.h"
#include <vtkGPUVolumeRayCastMapper.h>
gRen::gRen(QVTKOpenGLNativeWidget *m_qvtk){
CTinfos.clear();
qvtk= m_qvtk;
nmarker=0;
markerSources.clear();
markerMappers.clear();
markerActors.clear();
return;
}
void gRen::init()
{
qDebug() << "rw=" << qvtk->renderWindow()
<< "iren=" << qvtk->interactor();
if(!qvtk || !qvtk->renderWindow()) {
qDebug() << "QVTK widget not ready yet";
return;
}
// Interactor must exist before using it
if(!qvtk->renderWindow()->GetInteractor()) {
qvtk->renderWindow()->Render(); // forces initialization in many setups
}
qDebug()<<"buildRenderPipe";
buildRenderPipe();
qDebug()<<"createRenderers";
createRenderers();
qDebug()<<"Render";
qvtk->renderWindow()->Render();
}
void gRen::onAutoSkullMaskEnd(vtkImageData* fixedVol){
cout << "Auto masking complete"<<endl;
//CTvolume=vtkSmartPointer<vtkImageData>::New();
//CTvolume->Initialize();
CTvolume->DeepCopy(fixedVol);
CTvolume->Modified();
extractVOI->Update();
ren1->Render();
qvtk->renderWindow()->Render();
return;
}
void gRen::loadVolume(vtkImageData* volCT){
CTvolume=vtkSmartPointer<vtkImageData>::New();
CTvolume->Initialize();
CTvolume->DeepCopy(volCT);
CTvolume->Modified();
CTvolume->GetExtent(CTinfos.extent);
CTvolume->GetSpacing(CTinfos.spacing);
CTvolume->GetOrigin(CTinfos.origin);
cout<< "ORIGIN REN: "<<CTinfos.origin[0]<<" "<<CTinfos.origin[1]<<" "<<CTinfos.origin[2]<<" " <<endl;
#if VTK_MAJOR_VERSION <= 5
volumeMapper->SetInput(CTvolume/*extractVOI->GetOutput()*/);
#else
volumeMapper->SetInputData(CTvolume);
#endif
ren1->AddViewProp(volume);
if(volume->GetVisibility() == 0)
volume->SetVisibility(false);
else
volume->SetVisibility(true);
extractVOI->SetInputData(CTvolume);
extractVOI->SetVOI(CTvolume->GetExtent());
extractVOI->Update();
boxCallback_NEW->setNominalGeometry(volCT->GetExtent(),volCT->GetBounds(),volCT->GetSpacing());
boxWidget_NEW->SetRotationEnabled(false);
boxWidget_NEW->SetScalingEnabled(true);
boxWidget_NEW->SetTranslationEnabled(true);
boxWidget_NEW->SetPriority(1);
boxWidget_NEW->SetInputData((vtkDataSet *) CTvolume);
boxWidget_NEW->PlaceWidget();
boxWidget_NEW->InsideOutOn();
boxWidget_NEW->GetOutlineProperty()->SetRepresentationToWireframe();
boxWidget_NEW->GetOutlineProperty()->SetAmbient(1.0);
boxWidget_NEW->GetOutlineProperty()->SetAmbientColor(1,1,1);
boxWidget_NEW->GetOutlineProperty()->SetLineWidth(3);
boxWidget_NEW->GetSelectedOutlineProperty()->SetRepresentationToWireframe();
boxWidget_NEW->GetSelectedOutlineProperty()->SetAmbient(1.0);
boxWidget_NEW->GetSelectedOutlineProperty()->SetAmbientColor(1,0,0);
boxWidget_NEW->GetSelectedOutlineProperty()->SetLineWidth(3);
outline-> SetInputConnection(extractVOI->GetOutputPort());
planeWidgetX->SetInputConnection(extractVOI->GetOutputPort());
planeWidgetY->SetInputConnection(extractVOI->GetOutputPort());
planeWidgetZ->SetInputConnection(extractVOI->GetOutputPort());
if(outlineActor->GetVisibility() == 0){
}
else{
planeWidgetX->On();
planeWidgetY->On();
planeWidgetZ->On();
}
orthoPlanes->SetPlane(0, planeWidgetX);
orthoPlanes->SetPlane(1, planeWidgetY);
orthoPlanes->SetPlane(2, planeWidgetZ);
orthoPlanes->ResetPlanes();
vtkCamera * cam = ren1->GetActiveCamera();
cam->SetPosition(0, 0, -1);
cam->SetFocalPoint(0, 0, 0);
cam->SetViewUp(0, -1, 0);
ren1->ResetCamera();
ren1->Render();
qvtk->renderWindow()->Render();
emit PatientLoaded();
return;
}
void gRen::createRenderers(){
ren1 = vtkSmartPointer<vtkRenderer>::New();
ren1->SetBackground(0.13, 0.25, 0.32);
qvtk->renderWindow()->AddRenderer(ren1);
ren1->AddActor(assi);
ren1->AddActor( outlineActor);
boxWidget_NEW = vtkSmartPointer<vtkBoxWidget>::New();
boxWidget_NEW->SetInteractor(qvtk->interactor());
boxWidget_NEW->SetPlaceFactor(1.0);
// - - - - - - - - - - - - - - - - - - - - -
boxCallback_NEW->rcm=volumeMapper.GetPointer();
boxWidget_NEW->AddObserver(vtkCommand::InteractionEvent, boxCallback_NEW);
return;
}
void gRen::buildRenderPipe(){
qDebug()<<"buildRenderPipe: outline";
outline = vtkSmartPointer<vtkOutlineFilter>::New();
qDebug()<<"buildRenderPipe: outlineMapper";
vtkNew<vtkPolyDataMapper> outlineMapper;
outlineMapper->SetInputConnection(outline->GetOutputPort());
outlineActor = vtkSmartPointer <vtkActor> ::New();
outlineActor->SetMapper(outlineMapper);
qDebug()<<"buildRenderPipe: picker";
vtkNew<vtkCellPicker> picker;
picker->SetTolerance(0.005);
vtkNew<vtkProperty> ipwProp;
//// //assign default props to the ipw's texture plane actor
qDebug()<<"buildRenderPipe: planeX";
planeWidgetX = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidgetX->SetInteractor( qvtk->interactor());
planeWidgetX->SetKeyPressActivationValue('x');
planeWidgetX->SetPicker(picker);
planeWidgetX->RestrictPlaneToVolumeOn();
planeWidgetX->GetPlaneProperty()->SetColor(1,0,0);
planeWidgetX->SetTexturePlaneProperty(ipwProp);
planeWidgetX->TextureInterpolateOff();
planeWidgetX->SetResliceInterpolateToNearestNeighbour();
planeWidgetX->SetPlaneOrientationToXAxes();
planeWidgetX->DisplayTextOn();
planeWidgetX->InteractionOff();
planeWidgetX->InteractionOn();
qDebug()<<"buildRenderPipe: planeY";
planeWidgetY = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidgetY->SetInteractor( qvtk->interactor());
planeWidgetY->SetKeyPressActivationValue('y');
planeWidgetY->SetPicker(picker);
planeWidgetY->GetPlaneProperty()->SetColor(1,1,0);
planeWidgetY->SetTexturePlaneProperty(ipwProp);
planeWidgetY->TextureInterpolateOn();
planeWidgetY->SetResliceInterpolateToLinear();
planeWidgetY->SetPlaneOrientationToYAxes();
planeWidgetY->SetLookupTable( planeWidgetX->GetLookupTable());
planeWidgetY->DisplayTextOn();
planeWidgetY->UpdatePlacement();
qDebug()<<"buildRenderPipe: planeZ";
planeWidgetZ = vtkSmartPointer<vtkImagePlaneWidget>::New();
planeWidgetZ->SetInteractor( qvtk->interactor());
planeWidgetZ->SetKeyPressActivationValue('z');
planeWidgetZ->SetPicker(picker);
planeWidgetZ->GetPlaneProperty()->SetColor(0,0,1);
planeWidgetZ->SetTexturePlaneProperty(ipwProp);
planeWidgetZ->TextureInterpolateOn();
planeWidgetZ->SetResliceInterpolateToCubic();
planeWidgetZ->SetPlaneOrientationToZAxes();
planeWidgetZ->SetLookupTable( planeWidgetX->GetLookupTable());
planeWidgetZ->DisplayTextOn();
qDebug()<<"buildRenderPipe: assi";
assi = vtkSmartPointer<vtkAxesActor>::New();
assi->SetOrigin(0,0,0);
assi->AxisLabelsOff();
assi->SetTotalLength(15,15,15);
qDebug()<<"buildRenderPipe: volMapper";
// Create mapper (as vtkVolumeMapper smart pointer)
auto gpuMapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
gpuMapper->SetBlendModeToComposite();
if (!gpuMapper)
{
qDebug() << "ERROR: GPU volume mapper creation returned null";
return;
}
// store into the member (base type)
this->volumeMapper = gpuMapper;
qDebug()<<"buildRenderPipe: volProps";
volumeProperty = vtkSmartPointer<vtkVolumeProperty>::New();
volumeProperty->ShadeOff();
volumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION);
qDebug()<<"buildRenderPipe: opacity";
compositeOpacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
compositeOpacity->AddPoint(-3024, 0, 0.5, 0.0 );
compositeOpacity->AddPoint(-16, 0, .49, .61 );
compositeOpacity->AddPoint(-10, .1, .49, .4 );
compositeOpacity->AddPoint(500, .4, .49, .4 );
compositeOpacity->AddPoint(641, .72, .5, 0.0 );
compositeOpacity->AddPoint(1700, .8, .5, 0.0 );
compositeOpacity->AddPoint(2500, .8, .5, 0.0 );
compositeOpacity->AddPoint(3071, .71, 0.5, 0.0);
volumeProperty->SetScalarOpacity(compositeOpacity); // composite first.
qDebug()<<"buildRenderPipe: color";
color = vtkSmartPointer<vtkColorTransferFunction>::New();
color->AddRGBPoint( -3024, 0, 0, 0, 0.5, 0.0 );
color->AddRGBPoint( -16, 0.73, 0.25, 0.30, 0.49, .61 );
color->AddRGBPoint( -10, .3, .3, .3, .5, 0.0 );
color->AddRGBPoint( 500, .7, .7, .7, .5, 0.0 );
color->AddRGBPoint( 641, .90, .82, .56, .5, 0.0 );
color->AddRGBPoint( 1700, 1, 0,0, .5, 1 );
color->AddRGBPoint( 2500, 1, 0,0, .5,.1 );
color->AddRGBPoint( 3071, 1, 1, 1, .5, 0.0 );
volumeProperty->SetColor(color);
volumeProperty->ShadeOn();
volumeProperty->SetAmbient(0.1);
volumeProperty->SetDiffuse(0.9);
volumeProperty->SetSpecular(0.2);
volumeProperty->SetSpecularPower(10.0);
volumeProperty->SetScalarOpacityUnitDistance(0.8919);
qDebug()<<"buildRenderPipe: volume";
volume = vtkSmartPointer<vtkVolume>::New();
volume->SetMapper(volumeMapper);
volume->SetProperty(volumeProperty);
volume->SetVisibility(false);
// outlineActor->SetVisibility(true);
// planeWidgetX->EnabledOn();
// planeWidgetY->EnabledOn();
// planeWidgetZ->EnabledOn();
// planeWidgetX->On();
// planeWidgetY->On();
// planeWidgetZ->On();
qDebug()<<"buildRenderPipe: extractVOI";
extractVOI = vtkSmartPointer<vtkExtractVOI>::New();
qDebug()<<"buildRenderPipe: callback";
boxCallback_NEW = vtkSmartPointer<vtkMyCallback>::New();
boxCallback_NEW->setExtractVoiFilter(extractVOI);
qDebug()<<"buildRenderPipe: orthoplanes";
orthoPlanes = vtkSmartPointer<vtkImageOrthoPlanes>::New();
return;
}
void gRen::onSingleMarkerChange(int idx, bool state){
cout<< "onSingleMarkerChange : "<<idx<<" "<<(state == true? "true":"false")<<endl;
if (idx < 0 || idx >= static_cast<int>(markerActors.size()))
return;
auto &act = markerActors.at(static_cast<size_t>(idx));
if (!act)
return;
if(state)
act->GetProperty()->SetColor(0,1,0);
else
act->GetProperty()->SetColor(1,1,1);
qvtk->renderWindow()->Render();
return;
}
void gRen::setMarkers(MarkerList marker_list){
cout << "renderMarkers" << endl;
// Remove previous marker actors/labels
for (auto &a : markerActors)
{
if (a)
ren1->RemoveActor(a);
}
markerActors.clear();
markerMappers.clear();
markerSources.clear();
if (pointLabels)
{
ren1->RemoveActor(pointLabels);
pointLabels = nullptr;
}
nmarker = marker_list.size();
markerSources.reserve(static_cast<size_t>(nmarker));
markerMappers.reserve(static_cast<size_t>(nmarker));
markerActors.reserve(static_cast<size_t>(nmarker));
modelPoints = vtkSmartPointer<vtkPoints>::New();
modelPoints->Reset();
modelPoints->SetNumberOfPoints(nmarker);
stringData = vtkSmartPointer<vtkStringArray>::New();
stringData->Reset();
stringData->SetName("Labels");
for(int i=0;i<nmarker;i++){
stringData->InsertNextValue(QString::number(i).toLatin1().constData());
modelPoints->InsertPoint(i,marker_list[i].centroid.x*1000,marker_list[i].centroid.y*1000,marker_list[i].centroid.z*1000);
auto src = vtkSmartPointer<vtkSphereSource>::New();
src->SetCenter(marker_list[i].centroid.x*1000,marker_list[i].centroid.y*1000,marker_list[i].centroid.z*1000);
src->SetRadius(10);
auto map = vtkSmartPointer<vtkPolyDataMapper>::New();
map->SetInputConnection(src->GetOutputPort());
auto act = vtkSmartPointer<vtkActor>::New();
act->SetMapper(map);
act->GetProperty()->SetRepresentationToWireframe();
act->GetProperty()->SetColor(0,1,0);
ren1->AddActor(act);
markerSources.push_back(src);
markerMappers.push_back(map);
markerActors.push_back(act);
}
cout << "modelPoints" << endl;
modelPoints->Modified();
cells = vtkSmartPointer<vtkCellArray>::New();
cells->Reset();
cells->InsertNextCell(nmarker);
for(int i = 0; i < nmarker; i++)
cells->InsertCellPoint(i);
polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->Reset();
polyData->SetPoints(modelPoints);
polyData->SetVerts(cells);
polyData->GetPointData()->AddArray(stringData);
polyData->GetFieldData()->AddArray(stringData);
ldm = vtkSmartPointer<vtkLabeledDataMapper>::New();
ldm->SetInputData(polyData);
ldm->SetLabelModeToLabelFieldData();
ldm->SetFieldDataName("Labels");
ldm->GetLabelTextProperty()->SetShadow(false);
ldm->GetLabelTextProperty()->SetFontSize(22);
cout << "plab" << endl;
pointLabels = vtkSmartPointer<vtkActor2D>::New();
pointLabels->SetMapper( ldm );
ren1->AddActor(pointLabels);
qvtk->renderWindow()->Render();
return;
}
void gRen::onReferenceChange(double dx, double dy, double dz){
if (markerSources.empty())
return;
for(int i=0;i<nmarker;i++){
auto &src = markerSources.at(static_cast<size_t>(i));
const double* c = src->GetCenter();
src->SetCenter(c[0]-dx, c[1]-dy, c[2]-dz);
src->Update();
const double* p = modelPoints->GetPoint(i);
modelPoints->SetPoint(i, p[0]-dx, p[1]-dy, p[2]-dz);
}
modelPoints->Modified();
qvtk->renderWindow()->Render();
return;
}
void gRen::onRequestRenderChange(int idx){
switch (idx){
case 0:
volume->SetVisibility(true);
outlineActor->SetVisibility(false);
planeWidgetX->EnabledOff();
planeWidgetY->EnabledOff();
planeWidgetZ->EnabledOff();
//volumeMapper->SetRequestedRenderMode(2);
qvtk->renderWindow()->Render();
// Software mode, for coverage. It also makes sure we will get the same
// regression image on all platforms.
//volumeMapper->SetRequestedRenderModeToRayCast();
qvtk->renderWindow()->Render();
ren1->Render();
break;
case 1:
volume->SetVisibility(false);
outlineActor->SetVisibility(true);
planeWidgetX->EnabledOn();
planeWidgetY->EnabledOn();
planeWidgetZ->EnabledOn();
ren1->Render();
break;
default:
break;
}
return;
}
void gRen::onRequestManualMask(int idx){
switch (idx){
case 0:
boxWidget_NEW->On();
qvtk->renderWindow()->Render();
break;
case 1:
boxWidget_NEW->Off();
qvtk->renderWindow()->Render();
break;
default:
break;
}
return;
}