diff --git a/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml b/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml index 27d4b05091..5b0ddf80b5 100644 --- a/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml +++ b/Modules/DataTypesExt/Resources/Interactions/AffineInteraction3D.xml @@ -1,116 +1,64 @@ - + - + - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml b/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml index 055a898d7f..fb9c6fe6d1 100644 --- a/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml +++ b/Modules/DataTypesExt/Resources/Interactions/AffineRotationConfig.xml @@ -1,33 +1,13 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml b/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml index 4bcb41ee09..4040972f11 100644 --- a/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml +++ b/Modules/DataTypesExt/Resources/Interactions/AffineTranslationConfig.xml @@ -1,36 +1,58 @@ - - - - - - - - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp b/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp index 1751257632..0b1206a7cf 100644 --- a/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp +++ b/Modules/DataTypesExt/mitkAffineDataInteractor3D.cpp @@ -1,521 +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 "mitkInteractionConst.h" -#include "mitkInteractionPositionEvent.h" -#include "mitkRotationOperation.h" -#include "mitkSurface.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->RestoreNodeColor(); + 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("scaleKey",ScaleGeometry); - + 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*) +bool mitk::AffineDataInteractor3D::TranslateUpKey(StateMachineAction*, InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize); mitk::Vector3D movementVector; - movementVector.SetElement(0, stepSize); - movementVector.SetElement(1, 0.0); - movementVector.SetElement(2, 0.0); - this->TranslateGeometry(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*) +bool mitk::AffineDataInteractor3D::TranslateDownKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize); mitk::Vector3D movementVector; - movementVector.SetElement(0, -stepSize); - movementVector.SetElement(1, 0.0); - movementVector.SetElement(2, 0.0); - this->TranslateGeometry(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*) +bool mitk::AffineDataInteractor3D::TranslateLeftKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize); mitk::Vector3D movementVector; - movementVector.SetElement(0, 0.0); - movementVector.SetElement(1, -stepSize); - movementVector.SetElement(2, 0.0); - this->TranslateGeometry(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*) +bool mitk::AffineDataInteractor3D::TranslateRightKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize); mitk::Vector3D movementVector; - movementVector.SetElement(0, 0.0); - movementVector.SetElement(1, stepSize); - movementVector.SetElement(2, 0.0); - this->TranslateGeometry(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*) +bool mitk::AffineDataInteractor3D::TranslateUpModifierKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize); mitk::Vector3D movementVector; - movementVector.SetElement(0, 0.0); - movementVector.SetElement(1, 0.0); - movementVector.SetElement(2, stepSize); - this->TranslateGeometry(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*) +bool mitk::AffineDataInteractor3D::TranslateDownModifierKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(translationStepSizePropertyName, stepSize); mitk::Vector3D movementVector; - movementVector.SetElement(0, 0.0); - movementVector.SetElement(1, 0.0); - movementVector.SetElement(2, -stepSize); - this->TranslateGeometry(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*) +bool mitk::AffineDataInteractor3D::RotateUpKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { float stepSize = 1.0f; this->GetDataNode()->GetFloatProperty(rotationStepSizePropertyName, stepSize); - this->RotateGeometry(stepSize, 0); + this->RotateGeometry(-stepSize, 0, this->GetUpdatedTimeGeometry(interactionEvent)); return true; } -bool mitk::AffineDataInteractor3D::RotateDownKey(mitk::StateMachineAction*, mitk::InteractionEvent*) +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*) +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*) +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*) +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*) +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::ScaleGeometry(mitk::StateMachineAction*, mitk::InteractionEvent*) +bool mitk::AffineDataInteractor3D::ScaleDownKey(mitk::StateMachineAction*, mitk::InteractionEvent* interactionEvent) { + float stepSize = 0.1f; + this->GetDataNode()->GetFloatProperty(scaleStepSizePropertyName, stepSize); mitk::Point3D newScale; - newScale[0] = 1.5; - newScale[1] = 1.5; - newScale[2] = 1.5; - /* generate Operation and send it to the receiving geometry */ - PointOperation* doOp = new mitk::PointOperation(OpSCALE, newScale, 0); // Index is not used here + newScale.Fill(-stepSize); + this->ScaleGeometry(newScale, this->GetUpdatedTimeGeometry(interactionEvent)); + return true; +} - /* execute the Operation */ - this->GetDataNode()->GetData()->GetGeometry()->ExecuteOperation(doOp); +void mitk::AffineDataInteractor3D::ScaleGeometry(mitk::Point3D newScale, mitk::BaseGeometry* geometry) +{ + PointOperation* doOp = new mitk::PointOperation(OpSCALE, newScale, 0); + geometry->ExecuteOperation(doOp); - delete doOp; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); - return true; } -void mitk::AffineDataInteractor3D::RotateGeometry(mitk::ScalarType angle, int rotationaxis) +void mitk::AffineDataInteractor3D::RotateGeometry(mitk::ScalarType angle, int rotationaxis, mitk::BaseGeometry* geometry) { - BaseGeometry* geometry = this->GetDataNode()->GetData()->GetGeometry(); mitk::Vector3D rotationAxis = geometry->GetAxisVector(rotationaxis); mitk::Point3D center = geometry->GetCenter(); mitk::RotationOperation* doOp = new mitk::RotationOperation(OpROTATE, center, rotationAxis, angle); - /* execute the Operation */ geometry->ExecuteOperation(doOp); delete doOp; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } -void mitk::AffineDataInteractor3D::TranslateGeometry(mitk::Vector3D translate) +void mitk::AffineDataInteractor3D::TranslateGeometry(mitk::Vector3D translate, mitk::BaseGeometry* geometry) { - BaseGeometry* geometry = this->GetDataNode()->GetData()->GetUpdatedTimeGeometry()->GetGeometryForTimeStep( 0 ); geometry->Translate(translate); - - // indicate modification of data tree node this->GetDataNode()->Modified(); - - //update rendering 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(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->RestoreNodeColor(); //if there was another node set, restore it's color + 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::RestoreNodeColor() +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 index 24794ad068..20a24a42a7 100644 --- a/Modules/DataTypesExt/mitkAffineDataInteractor3D.h +++ b/Modules/DataTypesExt/mitkAffineDataInteractor3D.h @@ -1,98 +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); - void RotateGeometry(mitk::ScalarType angle, int rotationaxis); + 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*); - virtual bool TranslateDownKey(StateMachineAction*, InteractionEvent*); - virtual bool TranslateLeftKey(StateMachineAction*, InteractionEvent*); - virtual bool TranslateRightKey(StateMachineAction*, InteractionEvent*); - virtual bool TranslateUpModifierKey(StateMachineAction*, InteractionEvent*); - virtual bool TranslateDownModifierKey(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*); - virtual bool RotateDownKey(StateMachineAction*, InteractionEvent*); - virtual bool RotateLeftKey(StateMachineAction*, InteractionEvent*); - virtual bool RotateRightKey(StateMachineAction*, InteractionEvent*); - virtual bool RotateUpModifierKey(StateMachineAction*, InteractionEvent*); - virtual bool RotateDownModifierKey(StateMachineAction*, 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 ScaleGeometry(mitk::StateMachineAction *, mitk::InteractionEvent *); + virtual bool ScaleDownKey(mitk::StateMachineAction *, mitk::InteractionEvent* interactionEvent); + virtual bool ScaleUpKey(mitk::StateMachineAction *, mitk::InteractionEvent* interactionEvent); - virtual void RestoreNodeColor(); + virtual void RestoreNodeProperties(); private: double m_InitialPickedWorldPoint[4]; Point2D m_InitialPickedDisplayPoint; Geometry3D::Pointer m_OriginalGeometry; Vector3D m_ObjectNormal; }; } #endif diff --git a/Plugins/org.mitk.gui.qt.geometrytools/files.cmake b/Plugins/org.mitk.gui.qt.geometrytools/files.cmake index 39da839b64..599f90d2a6 100644 --- a/Plugins/org.mitk.gui.qt.geometrytools/files.cmake +++ b/Plugins/org.mitk.gui.qt.geometrytools/files.cmake @@ -1,42 +1,52 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES org_mitk_gui_qt_geometrytools_Activator.cpp - mitkGeometryToolsView.cpp + QmitkGeometryToolsView.cpp ) set(UI_FILES - src/internal/mitkGeometryToolsViewControls.ui + src/internal/QmitkGeometryToolsViewControls.ui ) set(MOC_H_FILES src/internal/org_mitk_gui_qt_geometrytools_Activator.h - src/internal/mitkGeometryToolsView.h + src/internal/QmitkGeometryToolsView.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/icon.xpm + resources/key_ctrl.png + resources/key_alt.png + resources/key_dash.png + resources/key_down.png + resources/key_left.png + resources/key_plus.png + resources/key_right.png + resources/key_shift.png + resources/key_up.png + plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) diff --git a/Plugins/org.mitk.gui.qt.geometrytools/plugin.xml b/Plugins/org.mitk.gui.qt.geometrytools/plugin.xml index efb63bfd54..47404dc68e 100644 --- a/Plugins/org.mitk.gui.qt.geometrytools/plugin.xml +++ b/Plugins/org.mitk.gui.qt.geometrytools/plugin.xml @@ -1,11 +1,11 @@ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/icon.xpm b/Plugins/org.mitk.gui.qt.geometrytools/resources/icon.xpm index 9057c20bc6..7b3b16dec1 100644 --- a/Plugins/org.mitk.gui.qt.geometrytools/resources/icon.xpm +++ b/Plugins/org.mitk.gui.qt.geometrytools/resources/icon.xpm @@ -1,21 +1,896 @@ /* XPM */ -static const char * icon_xpm[] = { -"16 16 2 1", -" c #FF0000", -". c #000000", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; +static char * geometrytools_color_xpm[] = { +"100 97 796 2", +" c None", +". c #0070C0", +"+ c #74B349", +"@ c #466C2C", +"# c #121C0C", +"$ c #223516", +"% c #60943D", +"& c #42672A", +"* c #111B0B", +"= c #263B18", +"- c #649A3F", +"; c #73B149", +"> c #3F6128", +", c #10190A", +"' c #2A401B", +") c #679F41", +"! c #71AF48", +"~ c #3B5B26", +"{ c #10180A", +"] c #2D471D", +"^ c #6AA443", +"/ c #70AC47", +"( c #375523", +"_ c #0F180A", +": c #314C1F", +"< c #6EAA46", +"[ c #74B34A", +"} c #73B249", +"| c #71AE48", +"1 c #70AD47", +"2 c #7ABD4D", +"3 c #3F6229", +"4 c #000000", +"5 c #0A1305", +"6 c #588C35", +"7 c #71B245", +"8 c #33521F", +"9 c #0F1A08", +"0 c #5D9338", +"a c #6FB044", +"b c #2E4B1C", +"c c #14220B", +"d c #61993B", +"e c #6EAD43", +"f c #2A4419", +"g c #19290E", +"h c #659F3D", +"i c #6CAA41", +"j c #253C16", +"k c #1F3412", +"l c #558634", +"m c #41642A", +"n c #476E2D", +"o c #639D3D", +"p c #6DAC42", +"q c #6CAB42", +"r c #6EAC44", +"s c #0E1609", +"t c #0A0B09", +"u c #73876A", +"v c #A6C39A", +"w c #B9D9AC", +"x c #8AA280", +"y c #5C6C54", +"z c #6F8367", +"A c #AAC79E", +"B c #B8D8AB", +"C c #879E7D", +"D c #5B6B54", +"E c #ADCBA0", +"F c #B7D6A9", +"G c #839A7A", +"H c #5A6A53", +"I c #768B6E", +"J c #B0CEA3", +"K c #B5D5A8", +"L c #809676", +"M c #819878", +"N c #63735C", +"O c #141713", +"P c #90A985", +"Q c #B6D5A8", +"R c #B7D6AB", +"S c #97C37D", +"T c #6DAC43", +"U c #10120F", +"V c #C7EBB7", +"W c #B5D5A6", +"X c #B4D4A4", +"Y c #B7D8A8", +"Z c #BBDCAB", +"` c #B9DAAA", +" . c #B4D4A5", +".. c #B9DAA9", +"+. c #B4D5A5", +"@. c #B8D8A8", +"#. c #B8D9A8", +"$. c #BEE0AE", +"%. c #6E8165", +"&. c #0F110D", +"*. c #252C22", +"=. c #92AD86", +"-. c #B6D6A7", +";. c #B5D5A7", +">. c #95C37B", +",. c #3F6228", +"'. c #365422", +"). c #536A46", +"!. c #BBDCAC", +"~. c #B3D4A4", +"{. c #A1BF94", +"]. c #8AA37E", +"^. c #90A984", +"/. c #ABCA9C", +"(. c #B4D4A6", +"_. c #95C27A", +":. c #72B248", +"<. c #9AC880", +"[. c #B2D3A3", +"}. c #B6D8A7", +"|. c #BCDEAC", +"1. c #BADDAB", +"2. c #73B248", +"3. c #9BC980", +"4. c #B5D7A6", +"5. c #8EA882", +"6. c #5E7057", +"7. c #6A7E61", +"8. c #A1BF93", +"9. c #0C1208", +"0. c #0B0D0B", +"a. c #BFE3AE", +"b. c #B1D3A2", +"c. c #B8DBA8", +"d. c #627459", +"e. c #10130F", +"f. c #8CA680", +"g. c #B3D6A4", +"h. c #B2D4A4", +"i. c #94C279", +"j. c #0D1408", +"k. c #0D0F0C", +"l. c #BEE2AD", +"m. c #B1D2A1", +"n. c #B6D9A6", +"o. c #6E8465", +"p. c #161A14", +"q. c #2A3327", +"r. c #91AD85", +"s. c #B3D4A3", +"t. c #94C179", +"u. c #49712E", +"v. c #416629", +"w. c #5F7B4F", +"x. c #B7D9A7", +"y. c #B0D2A0", +"z. c #A2C294", +"A. c #90AC83", +"B. c #94B187", +"C. c #AACA9B", +"D. c #B0D3A1", +"E. c #93C278", +"F. c #72B048", +"G. c #71B047", +"H. c #97C57C", +"I. c #B1D2A2", +"J. c #AFD19F", +"K. c #B2D5A2", +"L. c #B7DAA6", +"M. c #B6D9A5", +"N. c #B1D3A1", +"O. c #93C178", +"P. c #6FAC46", +"Q. c #94C17A", +"R. c #88A37C", +"S. c #56664E", +"T. c #627559", +"U. c #9DBB8E", +"V. c #B0D2A1", +"W. c #0A1007", +"X. c #090A09", +"Y. c #BBE1AA", +"Z. c #AED19E", +"`. c #B5D9A4", +" + c #5F7256", +".+ c #0E100C", +"++ c #89A47C", +"@+ c #B0D4A0", +"#+ c #AFD2A0", +"$+ c #92C177", +"%+ c #0C1207", +"&+ c #0B0C0B", +"*+ c #BBE0AA", +"=+ c #AED09E", +"-+ c #B3D6A2", +";+ c #708666", +">+ c #1D231B", +",+ c #313A2C", +"'+ c #90AD83", +")+ c #AFD29F", +"!+ c #AFD1A0", +"~+ c #92C077", +"{+ c #527F34", +"]+ c #4D7730", +"^+ c #6B8C58", +"/+ c #ADD09C", +"(+ c #AED19D", +"_+ c #A3C493", +":+ c #95B387", +"<+ c #98B78A", +"[+ c #A8CA98", +"}+ c #ADD09D", +"|+ c #92C076", +"1+ c #71AE47", +"2+ c #70AE46", +"3+ c #AED09F", +"4+ c #ACCF9C", +"5+ c #AED29E", +"6+ c #B1D5A0", +"7+ c #ADD09E", +"8+ c #91C076", +"9+ c #6BA544", +"0+ c #69A342", +"a+ c #8CB772", +"b+ c #AFD19E", +"c+ c #ACCF9B", +"d+ c #AFD39E", +"e+ c #839E76", +"f+ c #4C5C45", +"g+ c #596C51", +"h+ c #99B889", +"i+ c #91C075", +"j+ c #0A0F06", +"k+ c #080908", +"l+ c #B8DFA6", +"m+ c #ABCF9A", +"n+ c #B2D7A0", +"o+ c #5D7053", +"p+ c #0C0F0B", +"q+ c #86A279", +"r+ c #ADD19C", +"s+ c #0B1007", +"t+ c #B8DEA5", +"u+ c #AACE99", +"v+ c #AFD49E", +"w+ c #718966", +"x+ c #242C21", +"y+ c #374231", +"z+ c #8FAD81", +"A+ c #ACD09B", +"B+ c #90BF75", +"C+ c #5B8D3A", +"D+ c #578737", +"E+ c #769B60", +"F+ c #A3C693", +"G+ c #99BA8A", +"H+ c #9CBD8C", +"I+ c #A7CA96", +"J+ c #ABCF9B", +"K+ c #90BF74", +"L+ c #6FAD46", +"M+ c #92C176", +"N+ c #A9CE98", +"O+ c #AACF99", +"P+ c #ABD09A", +"Q+ c #AACF9A", +"R+ c #649B40", +"S+ c #61973D", +"T+ c #81AA69", +"U+ c #ABD19B", +"V+ c #A8CE97", +"W+ c #ACD29A", +"X+ c #7D9970", +"Y+ c #43523C", +"Z+ c #506248", +"`+ c #93B584", +" @ c #A9CF98", +".@ c #A9CF99", +"+@ c #8FBF73", +"@@ c #B5DDA1", +"#@ c #A8CD96", +"$@ c #AED59B", +"%@ c #5B6F51", +"&@ c #0B0D0A", +"*@ c #83A075", +"=@ c #AAD098", +"-@ c #A9CE97", +";@ c #8FBF72", +">@ c #C0EDAB", +",@ c #B3DDA0", +"'@ c #A8CF96", +")@ c #A6CD94", +"!@ c #A8D096", +"~@ c #A7CE95", +"{@ c #A9D197", +"]@ c #A7CD95", +"^@ c #AAD298", +"/@ c #ACD399", +"(@ c #B7E2A3", +"_@ c #7F9C71", +":@ c #2B3627", +"<@ c #43533C", +"[@ c #91B381", +"}@ c #A8CE96", +"|@ c #8EBF72", +"1@ c #63993F", +"2@ c #60963D", +"3@ c #709659", +"4@ c #0F110E", +"5@ c #8FB17F", +"6@ c #A6CD93", +"7@ c #8DAE7D", +"8@ c #0B0E0A", +"9@ c #99BD88", +"0@ c #A6CE94", +"a@ c #81A073", +"b@ c #0D100C", +"c@ c #0C0E0B", +"d@ c #A1C78F", +"e@ c #A8CF95", +"f@ c #759067", +"g@ c #0F120D", +"h@ c #A7CF94", +"i@ c #A9D196", +"j@ c #67805C", +"k@ c #11150F", +"l@ c #A2C990", +"m@ c #526649", +"n@ c #809E72", +"o@ c #8EBF71", +"p@ c #7EAA64", +"q@ c #8BAC7B", +"r@ c #A5CD92", +"s@ c #88A978", +"t@ c #96BA85", +"u@ c #A5CE92", +"v@ c #7B996D", +"w@ c #9FC68D", +"x@ c #6C8760", +"y@ c #A6CF93", +"z@ c #A8D195", +"A@ c #5D7453", +"B@ c #54694B", +"C@ c #1B2218", +"D@ c #8DBF70", +"E@ c #81AF66", +"F@ c #1A1F18", +"G@ c #191F16", +"H@ c #90B27F", +"I@ c #A5CC92", +"J@ c #8EB07E", +"K@ c #181E15", +"L@ c #99BD87", +"M@ c #83A374", +"N@ c #1A2017", +"O@ c #181E16", +"P@ c #A0C78E", +"Q@ c #A6CE93", +"R@ c #78946A", +"S@ c #192017", +"T@ c #A8CF94", +"U@ c #6C865F", +"V@ c #1D241A", +"W@ c #1F271C", +"X@ c #53684A", +"Y@ c #030302", +"Z@ c #1D2419", +"`@ c #8EB17E", +" # c #A8D094", +".# c #8DBE70", +"+# c #8FC172", +"@# c #B1DC9E", +"## c #AFDA9B", +"$# c #A3CC91", +"%# c #A4CD91", +"&# c #A4CC91", +"*# c #A3CC90", +"=# c #A7D194", +"-# c #A8D295", +";# c #AFDA9A", +"># c #A6D093", +",# c #586F4E", +"'# c #050604", +")# c #86A776", +"!# c #AAD496", +"~# c #8CBE70", +"{# c #8DBF71", +"]# c #A3CC8F", +"^# c #A2CB8E", +"/# c #596F4E", +"(# c #192016", +"_# c #82A272", +":# c #A9D394", +"<# c #8CBE6F", +"[# c #A2CC8E", +"}# c #A5D091", +"|# c #536A4A", +"1# c #86AA77", +"2# c #A4CE90", +"3# c #728E65", +"4# c #90C372", +"5# c #8DBE6F", +"6# c #A3CD8F", +"7# c #A1CC8D", +"8# c #AAD795", +"9# c #506647", +"0# c #1B2318", +"a# c #8DB27B", +"b# c #263021", +"c# c #1D2319", +"d# c #8FC371", +"e# c #6FAC45", +"f# c #A3CC8E", +"g# c #A1CB8C", +"h# c #A0CA8B", +"i# c #A8D593", +"j# c #556C4A", +"k# c #020302", +"l# c #11140F", +"m# c #69934F", +"n# c #71AF47", +"o# c #8CBE6E", +"p# c #A0CB8B", +"q# c #A2CE8D", +"r# c #546B49", +"s# c #030303", +"t# c #405F2C", +"u# c #8CBE6D", +"v# c #9FCB8A", +"w# c #97C082", +"x# c #2B3625", +"y# c #233616", +"z# c #6AA444", +"A# c #8BBE6D", +"B# c #A0CC8B", +"C# c #9ECB89", +"D# c #9FCD8A", +"E# c #4D6343", +"F# c #0C1308", +"G# c #5C8D3A", +"H# c #70AE47", +"I# c #89BD6A", +"J# c #9CC986", +"K# c #9BC883", +"L# c #9FCE87", +"M# c #8EB979", +"N# c #536D46", +"O# c #1D2818", +"P# c #0B1008", +"Q# c #020401", +"R# c #486E2E", +"S# c #77B151", +"T# c #7DB559", +"U# c #7CB558", +"V# c #7EB759", +"W# c #83BE5E", +"X# c #609040", +"Y# c #3D5E26", +"Z# c #203114", +"`# c #334E20", +" $ c #6DA845", +".$ c #61963D", +"+$ c #6FAB46", +"@$ c #0070C2", +"#$ c #2671AB", +"$$ c #2F71A6", +"%$ c #2771AB", +"&$ c #41719C", +"*$ c #3C719F", +"=$ c #0F71B8", +"-$ c #0070C1", +";$ c #3171A5", +">$ c #43719B", +",$ c #0C70B9", +"'$ c #ED7D31", +")$ c #ED7D30", +"!$ c #0B70BA", +"~$ c #3271A5", +"{$ c #40719C", +"]$ c #ED7C2F", +"^$ c #ED7B2D", +"/$ c #EC7A2B", +"($ c #EC792A", +"_$ c #ED7F35", +":$ c #ED7B2C", +"<$ c #ED7A2C", +"[$ c #ED7B2E", +"}$ c #0770BC", +"|$ c #ED7F34", +"1$ c #F09053", +"2$ c #F3A376", +"3$ c #F6B290", +"4$ c #F7BBA1", +"5$ c #F7BDA3", +"6$ c #F7BCA3", +"7$ c #F6B495", +"8$ c #F4A87F", +"9$ c #F1965D", +"0$ c #EE823B", +"a$ c #ED7C31", +"b$ c #ED7C30", +"c$ c #EF8845", +"d$ c #F3A172", +"e$ c #F6B99E", +"f$ c #F8BEA7", +"g$ c #F7BCA4", +"h$ c #F7BBA2", +"i$ c #F7BEA6", +"j$ c #F7BCA2", +"k$ c #F4A77E", +"l$ c #F08C4D", +"m$ c #EE8138", +"n$ c #EF8947", +"o$ c #F2A274", +"p$ c #F7BAA0", +"q$ c #F7B99F", +"r$ c #F7BAA1", +"s$ c #F7BBA3", +"t$ c #F08F51", +"u$ c #EC7D31", +"v$ c #88776E", +"w$ c #3B3737", +"x$ c #3B3838", +"y$ c #F19862", +"z$ c #F5B394", +"A$ c #F6BAA2", +"B$ c #F6B9A0", +"C$ c #F6B99F", +"D$ c #F6BCA5", +"E$ c #F5B293", +"F$ c #F5AE8C", +"G$ c #F5AD89", +"H$ c #F5B190", +"I$ c #F6BAA1", +"J$ c #F7BDA6", +"K$ c #F6BBA3", +"L$ c #F5B69A", +"M$ c #F2A071", +"N$ c #ED7E33", +"O$ c #E17C38", +"P$ c #70767C", +"Q$ c #0570BD", +"R$ c #F3A67D", +"S$ c #F6B79C", +"T$ c #F6B89F", +"U$ c #F6B89E", +"V$ c #F3A981", +"W$ c #F09157", +"X$ c #EE833C", +"Y$ c #EE8037", +"Z$ c #ED8036", +"`$ c #EF8C4C", +" % c #F3A276", +".% c #F6B79B", +"+% c #F4AE8A", +"@% c #EE7C30", +"#% c #E77D34", +"$% c #F3A67C", +"%% c #F6B79D", +"&% c #F6B69B", +"*% c #F5AA84", +"=% c #EF8742", +"-% c #EE8139", +";% c #F29E6F", +">% c #F6B498", +",% c #F5B191", +"'% c #EE8036", +")% c #F3A175", +"!% c #F4AE8C", +"~% c #F08F53", +"{% c #EC7A2C", +"]% c #F4A880", +"^% c #F4AB87", +"/% c #3A3737", +"(% c #F29C6B", +"_% c #F6B59A", +":% c #F6B69C", +"<% c #F4A67D", +"[% c #EE8541", +"}% c #ED7C2E", +"|% c #EE7D30", +"1% c #EE7C2E", +"2% c #F29C6A", +"3% c #F6B59B", +"4% c #F3A379", +"5% c #3A3636", +"6% c #434040", +"7% c #595757", +"8% c #393636", +"9% c #3C3939", +"0% c #5D5B5B", +"a% c #F09055", +"b% c #F6B49A", +"c% c #F6B499", +"d% c #F3A47C", +"e% c #E87D34", +"f% c #F07D2E", +"g% c #ED7D32", +"h% c #F19964", +"i% c #F29B6A", +"j% c #413F3F", +"k% c #848484", +"l% c #6D6C6C", +"m% c #373434", +"n% c #858585", +"o% c #686767", +"p% c #F5B297", +"q% c #F5B498", +"r% c #F5B59A", +"s% c #F4AA85", +"t% c #ED7E32", +"u% c #1A71B0", +"v% c #D17B42", +"w% c #F07D2F", +"x% c #F19E6F", +"y% c #F5B599", +"z% c #F5B59C", +"A% c #EE8845", +"B% c #423F3F", +"C% c #878686", +"D% c #929292", +"E% c #6A6868", +"F% c #363232", +"G% c #868585", +"H% c #959696", +"I% c #605E5E", +"J% c #F3A57C", +"K% c #F5B397", +"L% c #F5B499", +"M% c #F4AC8A", +"N% c #EE8137", +"O% c #1D72AF", +"P% c #F87D2A", +"Q% c #EC7B2C", +"R% c #F4A57D", +"S% c #F4AA88", +"T% c #454242", +"U% c #808080", +"V% c #939393", +"W% c #8F8F8F", +"X% c #8D8D8D", +"Y% c #919191", +"Z% c #969696", +"`% c #5D5A5A", +" & c #F5B194", +".& c #F08D4F", +"+& c #F4AC8C", +"@& c #F5B398", +"#& c #F5B49A", +"$& c #F19865", +"%& c #7B7A7A", +"&& c #949494", +"*& c #625F5F", +"=& c #F3A37B", +"-& c #F5B296", +";& c #F5B195", +">& c #F29D6E", +",& c #EC7C30", +"'& c #F08F54", +")& c #F5B196", +"!& c #F4AD8E", +"~& c #EE833D", +"{& c #444242", +"]& c #7D7C7C", +"^& c #909090", +"/& c #656464", +"(& c #3C3A3A", +"_& c #EF8D4F", +":& c #F5AF92", +"<& c #F5B094", +"[& c #F4AB8A", +"}& c #EF8744", +"|& c #EE823A", +"1& c #F3A47D", +"2& c #F5B093", +"3& c #F19764", +"4& c #3A3838", +"5& c #383535", +"6& c #6C6B6B", +"7& c #8E8E8E", +"8& c #888787", +"9& c #4F4D4D", +"0& c #F29C6D", +"a& c #F29F71", +"b& c #F09259", +"c& c #F5AE91", +"d& c #F5AF93", +"e& c #F3A47E", +"f& c #767575", +"g& c #8C8C8C", +"h& c #898989", +"i& c #F5AB8A", +"j& c #F6AF92", +"k& c #F6AF91", +"l& c #F6AD8E", +"m& c #EF8743", +"n& c #EE8038", +"o& c #F4A57F", +"p& c #F6AD8D", +"q& c #F08D50", +"r& c #3E3C3C", +"s& c #737272", +"t& c #8A8A8A", +"u& c #8B8B8B", +"v& c #363333", +"w& c #F08E51", +"x& c #F7B196", +"y& c #F6AD8F", +"z& c #F6AE91", +"A& c #F4A27A", +"B& c #ED7A2B", +"C& c #F29A69", +"D& c #F6AD90", +"E& c #F6AF93", +"F& c #F29967", +"G& c #706F6F", +"H& c #888888", +"I& c #878787", +"J& c #7D7D7D", +"K& c #717070", +"L& c #727171", +"M& c #848383", +"N& c #838383", +"O& c #585656", +"P& c #F39E71", +"Q& c #F08A4A", +"R& c #F6AC8C", +"S& c #F6AE90", +"T& c #F5A47D", +"U& c #EE813A", +"V& c #403D3D", +"W& c #868686", +"X& c #3E3B3B", +"Y& c #413E3E", +"Z& c #7B7B7B", +"`& c #828282", +" * c #555353", +".* c #F6AB8C", +"+* c #F6AC8D", +"@* c #F7AD8E", +"#* c #ED7E34", +"$* c #F6A985", +"%* c #F7AD8F", +"&* c #EE8540", +"** c #6E6D6D", +"=* c #646363", +"-* c #383434", +";* c #EF8542", +">* c #F8AD8F", +",* c #F7AB8B", +"'* c #F7AC8D", +")* c #F59E73", +"!* c #F29867", +"~* c #F8AE90", +"{* c #F18E52", +"]* c #504E4E", +"^* c #393535", +"/* c #F29158", +"(* c #F7AB8A", +"_* c #F7AD8D", +":* c #F2945F", +"<* c #F08B4E", +"[* c #F39968", +"}* c #F39A69", +"|* c #F7AA8A", +"1* c #F7A988", +"2* c #F8AC8E", +"3* c #F08A4B", +"4* c #EE823C", +"5* c #F49C6E", +"6* c #F7AA8B", +"7* c #F7AA89", +"8* c #F6A683", +"9* c #F39662", +"0* c #F59F75", +"a* c #F7A987", +"b* c #F7A887", +"c* c #EF8846", +"d* c #F7A784", +"e* c #F7A580", +"f* c #EF843F", +"g* c #F6A57F", +"h* c #F7A885", +"i* c #F7A886", +"j* c #F7A783", +"k* c #EF843E", +"l* c #F6A47F", +"m* c #F6A782", +"n* c #EF8642", +"o* c #F7A37D", +"p* c #F7A47E", +"q* c #F7A47F", +"r* c #F7A178", +"s* c #F08948", +"t* c #F08846", +"u* c #F08744", +" ", +" . ", +" . . ", +" . . . ", +" . . . . ", +" . . . . . ", +" . . . . . . ", +" . . . . . . . + @ # $ % + & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 1 1 1 1 1 1 1 1 1 1 ", +" . . . 2 3 4 5 6 7 8 4 9 0 a b 4 c d e f 4 g h i j 4 k l m n o p q q q q q q q r 1 1 ", +" . . . s 4 t u v w x y z A B C D u E F G H I J K L H M N 4 O P B Q Q Q Q Q Q R S T 1 ", +" . . . s 4 U V W X Y Z ` W .Y Z ..+. .@.Z ..+. .#.Z $.%.&.*.=.-. . . . . . .;.>.r 1 ", +" . . . ,.'.).!.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.+.{.].^./.X ~.~.~.~.~.~.(._.r 1 ", +" . . . ; :.<.(.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.}.|.1.+.[.[.[.[.[.[.[. ._.r 1 ", +" . . . } 2.3.(.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.4.5.6.7.8.~.[.[.[.[.[.[. ._.r 1 ", +" . . . 9.4 0.a.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.c.d.4 e.f.g.b.b.b.b.b.b.h.i.r 1 ", +" . . . j.4 k.l.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.m.n.o.p.q.r.s.m.m.m.m.m.m.[.t.r 1 ", +" . . . u.v.w.x.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.b.z.A.B.C.D.y.y.y.y.y.y.b.E.r 1 ", +" . . . F.G.H.I.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.L.M.N.J.J.J.J.J.J.J.m.O.r 1 ", +" . . . 1 P.Q.I.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.J.K.R.S.T.U.y.J.J.J.J.J.J.V.O.r 1 ", +" . . . W.4 X.Y.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.Z.`. +4 .+++@+Z.Z.Z.Z.Z.Z.#+$+r 1 ", +" . . . %+4 &+*+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+-+;+>+,+'+)+=+=+=+=+=+=+!+~+r 1 ", +" . . . {+]+^+-+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+(+_+:+<+[+}+/+/+/+/+/+/+Z.|+r 1 ", +" . . . 1+2+i.3+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+5+6+@+}+4+4+4+4+4+4+4+7+8+r 1 ", +" . . . 9+0+a+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+d+e+f+g+h+/+c+c+c+c+c+c+}+i+r 1 ", +" . . . j+4 k+l+m+m+m+m+m+m+m+m+m+m+m+m+m+m+m+m+m+m+m+n+o+4 p+q+r+m+m+m+m+m+m+4+i+r 1 ", +" . . . s+4 X.t+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+v+w+x+y+z+A+u+u+u+u+u+u+c+B+r 1 ", +" . . . C+D+E+5+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+u+m+F+G+H+I+u+u+u+u+u+u+u+J+K+r 1 ", +" . . . 1 L+M+J+N+N+N+N+N+N+N+N+N+N+N+N+N+N+N+N+N+N+N+N+O+P+P+N+N+N+N+N+N+N+N+Q+K+r 1 ", +" . . . R+S+T+U+V+V+V+V+V+V+V+V+V+V+V+V+V+V+V+V+V+V+V+W+X+Y+Z+`+ @V+V+V+V+V+V+.@+@r 1 ", +" . . . j+4 k+@@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@$@%@4 &@*@=@#@#@#@#@#@#@-@;@r 1 ", +" . . . j+4 X.>@,@'@)@!@,@,@~@)@{@,@,@]@)@^@,@,@)@)@/@(@_@:@<@[@'@)@)@)@)@)@)@}@|@r 1 ", +" . . . 1@2@3@4@p+5@6@7@p+8@9@0@a@b@c@d@e@f@g@b@h@i@j@k@&@l@m@n@i@6@6@6@6@6@6@~@o@r 1 ", +" . . . 1 L+p@4 4 q@r@s@4 4 t@u@v@4 4 w@h@x@4 4 y@z@A@4 4 B@4 C@5@r@r@r@r@r@r@0@D@r 1 ", +" . . . 1 L+E@F@G@H@I@J@G@K@L@I@M@N@O@P@Q@R@C@S@6@T@U@V@W@X@Y@4 Z@`@ #I@I@I@I@6@.#r 1 ", +" . . . 1 L++#@###u@$#u@####%#$#y@####&#*#=#####*#*#-###;#>#,#'#4 C@)#!#*#$#$#r@~#r 1 ", +" . . . 1 L+{#r@]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#]#*#^#/#Y@4 (#_#:#]#*#-#<#r 1 ", +" . . . 1 L+{#%#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#[#}#|#4 4 (#1#2#[#3#4#r 1 ", +" . . . 1 L+5#6#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#7#8#9#4 4 0#a#b#c#d#e#1 ", +" . . . 1 L+<#f#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#g#h#i#j#'#4 k#4 l#m#n#1 ", +" . . . 1 L+o#[#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#p#q#r#4 4 4 s#t#} 1 ", +" . . . 1 L+u#7#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#v#w#x#4 4 4 4 y#z#1 ", +" . . . 1 L+A#B#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#C#D#E#4 4 4 4 4 F#G#H# ", +" . . . 1 L+I#J#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#K#L#M#N#O#P#Q#4 R#1 ", +" . . . 1 1 S#T#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#V#W#W#X#Y#Z#`# $ ", +" . . . 1 1 L+P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.P.L+! } $.$+$ ", +" . . . 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 H#| 1 ", +" . . . ", +" . . . ", +" @$@$@$ ", +" #$$$%$ . . . ", +" &$&$&$*$ . . . . . ", +" &$&$&$&$*$=$-$. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +" ;$>$&$&$*$,$-$. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +" '$'$'$'$'$)$)$'$'$'$'$'$ . !$~${$&$ . . . . ", +" '$'$'$'$]$^$/$($'$_$:$/$<$[$)$'$'$'$ . . . }$ . . ", +" '$'$'$'$|$1$2$3$4$5$6$6$7$8$9$0$'$'$'$'$ . . . . ", +" a$'$b$_$c$d$e$f$g$h$4$4$4$4$h$6$i$j$k$l$m$b$'$a$ -$. . . ", +" '$'$[$n$o$e$g$p$q$q$p$r$4$h$r$p$q$q$p$s$g$8$t$'$)$u$v$. -$. w$ w$x$ ", +" '$'$<$y$z$A$B$C$C$A$D$g$E$F$G$H$I$J$K$B$C$C$I$L$M$N$)$O$P$Q$ x$x$ x$x$ ", +" '$)$b$R$S$T$U$U$C$B$V$W$X$Y$Y$Z$Y$m$`$ %.%B$U$U$T$U$+%Z$@%#% x$x$x$ x$x$x$ ", +" '$'$Z$$%%%%%%%%%&%*%=%<$b$'$'$'$'$'$'$)$[$-%;%>%%%%%%%U$,%0$b$'$ x$x$x$x$ x$x$x$x$ ", +" '$'$'%)%U$S$S$%%!%~%{%]$'$'$'$'$ '$'$'$'$)$($c$]%.%S$S$%%^%0$b$'$ x$/%x$x$x$ x$x$x$x$x$ ", +" '$'$]$(%%%&%_%:%<%[%}%'$'$ '$|%1%_$2%>%&%3%:%4%Z$'$'$ x$5%6%7%8%x$ x$x$9%0%9%/%x$ ", +" '$[$a%3%b%c%:%d%_$b$'$ e%f%g%h%c%c%b%3%i%'$'$'$ x$8%j%k%l%m%x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$9%n%o%x$x$x$ ", +" '$b$X$p%q%q%r%s%t%'$'$ -$u%v%w%^$x%y%q%q%z%A%)$'$ x$/%B%C%D%E%F%/%/%/%/%/%/%/%/%/%/%/%/%/%/%/%/%/%/%/%/%x$G%H%I%9%x$x$ ", +" '$[$J%K%K%L%M%N%'$'$ . . -$O%P%'$Q%R%L%K%q%S%'$'$'$ x$x$T%U%V%D%W%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%Y%D%Z%`%x$x$x$ ", +" '$[$a% &p%p% &.&'$'$ . . . . '$)$-%+&@&p%#&$&^$'$ x$/%T%%&V%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%Y%&&*&x$/%x$ ", +" '$'$Y$=&-&;&-&>&N$'$,& . . . . '$'$'&@&)&;&!&~&b$'$ x$/%{&]&D%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%W%^&W%/&(&x$x$ ", +" '$b$_&:&<&<&[&}&b$'$ . . . . '$'$|&1&)&<&2&3&<$'$ 4&x$5&6&D%7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&7&W%8&9&/%x$4& ", +" '$_$0&;&:&:&a&:$'$ . . . . '$]$b&c&:&d&e&-%)$a$ x$x$x$f&7&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&g&h&0%5&x$/% ", +" '$'$X$i&j&k&l&m&]$'$ . . . . '$)$n&o&k&k&p&q&b$'$ x$x$r&s&t&t&h&t&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&u&t&h&t&C%0%v&x$/% ", +" '$'$w&x&y&z&A&B&'$ . . . . '${%C&y&D&E&F&N$'$ x$/%j%G&H&I&J&K&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&L&s&M&h&N&O&m%x$/% ", +" '$b$P&z&l&j&~%}%'$ . . . . '$]$Q&R&l&S&T&U&'$'$ /%/%V&G&W&/&X&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&Y&B%Z&`& */%x$/% ", +" '$'$)$.*+*R&@*#*'$'$ . . . . '$'$}%$*R&R&%*&*'$'$ 4&x$9%**=*-*x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$x$9%f&O&/%x$/% ", +" '$b$;*>*,*'*)*b$'$ . . . . '$'$'$'$'$^$!*'*,*~*{*'$'$'$'$'$'$ x$x$x$9&5%x$ x$x$x$]*^*x$/% ", +" '$}%/*'*(*_*:*)$'$ . . . . '$'$'$'$N$<*'*(*'*[*'%N$'$'$'$ x$x$8%x$x$ x$x$8%x$/% ", +" '$^$}*|*1*2*3*'$'$ . . . . '$'$b$4*5*6*1*7*8*9*'$'$'$ /%x$x$x$ x$x$x$/% ", +" '$Q%0*a*b*|*~&'$'$ . . . . '$'$g%c*d*1*1*e*f*)$'$ /%x$x$ x$x$/% ", +" '$/$g*h*i*j*|&'$'$ . . . . '$'$'$k*l*m*n*'$'$'$ x$x$ x$x$ ", +" '${%o*p*q*r*m$'$'$ . . . . '$'$)$f*s*'$'$'$ x$ /% ", +" '$'$t*t*t*u*N$'$'$ . . . . '$'$]$]$'$'$ ", +" '$'$]$]$]$b$'$'$'$ . . . . '$'$'$ ", +" '$'$'$'$'$'$'$'$ . . . . '$ ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . ", +" . . . . . . ", +" . . . . . . ", +" . . . . . ", +" . . . . . . ", +" . . . . . . . ", +" . . . . . ", +" . . . ", +" ", +" "}; diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_alt.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_alt.png new file mode 100644 index 0000000000..cbfc4ed6cc Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_alt.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_ctrl.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_ctrl.png new file mode 100644 index 0000000000..a5670bc077 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_ctrl.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_dash.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_dash.png new file mode 100644 index 0000000000..e71a5194a1 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_dash.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_down.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_down.png new file mode 100644 index 0000000000..14cdcc119c Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_down.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_left.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_left.png new file mode 100644 index 0000000000..80d3c92233 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_left.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_plus.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_plus.png new file mode 100644 index 0000000000..7bba5edd89 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_plus.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_right.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_right.png new file mode 100644 index 0000000000..74dcb4af06 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_right.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_shift.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_shift.png new file mode 100644 index 0000000000..7d64848a2a Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_shift.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/resources/key_up.png b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_up.png new file mode 100644 index 0000000000..f651b67abb Binary files /dev/null and b/Plugins/org.mitk.gui.qt.geometrytools/resources/key_up.png differ diff --git a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsView.cpp b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsView.cpp new file mode 100644 index 0000000000..8ca2d970c6 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsView.cpp @@ -0,0 +1,139 @@ +/*=================================================================== + +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. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkGeometryToolsView.h" + +// Qt +#include + +//mitk image +#include +#include +#include +#include + +const std::string QmitkGeometryToolsView::VIEW_ID = "org.mitk.views.geometrytools"; + +void QmitkGeometryToolsView::SetFocus() +{ + m_Controls.m_AddInteractor->setFocus(); +} + +void QmitkGeometryToolsView::CreateQtPartControl( QWidget *parent ) +{ + m_Controls.setupUi( parent ); + connect( m_Controls.m_AddInteractor, SIGNAL(clicked()), this, SLOT(AddInteractor()) ); + connect( m_Controls.m_RemoveInteractor, SIGNAL(clicked()), this, SLOT(RemoveInteractor()) ); + connect( m_Controls.m_TranslationStep, SIGNAL(valueChanged(double)), this, SLOT(OnTranslationSpinBoxChanged(double)) ); + connect( m_Controls.m_RotationStep, SIGNAL(valueChanged(double)), this, SLOT(OnRotationSpinBoxChanged(double)) ); + connect( m_Controls.m_ScaleFactor, SIGNAL(valueChanged(double)), this, SLOT(OnScaleSpinBoxChanged(double)) ); + connect( m_Controls.m_UsageInfoCheckBox, SIGNAL(clicked(bool)), this, SLOT(OnUsageInfoBoxChanged(bool)) ); + + m_Controls.m_UsageInfo->hide(); +} + +void QmitkGeometryToolsView::OnUsageInfoBoxChanged(bool flag) +{ + m_Controls.m_UsageInfo->setVisible(flag); +} + +void QmitkGeometryToolsView::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes ) +{ + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() ) + { + m_Controls.m_AddInteractor->setEnabled( true ); + return; + } + } + m_Controls.m_AddInteractor->setEnabled( false ); +} + + +void QmitkGeometryToolsView::AddInteractor() +{ + QList nodes = this->GetDataManagerSelection(); + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() ) + { + mitk::AffineDataInteractor3D::Pointer affineDataInteractor = mitk::AffineDataInteractor3D::New(); + affineDataInteractor->LoadStateMachine("AffineInteraction3D.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); + affineDataInteractor->SetEventConfig("AffineTranslationConfig.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); + affineDataInteractor->SetDataNode(node); + node->SetBoolProperty("pickable", true); + node->SetFloatProperty("AffineDataInteractor3D.Translation Step Size", m_Controls.m_TranslationStep->value()); + node->SetFloatProperty("AffineDataInteractor3D.Rotation Step Size", m_Controls.m_RotationStep->value()); + node->SetFloatProperty("AffineDataInteractor3D.Scale Step Size", m_Controls.m_ScaleFactor->value()); + } + } +} + +void QmitkGeometryToolsView::RemoveInteractor() +{ + QList nodes = this->GetDataManagerSelection(); + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( (node.IsNotNull()) && (node->GetDataInteractor().IsNotNull()) ) + { + node->SetDataInteractor(NULL); + } + } +} + +void QmitkGeometryToolsView::OnTranslationSpinBoxChanged(double step) +{ + QList nodes = this->GetDataManagerSelection(); + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() && (node->GetDataInteractor().IsNotNull()) ) + { + node->SetFloatProperty("AffineDataInteractor3D.Translation Step Size", step); + } + } +} + +void QmitkGeometryToolsView::OnRotationSpinBoxChanged(double step) +{ + QList nodes = this->GetDataManagerSelection(); + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() && (node->GetDataInteractor().IsNotNull()) ) + { + node->SetFloatProperty("AffineDataInteractor3D.Rotation Step Size", step); + } + } +} + +void QmitkGeometryToolsView::OnScaleSpinBoxChanged(double factor) +{ + QList nodes = this->GetDataManagerSelection(); + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() && (node->GetDataInteractor().IsNotNull()) ) + { + node->SetFloatProperty("AffineDataInteractor3D.Scale Step Size", factor); + } + } +} diff --git a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsView.h b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsView.h similarity index 70% rename from Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsView.h rename to Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsView.h index b0bd72fcda..f7adeec255 100644 --- a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsView.h +++ b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsView.h @@ -1,66 +1,69 @@ /*=================================================================== 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 mitkGeometryToolsView_h -#define mitkGeometryToolsView_h +#ifndef QmitkGeometryToolsView_h +#define QmitkGeometryToolsView_h #include #include +#include -#include "ui_mitkGeometryToolsViewControls.h" +#include "ui_QmitkGeometryToolsViewControls.h" /** - \brief mitkGeometryToolsView + \brief QmitkGeometryToolsView \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ -class mitkGeometryToolsView : public QmitkAbstractView +class QmitkGeometryToolsView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; protected slots: - /// \brief Called when the user clicks the GUI button - void DoImageProcessing(); - void AddRotationInteractor(); + void RemoveInteractor(); + void AddInteractor(); + void OnRotationSpinBoxChanged(double step); + void OnScaleSpinBoxChanged(double factor); + void OnTranslationSpinBoxChanged(double step); + void OnUsageInfoBoxChanged(bool flag); protected: virtual void CreateQtPartControl(QWidget *parent); virtual void SetFocus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, const QList& nodes ); - Ui::mitkGeometryToolsViewControls m_Controls; - + Ui::QmitkGeometryToolsViewControls m_Controls; }; -#endif // mitkGeometryToolsView_h +#endif // QmitkGeometryToolsView_h diff --git a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsViewControls.ui b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsViewControls.ui new file mode 100644 index 0000000000..eb52a47f73 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/QmitkGeometryToolsViewControls.ui @@ -0,0 +1,401 @@ + + + QmitkGeometryToolsViewControls + + + + 0 + 0 + 372 + 584 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + Keyboard Mode + + + + + + + Remove Interactor + + + + + + + Mouse Mode + + + + + + + Rotation step size (°) + + + + + + + 360.000000000000000 + + + 1.000000000000000 + + + + + + + Scale factor (%) + + + + + + + 200.000000000000000 + + + 0.100000000000000 + + + 0.100000000000000 + + + + + + + Scale in origin + + + true + + + + + + + Show usage information + + + + + + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_up.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_shift.png + + + + + + + + + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_up.png + + + + + + + + + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_right.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_left.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_up.png + + + + + + + + + + + + + + + <html><head/><body><p>Translate <br/>Coronal</p></body></html> + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_down.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_ctrl.png + + + + + + + <html><head/><body><p>Rotate <br/>Coronal</p></body></html> + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_ctrl.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_down.png + + + + + + + <html><head/><body><p>Rotate <br/>Sagittal/Axial</p></body></html> + + + + + + + + + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_down.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_down.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_down.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_shift.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_up.png + + + + + + + <html><head/><body><p>Translate <br/>Sagittal/Axial</p></body></html> + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_left.png + + + + + + + Scale + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_plus.png + + + + + + + + + + :/org.mitk.gui.qt.geometrytools/resources/key_dash.png + + + + + + + + + + + + Do image processing + + + Add Interactor + + + + + + + Translation step size (mm) + + + + + + + 2 + + + 1000.000000000000000 + + + 1.000000000000000 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsView.cpp b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsView.cpp deleted file mode 100644 index 37de84d983..0000000000 --- a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsView.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - - -// Blueberry -#include -#include - -// Qmitk -#include "mitkGeometryToolsView.h" - -// Qt -#include - -//mitk image -#include -#include -#include -#include - -const std::string mitkGeometryToolsView::VIEW_ID = "org.mitk.views.geometrytools"; - -void mitkGeometryToolsView::SetFocus() -{ - m_Controls.m_TranslateButton->setFocus(); -} - -void mitkGeometryToolsView::CreateQtPartControl( QWidget *parent ) -{ - // create GUI widgets from the Qt Designer's .ui file - m_Controls.setupUi( parent ); - connect( m_Controls.m_TranslateButton, SIGNAL(clicked()), this, SLOT(DoImageProcessing()) ); - connect( m_Controls.m_RotateButton, SIGNAL(clicked()), this, SLOT(AddRotationInteractor()) ); -} - -void mitkGeometryToolsView::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, - const QList& nodes ) -{ - // iterate all selected objects, adjust warning visibility - foreach( mitk::DataNode::Pointer node, nodes ) - { - if( node.IsNotNull() ) - { - m_Controls.m_TranslateButton->setEnabled( true ); - return; - } - } - - m_Controls.m_TranslateButton->setEnabled( false ); -} - - -void mitkGeometryToolsView::DoImageProcessing() -{ - QList nodes = this->GetDataManagerSelection(); - if (nodes.empty()) return; - - mitk::DataNode::Pointer node = nodes.front(); - - mitk::AffineDataInteractor3D::Pointer affineDataInteractor = mitk::AffineDataInteractor3D::New(); - affineDataInteractor->LoadStateMachine("AffineInteraction3D.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); - affineDataInteractor->SetEventConfig("AffineTranslationConfig.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); - affineDataInteractor->SetDataNode(node); - node->SetBoolProperty("pickable", true); -} - -void mitkGeometryToolsView::AddRotationInteractor() -{ - QList nodes = this->GetDataManagerSelection(); - if (nodes.empty()) return; - - mitk::DataNode::Pointer node = nodes.front(); - - mitk::AffineDataInteractor3D::Pointer affineDataInteractor = mitk::AffineDataInteractor3D::New(); - affineDataInteractor->LoadStateMachine("AffineInteraction3D.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); - affineDataInteractor->SetEventConfig("AffineRotationConfig.xml", us::ModuleRegistry::GetModule("MitkDataTypesExt")); - affineDataInteractor->SetDataNode(node); - node->SetBoolProperty("pickable", true); -} diff --git a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsViewControls.ui b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsViewControls.ui deleted file mode 100644 index 5c2d4dc81b..0000000000 --- a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/mitkGeometryToolsViewControls.ui +++ /dev/null @@ -1,68 +0,0 @@ - - - mitkGeometryToolsViewControls - - - - 0 - 0 - 222 - 161 - - - - - 0 - 0 - - - - QmitkTemplate - - - - - - Do image processing - - - Translate - - - - - - - Rotate - - - - - - - Scale - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 220 - - - - - - - - - - diff --git a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/org_mitk_gui_qt_geometrytools_Activator.cpp b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/org_mitk_gui_qt_geometrytools_Activator.cpp index 8729a61d9e..1f87bea92f 100644 --- a/Plugins/org.mitk.gui.qt.geometrytools/src/internal/org_mitk_gui_qt_geometrytools_Activator.cpp +++ b/Plugins/org.mitk.gui.qt.geometrytools/src/internal/org_mitk_gui_qt_geometrytools_Activator.cpp @@ -1,40 +1,40 @@ /*=================================================================== 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 "org_mitk_gui_qt_geometrytools_Activator.h" #include -#include "mitkGeometryToolsView.h" +#include "QmitkGeometryToolsView.h" namespace mitk { void org_mitk_gui_qt_geometrytools_Activator::start(ctkPluginContext* context) { - BERRY_REGISTER_EXTENSION_CLASS(mitkGeometryToolsView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkGeometryToolsView, context) } void org_mitk_gui_qt_geometrytools_Activator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_gui_qt_geometrytools, mitk::org_mitk_gui_qt_geometrytools_Activator) #endif