1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/*****************************************************************************
* $CAMITK_LICENCE_BEGIN$
*
* CamiTK - Computer Assisted Medical Intervention ToolKit
* (c) 2001-2024 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
*
* Visit http://camitk.imag.fr for more information
*
* This file is part of CamiTK.
*
* CamiTK is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* CamiTK is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with CamiTK. If not, see <http://www.gnu.org/licenses/>.
*
* $CAMITK_LICENCE_END$
****************************************************************************/
#include "BoxWidget.h"
#include "BoxWidgetVtkCommand.h"
#include <InteractiveGeometryViewer.h>
#include <ActionWidget.h>
#include <Property.h>
#include <Log.h>
// disable warning generated by clang about the surrounded headers
#include <CamiTKDisableWarnings>
#include <vtkBoxWidget.h>
#include <vtkRenderWindow.h>
#include <CamiTKReEnableWarnings>
#include <QVector3D>
using namespace camitk;
// -------------------- constructor --------------------
BoxWidget::BoxWidget(ActionExtension* extension) : Action(extension) {
setName("Box Widget");
setDescription("Add a VTK 3D Widget to the 3D viewer.<br/>Mouse interaction<ul><li>Left button: grab on the six face handles → slide the faces</li><li>Left button: grab the center handle → move the entire box</li><li>Shift+Left button: inside the widget → Translation</li><li>Right button: inside the widget → up/down scaling</li><li>Left mouse: pick a face (not a face handle) → rotate (if <i>Rotation Enabled</i> is ticked)</li></ul>");
setComponentClassName(""); // nothing needed
setFamily("VTK Widget");
addTag("Demo");
addTag("3D Interaction");
setProperty("Translation Enabled", QVariant(true));
setProperty("Scaling Enabled", QVariant(true));
setProperty("Rotation Enabled", QVariant(false));
// Read-only parameter
Property* readOnlyProperty = new Property("Bottom Corner", QVector3D(0.0, 0.0, 0.0), "Bottom corner coordinates, automatically updated when the box widget is modified", "");
readOnlyProperty->setReadOnly(true);
addParameter(readOnlyProperty);
readOnlyProperty = new Property("Top Corner", QVector3D(1.0, 1.0, 1.0), "Top corner coordinates, automatically updated when the box widget is modified", "");
readOnlyProperty->setReadOnly(true);
addParameter(readOnlyProperty);
boxWidget = nullptr;
boxWidgetCommand = nullptr;
}
// --------------- destructor -------------------
BoxWidget::~BoxWidget() {
}
// --------------- getWidget -------------------
QWidget* BoxWidget::getWidget() {
if (boxWidget == nullptr) {
InteractiveGeometryViewer* default3DViewer = dynamic_cast<InteractiveGeometryViewer*>(Application::getViewer("3D Viewer"));
if (default3DViewer == nullptr) {
CAMITK_WARNING(tr("Cannot find \"3D Viewer\". This viewer is mandatory for running this action."))
}
else {
#if VTK_MAJOR_VERSION < 9
vtkRenderWindowInteractor* iren = default3DViewer->getRendererWidget()->GetRenderWindow()->GetInteractor();
#else
vtkRenderWindowInteractor* iren = default3DViewer->getRendererWidget()->renderWindow()->GetInteractor();
#endif
// Configure the box widget including callbacks
boxWidget = vtkSmartPointer<vtkBoxWidget>::New();
boxWidget->SetInteractor(iren);
boxWidget->InsideOutOff();
boxWidget->SetPlaceFactor(1);
// Initialize the dimension using the current bounding box
double bounds[6];
default3DViewer->getBounds(bounds);
boxWidget->PlaceWidget(bounds);
// Set box possible interactions
boxWidget->SetTranslationEnabled(property("Translation Enabled").toBool());
boxWidget->SetScalingEnabled(property("Scaling Enabled").toBool());
boxWidget->SetRotationEnabled(property("Rotation Enabled").toBool());
// add the call back
boxWidgetCommand = new BoxWidgetVtkCommand(this);
boxWidget->AddObserver(vtkCommand::EndInteractionEvent, boxWidgetCommand);
// Activate the box
boxWidget->EnabledOn();
}
}
return Action::getWidget();
}
// --------------- apply -------------------
Action::ApplyStatus BoxWidget::apply() {
// nothing is needed here, just check the user modifications for the possible interactions
boxWidget->SetTranslationEnabled(property("Translation Enabled").toBool());
boxWidget->SetScalingEnabled(property("Scaling Enabled").toBool());
boxWidget->SetRotationEnabled(property("Rotation Enabled").toBool());
return SUCCESS;
}
// --------------- updateWidget -------------------
void BoxWidget::updateWidget() {
// update action's widget from modified property (this is not the "usual" way, normally
// the user modify some property in the widget and the action gets the value to do
// something. In this case, the action's property is modified by some external
// mechanism (not the user), e.g. here the vtkBoxWidget, therefore the action's widget has
// to be updated
dynamic_cast<camitk::ActionWidget*>(Action::getWidget())->update();
}
|