a) {
if (a) {
rendererWidget->addProp(a);
actorMap.insert(comp, a);
}
}
// ---------------------- getMenu ----------------------------
QMenu* InteractiveViewer::getMenu() {
if (frame && !viewerMenu) {
//-- create the main menu
viewerMenu = new QMenu(objectName());
viewerMenu->setTearOffEnabled(true);
//-- add actions to the menu
QMenu* options = new QMenu("View Options");
options->addAction(backgroundColorAction);
options->addAction(toggleCopyrightAction);
options->addAction(toggleAxesAction);
if (myType == SLICE_VIEWER) {
options->addAction(toggleOrientationDecorationsAction);
options->addAction(toggleScreenshotAction);
}
// AxesView mode
QMenu* cameraOrientationMenu = new QMenu("Camera Orientation");
options->addMenu(cameraOrientationMenu);
cameraOrientationMenu->addAction(cameraOrientationRightDownAction);
cameraOrientationMenu->addAction(cameraOrientationLeftUpAction);
cameraOrientationMenu->addAction(cameraOrientationRightUpAction);
if (myType == GEOMETRY_VIEWER) {
options->addSeparator();
//options->addAction(toggleAxesAction);
options->addAction(toggleLabelAction);
options->addAction(toggleLinesAsTubesAction);
options->addAction(toggleBackfaceCullingAction);
// display mode
QMenu* highlightMenu = new QMenu("Highlight Mode");
options->addMenu(highlightMenu);
highlightMenu->addAction(highlightOffAction);
highlightMenu->addAction(highlightSelectionAction);
highlightMenu->addAction(highlightSelectionOnlyAction);
// camera menu
QMenu* controlModeMenu = new QMenu("Camera Control");
controlModeMenu->addAction(controlModeTrackballAction);
controlModeMenu->addAction(controlModeJoystickAction);
options->addMenu(controlModeMenu);
// force toolbar creation and add it
options->addSeparator();
options->addAction(getToolBar()->toggleViewAction());
}
viewerMenu->addMenu(options);
if (myType == GEOMETRY_VIEWER) {
viewerMenu->addSeparator();
// picking menu
QMenu* pickingMenu = new QMenu("&Picking");
pickingMenu->addAction(pickPointAction);
pickingMenu->addAction(pickCellAction);
viewerMenu->addMenu(pickingMenu);
viewerMenu->addMenu(renderingMenu);
}
viewerMenu->addAction(screenshotAction);
//-- update actions
updateActions();
}
return viewerMenu;
}
// ---------------------- getToolBar ----------------------------
QToolBar* InteractiveViewer::getToolBar() {
if (frame && !viewerToolbar) {
if (myType == GEOMETRY_VIEWER) {
viewerToolbar = new QToolBar(objectName() + " Toolbar");
// ensure object name is set for saving the state
viewerToolbar->setObjectName(objectName() + " Toolbar");
viewerToolbar->addAction(pickPointAction);
viewerToolbar->addAction(pickCellAction);
viewerToolbar->addAction(pickPointRegionAction);
viewerToolbar->addAction(pickCellRegionAction);
viewerToolbar->addSeparator();
viewerToolbar->addAction(surfaceAction);
viewerToolbar->addAction(wireframeAction);
viewerToolbar->addAction(pointsAction);
if (colorAction) {
viewerToolbar->addAction(colorAction);
}
viewerToolbar->addAction(glyphAction);
viewerToolbar->addAction(toggleLabelAction);
viewerToolbar->addSeparator();
viewerToolbar->addAction(toggleAxesAction);
viewerToolbar->addAction(screenshotAction);
viewerToolbar->addSeparator();
viewerToolbar->addAction(scalarDataColorAction);
}
/* if (myType == SLICE_VIEWER) {
viewerToolBar->addAction(toggleOrientationDecorationsAction);
}
*/
}
return viewerToolbar;
}
// ---------------------- initActions ----------------------------
void InteractiveViewer::initActions() {
//-- screenshot
screenshotAction = new QAction(QPixmap(":/snapShot"), tr("Screenshot"), this);
screenshotAction->setStatusTip(tr("Take a screenshot/snapshot of the renderer window"));
screenshotAction->setWhatsThis(tr("Screenshot\n\nTake a screenshot/snapshot of the renderer viewer"));
connect(screenshotAction, SIGNAL(triggered()), this, SLOT(screenshot()));
if (myType == GEOMETRY_VIEWER) {
//--- actions of the View menu
surfaceAction = new QAction(QPixmap(":/surfaceRendering"), tr("&Surface"), this);
surfaceAction->setCheckable(true);
surfaceAction->setStatusTip(tr("Enables/disables surface rendering"));
surfaceAction->setWhatsThis(tr("Enables/disables surface rendering"));
connect(surfaceAction, SIGNAL(triggered()), this, SLOT(renderingActorsChanged()));
wireframeAction = new QAction(QPixmap(":/wireframeRendering"), tr("&Wireframe"), this);
wireframeAction->setCheckable(true);
wireframeAction->setStatusTip(tr("Enables/disables wireframe rendering"));
wireframeAction->setWhatsThis(tr("Enables/disables wireframe rendering"));
connect(wireframeAction, SIGNAL(triggered()), this, SLOT(renderingActorsChanged()));
pointsAction = new QAction(QPixmap(":/pointRendering"), tr("&Points"), this);
pointsAction->setCheckable(true);
pointsAction->setStatusTip(tr("Enables/disables points rendering"));
pointsAction->setWhatsThis(tr("Enables/disables points rendering"));
connect(pointsAction, SIGNAL(triggered()), this, SLOT(renderingActorsChanged()));
toggleLabelAction = new QAction(QPixmap(":/label"), tr("Show &Label"), this);
toggleLabelAction->setCheckable(true);
toggleLabelAction->setStatusTip(tr("Show/hide label"));
toggleLabelAction->setWhatsThis(tr("Show/hide label"));
connect(toggleLabelAction, SIGNAL(toggled(bool)), this, SLOT(setLabel(bool)));
// check if the action is available
Action* changeColorAction = Application::getAction("Change Color");
// the InteractiveViewer colorAction is just the same as the action's QAction
if (changeColorAction) {
colorAction = changeColorAction->getQAction();
}
else {
colorAction = nullptr;
}
// -- show scalar data
// scalar data model, filter that will only select the scalars for the point and cell data
scalarDataModel = new MeshDataFilterModel(MeshComponent::POINTS | MeshComponent::CELLS, MeshComponent::SCALARS, this);
// combo box for viewing the scalar data model
scalarDataComboBox = new QComboBox(viewerToolbar);
scalarDataComboBox->setModel(scalarDataModel);
scalarDataComboBox->setMinimumWidth(150);
scalarDataColorAction = new QWidgetAction(this);
scalarDataColorAction->setDefaultWidget(scalarDataComboBox);
// TODO connect the combobox to the model (so that you can use the checkbox in the combo directly without going to the property tab)
glyphAction = new QAction(QPixmap(":/showGlyph"), tr("Show/Hide &Glyph"), this);
glyphAction->setCheckable(true);
glyphAction->setStatusTip(tr("Show/hide point glyph"));
glyphAction->setWhatsThis(tr("Show/hide point glyph"));
connect(glyphAction, SIGNAL(toggled(bool)), this, SLOT(setGlyph(bool)));
// rendering mode
renderingMenu = new QMenu("Rendering Mode");
renderingMenu->addAction(surfaceAction);
renderingMenu->addAction(wireframeAction);
renderingMenu->addAction(pointsAction);
// -- display mode
auto* displayGrp = new QActionGroup(this);
connect(displayGrp, SIGNAL(triggered(QAction*)), this, SLOT(highlightModeChanged(QAction*)));
highlightSelectionAction = new QAction(tr("&Selection"), displayGrp);
highlightSelectionAction->setCheckable(true);
highlightSelectionAction->setChecked(true); // by default the selected Item and the others are normal
highlightSelectionAction->setStatusTip(tr("display the selected component(s) normally while the others are shaded"));
highlightSelectionAction->setWhatsThis(tr("display the selected component(s) using their default rendering properties while the others are shaded (i.e., with transparency)"));
highlightSelectionOnlyAction = new QAction(tr("Selection &Only"), displayGrp);
highlightSelectionOnlyAction->setCheckable(true);
highlightSelectionOnlyAction->setStatusTip(tr("display the selected component(s) normally while the others are hidden"));
highlightSelectionOnlyAction->setWhatsThis(tr("display the selected component(s) using their default rendering properties while the others are masked (i.e., not displayed)"));
highlightOffAction = new QAction(tr("&No Highlight"), displayGrp);
highlightOffAction->setCheckable(true);
highlightOffAction->setStatusTip(tr("display all component(s) the same way"));
highlightOffAction->setWhatsThis(tr("display all component(s) using their default rendering properties, either they are selected or not"));
//-- camera mode
auto* cameraModeGrp = new QActionGroup(this);
connect(cameraModeGrp, SIGNAL(triggered(QAction*)), this, SLOT(viewControlModeChanged(QAction*)));
controlModeTrackballAction = new QAction(tr("&Trackball"), cameraModeGrp);
controlModeTrackballAction->setCheckable(true);
controlModeTrackballAction->setChecked(true);
controlModeTrackballAction->setStatusTip(tr("Set the camera control mode to trackball\n(the camera moves with the mouse)"));
controlModeTrackballAction->setWhatsThis(tr("Set the camera control mode to trackball\n(the camera moves with the mouse)"));
controlModeJoystickAction = new QAction(tr("&Joystick"), cameraModeGrp);
controlModeJoystickAction->setCheckable(true);
controlModeJoystickAction->setStatusTip(tr("Set the camera control mode to joystick\n(the camera moves when the mouse button is pressed)"));
controlModeJoystickAction->setWhatsThis(tr("Set the camera control mode to joystick\n(the camera moves when the mouse button is pressed)"));
}
//-- camera orientation mode
auto* cameraOrientationGrp = new QActionGroup(this);
connect(cameraOrientationGrp, SIGNAL(triggered(QAction*)), this, SLOT(cameraOrientationChanged(QAction*)));
cameraOrientationRightDownAction = new QAction(tr("x-right y-down z-back"), cameraOrientationGrp);
cameraOrientationRightDownAction->setCheckable(true);
cameraOrientationRightDownAction->setChecked(rendererWidget->getCameraOrientation() == RendererWidget::RIGHT_DOWN);
cameraOrientationRightDownAction->setStatusTip(tr("Set the camera such as x points to the right, y points downward, z points backward"));
cameraOrientationRightDownAction->setWhatsThis(tr("Set the camera such as x points to the right, y points downward, z points backward"));
cameraOrientationLeftUpAction = new QAction(tr("x-left y-up z-back"), cameraOrientationGrp);
cameraOrientationLeftUpAction->setCheckable(true);
cameraOrientationLeftUpAction->setChecked(rendererWidget->getCameraOrientation() == RendererWidget::LEFT_UP);
cameraOrientationLeftUpAction->setStatusTip(tr("Set the camera such as x points to the left, y points upward, z points backward"));
cameraOrientationLeftUpAction->setWhatsThis(tr("Set the camera such as x points to the left, y points upward, z points backward"));
cameraOrientationRightUpAction = new QAction(tr("x-right y-up z-front"), cameraOrientationGrp);
cameraOrientationRightUpAction->setCheckable(true);
cameraOrientationRightUpAction->setChecked(rendererWidget->getCameraOrientation() == RendererWidget::RIGHT_UP);
cameraOrientationRightUpAction->setStatusTip(tr("Set the camera such as x points to the right, y points upward, z points to the front"));
cameraOrientationRightUpAction->setWhatsThis(tr("Set the camera such as x points to the right, y points upward, z points to the front"));
//-- others
backgroundColorAction = new QAction(tr("Background &Color"), this);
backgroundColorAction->setStatusTip(tr("Change background color"));
backgroundColorAction->setWhatsThis(tr("Change the color background of the InteractiveViewer"));
connect(backgroundColorAction, SIGNAL(triggered()), this, SLOT(backgroundColor()));
toggleCopyrightAction = new QAction(tr("Show &Copyright Text"), this);
toggleCopyrightAction->setCheckable(true);
toggleCopyrightAction->setChecked(true);
toggleCopyrightAction->setStatusTip(tr("Display the copyright text"));
toggleCopyrightAction->setWhatsThis(tr("Display the copyright text"));
connect(toggleCopyrightAction, SIGNAL(toggled(bool)), this, SLOT(toggleCopyright(bool)));
toggleAxesAction = new QAction(QPixmap(":/axes"), tr("Show &Axes"), this);
toggleAxesAction->setCheckable(true);
toggleAxesAction->setStatusTip(tr("Display the coordinate axes"));
toggleAxesAction->setWhatsThis(tr("Display the coordinate axes of the InteractiveViewer"));
connect(toggleAxesAction, SIGNAL(toggled(bool)), this, SLOT(toggleAxes(bool)));
if (myType == SLICE_VIEWER) {
toggleOrientationDecorationsAction = new QAction(tr(" Show Slice Orientation Decoration"), this);
toggleOrientationDecorationsAction->setCheckable(true);
toggleOrientationDecorationsAction->setStatusTip(tr("Display Slice Orientation Information (Right, Left, Anterior, Posterior, Superior, Inferior"));
toggleOrientationDecorationsAction->setWhatsThis(tr("Display Slice Orientation Information (Right, Left, Anterior, Posterior, Superior, Inferior"));
connect(toggleOrientationDecorationsAction, SIGNAL(toggled(bool)), this, SLOT(toggleOrientationDecorations(bool)));
toggleScreenshotAction = new QAction(tr("&Toggle Screenshot Action"), this);
toggleScreenshotAction->setCheckable(true);
bool screenshotActionVisible = propertyObject->property(screenshotActionProperty->getName().toStdString().c_str()).toBool();
toggleScreenshotAction->setChecked(screenshotActionVisible);
toggleScreenshotAction->setStatusTip(tr("Show/Hide the screenshot button in the side bar of the slice viewer."));
toggleScreenshotAction->setWhatsThis(tr("Show/Hide the screenshot button in the side bar of the slice viewer."));
connect(toggleScreenshotAction, SIGNAL(toggled(bool)), this, SLOT(setScreenshotAction(bool)));
}
if (myType == GEOMETRY_VIEWER) {
toggleLinesAsTubesAction = new QAction(tr("Show Lines as Tubes"), this);
toggleLinesAsTubesAction->setCheckable(true);
toggleLinesAsTubesAction->setChecked(propertyObject->property(linesAsTubesProperty->getName().toStdString().c_str()).toBool());
toggleLinesAsTubesAction->setStatusTip(tr("Display the lines - if in a vtkDataSet - as tubes"));
toggleLinesAsTubesAction->setWhatsThis(tr("Display the lines - if in a vtkDataSet - as tubes"));
connect(toggleLinesAsTubesAction, SIGNAL(toggled(bool)), this, SLOT(setLinesAsTubes(bool)));
toggleBackfaceCullingAction = new QAction(tr("&Backface Culling"), this);
toggleBackfaceCullingAction->setCheckable(true);
bool backfaceCulling = propertyObject->property(backfaceCullingProperty->getName().toStdString().c_str()).toBool();
toggleBackfaceCullingAction->setChecked(backfaceCulling);
toggleBackfaceCullingAction->setStatusTip(tr("Set cull face on/off\nIf backface culling is on, polygons facing away from camera are not drawn."));
toggleBackfaceCullingAction->setWhatsThis(tr("Set cull face on/off\nIf backface culling is on, polygons facing away from camera are not drawn."));
connect(toggleBackfaceCullingAction, SIGNAL(toggled(bool)), this, SLOT(setBackfaceCulling(bool)));
//--- actions of the picking menu
auto* pickingGrp = new QActionGroup(this);
connect(pickingGrp, SIGNAL(triggered(QAction*)), this, SLOT(pickingModeChanged(QAction*)));
pickCellAction = new QAction(QPixmap(":/pick_cell"), tr("Pick &cell"), pickingGrp);
pickCellAction->setCheckable(true);
pickCellAction->setStatusTip(tr("Picking mode sets to pick cells"));
pickCellAction->setWhatsThis(tr("Pick cell\n\nSets the picking mode to pick one or more cells\nUse Ctrl+Left clic to select a cell,\nEscape to reset selection"));
pickPointAction = new QAction(QPixmap(":/pick_point"), tr("Pick &Points"), pickingGrp);
pickPointAction->setCheckable(true);
pickPointAction->setStatusTip(tr("Picking mode sets to pick points"));
pickPointAction->setWhatsThis(tr("Pick points\n\nSets the picking mode to pick one or more points\nUse Ctrl+Left clic to select an point\n\nEscape to reset selection"));
pickCellRegionAction = new QAction(QPixmap(":/pick_cell_region"), tr("Pick cell region"), pickingGrp);
pickCellRegionAction->setCheckable(true);
pickCellRegionAction->setStatusTip(tr("Picking mode set to pick cell region"));
pickCellRegionAction->setWhatsThis(tr("Pick cells in rectangular region"));
pickPointRegionAction = new QAction(QPixmap(":/pick_point_region"), tr("Pick point region"), pickingGrp);
pickPointRegionAction->setCheckable(true);
pickPointRegionAction->setStatusTip(tr("Picking mode set to pick point region"));
pickPointRegionAction->setWhatsThis(tr("Pick points in rectangular region"));
}
}
// ----------------------initWhatsThis ----------------------------
void InteractiveViewer::initWhatsThis() {
QColor bgColor = frame->palette().color(QPalette::Button);
QColor textColor = frame->palette().color(QPalette::ButtonText);
whatsThis = "3D view interaction Shortcuts
";
}
// ----------------------startWhatsThisSection ----------------------------
void InteractiveViewer::startWhatsThisSection(const QString& title) {
QColor bgColor = frame->palette().color(QPalette::Button);
QColor textColor = frame->palette().color(QPalette::ButtonText);
whatsThis += "" + title + "\
";
oddWhatsThis = true;
}
// ----------------------endWhatsThisSection ----------------------------
void InteractiveViewer::endWhatsThisSection() {
whatsThis += "
\
";
}
// ----------------------addWhatsThisItem ----------------------------
void InteractiveViewer::addWhatsThisItem(const QString& key, const QString& description) {
if (oddWhatsThis) {
QColor bgColor = frame->palette().color(QPalette::Midlight);
whatsThis += "";
}
else {
whatsThis += "
";
}
oddWhatsThis = !oddWhatsThis;
whatsThis += R"()" + key + " | \
" + description + " | \
";
}
// ----------------------keyPressEvent ----------------------------
void InteractiveViewer::keyPressEvent(QKeyEvent* e) {
/// NOTE:
///
/// PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE
///
/// DO NOT FORGET TO ADD A NEW LINE IN THE "WHAT'S THIS" MESSAGE (see constructor)
///
/// The call to methods startWhatsThisSection and addWhatsThisItem is a good comment line
/// to add here (see below!). Please use the same order here than in the
/// what's this help (by category, then by function, then by key name)
///
/// (PLEASE)
//-- Look at the key code
switch (e->key()) {
///
/// startWhatsThisSection("Keyboard bindings (upper or lower case)");
///
case Qt::Key_3:
rendererWidget->toogle3DRedBlue();
rendererWidget->refresh();
break;
case Qt::Key_A:
// addWhatsThisItem("A", "Toggle view axes");
if (e->modifiers() == Qt::NoModifier /*&& myType == GEOMETRY_VIEWER*/) {
toggleAxesAction->toggle();
}
break;
case Qt::Key_C:
// addWhatsThisItem("C", "Toggle color scale");
if (e->modifiers() == Qt::NoModifier) {
setColorScale(!rendererWidget->getColorScale());
refresh(this);
}
break;
case Qt::Key_F:
// addWhatsThisItem("F", "Toggle backface culling");
if (e->modifiers() == Qt::NoModifier) {
rendererWidget->setBackfaceCulling(!rendererWidget->getBackfaceCulling());
}
break;
case Qt::Key_I:
// addWhatsThisItem("I", "Toggle image interpolation on slices");
if (e->modifiers() == Qt::NoModifier) {
toggleInterpolation();
}
break;
case Qt::Key_J:
if (e->modifiers() == Qt::NoModifier) {
// addWhatsThisItem("J", "Joystick interaction mode");
rendererWidget->setControlMode(RendererWidget::JOYSTICK);
}
break;
case Qt::Key_L:
// addWhatsThisItem("L", "Toggle view labels");
if (e->modifiers() == Qt::NoModifier && myType == GEOMETRY_VIEWER) {
toggleLabelAction->toggle();
}
else
if (e->modifiers() == Qt::AltModifier) {
// addWhatsThisItem("Alt+L", "Toggle light follows camera");
rendererWidget->setLightFollowCamera(!rendererWidget->getLightFollowCamera());
rendererWidget->refresh();
}
break;
break;
case Qt::Key_P:
// addWhatsThisItem("Alt+P", "Toggle point rendering");
if (e->modifiers() == Qt::AltModifier) {
foreach (Component* comp, Application::getSelectedComponents()) {
// check if the Component is to be displayed here
if (comp->getVisibility(this) && comp->getRepresentation() == Component::GEOMETRY) {
comp->setRenderingModes(comp->getRenderingModes() ^ InterfaceGeometry::Points); //XOR
}
}
refresh(this);
}
else
// addWhatsThisItem("P", "Picking action");
if (e->modifiers() == Qt::NoModifier) {
rendererWidget->pick();
}
break;
case Qt::Key_R:
if (myType == SLICE_VIEWER) {
resetLUT();
}
break;
case Qt::Key_S:
// addWhatsThisItem("Alt+S", "Toggle surface rendering");
if (e->modifiers() == Qt::AltModifier) {
foreach (Component* comp, Application::getSelectedComponents()) {
// check if the Component is to be displayed here
if (comp->getVisibility(this) && comp->getRepresentation() == Component::GEOMETRY) {
comp->setRenderingModes(comp->getRenderingModes() ^ InterfaceGeometry::Surface); //XOR
}
}
refresh(this);
}
else
if (e->modifiers() == Qt::NoModifier) {
// addWhatsThisItem("S", "Take a screenshot");
screenshot();
}
break;
case Qt::Key_T:
if (e->modifiers() == Qt::NoModifier) {
// addWhatsThisItem("T", "Trackball interaction mode");
rendererWidget->setControlMode(RendererWidget::TRACKBALL);
}
break;
case Qt::Key_W:
// addWhatsThisItem("Alt+W", "Toggle wireframe rendering");
if (e->modifiers() == Qt::AltModifier) {
foreach (Component* comp, Application::getSelectedComponents()) {
// check if the Component is to be displayed here
if (comp->getVisibility(this) && comp->getRepresentation() == Component::GEOMETRY) {
comp->setRenderingModes(comp->getRenderingModes() ^ InterfaceGeometry::Wireframe); //XOR
}
}
refresh(this);
}
break;
///
/// startWhatsThisSection();
///
case Qt::Key_Space:
// addWhatsThisItem("SPACE", "Update/refresh view");
refresh(this);
break;
case Qt::Key_Home:
// addWhatsThisItem("HOME", "Reset camera to default view point or so that everything is visible");
resetCamera();
break;
case Qt::Key_Left:
if (myType == GEOMETRY_VIEWER) {
if (e->modifiers() == Qt::ControlModifier)
// addWhatsThisItem("Ctrl+LEFT", "Turn -90° around camera Y axis");
{
rendererWidget->rotateCamera(-90, 1);
}
else
// addWhatsThisItem("LEFT", "Turn -5° around camera Y axis");
{
rendererWidget->rotateCamera(-5, 1);
}
}
break;
case Qt::Key_Right:
if (myType == GEOMETRY_VIEWER) {
if (e->modifiers() == Qt::ControlModifier)
// addWhatsThisItem("Ctrl+RIGHT", "Turn 90° around camera Y axis");
{
rendererWidget->rotateCamera(90, 1);
}
else
// addWhatsThisItem("Ctrl+LEFT", "Turn -90° around camera Y axis");
{
rendererWidget->rotateCamera(5, 1);
}
}
break;
case Qt::Key_Up:
if (myType == GEOMETRY_VIEWER) {
if (e->modifiers() == Qt::ControlModifier)
// addWhatsThisItem("Ctrl+UP", "Turn -90° around camera X axis");
{
rendererWidget->rotateCamera(-90, 0);
}
else
// addWhatsThisItem("UP", "Turn -5° around camera X axis");
{
rendererWidget->rotateCamera(-5, 0);
}
}
break;
case Qt::Key_Down:
if (myType == GEOMETRY_VIEWER) {
if (e->modifiers() == Qt::ControlModifier)
// addWhatsThisItem("Ctrl+DOWN", "Turn 90° around camera X axis");
{
rendererWidget->rotateCamera(90, 0);
}
else
// addWhatsThisItem("DOWN", "Turn 5° around camera X axis");
{
rendererWidget->rotateCamera(5, 0);
}
}
break;
case Qt::Key_Plus:
// addWhatsThisItem("+", "Move slider a step above");
if (myType == SLICE_VIEWER) {
sliceSlider->addSingleStep();
}
break;
case Qt::Key_Minus:
// addWhatsThisItem("-", "Move slider a step below");
if (myType == SLICE_VIEWER) {
sliceSlider->subSingleStep();
}
break;
case Qt::Key_PageUp:
// addWhatsThisItem("PAGE Up", "Move slider a page above");
if (myType == SLICE_VIEWER) {
sliceSlider->addPageStep();
}
break;
case Qt::Key_PageDown:
// addWhatsThisItem("PAGE Down", "Move slider a page down");
if (myType == SLICE_VIEWER) {
sliceSlider->subPageStep();
}
break;
case Qt::Key_Escape: {
// addWhatsThisItem("ESC", "Clear current selection");
clearSelection();
refresh(this);
}
break;
///
/// startWhatsThisSection("Other Shortcuts");
///
case Qt::Key_F1:
if (e->modifiers() == Qt::NoModifier) {
//addWhatsThisItem("Shift+F1", "Show this help (i.e. the what's this help)");
QWhatsThis::showText(QCursor::pos(), whatsThis);
}
break;
case Qt::Key_F2:
if (e->modifiers() == Qt::NoModifier) {
// addWhatsThisItem("F2", "Print debugging information on console");
QString debugString;
QTextStream debugStream(&debugString);
debugStream << "=== F2 pressed (debug information) ===" << endl;
debugStream << "InteractiveViewer: \"" << getName() << "\" (total nr of displayed actors: " << actorMap.size() << ")" << endl;
debugStream << endl;
double position[3];
double focalPoint[3];
double viewUp[3];
rendererWidget->getCameraSettings(position, focalPoint, viewUp);
debugStream << "Camera Position: (" << position[0] << "," << position[1] << "," << position[2] << ")" << endl;
debugStream << "Camera Focal Point: (" << focalPoint[0] << "," << focalPoint[1] << "," << focalPoint[2] << ")" << endl;
debugStream << "Camera Up Direction: (" << viewUp[0] << "," << viewUp[1] << "," << viewUp[2] << ")" << endl;
debugStream << endl;
double bounds[6];
rendererWidget->computeVisiblePropBounds(bounds);
debugStream << "Bounds Of All Components: xmin=" << bounds[0] << " xmax=" << bounds[1]
<< " ymin=" << bounds[2] << " ymax=" << bounds[3]
<< " zmin=" << bounds[4] << " zmax=" << bounds[5] << endl;
getBoundsOfSelected(bounds);
debugStream << "Bounds Of Selected Components: xmin=" << bounds[0] << " xmax=" << bounds[1]
<< " ymin=" << bounds[2] << " ymax=" << bounds[3]
<< " zmin=" << bounds[4] << " zmax=" << bounds[5] << endl;
debugStream << endl;
debugStream << "== Component vtkProp ==" << endl;
foreach (Component* c, actorMap.keys().toSet()) {
debugStream << "- Component: \"" << c->getName()
<< "\" of type \"" << c->metaObject()->className()
<< "\" has " << actorMap.values(c).size() << " vtkProp:" << endl;
std::list > allActors = actorMap.values(c).toStdList();
allActors.sort();
allActors.unique();
foreach (vtkSmartPointer p, allActors) {
// get more information by comparing with the getActor/getProp method of c
bool found = false;
switch (myType) {
case GEOMETRY_VIEWER:
if (c->getActor(InterfaceGeometry::Surface) == p) {
found = true;
debugStream << "\t- Surface Actor" << endl;
}
else
if (c->getActor(InterfaceGeometry::Wireframe) == p) {
found = true;
debugStream << "\t- Wireframe Actor" << endl;
}
else
if (c->getActor(InterfaceGeometry::Points) == p) {
found = true;
debugStream << "\t- Points Actor" << endl;
}
break;
case SLICE_VIEWER:
if (c->getPixelActor() == p) {
found = true;
debugStream << "\t- Pixel Actor" << endl;
}
else
if (c->get2DImageActor() == p) {
found = true;
debugStream << "\t- 2D Image Actor" << endl;
}
else
if (c->getPickPlaneActor() == p) {
found = true;
debugStream << "\t- Picked Plane Actor" << endl;
}
break;
default:
// no other thing is possible
break;
}
// check additional prop
if (!found) {
unsigned int i = 0;
while (i < c->getNumberOfProp() && c->getProp(i) != p) {
i++;
}
if (i == c->getNumberOfProp()) {
debugStream << "\t- Unknown Prop" << endl;
}
else {
debugStream << "\t- Additional Prop #" << i << endl;
}
}
}
}
debugStream << "=== (end of debug information) ===" << endl;
CAMITK_INFO(tr("InteractiveViewer Debug Information: ").arg(debugString))
}
break;
/// NOTE:
///
/// PLEASE, PLEASE, PLEASE, PLEASE, PLEASE, PLEASE?
///
/// DO NOT FORGET TO ADD A NEW LINE IN THE "WHAT'S THIS" MESSAGE (see constructor)
///
/// The call to methods startWhatsThisSection and addWhatsThisItem is a good comment line
/// to add here (see below!). Please use the same order here than in the
/// what's this help (by category, then by function, then by key name)
///
/// (PLEASE)
default: // If not an interesting key,
break;
}
}
//---------------------resetCamera------------------------
void InteractiveViewer::resetCamera() {
if (myType == SLICE_VIEWER && actorMap.size() >= 1) {
double bounds[6];
// get the first Component to determine the right bounds
actorMap.begin().key()->get2DImageActor()->GetBounds(bounds);
// scale correctly for square objects like a slice
// instead of a bounding box, it transforms the bounds in a enclosed
// box, thus the radius used in the VTK ResetCamera is now smaller
// and correspond to the longest side of the slice devided by 2.0
// => VTK is "tricked"
double max = 0.0;
double radius = 0.0;
double center[3];
double halfDist[3];
for (unsigned int i = 0; i < 3; i++) {
halfDist[i] = (bounds[i * 2 + 1] - bounds[i * 2]) / 2.0;
center[i] = bounds[i * 2] + halfDist[i];
radius += halfDist[i] * halfDist[i];
if (halfDist[i] > max) {
max = halfDist[i];
}
}
radius = sqrt(radius);
for (unsigned int i = 0; i < 3; i++) {
// rescale
halfDist[i] *= max / radius;
// recompute bounds
bounds[i * 2] = center[i] - halfDist[i];
bounds[i * 2 + 1] = center[i] + halfDist[i];
}
rendererWidget->resetCamera(bounds);
}
else
// automatically set the camera so that everything is visible
{
rendererWidget->resetCamera();
}
}
// ---------------------- setActiveCamera ----------------------------
void InteractiveViewer::setActiveCamera(QString cameraName) {
if (cameraMap.contains(cameraName)) {
rendererWidget->setActiveCamera(cameraMap.value(cameraName));
}
}
// ---------------------- getCamera ----------------------------
vtkSmartPointer InteractiveViewer::getCamera(QString cameraName) {
if (cameraMap.contains(cameraName)) {
return cameraMap.value(cameraName);
}
else {
// create a new camera
vtkSmartPointer newCam = vtkSmartPointer::New();
// associate it with the given name
cameraMap.insert(cameraName, newCam);
return newCam;
}
}
// ---------------------- slotSliderChanged ----------------------------
void InteractiveViewer::sliderChanged(int i) {
if (myType == SLICE_VIEWER) {
if (actorMap.size() > 0) {
// current interaction changed
isChangingSlice = true;
actorMap.begin().key()->setSlice(i);
// the Component was modified in the viewer, ask the Component to update all its other viewers
actorMap.begin().key()->refresh();
// user has changed the slide, the selection has changed then
emit selectionChanged();
// current interaction is processed
isChangingSlice = false;
}
}
}
// ---------------------- slotXAngleChanged ----------------------------
void InteractiveViewer::xAngleChanged(double angle) {
if (myType == SLICE_VIEWER) {
if (actorMap.size() > 0) {
//TODO implement this method for the arbitrary slice
actorMap.begin().key()->rotate(angle, 0, 0);
// the Component was modified in the viewer, ask the Component to update all its other viewers
actorMap.begin().key()->refresh();
}
}
}
// ---------------------- slotYAngleChanged ----------------------------
void InteractiveViewer::yAngleChanged(double angle) {
if (myType == SLICE_VIEWER) {
if (actorMap.size() > 0) {
//TODO implement this method for the arbitrary slice
actorMap.begin().key()->rotate(0, angle, 0);
// the Component was modified in the viewer, ask the Component to update all its other viewers
actorMap.begin().key()->refresh();
}
}
}
// ---------------------- slotZAngleChanged ----------------------------
void InteractiveViewer::zAngleChanged(double angle) {
if (myType == SLICE_VIEWER) {
if (actorMap.size() > 0) {
//TODO implement this method for the arbitrary slice
actorMap.begin().key()->rotate(0, 0, angle);
// the Component was modified in the viewer, ask the Component to update all its other viewers
actorMap.begin().key()->refresh();
}
}
}
//--------------------- setGradientBackground --------------
void InteractiveViewer::setGradientBackground(bool g) {
propertyObject->setProperty(backgroundGradientColorProperty->getName().toStdString().c_str(), g);
}
// --------------- setBackgroundColor --------------------
void InteractiveViewer::setBackgroundColor(QColor c) {
propertyObject->setProperty(backgroundColorProperty->getName().toStdString().c_str(), c);
}
//--------------------- getBounds -------------------
void InteractiveViewer::getBounds(double* bounds) {
rendererWidget->computeVisiblePropBounds(bounds);
}
//--------------------- getBoundsOfSelected -------------------
void InteractiveViewer::getBoundsOfSelected(double* bounds) {
// booleen which allows one to know if at least 1 element is selected
bool oneElementSelected = false;
// init the bound to have the bigger box
for (unsigned int i = 0; i < 6; i += 2) {
bounds[i] = VTK_DOUBLE_MAX;
bounds[i + 1] = -VTK_DOUBLE_MAX;
}
// check the bound of all selected Component in the InteractiveViewer
foreach (Component* comp, actorMap.keys()) {
if (comp->isSelected()) {
//if we are in this loop that is 1 element at least is selected then
oneElementSelected = true;
// get the bounds
double compBounds[6];
comp->getBounds(compBounds);
// check against min/max
for (unsigned int i = 0; i < 6; i += 2) {
if (compBounds[i] < bounds[i]) {
bounds[i] = compBounds[i];
}
if (compBounds[i + 1] > bounds[i + 1]) {
bounds[i + 1] = compBounds[i + 1];
}
}
}
}
// if nothing element is selected then we take the bb at 0,1,0,1,0,1
if (!oneElementSelected)
for (unsigned int i = 0; i < 6; i += 2) {
bounds[i] = 0;
bounds[i + 1] = 1;
}
}
//------------------------- setSideFrameVisible ----------------------------
void InteractiveViewer::setSideFrameVisible(bool visibility) {
if (sideFrame) {
sideFrame->setVisible(visibility);
}
}
//------------------------- toggleInterpolation ----------------------------
void InteractiveViewer::toggleInterpolation() {
foreach (Component* comp, actorMap.keys()) {
if (comp->getRepresentation() == Component::SLICE) {
bool state = comp->get2DImageActor()->GetInterpolate();
comp->get2DImageActor()->SetInterpolate(!state);
state = comp->get3DImageActor()->GetInterpolate();
comp->get3DImageActor()->SetInterpolate(!state);
// the Component was modified inside the viewer, refresh all its other viewer
comp->refresh();
}
}
}
//------------------------- resetLUT ----------------------------
void InteractiveViewer::resetLUT() {
foreach (Component* comp, actorMap.keys()) {
if (comp->getRepresentation() == Component::SLICE) {
// reset property LUT
vtkSmartPointer initProp = vtkImageProperty::New();
initProp->SetInterpolationTypeToLinear();
initProp->SetAmbient(1.0);
initProp->SetDiffuse(0.0);
comp->get2DImageActor()->SetProperty(initProp);
// the Component was modified inside the viewer, refresh all its other viewer
comp->refresh();
}
}
}
//---------------------updateSelectionDisplay------------------------
void InteractiveViewer::updateSelectionDisplay(Component* comp) {
InterfaceGeometry::EnhancedModes m = InterfaceGeometry::Normal;
switch ((HighlightMode) propertyObject->property(highlightModeProperty->getName().toStdString().c_str()).toInt()) { //set the option for the item(s) not selected
case InteractiveViewer::SELECTION:
// nobody is highlighted
// shade if not selected
if (!comp->isSelected()) {
m = InterfaceGeometry::Shaded;
}
break;
case InteractiveViewer::SELECTION_ONLY:
// nobody is highlighted,
if (!comp->isSelected()) {
// hide if not selected
m = InterfaceGeometry::Hidden;
}
break;
default:
break;
}
comp->setEnhancedModes(m);
}
// ---------------------- initPicking ----------------------------
void InteractiveViewer::initPicking(PickingMode pickingMode) {
this->pickingMode = pickingMode;
switch (pickingMode) {
case PIXEL_PICKING: {
vtkSmartPointer< vtkPointPicker > picker = vtkSmartPointer::New();
picker->SetTolerance(0.01);
rendererWidget->setPicker(picker);
break;
}
case POINT_PICKING: {
vtkSmartPointer< vtkPointPicker > picker = vtkSmartPointer< vtkPointPicker >::New();
picker->SetTolerance(0.01);
this->rendererWidget->setPicker(picker);
this->rendererWidget->setAreaPicking(false);
break;
}
case CELL_PICKING: {
vtkSmartPointer< vtkCellPicker > picker = vtkSmartPointer< vtkCellPicker >::New();
picker->SetTolerance(0.0001);
this->rendererWidget->setPicker(picker);
this->rendererWidget->setAreaPicking(false);
break;
}
case AREA_CELL_PICKING: {
vtkSmartPointer< vtkRenderedAreaPicker > picker = vtkSmartPointer< vtkRenderedAreaPicker >::New();
this->rendererWidget->setPicker(picker);
this->rendererWidget->setAreaPicking(true);
break;
}
case AREA_POINT_PICKING: {
vtkSmartPointer< vtkRenderedAreaPicker > picker = vtkSmartPointer< vtkRenderedAreaPicker >::New();
this->rendererWidget->setPicker(picker);
this->rendererWidget->setAreaPicking(true);
break;
}
default:
case NO_PICKING:
rendererWidget->setPicker(nullptr);
break;
}
// picking effect no yet decided
pickingEffectUpdated = true;
}
//------------------------- screenshot ----------------------------
void InteractiveViewer::screenshot() {
//-- build list of supported format
QString filter("All supported image formats(");
for (unsigned int i = 0; i < RendererWidget::NOT_SUPPORTED; i++) {
filter += " *." + RendererWidget::getScreenshotFormatInfo(i)->extension;
}
filter += QString(");;");
// also add each entry individually
for (unsigned int i = 0; i < RendererWidget::NOT_SUPPORTED; i++) {
filter += RendererWidget::getScreenshotFormatInfo(i)->description + "(*." + RendererWidget::getScreenshotFormatInfo(i)->extension + ");;";
}
// ask the user
QString filename = QFileDialog::getSaveFileName(nullptr, tr("Save Screenshot As.."), "", filter);
if (!filename.isEmpty()) {
screenshot(filename);
}
}
void InteractiveViewer::screenshot(QString filename) {
// refresh the screen after the screenshot (so that the dialog does not appear in the screenshot!
refresh(this);
// take the snapshot
rendererWidget->screenshot(filename);
}
//------------------------- getColorScale ----------------------------
bool InteractiveViewer::getColorScale() const {
return rendererWidget->getColorScale();
}
//------------------------- setColorScale ----------------------------
void InteractiveViewer::setColorScale(bool state) {
rendererWidget->setColorScale(state);
}
//------------------------- setColorScaleMinMax ----------------------------
void InteractiveViewer::setColorScaleMinMax(double min, double max) {
rendererWidget->setColorScaleMinMax(min, max);
}
//------------------------- setColorScaleTitle ----------------------------
void InteractiveViewer::setColorScaleTitle(QString title) {
rendererWidget->setColorScaleTitle(title);
}
// ------------- updateActions -----------------
void InteractiveViewer::updateActions() {
if (myType == GEOMETRY_VIEWER) {
// block signals
surfaceAction->blockSignals(true);
wireframeAction->blockSignals(true);
pointsAction->blockSignals(true);
glyphAction->blockSignals(true);
toggleLabelAction->blockSignals(true);
scalarDataColorAction->blockSignals(true);
surfaceAction->setEnabled(true);
wireframeAction->setEnabled(true);
pointsAction->setEnabled(true);
glyphAction->setEnabled(true);
toggleLabelAction->setEnabled(true);
scalarDataColorAction->setEnabled(false);
if (colorAction) {
colorAction->setEnabled(true);
}
// update the rendering mode buttons
switch (Application::getSelectedComponents().size()) {
case 0:
surfaceAction->setEnabled(false);
wireframeAction->setEnabled(false);
pointsAction->setEnabled(false);
glyphAction->setEnabled(false);
toggleLabelAction->setEnabled(false);
if (colorAction) {
colorAction->setEnabled(false);
}
break;
case 1: {
Component* first = Application::getSelectedComponents().first();
if (first->getVisibility(this) && first->getRepresentation() == Component::GEOMETRY) {
surfaceAction->setChecked(first->getRenderingModes() & InterfaceGeometry::Surface);
wireframeAction->setChecked(first->getRenderingModes() & InterfaceGeometry::Wireframe);
pointsAction->setChecked(first->getRenderingModes() & InterfaceGeometry::Points);
glyphAction->setChecked(Application::getSelectedComponents().first()->getProp("glyph")->GetVisibility());
toggleLabelAction->setChecked(Application::getSelectedComponents().first()->getProp("label")->GetVisibility());
auto* mesh = dynamic_cast< MeshComponent* >(first);
if (mesh) {
// active scalar data colors and populate combobox with scalar data from the component
scalarDataColorAction->setEnabled(true);
scalarDataModel->setSourceModel(mesh->getDataModel());
}
}
else {
surfaceAction->setEnabled(false);
wireframeAction->setEnabled(false);
pointsAction->setEnabled(false);
glyphAction->setEnabled(false);
toggleLabelAction->setEnabled(false);
if (colorAction) {
colorAction->setEnabled(false);
}
}
break;
}
default: {
// they should all have the same rendering mode to be able to determine a default state
InterfaceGeometry::RenderingModes m = Application::getSelectedComponents() [0]->getRenderingModes();
int i = 1;
while (i < Application::getSelectedComponents().size() && (m == Application::getSelectedComponents() [i]->getRenderingModes())) {
i++;
}
if (i == Application::getSelectedComponents().size()) {
surfaceAction->setChecked(m & InterfaceGeometry::Surface);
wireframeAction->setChecked(m & InterfaceGeometry::Wireframe);
pointsAction->setChecked(m & InterfaceGeometry::Points);
}
else {
surfaceAction->setChecked(false);
pointsAction->setChecked(false);
wireframeAction->setChecked(false);
}
Component* first = Application::getSelectedComponents().first();
if (first->getVisibility(this) && first->getRepresentation() == Component::GEOMETRY) {
glyphAction->setChecked(first->getProp("glyph")->GetVisibility());
toggleLabelAction->setChecked(first->getProp("label")->GetVisibility());
}
break;
}
}
// unblock signals
surfaceAction->blockSignals(false);
wireframeAction->blockSignals(false);
pointsAction->blockSignals(false);
glyphAction->blockSignals(false);
toggleLabelAction->blockSignals(false);
scalarDataColorAction->blockSignals(false);
if (viewerMenu) {
renderingMenu->setEnabled(Application::getSelectedComponents().size() > 0);
}
}
}
// ------------- slotRenderingActorsChanged -----------------
void InteractiveViewer::renderingActorsChanged() {
InterfaceGeometry::RenderingModes m = InterfaceGeometry::None;
if (surfaceAction->isChecked()) {
m |= InterfaceGeometry::Surface;
}
if (wireframeAction->isChecked()) {
m |= InterfaceGeometry::Wireframe;
}
if (pointsAction->isChecked()) {
m |= InterfaceGeometry::Points;
}
// update the rendering mode of selected
foreach (Component* comp, Application::getSelectedComponents()) {
comp->setRenderingModes(m);
}
refresh(this);
}
// --------------- setHighlightMode --------------------
void InteractiveViewer::setHighlightMode(InteractiveViewer::HighlightMode h) {
HighlightMode highlightMode = (HighlightMode) propertyObject->property(highlightModeProperty->getName().toStdString().c_str()).toInt();
refresh(this);
QSettings& settings = Application::getSettings();
settings.beginGroup(Application::getName() + ".InteractiveViewer." + objectName().simplified().replace(" ", ""));
settings.setValue("highlightMode", highlightMode);
settings.endGroup();
}
//// --------------- getHighlightMode --------------------
//InteractiveViewer::HighlightMode InteractiveViewer::getHighlightMode() const {
// return highlightMode;
//}
// --------------- slotHighlightModeChanged -----------------------------------
void InteractiveViewer::highlightModeChanged(QAction* selectedAction) {
if (selectedAction == highlightSelectionAction) {
propertyObject->setProperty(highlightModeProperty->getName().toStdString().c_str(), InteractiveViewer::SELECTION);
}
else
if (selectedAction == highlightSelectionOnlyAction) {
propertyObject->setProperty(highlightModeProperty->getName().toStdString().c_str(), InteractiveViewer::SELECTION_ONLY);
}
else
/*
if (selectedAction == highlightModeXtraHotAction) {
highlightMode = InteractiveViewer::XTRA_HOT;
}
else
*/
if (selectedAction == highlightOffAction) {
propertyObject->setProperty(highlightModeProperty->getName().toStdString().c_str(), InteractiveViewer::OFF);
}
refresh(this);
}
// --------------- slotCameraOrientationChanged -----------------------------------
void InteractiveViewer::cameraOrientationChanged(QAction* selectedAction) {
if (selectedAction == cameraOrientationRightDownAction) {
rendererWidget->setCameraOrientation(RendererWidget::RIGHT_DOWN);
resetCamera();
rendererWidget->refresh();
}
else
if (selectedAction == cameraOrientationLeftUpAction) {
rendererWidget->setCameraOrientation(RendererWidget::LEFT_UP);
resetCamera();
rendererWidget->refresh();
}
else
if (selectedAction == cameraOrientationRightUpAction) {
rendererWidget->setCameraOrientation(RendererWidget::RIGHT_UP);
resetCamera();
rendererWidget->refresh();
}
QSettings& settings = Application::getSettings();
settings.beginGroup(Application::getName() + ".InteractiveViewer." + objectName().simplified().replace(" ", ""));
settings.setValue("cameraOrientation", rendererWidget->getCameraOrientation());
refresh(this);
settings.endGroup();
}
// -------------- slotViewControlModeChanged --------------
void InteractiveViewer::viewControlModeChanged(QAction* selectedAction) {
if (selectedAction == controlModeTrackballAction) {
rendererWidget->setControlMode(RendererWidget::TRACKBALL);
}
else {
rendererWidget->setControlMode(RendererWidget::JOYSTICK);
}
}
// ------------- slotBackgroundColor -----------------
void InteractiveViewer::backgroundColor() {
QColor oldColor = propertyObject->property(backgroundColorProperty->getName().toStdString().c_str()).value();
QColor newColor = QColorDialog::getColor(oldColor);
if (newColor.isValid()) {
propertyObject->setProperty(backgroundColorProperty->getName().toStdString().c_str(), newColor);
}
}
// ------------- slotToggleAxes -----------------
void InteractiveViewer::toggleAxes(bool f) {
rendererWidget->toggleAxes(f);
resetCamera();
rendererWidget->refresh();
}
// ------------- toggleOrientationDecorations -----------------
void InteractiveViewer::toggleOrientationDecorations(bool f) {
if (myType == SLICE_VIEWER) {
rendererWidget->toggleOrientationDecorations(f);
rendererWidget->refresh();
}
}
// ------------- slotToggleCopyright -----------------
void InteractiveViewer::toggleCopyright(bool c) {
rendererWidget->toggleCopyright(c);
rendererWidget->refresh();
}
// ------------- setLabel -----------------
void InteractiveViewer::setLabel(bool b) {
// update the rendering mode of selected
foreach (Component* comp, Application::getSelectedComponents()) {
if (comp->getVisibility(this) && comp->getRepresentation() == Component::GEOMETRY) {
comp->getProp("label")->SetVisibility(b);
}
}
refresh(this);
}
// ------------- setGlyph -----------------
void InteractiveViewer::setGlyph(bool b) {
// update the rendering mode of selected
foreach (Component* comp, Application::getSelectedComponents()) {
if (comp->getVisibility(this) && comp->getRepresentation() == Component::GEOMETRY) {
comp->getProp("glyph")->SetVisibility(b);
}
}
refresh(this);
}
// ------------- setLinesAsTubes -----------------
void InteractiveViewer::setLinesAsTubes(bool tubes) {
propertyObject->setProperty(linesAsTubesProperty->getName().toStdString().c_str(), tubes);
}
// -------------- setBackfaceCulling --------------
void InteractiveViewer::setBackfaceCulling(bool b) {
propertyObject->setProperty(backfaceCullingProperty->getName().toStdString().c_str(), b);
}
// -------------- setScreenshotAction --------------
void InteractiveViewer::setScreenshotAction(bool b) {
propertyObject->setProperty(screenshotActionProperty->getName().toStdString().c_str(), b);
if (screenshotActionMenu) {
screenshotActionMenu->setVisible(b);
}
}
//-------------------- pickingModeChanged ---------------------
void InteractiveViewer::pickingModeChanged(QAction* selectedAction) {
if (selectedAction == pickCellAction) {
initPicking(CELL_PICKING);
}
else
if (selectedAction == pickPointAction) {
initPicking(POINT_PICKING);
}
else
if (selectedAction == pickCellRegionAction) {
initPicking(AREA_CELL_PICKING);
}
else
if (selectedAction == pickPointRegionAction) {
initPicking(AREA_POINT_PICKING);
}
}
//-------------------- picked ---------------------
void InteractiveViewer::picked() {
vtkSmartPointer picker = vtkAbstractPropPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker());
if (!picker) {
pickingEffectUpdated = false;
return;
}
// get the Component that owns the picked actor
Component* comp = actorMap.key(picker->GetProp3D());
// if it is not a prop picker or if the selected actor is not a component one then good bye !
if (!comp || (pickingMode == NO_PICKING)) {
return;
}
vtkSmartPointer itemPicker;
if (!pickingEffectUpdated && (itemPicker = vtkPicker::SafeDownCast(picker))) {
pickingEffectUpdated = true;
// decide of the state: if one of the possible picked is selected, then try unselect
bool hasSelected = false;
int i = 0;
while (i < itemPicker->GetProp3Ds()->GetNumberOfItems() && !hasSelected) {
vtkSmartPointer actor = vtkActor::SafeDownCast(itemPicker->GetProp3Ds()->GetItemAsObject(i));
Component* cpt = actorMap.key(actor);
hasSelected = (cpt && cpt->isSelected());
i++;
}
pickingEffectIsSelecting = !hasSelected;
}
switch (pickingMode) {
case PIXEL_PICKING: {
vtkSmartPointer pixelPicker = vtkPicker::SafeDownCast(picker);
//-- get the points picked
vtkSmartPointer pickedPlanePts = pixelPicker->GetPickedPositions();
// Looking for the intersection point that as a zero coordinate in the Z direction.
int pointIndex = 0;
for (int i = 0 ; i < pickedPlanePts->GetNumberOfPoints(); i++) {
if (pickedPlanePts->GetPoint(i) [2] == 0.0) {
pointIndex = i;
}
}
if (pickedPlanePts != nullptr && pickedPlanePts->GetNumberOfPoints() > 0) {
// picking worked
isPicking = true;
//-- tells the Component it's been picked in (x,y,z)
comp->pixelPicked(pickedPlanePts->GetPoint(pointIndex) [0], pickedPlanePts->GetPoint(pointIndex) [1], pickedPlanePts->GetPoint(pointIndex) [2]);
refresh(this);
// picking is a kind of selection, but for pixel picking, only one Component is allowed at a time
selectionChanged(comp);
}
}
break;
case POINT_PICKING: {
vtkSmartPointer pointPicker = vtkPointPicker::SafeDownCast(picker);
if (pointPicker) {
vtkIdType currentId = pointPicker->GetPointId();
if (currentId != -1) {
vtkSmartPointer ids = vtkSmartPointer::New();
ids->InsertNextValue(currentId);
// tell the component it has been picked
comp->pointPicked(currentId, pickingEffectIsSelecting);
// show informations on the status bar
double* pickedPos;
pickedPos = pointPicker->GetPickPosition();
Application::showStatusBarMessage("Picked : " + comp->getName() + ", Point#" + QString::number(currentId) + ", position =(" + QString::number(pickedPos[0]) + "," + QString::number(pickedPos[1]) + "," + QString::number(pickedPos[2]) + ")");
// pointPicked can have changed something
auto* mesh = dynamic_cast(comp);
if (mesh) {
mesh->addToSelectedSelection(vtkSelectionNode::POINT, vtkSelectionNode::INDICES, ids);
}
refresh(this);
emit selectionChanged();
}
}
}
break;
case CELL_PICKING : {
vtkSmartPointer cellPicker = vtkCellPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker());
auto* mesh = dynamic_cast(comp);
if (cellPicker && mesh) {
vtkIdType currentId = cellPicker->GetCellId();
if (currentId != -1) {
vtkSmartPointer ids = vtkSmartPointer::New();
ids->InsertNextValue(currentId);
// tell the component it has been picked
comp->cellPicked(currentId, pickingEffectIsSelecting);
Application::showStatusBarMessage("Picked : " + comp->getName() + ", Cell#" + QString::number(currentId));
// cellPicked can have change something
mesh->addToSelectedSelection(vtkSelectionNode::CELL, vtkSelectionNode::INDICES, ids);
refresh(this);
emit selectionChanged();
}
}
}
break;
case AREA_CELL_PICKING : {
vtkSmartPointer areaPicker = vtkRenderedAreaPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker());
auto* mesh = dynamic_cast(comp);
if (areaPicker && mesh) {
vtkSmartPointer extractor = vtkSmartPointer::New();
extractor->SetInputData(mesh->getPointSet());
extractor->PreserveTopologyOff();
extractor->SetFrustum(areaPicker->GetFrustum());
extractor->Update();
vtkDataSet* dataSet = vtkDataSet::SafeDownCast(extractor->GetOutput());
if (dataSet) {
Application::showStatusBarMessage("Picked : " + comp->getName() + " (" + QString::number(dataSet->GetCellData()->GetArray(0)->GetNumberOfTuples()) + " cells )");
mesh->addToSelectedSelection(vtkSelectionNode::CELL, vtkSelectionNode::INDICES, dataSet->GetCellData()->GetArray(0));
refresh(this);
emit selectionChanged();
}
}
}
break;
case AREA_POINT_PICKING : {
vtkSmartPointer areaPicker = vtkRenderedAreaPicker::SafeDownCast(this->rendererWidget->GetInteractor()->GetPicker());
auto* mesh = dynamic_cast(comp);
if (areaPicker && mesh) {
vtkSmartPointer extractor = vtkSmartPointer::New();
extractor->SetInputData(mesh->getPointSet());
extractor->PreserveTopologyOff();
extractor->SetFrustum(areaPicker->GetFrustum());
extractor->SetFieldType(vtkSelection::POINT);
extractor->Update();
vtkDataSet* dataSet = vtkDataSet::SafeDownCast(extractor->GetOutput());
if (dataSet) {
Application::showStatusBarMessage("Picked : " + comp->getName() + " (" + QString::number(dataSet->GetPointData()->GetArray(0)->GetNumberOfTuples()) + " points )");
mesh->addToSelectedSelection(vtkSelectionNode::POINT, vtkSelectionNode::INDICES, dataSet->GetPointData()->GetArray(0));
refresh(this);
emit selectionChanged();
}
}
}
break;
case NO_PICKING :
default :
break;
}
isPicking = false;
comp = nullptr;
}
//-------------------- rightClick ---------------------
void InteractiveViewer::rightClick() {
if (QApplication::keyboardModifiers() == Qt::ControlModifier) {
// display the popup menu
getMenu()->popup(QCursor::pos());
// generate a synthetic event to tell the renderer the right button was released
// see Qt Quarterly Issue 11 ยท Q3 2004
QApplication::postEvent(rendererWidget, new QMouseEvent(QEvent::MouseButtonRelease, QCursor::pos(), Qt::RightButton, Qt::RightButton, Qt::ControlModifier));
}
}
//-------------------- createProperties ---------------------
void InteractiveViewer::createProperties() {
propertyObject = new PropertyObject(getName());
// 3D Viewer properties
// highlight mode
highlightModeProperty = new Property("Highlight Mode", InteractiveViewer::SELECTION,
"Select the highlight mode for selecting components. \n OFF: both selected and non-selected Components are in default mode \n SELECTION: the selected Components are in default mode, the non-selected Components are shaded \n ELECTION_ONLY: the selected Components are in default mode, the non-selected are hidden", "");
highlightModeProperty->setEnumTypeName("camitk::InteractiveViewer::HighlightMode");
QStringList highlightModeNames;
highlightModeNames << "Off" << "Selection" << "Selection only";
highlightModeProperty->setAttribute("enumNames", highlightModeNames);
propertyObject->addProperty(highlightModeProperty);
// background color
backgroundColorProperty = new Property("Background color", QColor(255, 255, 255), "The background color of this viewer.", "");
propertyObject->addProperty(backgroundColorProperty);
// background color property
backgroundGradientColorProperty = new Property("Use a background gradient color?", true, "Does this viewer use a gradient to render its background color?", "");
propertyObject->addProperty(backgroundGradientColorProperty);
// lines as tubes property
linesAsTubesProperty = new Property("Lines considered as tube?", false, "Does this viewer replace drawn lines as tubes?", "");
propertyObject->addProperty(linesAsTubesProperty);
// screenshot action property
screenshotActionProperty = new Property("Screenshot button visible", false, "Is the screenshot button visible in the slice viewer sidebar", "");
propertyObject->addProperty(screenshotActionProperty);
// backface culling property
backfaceCullingProperty = new Property("Backface culling", false, "Compute the non visible polygons and display them?", "");
propertyObject->addProperty(backfaceCullingProperty);
// point size property
pointSizeProperty = new Property("Point size?", 4.0, "The 3D point size of each node", "");
propertyObject->addProperty(pointSizeProperty);
// TODO BlockZOOM
// backface culling property
//backfaceCullingProperty = new Property("Backface culling", false, "Compute the non visible polygons and display them?", "");
//propertyObject->addProperty(backfaceCullingProperty);
}
// ---------------- eventFilter ----------------
bool InteractiveViewer::eventFilter(QObject* object, QEvent* event) {
// watch propertyObject instance for dynamic property changes
if (event->type() == QEvent::DynamicPropertyChange) {
// first perform the proper action
// and then save the settings accordingly
// highlight mode update
HighlightMode highlightMode = (HighlightMode) propertyObject->property(highlightModeProperty->getName().toStdString().c_str()).toInt();
// background color update
QColor backgroundColor = propertyObject->property(backgroundColorProperty->getName().toStdString().c_str()).value();
rendererWidget->setBackgroundColor(backgroundColor.redF(), backgroundColor.greenF(), backgroundColor.blueF());
// background gradient color
bool useGradientBackgroundColor = propertyObject->property(backgroundGradientColorProperty->getName().toStdString().c_str()).toBool();
rendererWidget->setGradientBackground(useGradientBackgroundColor);
// lines as tubes
bool linesAsTubes = propertyObject->property(linesAsTubesProperty->getName().toStdString().c_str()).toBool();
// backface culling
bool backfaceCulling = propertyObject->property(backfaceCullingProperty->getName().toStdString().c_str()).toBool();
rendererWidget->setBackfaceCulling(backfaceCulling);
// screenshot action
bool screenshotActionVisible = propertyObject->property(screenshotActionProperty->getName().toStdString().c_str()).toBool();
// point size
double pointSize = propertyObject->property(pointSizeProperty->getName().toStdString().c_str()).toDouble();
rendererWidget->setPointSize(pointSize);
// ..and finally refresh
refresh(this);
rendererWidget->refresh();
// save the settings
QSettings& settings = Application::getSettings();
settings.beginGroup(Application::getName() + ".InteractiveViewer." + objectName().simplified().replace(" ", ""));
settings.setValue("highlightMode", highlightMode);
settings.setValue("backgroundColor", backgroundColor.name());
settings.setValue("gradientBackground", useGradientBackgroundColor);
settings.setValue("linesAsTubes", linesAsTubes);
settings.setValue("backfaceCulling", backfaceCulling);
settings.setValue("screenshotActionVisible", screenshotActionVisible);
settings.setValue("pointSize", pointSize);
settings.endGroup();
return true;
}
else {
// otherwise pass the event on to the parent class
return Viewer::eventFilter(object, event);
}
}
//--------------------------------------------------------------
//-------------------- InteractiveViewerFrame ------------------
//--------------------------------------------------------------
//-------------------- keyPressEvent ------------------
void InteractiveViewerFrame::keyPressEvent(QKeyEvent* e) {
myInteractiveViewer->keyPressEvent(e);
//-- give the parent a chance!
QWidget::keyPressEvent(e);
}
// keep this include here (in the namespace camitk) as long as
// CMake automoc generates a camitk namespace error on this moc
// for the RendererWidget member of the InteractiveViewer class.
// By including it, the file kept out library-camitkcore_automoc.cpp
#include "moc_InteractiveViewer.cpp"
}