#include "widget3d.h"
#include "tabwidget.h"
#include
#include
#include
#include
asclepios::gui::Widget3D::Widget3D(QWidget* parent)
: WidgetBase(parent)
{
initData();
initView();
createConnections();
m_tabWidget = parent;
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::render()
{
if (!m_image)
{
throw std::runtime_error("No image for widget 3d!");
}
try
{
m_toolbar->getUI().toolButtonCrop->setVisible(false);
m_toolbar->getUI().comboBoxFilters->setVisible(false);
startLoadingAnimation();
m_vtkWidget->setImage(m_image);
m_vtkWidget->setSeries(m_series);
m_vtkWidget->setInteractor(m_qtvtkWidget->GetInteractor());
m_future = QtConcurrent::run(onRenderAsync, this);
Q_UNUSED(connect(this, &Widget3D::finishedRenderAsync,
this, &Widget3D::onFinishedRenderAsync));
}
catch (const std::exception& ex)
{
//todo log
}
}
//-----------------------------------------------------------------------------
bool asclepios::gui::Widget3D::eventFilter(QObject* watched, QEvent* event)
{
if (event->type() == QEvent::KeyPress)
{
auto* const keyEvent = dynamic_cast
const int key = keyEvent->key();
auto* const combo = m_toolbar->getUI().comboBoxFilters;
switch (key)
{
case Qt::Key_Left:
{
const int currentIndex = combo->currentIndex();
combo->setCurrentIndex(!combo->currentIndex()
? combo->count() - 1
: currentIndex - 1);
break;
}
case Qt::Key_Right:
{
const int currentIndex = combo->currentIndex();
combo->setCurrentIndex(currentIndex == combo->count() - 1
? 0
: currentIndex + 1);
break;
}
default:
break;
}
}
return QWidget::eventFilter(watched, event);
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::onfilterChanged(const QString& t_filter) const
{
if (m_qtvtkWidget && m_vtkWidget)
{
m_vtkWidget->setFilter(t_filter);
m_qtvtkWidget->GetRenderWindow()->Render();
}
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::onCropPressed(const bool& t_pressed) const
{
m_vtkWidget->activateBoxWidget(t_pressed);
m_qtvtkWidget->GetRenderWindow()->Render();
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::onActivateWidget(const bool& t_flag)
{
if (t_flag)
{
auto* event = new QFocusEvent(QEvent::FocusIn,
Qt::FocusReason::MouseFocusReason);
focusInEvent(event);
delete event;
}
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::onSetMaximized() const
{
if (m_tabWidget)
{
dynamic_cast
(m_tabWidget)->onMaximize();
}
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::onFinishedRenderAsync()
{
auto* const renderWindow =
m_qtvtkWidget->GetRenderWindow();
renderWindow->AddRenderer(m_vtkWidget->
getRenderWindows()[0]->GetRenderers()->
GetFirstRenderer());
renderWindow->Render();
onfilterChanged(m_toolbar->getUI()
.comboBoxFilters->itemData(0).toString());
stopLoadingAnimation();
disconnect(this, &Widget3D::finishedRenderAsync,
this, &Widget3D::onFinishedRenderAsync);
m_toolbar->getUI().toolButtonCrop->setVisible(true);
m_toolbar->getUI().comboBoxFilters->setVisible(true);
installEventFilter(this);
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::onRenderAsync(Widget3D* t_self)
{
t_self->m_vtkWidget->render();
emit t_self->finishedRenderAsync();
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::initView()
{
m_ui.setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
auto* const layout = new QVBoxLayout(this);
layout->setSpacing(0);
layout->setMargin(0);
layout->addWidget(m_toolbar);
layout->addWidget(m_qtvtkWidget);
setLayout(layout);
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::initData()
{
m_qtvtkWidget = new QVTKOpenGLNativeWidget(this);
m_qtvtkWidget->SetRenderWindow(vtkNew
m_qtvtkWidget->GetRenderWindow()->SetDoubleBuffer(true);
m_vtkWidget = std::make_unique
m_toolbar = new ToolbarWidget3D(this);
m_vtkEvents = std::make_unique
setWidgetType(WidgetType::widget3d);
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::createConnections()
{
if (m_toolbar)
{
Q_UNUSED(connect(m_toolbar,
&ToolbarWidget3D::filterChanged, this,
&Widget3D::onfilterChanged));
Q_UNUSED(connect(m_toolbar, &ToolbarWidget3D::cropPressed,
this, &Widget3D::onCropPressed));
}
setFocusPolicy(Qt::FocusPolicy::WheelFocus);
m_qtvtkWidget->installEventFilter(m_vtkEvents.get());
Q_UNUSED(connect(m_vtkEvents.get(),
&vtkEventFilter::activateWidget,
this, &Widget3D::onActivateWidget));
Q_UNUSED(connect(m_vtkEvents.get(),
&vtkEventFilter::setMaximized,
this, &Widget3D::onSetMaximized));
}
//-----------------------------------------------------------------------------
void asclepios::gui::Widget3D::startLoadingAnimation()
{
m_loadingAnimation = std::make_unique
m_loadingAnimation->setWindowFlags(Qt::Widget);
layout()->addWidget(m_loadingAnimation.get());
m_loadingAnimation->show();
}
#include "vtkwidget3d.h"
#include
#include
#include
#include
#include
#include
#include
void asclepios::gui::vtkWidget3D::initWidget()
{
m_renderWindows[0] = vtkSmartPointer
m_mapper = vtkSmartPointer
m_renderer = vtkSmartPointer
m_volume = vtkSmartPointer
m_transferFunction = std::make_unique
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::initBoxWidget()
{
if (!m_renderer || !m_volume)
{
return;
}
m_boxWidget = vtkSmartPointer
m_boxWidget->SetInteractor(m_renderer->GetRenderWindow()->GetInteractor());
m_boxWidget->CreateDefaultRepresentation();
m_boxWidget->GetRepresentation()->SetPlaceFactor(1);
m_boxWidget->GetRepresentation()->PlaceWidget(m_volume->GetBounds());
initBoxWidgetCallback();
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::initBoxWidgetCallback()
{
m_boxWidgetCallback = vtkSmartPointer
m_boxWidgetCallback->setVolume(m_volume);
m_boxWidget->AddObserver(vtkCommand::InteractionEvent, m_boxWidgetCallback);
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::initInteractorStyle()
{
m_interactorStyle =
vtkSmartPointer
m_interactorStyle->setWidget(this);
m_interactorStyle->setTransferFunction(m_transferFunction.get());
m_interactor->SetInteractorStyle(m_interactorStyle);
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::setVolumeMapperBlend() const
{
m_mapper->SetBlendMode(vtkVolumeMapper::COMPOSITE_BLEND);
}
//-----------------------------------------------------------------------------
std::tuple
{
const auto imageReader =
m_image->getImageReader();
return std::make_tuple
GetMetaData()->Get(DC::WindowCenter).AsInt(),
imageReader->GetMetaData()->Get(DC::WindowWidth).AsInt());
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::setFilter(const QString& t_filePath)
{
try
{
if (t_filePath == "MIP")
{
m_transferFunction.reset();
m_transferFunction = std::make_unique
m_mapper->SetBlendMode(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND);
m_transferFunction->setMaximumIntensityProjectionFunction(0, 0);
const auto [window, level] = getWindowLevel();
m_transferFunction->updateWindowLevel(window, level);
}
else
{
m_mapper->SetBlendMode(vtkVolumeMapper::COMPOSITE_BLEND);
m_transferFunction->loadFilterFromFile(t_filePath);
}
updateFilter();
m_interactorStyle->setTransferFunction(m_transferFunction.get());
}
catch (const std::exception& ex)
{
//todo log
}
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::render()
{
m_renderWindows[0]->OffScreenRenderingOn();
setVolumeMapperBlend();
const auto [window, level] = getWindowLevel();
const auto reader = m_image && m_image->getIsMultiFrame()
? m_image->getImageReader()
: m_series->getReaderForAllSingleFrameImages();
m_mapper->SetInputConnection(reader->GetOutputPort());
m_transferFunction->updateWindowLevel(window, level);
m_volume->SetMapper(m_mapper);
m_renderer->AddActor(m_volume);
m_renderWindows[0]->AddRenderer(m_renderer);
m_renderWindows[0]->Render();
m_renderWindows[0]->OffScreenRenderingOff();
auto* const extend = m_volume->GetBounds();
m_volume->SetOrigin(extend[0] + (extend[1] - extend[0]) / 2,
extend[2] + (extend[3] - extend[2]) / 2, 0);
initInteractorStyle();
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::activateBoxWidget(const bool& t_flag)
{
if (!m_boxWidget)
{
initBoxWidget();
}
m_boxWidget->SetEnabled(t_flag);
}
//-----------------------------------------------------------------------------
void asclepios::gui::vtkWidget3D::updateFilter() const
{
m_volume->GetProperty()->SetInterpolationTypeToLinear();
m_volume->GetProperty()->SetScalarOpacity(m_transferFunction->getOpacityFunction());
m_volume->GetProperty()->SetAmbient(m_transferFunction->getAmbient());
m_volume->GetProperty()->SetColor(m_transferFunction->getColorFunction());
m_volume->GetProperty()->SetDiffuse(m_transferFunction->getDiffuse());
m_volume->GetProperty()->SetSpecular(m_transferFunction->getSpecular());
m_volume->GetProperty()->SetSpecularPower(m_transferFunction->getSpecularPower());
m_volume->GetProperty()->GetIsoSurfaceValues()->SetValue(0, 0);
(m_transferFunction->getHasShade()) ? m_volume->GetProperty()->ShadeOn() : m_volume->GetProperty()->ShadeOff();
}
{
"name":"Dark Bone",
"color": [
{
"value": 46.733612060546875,
"red": 0.0,
"green": 0.0,
"blue": 0.0
},
{
"value": 134.97621154785156,
"red": 1,
"green": 1,
"blue": 1
},
{
"value": 244.72689819335938,
"red": 0.20000000298023224,
"green": 0.20000000298023224,
"blue": 0.20000000298023224
},
{
"value": -812.04962158203125,
"red": 0.0,
"green": 1,
"blue": 1
},
{
"value": -622.0498046875,
"red": 0.0,
"green": 1,
"blue": 1
},
{
"value": -420.04998779296875,
"red": 0.0,
"green": 1,
"blue": 1
},
{
"value": -262.84738159179688,
"red": 0,
"green": 1,
"blue": 1
}
],
"opacity": [
{
"value": 46.733612060546875,
"alpha": 0.0
},
{
"value": 134.97621154785156,
"alpha": 0.25999999046325684
},
{
"value": 244.72689819335938,
"alpha": 0.5300024151802063
},
{
"value": -812.04962158203125,
"alpha": 0.0
},
{
"value": -622.0498046875,
"alpha": 0.1643165796995163
},
{
"value": -420.04998779296875,
"alpha": 0.36469146609306335
},
{
"value": -262.84738159179688,
"alpha": 0.0
}
],
"ambient":
{
"value": 0.4
},
"diffuse":
{
"value": 0.7
},
"specular":
{
"value": 1.0
},
"specularpower":
{
"value": 64
},
"shade":
{
"value": 1
}
}