diff --git a/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml b/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml
new file mode 100644
index 0000000000..5b0ddf80b5
--- /dev/null
+++ b/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml b/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml
new file mode 100644
index 0000000000..fb9c6fe6d1
--- /dev/null
+++ b/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml b/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml
new file mode 100644
index 0000000000..4040972f11
--- /dev/null
+++ b/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Modules/DataTypesExt/files.cmake b/Modules/DataTypesExt/files.cmake
index c3e5085e70..d84459eb02 100644
--- a/Modules/DataTypesExt/files.cmake
+++ b/Modules/DataTypesExt/files.cmake
@@ -1,44 +1,44 @@
set(CPP_FILES
+ mitkAffineDataInteractor3D.cpp
mitkApplyDiffImageOperation.cpp
mitkBoundingObject.cpp
mitkBoundingObjectGroup.cpp
mitkCellOperation.cpp
mitkClippingPlaneInteractor3D.cpp
mitkColorSequence.cpp
mitkColorSequenceCycleH.cpp
mitkColorSequenceRainbow.cpp
mitkCompressedImageContainer.cpp
mitkCone.cpp
mitkCuboid.cpp
mitkCylinder.cpp
mitkDataStorageSelection.cpp
mitkEllipsoid.cpp
mitkGridRepresentationProperty.cpp
mitkGridVolumeMapperProperty.cpp
mitkLabeledImageLookupTable.cpp
mitkLabeledImageVolumeCalculator.cpp
mitkLineOperation.cpp
mitkLookupTableSource.cpp
mitkMesh.cpp
mitkMultiStepper.cpp
mitkOrganTypeProperty.cpp
mitkPlane.cpp
mitkSurfaceDeformationDataInteractor3D.cpp
mitkUnstructuredGrid.cpp
mitkUnstructuredGridSource.cpp
mitkVideoSource.cpp
Internal/mitkColorConversions.cpp
)
set(RESOURCE_FILES
- #Interactions/AffineInteraction3D.xml
- #Interactions/AffineTranslationConfig.xml
- #Interactions/AffineRotationConfig.xml
- #Interactions/AffineDeformationConfig.xml
+ Interactions/AffineInteraction3D.xml
+ Interactions/AffineTranslationConfig.xml
+ Interactions/AffineRotationConfig.xml
Interactions/ClippingPlaneInteraction3D.xml
Interactions/ClippingPlaneTranslationConfig.xml
Interactions/ClippingPlaneRotationConfig.xml
Interactions/ClippingPlaneDeformationConfig.xml
)
diff --git a/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp b/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp
new file mode 100644
index 0000000000..0b1206a7cf
--- /dev/null
+++ b/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp
@@ -0,0 +1,544 @@
+/*===================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center,
+Division of Medical and Biological Informatics.
+All rights reserved.
+
+This software is distributed WITHOUT ANY WARRANTY; without
+even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.
+
+See LICENSE.txt or http://www.mitk.org for details.
+
+===================================================================*/
+
+#include "mitkAffineDataInteractor3D.h"
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+const char* translationStepSizePropertyName = "AffineDataInteractor3D.Translation Step Size";
+const char* selectedColorPropertyName = "AffineDataInteractor3D.Selected Color";
+const char* deselectedColorPropertyName = "AffineDataInteractor3D.Deselected Color";
+const char* priorPropertyName = "AffineDataInteractor3D.Prior Color";
+const char* rotationStepSizePropertyName = "AffineDataInteractor3D.Rotation Step Size";
+const char* scaleStepSizePropertyName = "AffineDataInteractor3D.Scale Step Size";
+
+mitk::AffineDataInteractor3D::AffineDataInteractor3D()
+{
+ m_OriginalGeometry = mitk::Geometry3D::New();
+
+ // Initialize vector arithmetic
+ m_ObjectNormal[0] = 0.0;
+ m_ObjectNormal[1] = 0.0;
+ m_ObjectNormal[2] = 1.0;
+}
+
+mitk::AffineDataInteractor3D::~AffineDataInteractor3D()
+{
+ this->RestoreNodeProperties();
+}
+
+void mitk::AffineDataInteractor3D::ConnectActionsAndFunctions()
+{
+ // **Conditions** that can be used in the state machine, to ensure that certain conditions are met, before actually executing an action
+ CONNECT_CONDITION("isOverObject", CheckOverObject);
+
+ // **Function** in the statmachine patterns also referred to as **Actions**
+ CONNECT_FUNCTION("selectObject",SelectObject);
+ CONNECT_FUNCTION("deselectObject",DeselectObject);
+ CONNECT_FUNCTION("initTranslate",InitTranslate);
+ CONNECT_FUNCTION("initRotate",InitRotate);
+ CONNECT_FUNCTION("translateObject",TranslateObject);
+ CONNECT_FUNCTION("rotateObject",RotateObject);
+
+ CONNECT_FUNCTION("translateUpKey",TranslateUpKey);
+ CONNECT_FUNCTION("translateDownKey",TranslateDownKey);
+ CONNECT_FUNCTION("translateLeftKey",TranslateLeftKey);
+ CONNECT_FUNCTION("translateRightKey",TranslateRightKey);
+ CONNECT_FUNCTION("translateUpModifierKey",TranslateUpModifierKey);
+ CONNECT_FUNCTION("translateDownModifierKey",TranslateDownModifierKey);
+
+ CONNECT_FUNCTION("scaleDownKey",ScaleDownKey);
+ CONNECT_FUNCTION("scaleUpKey",ScaleUpKey);
+
+ CONNECT_FUNCTION("rotateUpKey",RotateUpKey);
+ CONNECT_FUNCTION("rotateDownKey",RotateDownKey);
+ CONNECT_FUNCTION("rotateLeftKey",RotateLeftKey);
+ CONNECT_FUNCTION("rotateRightKey",RotateRightKey);
+ CONNECT_FUNCTION("rotateUpModifierKey",RotateUpModifierKey);
+ CONNECT_FUNCTION("rotateDownModifierKey",RotateDownModifierKey);
+}
+
+bool mitk::AffineDataInteractor3D::TranslateUpKey(StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize);
+ mitk::Vector3D movementVector;
+ movementVector.Fill(0.0);
+ movementVector.SetElement(2, stepSize);
+ this->TranslateGeometry(movementVector, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::TranslateDownKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize);
+ mitk::Vector3D movementVector;
+ movementVector.Fill(0.0);
+ movementVector.SetElement(2, -stepSize);
+ this->TranslateGeometry(movementVector, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::TranslateLeftKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize);
+ mitk::Vector3D movementVector;
+ movementVector.Fill(0.0);
+ movementVector.SetElement(0, -stepSize);
+ this->TranslateGeometry(movementVector, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::TranslateRightKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize);
+ mitk::Vector3D movementVector;
+ movementVector.Fill(0.0);
+ movementVector.SetElement(0, stepSize);
+ this->TranslateGeometry(movementVector, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::TranslateUpModifierKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize);
+ mitk::Vector3D movementVector;
+ movementVector.Fill(0.0);
+ movementVector.SetElement(1, stepSize);
+ this->TranslateGeometry(movementVector, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::TranslateDownModifierKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize);
+ mitk::Vector3D movementVector;
+ movementVector.Fill(0.0);
+ movementVector.SetElement(1, -stepSize);
+ this->TranslateGeometry(movementVector, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateUpKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize);
+ this->RotateGeometry(-stepSize, 0, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateDownKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize);
+ this->RotateGeometry(stepSize, 0, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateLeftKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize);
+ this->RotateGeometry(-stepSize, 2, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateRightKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize);
+ this->RotateGeometry(stepSize, 2, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateUpModifierKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize);
+ this->RotateGeometry(stepSize, 1, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateDownModifierKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 1.0f;
+ this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize);
+ this->RotateGeometry(-stepSize, 1, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::ScaleUpKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 0.1f;
+ this->GetDataNode()->GetFloatProperty(scaleStepSizePropertyName, stepSize);
+ mitk::Point3D newScale;
+ newScale.Fill(stepSize);
+ this->ScaleGeometry(newScale, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::ScaleDownKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent)
+{
+ float stepSize = 0.1f;
+ this->GetDataNode()->GetFloatProperty(scaleStepSizePropertyName, stepSize);
+ mitk::Point3D newScale;
+ newScale.Fill(-stepSize);
+ this->ScaleGeometry(newScale, this->GetUpdatedTimeGeometry(interactionEvent));
+ return true;
+}
+
+void mitk::AffineDataInteractor3D::ScaleGeometry(mitk::Point3D newScale, mitk::BaseGeometry* geometry)
+{
+ PointOperation* doOp = new mitk::PointOperation(OpSCALE, newScale, 0);
+ geometry->ExecuteOperation(doOp);
+
+ mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+}
+
+void mitk::AffineDataInteractor3D::RotateGeometry(mitk::ScalarType angle, int rotationaxis, mitk::BaseGeometry* geometry)
+{
+ mitk::Vector3D rotationAxis = geometry->GetAxisVector(rotationaxis);
+ mitk::Point3D center = geometry->GetCenter();
+
+ mitk::RotationOperation* doOp = new mitk::RotationOperation(OpROTATE, center, rotationAxis, angle);
+
+ geometry->ExecuteOperation(doOp);
+ delete doOp;
+ mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+}
+
+void mitk::AffineDataInteractor3D::TranslateGeometry(mitk::Vector3D translate, mitk::BaseGeometry* geometry)
+{
+ geometry->Translate(translate);
+ this->GetDataNode()->Modified();
+ mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+}
+
+mitk::BaseGeometry* mitk::AffineDataInteractor3D::GetUpdatedTimeGeometry(mitk::InteractionEvent* interactionEvent)
+{
+ //Get the correct time geometry to support 3D + t
+ int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
+ BaseGeometry* geometry = this->GetDataNode()->GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( timeStep );
+ if(geometry == NULL)
+ MITK_ERROR << "Geometry is NULL. Cannot modify it.";
+ return geometry;
+}
+
+void mitk::AffineDataInteractor3D::DataNodeChanged()
+{
+ mitk::DataNode::Pointer newInputNode = this->GetDataNode();
+ //add default properties
+ newInputNode->AddProperty( selectedColorPropertyName, mitk::ColorProperty::New(0.0,1.0,0.0) );
+ newInputNode->AddProperty( deselectedColorPropertyName, mitk::ColorProperty::New(0.0,0.0,1.0) );
+ newInputNode->AddProperty( translationStepSizePropertyName, mitk::FloatProperty::New(1.0f) );
+ newInputNode->AddProperty( rotationStepSizePropertyName, mitk::FloatProperty::New(1.0f) );
+ newInputNode->AddProperty( scaleStepSizePropertyName, mitk::FloatProperty::New(0.1f) );
+
+ //save the previous color of the node, in order to restore it after the interactor is destroyed
+ mitk::ColorProperty::Pointer priorColor = dynamic_cast(newInputNode->GetProperty("color"));
+ if ( priorColor.IsNotNull() )
+ {
+ mitk::ColorProperty::Pointer tmpCopyOfPriorColor = mitk::ColorProperty::New();
+ tmpCopyOfPriorColor->SetColor( priorColor->GetColor() );
+ newInputNode->AddProperty( priorPropertyName, tmpCopyOfPriorColor );
+ }
+ newInputNode->SetColor(0.0,0.0,1.0);
+ mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+}
+
+void mitk::AffineDataInteractor3D::SetDataNode(mitk::DataInteractor::NodeType node)
+{
+ this->RestoreNodeProperties(); //if there was another node set, restore it's color
+ DataInteractor::SetDataNode(node);
+}
+
+bool mitk::AffineDataInteractor3D::CheckOverObject(const InteractionEvent* interactionEvent)
+{
+ const InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent);
+ if(positionEvent == NULL)
+ return false;
+
+ Point3D currentWorldPoint;
+ if(interactionEvent->GetSender()->PickObject(positionEvent->GetPointerPositionOnScreen(), currentWorldPoint) == this->GetDataNode().GetPointer())
+ return true;
+
+ return false;
+}
+
+bool mitk::AffineDataInteractor3D::SelectObject(StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ DataNode::Pointer node = this->GetDataNode();
+
+ if (node.IsNull())
+ return false;
+
+ mitk::ColorProperty::Pointer selectedColor = dynamic_cast(node->GetProperty(selectedColorPropertyName));
+ if ( selectedColor.IsNotNull() )
+ {
+ node->GetPropertyList()->SetProperty("color", selectedColor);
+ }
+ interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
+
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::DeselectObject(StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ DataNode::Pointer node = this->GetDataNode();
+
+ if (node.IsNull())
+ return false;
+
+ mitk::ColorProperty::Pointer selectedColor = dynamic_cast(node->GetProperty(deselectedColorPropertyName));
+ if ( selectedColor.IsNotNull() )
+ {
+ node->GetPropertyList()->SetProperty("color", selectedColor);
+ }
+
+ interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
+
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::InitTranslate(StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent);
+ if(positionEvent == NULL)
+ return false;
+
+ m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
+
+ vtkInteractorObserver::ComputeDisplayToWorld(
+ interactionEvent->GetSender()->GetVtkRenderer(),
+ m_InitialPickedDisplayPoint[0],
+ m_InitialPickedDisplayPoint[1],
+ 0.0, //m_InitialInteractionPickedPoint[2],
+ m_InitialPickedWorldPoint );
+
+ // Get the timestep to also support 3D+t
+ int timeStep = 0;
+ if ((interactionEvent->GetSender()) != NULL)
+ timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
+
+ // Make deep copy of current Geometry3D of the plane
+ this->GetDataNode()->GetData()->UpdateOutputInformation(); // make sure that the Geometry is up-to-date
+ m_OriginalGeometry = static_cast(this->GetDataNode()->GetData()->GetGeometry(timeStep)->Clone().GetPointer());
+
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::InitRotate(StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent);
+
+ m_InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
+
+ vtkInteractorObserver::ComputeDisplayToWorld(
+ interactionEvent->GetSender()->GetVtkRenderer(),
+ m_InitialPickedDisplayPoint[0],
+ m_InitialPickedDisplayPoint[1],
+ 0.0, //m_InitialInteractionPickedPoint[2],
+ m_InitialPickedWorldPoint );
+
+ // Get the timestep to also support 3D+t
+ int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
+
+ // Make deep copy of current Geometry3D of the plane
+ this->GetDataNode()->GetData()->UpdateOutputInformation(); // make sure that the Geometry is up-to-date
+ m_OriginalGeometry = static_cast(this->GetDataNode()->GetData()->GetGeometry(timeStep)->Clone().GetPointer());
+
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::TranslateObject (StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent);
+ if(positionEvent == NULL)
+ return false;
+
+ double currentWorldPoint[4];
+ mitk::Point2D currentDisplayPoint = positionEvent->GetPointerPositionOnScreen();
+ vtkInteractorObserver::ComputeDisplayToWorld(
+ interactionEvent->GetSender()->GetVtkRenderer(),
+ currentDisplayPoint[0],
+ currentDisplayPoint[1],
+ 0.0, //m_InitialInteractionPickedPoint[2],
+ currentWorldPoint);
+
+ Vector3D interactionMove;
+ interactionMove[0] = currentWorldPoint[0] - m_InitialPickedWorldPoint[0];
+ interactionMove[1] = currentWorldPoint[1] - m_InitialPickedWorldPoint[1];
+ interactionMove[2] = currentWorldPoint[2] - m_InitialPickedWorldPoint[2];
+
+ Point3D origin = m_OriginalGeometry->GetOrigin();
+
+ // Get the timestep to also support 3D+t
+ int timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
+
+ // If data is an mitk::Surface, extract it
+ Surface::Pointer surface = dynamic_cast< Surface* >(this->GetDataNode()->GetData());
+ vtkPolyData* polyData = NULL;
+ if (surface.IsNotNull())
+ {
+ polyData = surface->GetVtkPolyData( timeStep );
+
+ // Extract surface normal from surface (if existent, otherwise use default)
+ vtkPointData* pointData = polyData->GetPointData();
+ if (pointData != NULL)
+ {
+ vtkDataArray* normal = polyData->GetPointData()->GetVectors("planeNormal");
+ if (normal != NULL)
+ {
+ m_ObjectNormal[0] = normal->GetComponent( 0, 0 );
+ m_ObjectNormal[1] = normal->GetComponent( 0, 1 );
+ m_ObjectNormal[2] = normal->GetComponent( 0, 2 );
+ }
+ }
+ }
+
+ Vector3D transformedObjectNormal;
+ this->GetDataNode()->GetData()->GetGeometry( timeStep )->IndexToWorld(m_ObjectNormal, transformedObjectNormal);
+
+ this->GetDataNode()->GetData()->GetGeometry( timeStep )->SetOrigin(origin + transformedObjectNormal * (interactionMove * transformedObjectNormal));
+
+ interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
+
+ return true;
+}
+
+bool mitk::AffineDataInteractor3D::RotateObject (StateMachineAction*, InteractionEvent* interactionEvent)
+{
+ InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent);
+ if(positionEvent == NULL)
+ return false;
+
+ double currentWorldPoint[4];
+ Point2D currentPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
+ vtkInteractorObserver::ComputeDisplayToWorld(
+ interactionEvent->GetSender()->GetVtkRenderer(),
+ currentPickedDisplayPoint[0],
+ currentPickedDisplayPoint[1],
+ 0.0, //m_InitialInteractionPickedPoint[2],
+ currentWorldPoint);
+
+ vtkCamera* camera = NULL;
+ vtkRenderer* currentVtkRenderer = NULL;
+
+ if ((interactionEvent->GetSender()) != NULL)
+ {
+ vtkRenderWindow* renderWindow = interactionEvent->GetSender()->GetRenderWindow();
+ if (renderWindow != NULL)
+ {
+ vtkRenderWindowInteractor* renderWindowInteractor = renderWindow->GetInteractor();
+ if ( renderWindowInteractor != NULL )
+ {
+ currentVtkRenderer = renderWindowInteractor->GetInteractorStyle()->GetCurrentRenderer();
+ if (currentVtkRenderer != NULL)
+ camera = currentVtkRenderer->GetActiveCamera();
+ }
+ }
+ }
+ if ( camera )
+ {
+ double vpn[3];
+ camera->GetViewPlaneNormal( vpn );
+
+ Vector3D viewPlaneNormal;
+ viewPlaneNormal[0] = vpn[0];
+ viewPlaneNormal[1] = vpn[1];
+ viewPlaneNormal[2] = vpn[2];
+
+ Vector3D interactionMove;
+ interactionMove[0] = currentWorldPoint[0] - m_InitialPickedWorldPoint[0];
+ interactionMove[1] = currentWorldPoint[1] - m_InitialPickedWorldPoint[1];
+ interactionMove[2] = currentWorldPoint[2] - m_InitialPickedWorldPoint[2];
+
+ if (interactionMove[0] == 0 && interactionMove[1] == 0 && interactionMove[2] == 0)
+ return true;
+
+ Vector3D rotationAxis = itk::CrossProduct(viewPlaneNormal, interactionMove);
+ rotationAxis.Normalize();
+
+ int* size = currentVtkRenderer->GetSize();
+ double l2 =
+ (currentPickedDisplayPoint[0] - m_InitialPickedDisplayPoint[0]) *
+ (currentPickedDisplayPoint[0] - m_InitialPickedDisplayPoint[0]) +
+ (currentPickedDisplayPoint[1] - m_InitialPickedDisplayPoint[1]) *
+ (currentPickedDisplayPoint[1] - m_InitialPickedDisplayPoint[1]);
+
+ double rotationAngle = 360.0 * sqrt(l2 / (size[0] * size[0] + size[1] * size[1]));
+
+ // Use center of data bounding box as center of rotation
+ Point3D rotationCenter = m_OriginalGeometry->GetCenter();
+
+ int timeStep = 0;
+ if ((interactionEvent->GetSender()) != NULL)
+ timeStep = interactionEvent->GetSender()->GetTimeStep(this->GetDataNode()->GetData());
+
+ // Reset current Geometry3D to original state (pre-interaction) and
+ // apply rotation
+ RotationOperation op( OpROTATE, rotationCenter, rotationAxis, rotationAngle );
+ Geometry3D::Pointer newGeometry = static_cast(m_OriginalGeometry->Clone().GetPointer());
+ newGeometry->ExecuteOperation( &op );
+ mitk::TimeGeometry::Pointer timeGeometry = this->GetDataNode()->GetData()->GetTimeGeometry();
+ if (timeGeometry.IsNotNull())
+ timeGeometry->SetTimeStepGeometry(newGeometry, timeStep);
+
+ interactionEvent->GetSender()->GetRenderingManager()->RequestUpdateAll();
+
+ return true;
+ }
+ else
+ return false;
+}
+
+void mitk::AffineDataInteractor3D::RestoreNodeProperties()
+{
+ mitk::DataNode::Pointer inputNode = this->GetDataNode();
+ if(inputNode.IsNull())
+ return;
+ mitk::ColorProperty::Pointer color = dynamic_cast(inputNode->GetProperty(priorPropertyName));
+ if ( color.IsNotNull() )
+ {
+ inputNode->GetPropertyList()->SetProperty("color", color);
+ }
+
+ inputNode->GetPropertyList()->DeleteProperty(selectedColorPropertyName);
+ inputNode->GetPropertyList()->DeleteProperty(deselectedColorPropertyName);
+ inputNode->GetPropertyList()->DeleteProperty(priorPropertyName);
+ inputNode->GetPropertyList()->DeleteProperty(translationStepSizePropertyName);
+ inputNode->GetPropertyList()->DeleteProperty(rotationStepSizePropertyName);
+ inputNode->GetPropertyList()->DeleteProperty(scaleStepSizePropertyName);
+
+ //update rendering
+ mitk::RenderingManager::GetInstance()->RequestUpdateAll();
+}
diff --git a/Modules/DataTypesExt/mitkAffineDataInteractor3D.h b/Modules/DataTypesExt/mitkAffineDataInteractor3D.h
new file mode 100644
index 0000000000..20a24a42a7
--- /dev/null
+++ b/Modules/DataTypesExt/mitkAffineDataInteractor3D.h
@@ -0,0 +1,101 @@
+/*===================================================================
+
+The Medical Imaging Interaction Toolkit (MITK)
+
+Copyright (c) German Cancer Research Center,
+Division of Medical and Biological Informatics.
+All rights reserved.
+
+This software is distributed WITHOUT ANY WARRANTY; without
+even the implied warranty of MERCHANTABILITY or FITNESS FOR
+A PARTICULAR PURPOSE.
+
+See LICENSE.txt or http://www.mitk.org for details.
+
+===================================================================*/
+
+#ifndef mitkAffineDataInteractor3D_h_
+#define mitkAffineDataInteractor3D_h_
+
+#include
+#include
+#include "MitkDataTypesExtExports.h"
+
+namespace mitk
+{
+/**
+ * \brief Affine interaction with objects in 3D windows.
+ *
+ * \ingroup Interaction
+ */
+// Inherit from DataInteratcor, this provides functionality of a state machine and configurable inputs.
+class MitkDataTypesExt_EXPORT AffineDataInteractor3D: public DataInteractor
+{
+
+public:
+ mitkClassMacro(AffineDataInteractor3D, DataInteractor);
+ itkFactorylessNewMacro(Self)
+ itkCloneMacro(Self)
+
+ virtual void SetDataNode(NodeType node);
+ void TranslateGeometry(mitk::Vector3D translate, mitk::BaseGeometry* geometry);
+ void RotateGeometry(mitk::ScalarType angle, int rotationaxis, mitk::BaseGeometry* geometry);
+ void ScaleGeometry(mitk::Point3D newScale, mitk::BaseGeometry* geometry);
+ mitk::BaseGeometry *GetUpdatedTimeGeometry(mitk::InteractionEvent *interactionEvent);
+protected:
+ AffineDataInteractor3D();
+ virtual ~AffineDataInteractor3D();
+ /**
+ * Here actions strings from the loaded state machine pattern are mapped to functions of
+ * the DataInteractor. These functions are called when an action from the state machine pattern is executed.
+ */
+ virtual void ConnectActionsAndFunctions();
+ /**
+ * This function is called when a DataNode has been set/changed.
+ */
+ virtual void DataNodeChanged();
+
+
+ /**
+ * Initializes the movement, stores starting position.
+ */
+ virtual bool CheckOverObject (const InteractionEvent*);
+ virtual bool SelectObject (StateMachineAction*, InteractionEvent*);
+ virtual bool DeselectObject (StateMachineAction*, InteractionEvent*);
+ virtual bool InitTranslate (StateMachineAction*, InteractionEvent*);
+ virtual bool InitRotate (StateMachineAction*, InteractionEvent*);
+ virtual bool TranslateObject (StateMachineAction*, InteractionEvent*);
+ virtual bool RotateObject (StateMachineAction*, InteractionEvent*);
+ virtual bool TranslateUpKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool TranslateDownKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool TranslateLeftKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool TranslateRightKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool TranslateUpModifierKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool TranslateDownModifierKey(StateMachineAction*, InteractionEvent* interactionEvent);
+
+ virtual bool RotateUpKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool RotateDownKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool RotateLeftKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool RotateRightKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool RotateUpModifierKey(StateMachineAction*, InteractionEvent* interactionEvent);
+ virtual bool RotateDownModifierKey(StateMachineAction*, InteractionEvent* interactionEvent);
+
+ virtual bool ScaleDownKey(mitk::StateMachineAction *, mitk::InteractionEvent* interactionEvent);
+ virtual bool ScaleUpKey(mitk::StateMachineAction *, mitk::InteractionEvent* interactionEvent);
+
+
+ virtual void RestoreNodeProperties();
+
+private:
+
+ double m_InitialPickedWorldPoint[4];
+ Point2D m_InitialPickedDisplayPoint;
+
+ Geometry3D::Pointer m_OriginalGeometry;
+
+ Vector3D m_ObjectNormal;
+
+};
+
+}
+#endif