diff --git a/CMakeLists.txt b/CMakeLists.txt index 159f407..3cd340d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,8 @@ set(UI_RESOURCES # Create executable qt5_wrap_ui(UISrcs ${UI_FILES} ) # CMAKE_AUTOMOC is ON so the MOC headers will be automatically wrapped. -add_executable(Segmentor MACOSX_BUNDLE WIN32 ${CXX_FILES} ${UISrcs} ${QT_WRAP} ${UI_RESOURCES}) -#add_executable(Segmentor MACOSX_BUNDLE ${CXX_FILES} ${UISrcs} ${QT_WRAP} ${UI_RESOURCES}) +#add_executable(Segmentor MACOSX_BUNDLE WIN32 ${CXX_FILES} ${UISrcs} ${QT_WRAP} ${UI_RESOURCES}) +add_executable(Segmentor MACOSX_BUNDLE ${CXX_FILES} ${UISrcs} ${QT_WRAP} ${UI_RESOURCES}) qt5_use_modules(Segmentor Core Gui) target_link_libraries(Segmentor ${VTK_LIBRARIES}) install(TARGETS Segmentor diff --git a/qt/MainWindow.cxx b/qt/MainWindow.cxx index c5d898f..2f33714 100644 --- a/qt/MainWindow.cxx +++ b/qt/MainWindow.cxx @@ -117,20 +117,20 @@ MainWindow::MainWindow() { brushRadiusSpinBox->setToolTip("Adjust brush radius (left / right arrow)"); // Overlay opacity shortcut - QShortcut* overlayUp = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right), this); - QShortcut* overlayDown = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left), this); + QShortcut* overlayOpacityUp = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right), this); + QShortcut* overlayOpacityDown = new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left), this); - QObject::connect(overlayUp, &QShortcut::activated, this, &MainWindow::on_overlayUp); - QObject::connect(overlayDown, &QShortcut::activated, this, &MainWindow::on_overlayDown); - QObject::connect(this, &MainWindow::overlayChanged, settingsDialog, &SettingsDialog::on_overlayChanged); + QObject::connect(overlayOpacityUp, &QShortcut::activated, this, &MainWindow::on_overlayOpacityUp); + QObject::connect(overlayOpacityDown, &QShortcut::activated, this, &MainWindow::on_overlayOpacityDown); + QObject::connect(this, &MainWindow::overlayOpacityChanged, settingsDialog, &SettingsDialog::on_overlayOpacityChanged); - // Region opacity shortcut - QShortcut* opacityUp = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Right), this); - QShortcut* opacityDown = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Left), this); + // Surface opacity shortcut + QShortcut* surfaceOpacityUp = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Right), this); + QShortcut* surfaceOpacityDown = new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Left), this); - QObject::connect(opacityUp, &QShortcut::activated, this, &MainWindow::on_opacityUp); - QObject::connect(opacityDown, &QShortcut::activated, this, &MainWindow::on_opacityDown); - QObject::connect(this, &MainWindow::opacityChanged, settingsDialog, &SettingsDialog::on_opacityChanged); + QObject::connect(surfaceOpacityUp, &QShortcut::activated, this, &MainWindow::on_surfaceOpacityUp); + QObject::connect(surfaceOpacityDown, &QShortcut::activated, this, &MainWindow::on_surfaceOpacityDown); + QObject::connect(this, &MainWindow::surfaceOpacityChanged, settingsDialog, &SettingsDialog::on_surfaceOpacityChanged); // 2D/3D toggle QShortcut* toggleView = new QShortcut(QKeySequence("t"), this); @@ -861,40 +861,40 @@ void MainWindow::on_regionColor(int label, QColor color) { visualizationContainer->SetRegionColor((unsigned short)label, color.redF(), color.greenF(), color.blueF()); } -void MainWindow::on_overlayDown() { +void MainWindow::on_overlayOpacityDown() { SliceView* sliceView = visualizationContainer->GetSliceView(); double value = qMax(sliceView->GetOverlayOpacity() - 0.1, 0.0); sliceView->SetOverlayOpacity(value); - emit overlayChanged(value); + emit overlayOpacityChanged(value); } -void MainWindow::on_overlayUp() { +void MainWindow::on_overlayOpacityUp() { SliceView* sliceView = visualizationContainer->GetSliceView(); double value = qMin(sliceView->GetOverlayOpacity() + 0.1, 1.0); sliceView->SetOverlayOpacity(value); - emit overlayChanged(value); + emit overlayOpacityChanged(value); } -void MainWindow::on_opacityDown() { +void MainWindow::on_surfaceOpacityDown() { double value = qMax(visualizationContainer->GetVolumeView()->GetVisibleOpacity() - 0.1, 0.0); visualizationContainer->SetVisibleOpacity(value); - emit opacityChanged(value); + emit surfaceOpacityChanged(value); } -void MainWindow::on_opacityUp() { +void MainWindow::on_surfaceOpacityUp() { double value = qMin(visualizationContainer->GetVolumeView()->GetVisibleOpacity() + 0.1, 1.0); visualizationContainer->SetVisibleOpacity(value); - emit opacityChanged(value); + emit surfaceOpacityChanged(value); } void MainWindow::on_brushRadiusDown() { diff --git a/qt/MainWindow.h b/qt/MainWindow.h index 29b8cd1..63ae566 100644 --- a/qt/MainWindow.h +++ b/qt/MainWindow.h @@ -132,18 +132,18 @@ public slots: virtual void on_regionColor(int label, QColor color); // Shortcuts for settings - virtual void on_overlayDown(); - virtual void on_overlayUp(); - virtual void on_opacityDown(); - virtual void on_opacityUp(); + virtual void on_overlayOpacityDown(); + virtual void on_overlayOpacityUp(); + virtual void on_surfaceOpacityDown(); + virtual void on_surfaceOpacityUp(); virtual void on_brushRadiusDown(); virtual void on_brushRadiusUp(); signals: void windowLevelChanged(double window, double value); - void overlayChanged(double value); - void opacityChanged(double value); + void overlayOpacityChanged(double value); + void surfaceOpacityChanged(double value); protected: // The visualization container diff --git a/qt/SettingsDialog.cxx b/qt/SettingsDialog.cxx index b210859..1b2aee8 100644 --- a/qt/SettingsDialog.cxx +++ b/qt/SettingsDialog.cxx @@ -49,10 +49,10 @@ void SettingsDialog::initializeSettings() { levelSpinBox->setValue(sliceView->GetLevel()); // Overlay opacity - overlaySpinBox->setValue(sliceView->GetOverlayOpacity()); + overlayOpacitySpinBox->setValue(sliceView->GetOverlayOpacity()); - // Region opacity - opacitySpinBox->setValue(volumeView->GetVisibleOpacity()); + // Surface opacity + surfaceOpacitySpinBox->setValue(volumeView->GetVisibleOpacity()); } void SettingsDialog::on_windowSpinBox_valueChanged(double value) { @@ -63,28 +63,28 @@ void SettingsDialog::on_levelSpinBox_valueChanged(double value) { visualizationContainer->GetSliceView()->SetLevel(value); } -void SettingsDialog::on_overlaySpinBox_valueChanged(double value) { +void SettingsDialog::on_overlayOpacitySpinBox_valueChanged(double value) { visualizationContainer->GetSliceView()->SetOverlayOpacity(value); } -void SettingsDialog::on_overlayUp() { - overlaySpinBox->stepUp(); +void SettingsDialog::on_overlayOpacityUp() { + overlayOpacitySpinBox->stepUp(); } -void SettingsDialog::on_overlayDown() { - overlaySpinBox->stepDown(); +void SettingsDialog::on_overlayOpacityDown() { + overlayOpacitySpinBox->stepDown(); } -void SettingsDialog::on_opacitySpinBox_valueChanged(double value) { +void SettingsDialog::on_surfaceOpacitySpinBox_valueChanged(double value) { visualizationContainer->SetVisibleOpacity(value); } -void SettingsDialog::on_opacityUp() { - opacitySpinBox->stepUp(); +void SettingsDialog::on_surfaceOpacityUp() { + surfaceOpacitySpinBox->stepUp(); } -void SettingsDialog::on_opacityDown() { - opacitySpinBox->stepDown(); +void SettingsDialog::on_surfaceOpacityDown() { + surfaceOpacitySpinBox->stepDown(); } void SettingsDialog::on_voxelSizeSpinBox() { @@ -100,10 +100,18 @@ void SettingsDialog::on_windowLevelChanged(double window, double level) { levelSpinBox->setValue(level); } -void SettingsDialog::on_overlayChanged(double value) { - overlaySpinBox->setValue(value); +void SettingsDialog::on_overlayOpacityChanged(double value) { + overlayOpacitySpinBox->setValue(value); } -void SettingsDialog::on_opacityChanged(double value) { - opacitySpinBox->setValue(value); +void SettingsDialog::on_surfaceOpacityChanged(double value) { + surfaceOpacitySpinBox->setValue(value); +} + +void SettingsDialog::on_gradientOpacityCheckBox_stateChanged(int state) { + visualizationContainer->GetVolumeView()->SetVolumeRenderingGradientOpacity(state != 0); +} + +void SettingsDialog::on_autoAdjustSamplingCheckBox_stateChanged(int state) { + visualizationContainer->GetVolumeView()->SetVolumeRenderingAutoAdjustSampling(state != 0); } \ No newline at end of file diff --git a/qt/SettingsDialog.h b/qt/SettingsDialog.h index 005dec6..396fa18 100644 --- a/qt/SettingsDialog.h +++ b/qt/SettingsDialog.h @@ -23,19 +23,22 @@ public slots: virtual void on_windowSpinBox_valueChanged(double value); virtual void on_levelSpinBox_valueChanged(double value); - virtual void on_overlaySpinBox_valueChanged(double value); - virtual void on_overlayUp(); - virtual void on_overlayDown(); + virtual void on_overlayOpacitySpinBox_valueChanged(double value); + virtual void on_overlayOpacityUp(); + virtual void on_overlayOpacityDown(); - virtual void on_opacitySpinBox_valueChanged(double value); - virtual void on_opacityUp(); - virtual void on_opacityDown(); + virtual void on_surfaceOpacitySpinBox_valueChanged(double value); + virtual void on_surfaceOpacityUp(); + virtual void on_surfaceOpacityDown(); virtual void on_voxelSizeSpinBox(); virtual void on_windowLevelChanged(double window, double level); - virtual void on_overlayChanged(double value); - virtual void on_opacityChanged(double value); + virtual void on_overlayOpacityChanged(double value); + virtual void on_surfaceOpacityChanged(double value); + + virtual void on_gradientOpacityCheckBox_stateChanged(int state); + virtual void on_autoAdjustSamplingCheckBox_stateChanged(int state); protected: VisualizationContainer* visualizationContainer; diff --git a/qt/SettingsDialog.ui b/qt/SettingsDialog.ui index 535d540..3fa258e 100644 --- a/qt/SettingsDialog.ui +++ b/qt/SettingsDialog.ui @@ -7,7 +7,7 @@ 0 0 314 - 251 + 367 @@ -199,96 +199,136 @@ - - - - - - 0 - 0 - - - - Overlay opacity (Left / right arrow) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 2 - - - 0.000000000000000 - - - 1.000000000000000 - - - 0.050000000000000 - - - 0.100000000000000 - - - - + + + Region opacity + + + + + + + + + 0 + 0 + + + + Overlay (Left / right arrow) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 2 + + + 0.000000000000000 + + + 1.000000000000000 + + + 0.050000000000000 + + + 0.100000000000000 + + + + + + + + + + + + 0 + 0 + + + + Surface (Shift + left / right arrow) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1.000000000000000 + + + 0.050000000000000 + + + 1.000000000000000 + + + + + + + - - - - - - 0 - 0 - - - - Region opacity (Shift + left / right arrow) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 1.000000000000000 - - - 0.050000000000000 - - - 1.000000000000000 - - - - + + + Volume rendering + + + + + + + + Gradient opacity (\) + + + + + + + + + + + Auto adjust sampling + + + + + + + diff --git a/visualization/VolumeView.cxx b/visualization/VolumeView.cxx index bc79399..c151789 100644 --- a/visualization/VolumeView.cxx +++ b/visualization/VolumeView.cxx @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -24,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -447,11 +447,35 @@ void VolumeView::UpdateVolumeMask(bool filter) { } } +void VolumeView::SetVolumeRenderingGradientOpacity(bool gradientOpacity) { + volume->GetProperty()->SetDisableGradientOpacity(!gradientOpacity); + + Render(); +} + +bool VolumeView::GetVolumeRenderingGradientOpacity() { + return !volume->GetProperty()->GetDisableGradientOpacity(); +} + +void VolumeView::SetVolumeRenderingAutoAdjustSampling(bool autoAdjust) { + volumeMapper->SetAutoAdjustSampleDistances(autoAdjust); + volumeMapper->SetInteractiveAdjustSampleDistances(autoAdjust); +} + void VolumeView::UpdateVolumeRenderingTransferFunctions(double x1, double x2) { + vtkPiecewiseFunction* opacity = volume->GetProperty()->GetScalarOpacity(); + vtkPiecewiseFunction* gradientOpacity = volume->GetProperty()->GetStoredGradientOpacity(); + vtkColorTransferFunction* color = volume->GetProperty()->GetRGBTransferFunction(); + // Opacity - volumeOpacity->RemoveAllPoints(); - volumeOpacity->AddPoint(x1, 0.0); - volumeOpacity->AddPoint(x2, 0.5); + opacity->RemoveAllPoints(); + opacity->AddPoint(x1, 0.0); + opacity->AddPoint(x2, 0.5); + + // Gradient opacity + gradientOpacity->RemoveAllPoints(); + gradientOpacity->AddPoint(0, 0.0); + gradientOpacity->AddPoint((x2 - x1) / 2, 1.0); // Colors // Paraview diverging @@ -468,10 +492,10 @@ void VolumeView::UpdateVolumeRenderingTransferFunctions(double x1, double x2) { } } - volumeColor->RemoveAllPoints(); + color->RemoveAllPoints(); for (int i = 0; i < numColors; i++) { double x = x1 + (double)i / (numColors - 1) * (x2 - x1); - volumeColor->AddRGBPoint(x, colors[i][0], colors[i][1], colors[i][2]); + color->AddRGBPoint(x, colors[i][0], colors[i][1], colors[i][2]); } } @@ -505,23 +529,24 @@ void VolumeView::CreateVolumeRenderer() { volumeMask = vtkSmartPointer::New(); volumeMask->SetMaskInputData(volumeCopy->GetOutput()); - volumeMapper = vtkSmartPointer::New(); + volumeMapper = vtkSmartPointer::New(); volumeMapper->SetBlendModeToComposite(); volumeMapper->AutoAdjustSampleDistancesOn(); volumeMapper->SetSampleDistance(0.1); - volumeMapper->SetInteractiveSampleDistance(0.1); - volumeMapper->SetImageSampleDistance(0.5); - volumeMapper->SetMaximumImageSampleDistance(2); + volumeMapper->SetAutoAdjustSampleDistances(false); + volumeMapper->SetInteractiveAdjustSampleDistances(false); - volumeOpacity = vtkSmartPointer::New(); - - volumeColor = vtkSmartPointer::New(); + vtkSmartPointer opacity = vtkSmartPointer::New(); + vtkSmartPointer gradientOpacity = vtkSmartPointer::New(); + vtkSmartPointer color = vtkSmartPointer::New(); vtkSmartPointer volumeProperty = vtkSmartPointer::New(); volumeProperty->ShadeOff(); volumeProperty->SetInterpolationTypeToLinear(); - volumeProperty->SetScalarOpacity(volumeOpacity); - volumeProperty->SetColor(volumeColor); + volumeProperty->SetScalarOpacity(opacity); + volumeProperty->SetGradientOpacity(gradientOpacity); + volumeProperty->SetDisableGradientOpacity(true); + volumeProperty->SetColor(color); volume = vtkSmartPointer::New(); volume->SetMapper(volumeMapper); diff --git a/visualization/VolumeView.h b/visualization/VolumeView.h index c6ce198..ba119e7 100644 --- a/visualization/VolumeView.h +++ b/visualization/VolumeView.h @@ -16,14 +16,14 @@ class vtkImageData; class vtkLookupTable; class vtkImageMapToColors; class vtkImageMask; -class vtkFixedPointVolumeRayCastMapper; class vtkPiecewiseFunction; class vtkPlaneSource; class vtkObject; class vtkOutlineCornerFilter; class vtkPassThrough; class vtkRenderer; -class vtkRenderWindowInteractor; +class vtkRenderWindowInteractor; +class vtkSmartVolumeMapper; class vtkTextActor; class vtkVolume; @@ -83,9 +83,13 @@ class VolumeView { void SetBrushRadius(int radius); + // Volume rendering void SetWindowLevel(double window, double level); - void UpdateVolumeMask(bool filter); + void SetVolumeRenderingGradientOpacity(bool gradientOpacity); + bool GetVolumeRenderingGradientOpacity(); + void SetVolumeRenderingAutoAdjustSampling(bool autoAdjust); + bool GetVolumeRenderingAutoAdjustSampling(); void Render(); @@ -142,10 +146,8 @@ class VolumeView { // Volume rendering vtkSmartPointer volumeCopy; vtkSmartPointer volumeMask; - vtkSmartPointer volumeMapper; + vtkSmartPointer volumeMapper; vtkSmartPointer volume; - vtkSmartPointer volumeOpacity; - vtkSmartPointer volumeColor; void CreateVolumeRenderer(); void UpdateVolumeRenderer(); void UpdateVolumeRenderingTransferFunctions(double x1, double x2);