32 #include <vtkCamera.h>
33 #include <vtkInteractorObserver.h>
34 #include <vtkInteractorStyle.h>
36 #include <vtkPointData.h>
37 #include <vtkPolyData.h>
38 #include <vtkRenderWindowInteractor.h>
39 #include <vtkVector.h>
40 #include <vtkVectorOperators.h>
42 mitk::GizmoInteractor::GizmoInteractor()
46 mitk::GizmoInteractor::~GizmoInteractor()
50 void mitk::GizmoInteractor::ConnectActionsAndFunctions()
80 bool mitk::GizmoInteractor::HasPickedHandle(
const InteractionEvent *interactionEvent)
83 if (positionEvent == NULL)
95 if (m_ManipulatedObjectGeometry.IsNull())
107 m_PickedHandle = PickFrom2D(positionEvent);
111 m_PickedHandle = PickFrom3D(positionEvent);
120 m_InitialClickPosition2D = positionEvent->GetPointerPositionOnScreen();
121 m_InitialClickPosition3D = positionEvent->GetPositionInWorld();
123 auto renderer = positionEvent->GetSender()->GetVtkRenderer();
124 renderer->SetWorldPoint(m_InitialClickPosition3D[0], m_InitialClickPosition3D[1], m_InitialClickPosition3D[2], 0);
125 renderer->WorldToDisplay();
126 m_InitialClickPosition2DZ = renderer->GetDisplayPoint()[2];
128 m_InitialGizmoCenter3D = m_Gizmo->GetCenter();
129 positionEvent->GetSender()->WorldToDisplay(m_InitialGizmoCenter3D, m_InitialGizmoCenter2D);
131 m_InitialManipulatedObjectGeometry = m_ManipulatedObjectGeometry->Clone();
133 switch (m_PickedHandle)
138 m_AxisOfMovement = m_InitialManipulatedObjectGeometry->GetAxisVector(0);
143 m_AxisOfMovement = m_InitialManipulatedObjectGeometry->GetAxisVector(1);
148 m_AxisOfMovement = m_InitialManipulatedObjectGeometry->GetAxisVector(2);
153 m_AxisOfMovement.Normalize();
154 m_AxisOfRotation = m_AxisOfMovement;
158 Vector3D intendedAxis = m_InitialClickPosition3D - m_InitialGizmoCenter3D;
160 if (intendedAxis * m_AxisOfMovement < 0)
162 m_AxisOfMovement *= -1.0;
167 vtkCamera *camera = renderer->GetActiveCamera();
168 vtkVector3d cameraDirection(camera->GetDirectionOfProjection());
170 double angle_rad = vtkMath::AngleBetweenVectors(cameraDirection.GetData(), m_AxisOfRotation.GetDataPointer());
172 if (angle_rad < vtkMath::Pi() / 2.0)
174 m_AxisOfRotation *= -1.0;
185 void mitk::GizmoInteractor::DecideInteraction(StateMachineAction *, InteractionEvent *interactionEvent)
190 switch (m_PickedHandle)
195 decision =
InternalEvent::New(interactionEvent->GetSender(),
this,
"StartTranslationAlongAxis");
200 decision =
InternalEvent::New(interactionEvent->GetSender(),
this,
"StartRotationAroundAxis");
214 interactionEvent->GetSender()->GetDispatcher()->QueueEvent(decision);
217 void mitk::GizmoInteractor::MoveAlongAxis(StateMachineAction *, InteractionEvent *interactionEvent)
219 auto positionEvent =
dynamic_cast<const InteractionPositionEvent *
>(interactionEvent);
220 if (positionEvent == NULL)
225 Vector2D axisVector2D = m_InitialClickPosition2D - m_InitialGizmoCenter2D;
226 axisVector2D.Normalize();
228 Vector2D movement2D = positionEvent->GetPointerPositionOnScreen() - m_InitialClickPosition2D;
229 double relativeMovement = movement2D * axisVector2D;
231 Vector3D movement3D = relativeMovement * m_AxisOfMovement;
233 ApplyTranslationToManipulatedObject(movement3D);
237 void mitk::GizmoInteractor::RotateAroundAxis(StateMachineAction *, InteractionEvent *interactionEvent)
239 auto positionEvent =
dynamic_cast<const InteractionPositionEvent *
>(interactionEvent);
240 if (positionEvent == NULL)
245 Vector2D originalVector = m_InitialClickPosition2D - m_InitialGizmoCenter2D;
246 Vector2D currentVector = positionEvent->GetPointerPositionOnScreen() - m_InitialGizmoCenter2D;
248 originalVector.Normalize();
249 currentVector.Normalize();
251 double angle_rad = std::atan2(currentVector[1], currentVector[0]) - std::atan2(originalVector[1], originalVector[0]);
253 ApplyRotationToManipulatedObject(vtkMath::DegreesFromRadians(angle_rad));
257 void mitk::GizmoInteractor::MoveFreely(StateMachineAction *, InteractionEvent *interactionEvent)
259 auto positionEvent =
dynamic_cast<const InteractionPositionEvent *
>(interactionEvent);
260 if (positionEvent == NULL)
265 Point2D currentPosition2D = positionEvent->GetPointerPositionOnScreen();
268 auto renderer = positionEvent->GetSender()->GetVtkRenderer();
269 renderer->SetDisplayPoint(currentPosition2D[0], currentPosition2D[1], m_InitialClickPosition2DZ);
270 renderer->DisplayToWorld();
271 vtkVector3d worldPointVTK(renderer->GetWorldPoint());
272 Point3D worldPointITK(worldPointVTK.GetData());
273 Vector3D movementITK(worldPointITK - m_InitialClickPosition3D);
275 ApplyTranslationToManipulatedObject(movementITK);
279 void mitk::GizmoInteractor::ScaleEqually(StateMachineAction *, InteractionEvent *interactionEvent)
281 auto positionEvent =
dynamic_cast<const InteractionPositionEvent *
>(interactionEvent);
282 if (positionEvent == NULL)
287 Point2D currentPosition2D = positionEvent->GetPointerPositionOnScreen();
288 double relativeSize = (currentPosition2D - m_InitialGizmoCenter2D).GetNorm() /
289 (m_InitialClickPosition2D - m_InitialGizmoCenter2D).GetNorm();
291 ApplyEqualScalingToManipulatedObject(relativeSize);
295 void mitk::GizmoInteractor::ApplyTranslationToManipulatedObject(
const Vector3D &translation)
297 assert(m_ManipulatedObjectGeometry.IsNotNull());
299 auto manipulatedGeometry = m_InitialManipulatedObjectGeometry->Clone();
300 m_FinalDoOperation.reset(
new PointOperation(
OpMOVE, translation));
303 m_FinalUndoOperation.reset(
new PointOperation(
OpMOVE, -translation));
306 manipulatedGeometry->ExecuteOperation(m_FinalDoOperation.get());
307 m_ManipulatedObjectGeometry->SetIdentity();
308 m_ManipulatedObjectGeometry->Compose(manipulatedGeometry->GetIndexToWorldTransform());
311 void mitk::GizmoInteractor::ApplyEqualScalingToManipulatedObject(
double scalingFactor)
313 assert(m_ManipulatedObjectGeometry.IsNotNull());
314 auto manipulatedGeometry = m_InitialManipulatedObjectGeometry->Clone();
316 m_FinalDoOperation.reset(
new ScaleOperation(
OpSCALE, scalingFactor - 1.0, m_InitialGizmoCenter3D));
319 m_FinalUndoOperation.reset(
new ScaleOperation(
OpSCALE, -(scalingFactor - 1.0), m_InitialGizmoCenter3D));
322 manipulatedGeometry->ExecuteOperation(m_FinalDoOperation.get());
323 m_ManipulatedObjectGeometry->SetIdentity();
324 m_ManipulatedObjectGeometry->Compose(manipulatedGeometry->GetIndexToWorldTransform());
327 void mitk::GizmoInteractor::ApplyRotationToManipulatedObject(
double angle_deg)
329 assert(m_ManipulatedObjectGeometry.IsNotNull());
331 auto manipulatedGeometry = m_InitialManipulatedObjectGeometry->Clone();
333 m_FinalDoOperation.reset(
new RotationOperation(
OpROTATE, m_InitialGizmoCenter3D, m_AxisOfRotation, angle_deg));
336 m_FinalUndoOperation.reset(
new RotationOperation(
OpROTATE, m_InitialGizmoCenter3D, m_AxisOfRotation, -angle_deg));
339 manipulatedGeometry->ExecuteOperation(m_FinalDoOperation.get());
340 m_ManipulatedObjectGeometry->SetIdentity();
341 m_ManipulatedObjectGeometry->Compose(manipulatedGeometry->GetIndexToWorldTransform());
344 void mitk::GizmoInteractor::FeedUndoStack(StateMachineAction *, InteractionEvent *)
348 OperationEvent *operationEvent =
new OperationEvent(m_ManipulatedObjectGeometry,
351 m_FinalDoOperation.release(),
352 m_FinalUndoOperation.release(),
353 "Direct geometry manipulation");
355 m_UndoController->SetOperationEvent(operationEvent);
361 BaseRenderer *renderer = positionEvent->GetSender();
364 auto gizmo_mapper =
dynamic_cast<GizmoMapper2D *
>(mapper);
365 auto &picker = m_Picker[renderer];
367 if (picker ==
nullptr)
370 picker->SetTolerance(0.005);
374 picker->AddPickList(gizmo_mapper->GetVtkProp(renderer));
375 picker->PickFromListOn();
379 auto displayPosition = positionEvent->GetPointerPositionOnScreen();
380 picker->Pick(displayPosition[0], displayPosition[1], 0, positionEvent->GetSender()->GetVtkRenderer());
382 vtkIdType pickedPointID = picker->GetPointId();
383 if (pickedPointID == -1)
388 vtkPolyData *polydata = gizmo_mapper->GetVtkPolyData(renderer);
390 if (polydata && polydata->GetPointData() && polydata->GetPointData()->GetScalars())
392 double dataValue = polydata->GetPointData()->GetScalars()->GetTuple1(pickedPointID);
393 return m_Gizmo->GetHandleFromPointDataValue(dataValue);
401 BaseRenderer *renderer = positionEvent->GetSender();
402 auto &picker = m_Picker[renderer];
403 if (picker ==
nullptr)
406 picker->SetTolerance(0.005);
408 auto vtk_mapper =
dynamic_cast<VtkMapper *
>(mapper);
411 picker->AddPickList(vtk_mapper->GetVtkProp(renderer));
412 picker->PickFromListOn();
416 auto displayPosition = positionEvent->GetPointerPositionOnScreen();
417 picker->Pick(displayPosition[0], displayPosition[1], 0, positionEvent->GetSender()->GetVtkRenderer());
419 vtkIdType pickedPointID = picker->GetPointId();
420 if (pickedPointID == -1)
426 return m_Gizmo->GetHandleFromPointID(pickedPointID);
void SetGizmoNode(DataNode *node)
Point< ScalarType, 2 > Point2D
Super class for all position events.
void SetManipulatedObjectNode(DataNode *node)
BaseRenderer * GetSender() const
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
Constants for most interaction classes, due to the generic StateMachines.
itk::SmartPointer< Self > Pointer
HandleType
Names for the different parts of the gizmo.
itk::SmartPointer< Self > Pointer
Vector< ScalarType, 2 > Vector2D
Vector< ScalarType, 3 > Vector3D
static RenderingManager * GetInstance()
virtual MapperSlotId GetMapperID()
Get the MapperSlotId to use.
Point< ScalarType, 3 > Point3D
virtual void SetDataNode(DataNode *dataNode)
#define CONNECT_CONDITION(a, f)
void ForceImmediateUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
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)
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
vtkRenderWindow * GetRenderWindow() const
Access the RenderWindow into which this renderer renders.
Class for nodes of the DataTree.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.