29 #include <vtkCamera.h> 30 #include <vtkInteractorObserver.h> 31 #include <vtkInteractorStyle.h> 33 #include <vtkPointData.h> 34 #include <vtkPolyData.h> 35 #include <vtkRenderWindowInteractor.h> 36 #include <vtkVector.h> 37 #include <vtkVectorOperators.h> 39 mitk::GizmoInteractor::GizmoInteractor()
41 m_ColorForHighlight[0] = 1.0;
42 m_ColorForHighlight[1] = 0.5;
43 m_ColorForHighlight[2] = 0.0;
44 m_ColorForHighlight[3] = 1.0;
52 mitk::GizmoInteractor::~GizmoInteractor()
56 void mitk::GizmoInteractor::ConnectActionsAndFunctions()
86 bool mitk::GizmoInteractor::HasPickedHandle(
const InteractionEvent *interactionEvent)
89 if (positionEvent ==
nullptr ||
91 m_ManipulatedObjectGeometry.IsNull() ||
99 m_PickedHandle = PickFrom2D(positionEvent);
103 m_PickedHandle = PickFrom3D(positionEvent);
106 UpdateHandleHighlight();
116 if (positionEvent ==
nullptr)
125 m_InitialClickPosition2D = positionEvent->GetPointerPositionOnScreen();
126 m_InitialClickPosition3D = positionEvent->GetPositionInWorld();
128 auto renderer = positionEvent->GetSender()->GetVtkRenderer();
129 renderer->SetWorldPoint(m_InitialClickPosition3D[0], m_InitialClickPosition3D[1], m_InitialClickPosition3D[2], 0);
130 renderer->WorldToDisplay();
131 m_InitialClickPosition2DZ = renderer->GetDisplayPoint()[2];
133 m_InitialGizmoCenter3D = m_Gizmo->GetCenter();
134 positionEvent->GetSender()->WorldToDisplay(m_InitialGizmoCenter3D, m_InitialGizmoCenter2D);
136 m_InitialManipulatedObjectGeometry = m_ManipulatedObjectGeometry->Clone();
138 switch ( m_PickedHandle ) {
142 m_AxisOfMovement = m_InitialManipulatedObjectGeometry->GetAxisVector(0);
147 m_AxisOfMovement = m_InitialManipulatedObjectGeometry->GetAxisVector(1);
152 m_AxisOfMovement = m_InitialManipulatedObjectGeometry->GetAxisVector(2);
157 m_AxisOfMovement.Normalize();
158 m_AxisOfRotation = m_AxisOfMovement;
162 Vector3D intendedAxis = m_InitialClickPosition3D - m_InitialGizmoCenter3D;
164 if ( intendedAxis * m_AxisOfMovement < 0 ) {
165 m_AxisOfMovement *= -1.0;
170 vtkCamera *camera = renderer->GetActiveCamera();
171 vtkVector3d cameraDirection(camera->GetDirectionOfProjection());
173 double angle_rad = vtkMath::AngleBetweenVectors(cameraDirection.GetData(), m_AxisOfRotation.GetDataPointer());
175 if ( angle_rad < vtkMath::Pi() / 2.0 ) {
176 m_AxisOfRotation *= -1.0;
180 switch (m_PickedHandle)
216 if (positionEvent ==
nullptr)
221 Vector3D mouseMovement3D = positionEvent->GetPositionInWorld() - m_InitialClickPosition3D;
222 double projectedMouseMovement3D = mouseMovement3D * m_AxisOfMovement;
223 Vector3D movement3D = projectedMouseMovement3D * m_AxisOfMovement;
225 ApplyTranslationToManipulatedObject(movement3D);
232 if (positionEvent ==
nullptr)
237 Vector2D originalVector = m_InitialClickPosition2D - m_InitialGizmoCenter2D;
238 Vector2D currentVector = positionEvent->GetPointerPositionOnScreen() - m_InitialGizmoCenter2D;
240 originalVector.Normalize();
241 currentVector.Normalize();
243 double angle_rad = std::atan2(currentVector[1], currentVector[0]) - std::atan2(originalVector[1], originalVector[0]);
245 ApplyRotationToManipulatedObject(vtkMath::DegreesFromRadians(angle_rad));
252 if (positionEvent ==
nullptr)
257 Point2D currentPosition2D = positionEvent->GetPointerPositionOnScreen();
260 auto renderer = positionEvent->GetSender()->GetVtkRenderer();
261 renderer->SetDisplayPoint(currentPosition2D[0], currentPosition2D[1], m_InitialClickPosition2DZ);
262 renderer->DisplayToWorld();
263 vtkVector3d worldPointVTK(renderer->GetWorldPoint());
264 Point3D worldPointITK(worldPointVTK.GetData());
265 Vector3D movementITK(worldPointITK - m_InitialClickPosition3D);
267 ApplyTranslationToManipulatedObject(movementITK);
274 if (positionEvent ==
nullptr)
279 Point2D currentPosition2D = positionEvent->GetPointerPositionOnScreen();
280 double relativeSize = (currentPosition2D - m_InitialGizmoCenter2D).GetNorm() /
281 (m_InitialClickPosition2D - m_InitialGizmoCenter2D).GetNorm();
283 ApplyEqualScalingToManipulatedObject(relativeSize);
287 void mitk::GizmoInteractor::ApplyTranslationToManipulatedObject(
const Vector3D &translation)
289 assert(m_ManipulatedObjectGeometry.IsNotNull());
291 auto manipulatedGeometry = m_InitialManipulatedObjectGeometry->Clone();
298 manipulatedGeometry->ExecuteOperation(m_FinalDoOperation.get());
299 m_ManipulatedObjectGeometry->SetIndexToWorldTransform(manipulatedGeometry->GetIndexToWorldTransform());
302 void mitk::GizmoInteractor::ApplyEqualScalingToManipulatedObject(
double scalingFactor)
304 assert(m_ManipulatedObjectGeometry.IsNotNull());
305 auto manipulatedGeometry = m_InitialManipulatedObjectGeometry->Clone();
310 m_FinalUndoOperation.reset(
new ScaleOperation(
OpSCALE, -(scalingFactor - 1.0), m_InitialGizmoCenter3D));
313 manipulatedGeometry->ExecuteOperation(m_FinalDoOperation.get());
314 m_ManipulatedObjectGeometry->SetIndexToWorldTransform(manipulatedGeometry->GetIndexToWorldTransform());
317 void mitk::GizmoInteractor::ApplyRotationToManipulatedObject(
double angle_deg)
319 assert(m_ManipulatedObjectGeometry.IsNotNull());
321 auto manipulatedGeometry = m_InitialManipulatedObjectGeometry->Clone();
329 manipulatedGeometry->ExecuteOperation(m_FinalDoOperation.get());
330 m_ManipulatedObjectGeometry->SetIndexToWorldTransform(manipulatedGeometry->GetIndexToWorldTransform());
340 m_FinalDoOperation.release(),
341 m_FinalUndoOperation.release(),
342 "Direct geometry manipulation");
354 auto &picker = m_Picker[renderer];
356 if (picker ==
nullptr)
358 picker = vtkSmartPointer<vtkCellPicker>::New();
359 picker->SetTolerance(0.005);
363 picker->AddPickList(gizmo_mapper->GetVtkProp(renderer));
364 picker->PickFromListOn();
371 vtkIdType pickedPointID = picker->GetPointId();
372 if (pickedPointID == -1)
377 vtkPolyData *polydata = gizmo_mapper->GetVtkPolyData(renderer);
379 if (polydata && polydata->GetPointData() && polydata->GetPointData()->GetScalars())
381 double dataValue = polydata->GetPointData()->GetScalars()->GetTuple1(pickedPointID);
382 return m_Gizmo->GetHandleFromPointDataValue(dataValue);
391 auto &picker = m_Picker[renderer];
392 if (picker ==
nullptr)
394 picker = vtkSmartPointer<vtkCellPicker>::New();
395 picker->SetTolerance(0.005);
397 auto vtk_mapper =
dynamic_cast<VtkMapper *
>(mapper);
400 picker->AddPickList(vtk_mapper->GetVtkProp(renderer));
401 picker->PickFromListOn();
408 vtkIdType pickedPointID = picker->GetPointId();
409 if (pickedPointID == -1)
415 return m_Gizmo->GetHandleFromPointID(pickedPointID);
418 void mitk::GizmoInteractor::UpdateHandleHighlight()
420 if (m_HighlightedHandle != m_PickedHandle) {
423 if (node ==
nullptr)
return;
425 auto base_prop = node->GetProperty(
"LookupTable");
426 if (base_prop ==
nullptr)
return;
429 if (lut_prop ==
nullptr)
return;
432 if (lut ==
nullptr)
return;
435 assert(lut->GetVtkLookupTable()->GetNumberOfTableValues() >
std::max(m_PickedHandle, m_HighlightedHandle));
440 lut->
SetTableValue(m_HighlightedHandle, m_ColorReplacedByHighlight);
446 lut->GetTableValue(m_PickedHandle, m_ColorReplacedByHighlight);
447 lut->SetTableValue(m_PickedHandle, m_ColorForHighlight);
454 m_HighlightedHandle = m_PickedHandle;
virtual void SetTableValue(int index, double rgba[4])
SetTableValue convenience method wrapping the vtkLookupTable::SetTableValue() method.
void SetGizmoNode(DataNode *node)
Super class for all position events.
void SetManipulatedObjectNode(DataNode *node)
vtkRenderer * GetVtkRenderer() const
Organizes the rendering process.
Constants for most interaction classes, due to the generic StateMachines.
bool SetOperationEvent(UndoStackItem *operationEvent)
Base class of all Vtk Mappers in order to display primitives by exploiting Vtk functionality.
DataNode * GetDataNode() const
BaseRenderer * GetSender() const
HandleType
Names for the different parts of the gizmo.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
The LookupTableProperty class Property to associate mitk::LookupTable to an mitk::DataNode.
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual MapperSlotId GetMapperID()
Get the MapperSlotId to use.
Operation that handles all actions on one Point.
virtual LookupTable * GetLookupTable()
UndoController * m_UndoController
mitk::Mapper * GetMapper(MapperSlotId id) const
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
virtual void SetDataNode(DataNode *dataNode)
#define CONNECT_CONDITION(a, f)
void ForceImmediateUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
The ScaleOperation is an operation to scale any mitk::BaseGeometry.
Dispatcher::Pointer GetDispatcher() const
Returns the Dispatcher which handles Events for this BaseRenderer.
Point2D GetPointerPositionOnScreen() const
static Pointer New(BaseRenderer *_arga, DataInteractor *_argb, const std::string &_argc)
static void IncCurrObjectEventId()
Increases the current ObjectEventId For example if a button click generates operations the ObjectEven...
#define CONNECT_FUNCTION(a, f)
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
Represents a pair of operations: undo and the according redo.
Class for nodes of the DataTree.