13 #include "../DataManagement/mitkBoundingShapeUtil.h" 22 #include <vtkCamera.h> 23 #include <vtkInteractorObserver.h> 24 #include <vtkInteractorStyle.h> 25 #include <vtkPointData.h> 26 #include <vtkRenderWindowInteractor.h> 27 #include <vtkSmartPointer.h> 40 class BoundingShapeInteractor::Impl
43 Impl() : ScrollEnabled(
false), RotationEnabled(
false)
46 initialPoint.Fill(0.0);
48 for (
int i = 0; i < 6; ++i)
54 Point3D InitialPickedWorldPoint;
56 Point2D InitialPickedDisplayPoint;
57 std::vector<Handle> Handles;
61 std::map<us::ServiceReferenceU, mitk::EventConfig> DisplayInteractorConfigs;
118 m_Impl->RotationEnabled = rotationEnabled;
125 if (newInputNode ==
nullptr)
134 if (selectedColor.IsNull())
137 if (deselectedColor.IsNull())
144 newInputNode->SetBoolProperty(
"pickable",
true);
148 if (initialColor.IsNotNull())
150 newInputNode->SetColor(initialColor->GetColor());
163 if (m_Impl->Handles.size() == 6)
173 m_Impl->Handles[0].SetPosition(pointLeft);
174 m_Impl->Handles[1].SetPosition(pointRight);
175 m_Impl->Handles[2].SetPosition(pointTop);
176 m_Impl->Handles[3].SetPosition(pointBottom);
177 m_Impl->Handles[4].SetPosition(pointFront);
178 m_Impl->Handles[5].SetPosition(pointBack);
181 center =
CalcAvgPoint(cornerPoints[7], cornerPoints[0]);
198 if (positionEvent ==
nullptr)
207 vtkSmartPointer<vtkMatrix4x4> imageTransform = geometry->GetVtkTransform()->GetMatrix();
208 Point3D center = geometry->GetCenter();
209 auto translation = vtkSmartPointer<vtkTransform>::New();
210 auto transform = vtkSmartPointer<vtkTransform>::New();
211 translation->Translate(center[0] - imageTransform->GetElement(0, 3),
212 center[1] - imageTransform->GetElement(1, 3),
213 center[2] - imageTransform->GetElement(2, 3));
214 transform->SetMatrix(imageTransform);
215 transform->PostMultiply();
216 transform->Concatenate(translation);
220 for (
unsigned int i = 0; i < 3; ++i)
221 extent[i] = (geometry->GetExtent(i));
224 Point2D currentDisplayPosition = positionEvent->GetPointerPositionOnScreen();
228 transformedPosition[0] = currentWorldPosition[0];
229 transformedPosition[1] = currentWorldPosition[1];
230 transformedPosition[2] = currentWorldPosition[2];
231 transformedPosition[3] = 1;
233 transform->GetInverse()->TransformPoint(transformedPosition, transformedPosition);
235 bool isInside = (transformedPosition[0] >= (-extent[0] / 2.0)) && (transformedPosition[0] <= (extent[0] / 2.0)) &&
236 (transformedPosition[1] >= (-extent[1] / 2.0)) && (transformedPosition[1] <= (extent[1] / 2.0)) &&
237 (transformedPosition[2] >= (-extent[2] / 2.0)) && (transformedPosition[2] <= (extent[2] / 2.0));
247 if (positionEvent ==
nullptr)
255 BaseGeometry::Pointer geometry = geometryData->GetUpdatedTimeGeometry()->GetGeometryForTimeStep(timeStep);
263 if (handleSizeProperty !=
nullptr)
264 initialHandleSize = handleSizeProperty->GetValue();
266 initialHandleSize = 1.0 / 40.0;
269 ScalarType handlesize = ((displaysize[0] + displaysize[1]) / 2.0) * initialHandleSize;
270 unsigned int handleNum = 0;
272 for (
auto &handle : m_Impl->Handles)
276 Point2D currentDisplayPosition = positionEvent->GetPointerPositionOnScreen();
278 if ((currentDisplayPosition.EuclideanDistanceTo(centerpoint) < (handlesize / scale)) &&
279 (currentDisplayPosition.EuclideanDistanceTo(displayCenterPoint) >
280 (handlesize / scale)))
282 handle.SetActive(
true);
283 m_Impl->ActiveHandle = handle;
293 handle.SetActive(
false);
303 this->DisableCrosshairNavigation();
311 if (selectedColor.IsNotNull())
323 this->DisableCrosshairNavigation();
339 this->DisableCrosshairNavigation();
347 if (selectedColor.IsNotNull())
349 node->GetPropertyList()->SetProperty(
"color", selectedColor);
359 this->EnableCrosshairNavigation();
368 if (deselectedColor.IsNotNull())
370 node->GetPropertyList()->SetProperty(
"color", deselectedColor);
387 if (positionEvent ==
nullptr)
391 m_Impl->InitialPickedDisplayPoint = positionEvent->GetPointerPositionOnScreen();
392 m_Impl->InitialPickedWorldPoint = positionEvent->GetPositionInWorld();
393 m_Impl->LastPickedWorldPoint = positionEvent->GetPositionInWorld();
401 if (positionEvent ==
nullptr)
407 Vector3D spacing = geometry->GetSpacing();
409 interactionEvent->
GetSender()->
DisplayToWorld(positionEvent->GetPointerPositionOnScreen(), currentPickedPoint);
413 interactionMove[0] = std::round((currentPickedPoint[0] - m_Impl->LastPickedWorldPoint[0]) / spacing[0]) * spacing[0];
414 interactionMove[1] = std::round((currentPickedPoint[1] - m_Impl->LastPickedWorldPoint[1]) / spacing[1]) * spacing[1];
415 interactionMove[2] = std::round((currentPickedPoint[2] - m_Impl->LastPickedWorldPoint[2]) / spacing[2]) * spacing[2];
417 if ((interactionMove[0] + interactionMove[1] + interactionMove[2]) !=
420 m_Impl->LastPickedWorldPoint = currentPickedPoint;
422 geometry->SetOrigin(geometry->GetOrigin() + interactionMove);
434 if (positionEvent ==
nullptr)
438 Point3D handlePickedPoint = m_Impl->ActiveHandle.GetPosition();
440 interactionEvent->
GetSender()->
DisplayToWorld(positionEvent->GetPointerPositionOnScreen(), currentPickedPoint);
443 Vector3D spacing = geometry->GetSpacing();
447 interactionMove[0] = (currentPickedPoint[0] - m_Impl->LastPickedWorldPoint[0]);
448 interactionMove[1] = (currentPickedPoint[1] - m_Impl->LastPickedWorldPoint[1]);
449 interactionMove[2] = (currentPickedPoint[2] - m_Impl->LastPickedWorldPoint[2]);
451 std::vector<int> faces = m_Impl->ActiveHandle.GetFaceIndices();
452 auto pointscontainer = mitk::BoundingBox::PointsContainer::New();
456 unsigned int num = 0;
457 for (
auto point : cornerPoints)
459 pointscontainer->InsertElement(num++, point);
466 faceNormal[0] = handlePickedPoint[0] - center[0];
467 faceNormal[1] = handlePickedPoint[1] - center[1];
468 faceNormal[2] = handlePickedPoint[2] - center[2];
469 Vector3D faceShift = ((faceNormal * interactionMove) / (faceNormal.GetNorm() * faceNormal.GetNorm())) * faceNormal;
474 for (
auto point : cornerPoints)
476 pointscontainer->InsertElement(num++, point);
479 bool positionChangeThreshold =
true;
480 for (
int numFaces = 0; numFaces < 8; numFaces++)
482 if ((numFaces != faces[0]) && (numFaces != faces[1]) && (numFaces != faces[2]) && (numFaces != faces[3]))
484 Point3D point = pointscontainer->GetElement(numFaces);
485 if (m_Impl->RotationEnabled)
487 point[0] += faceShift[0];
488 point[1] += faceShift[1];
489 point[2] += faceShift[2];
493 point[0] += std::round(faceShift[0] / spacing[0]) * spacing[0];
494 point[1] += std::round(faceShift[1] / spacing[1]) * spacing[1];
495 point[2] += std::round(faceShift[2] / spacing[2]) * spacing[2];
498 if (point == pointscontainer->GetElement(numFaces))
499 positionChangeThreshold =
false;
501 m_Impl->LastPickedWorldPoint = point;
503 pointscontainer->InsertElement(numFaces, point);
507 if (positionChangeThreshold)
509 auto inverse = mitk::AffineTransform3D::New();
510 geometry->GetIndexToWorldTransform()->GetInverse(inverse);
511 for (
unsigned int pointid = 0; pointid < 8; pointid++)
513 pointscontainer->InsertElement(pointid, inverse->TransformPoint(pointscontainer->GetElement(pointid)));
516 auto bbox = mitk::BoundingBox::New();
517 bbox->SetPoints(pointscontainer);
518 bbox->ComputeBoundingBox();
521 if (std::abs(BBmin[0] - BBmax[0]) > 0.01 && std::abs(BBmin[1] - BBmax[1]) > 0.01 &&
522 std::abs(BBmin[2] - BBmax[2]) > 0.01)
524 geometry->SetBounds(bbox->GetBounds());
525 geometry->Modified();
537 if (inputNode.IsNull())
541 if (color.IsNotNull())
543 inputNode->GetPropertyList()->SetProperty(
"color", color);
549 EnableCrosshairNavigation();
554 void mitk::BoundingShapeInteractor::EnableCrosshairNavigation()
559 for (
auto it = m_Impl->DisplayInteractorConfigs.begin();
560 it != m_Impl->DisplayInteractorConfigs.end();
567 if (displayInteractor !=
nullptr)
575 m_Impl->DisplayInteractorConfigs.clear();
576 m_Impl->ScrollEnabled =
true;
579 void mitk::BoundingShapeInteractor::DisableCrosshairNavigation()
582 if (m_Impl->ScrollEnabled ==
false)
589 m_Impl->DisplayInteractorConfigs.clear();
590 std::vector<us::ServiceReference<mitk::InteractionEventObserver>> listEventObserver =
592 for (
auto it = listEventObserver.begin();
593 it != listEventObserver.end();
596 auto *displayInteractor =
598 if (displayInteractor !=
nullptr)
601 m_Impl->DisplayInteractorConfigs.insert(std::make_pair(*it, displayInteractor->GetEventConfig()));
603 displayInteractor->SetEventConfig(
"DisplayConfigMITKNoCrosshair.xml");
608 m_Impl->ScrollEnabled =
false;
virtual void SelectObject(StateMachineAction *, InteractionEvent *)
Called if the mouse pointer is over the object indicated by a color change.
void DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const
This method converts a display point to the 3D world index using the geometry of the renderWindow...
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr, bool fallBackOnDataProperties=true) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
virtual void DeselectHandles(StateMachineAction *, InteractionEvent *interactionEvent)
Deselects all Handles at the end of interaction.
Point< ScalarType, 2 > Point2D
const char * boundingShapePropertyName
Super class for all position events.
virtual bool CheckOverObject(const InteractionEvent *)
Checks if the mouse pointer is over the object.
Base class to implement InteractionEventObservers.
Observer that manages the interaction with the display.
BoundingShapeInteractor()
Point2D GetDisplaySizeInMM() const
double GetScaleFactorMMPerDisplayUnit() const
void ConnectActionsAndFunctions() override
const char * activeHandleIdPropertyName
DataCollection - Class to facilitate loading/accessing structured data.
Constants for most interaction classes, due to the generic StateMachines.
virtual void DeselectObject(StateMachineAction *, InteractionEvent *)
Called if the mouse pointer leaves the area of the object.
void HandlePositionChanged(const InteractionEvent *interactionEvent, Point3D ¢er)
std::vector< mitk::Point3D > GetCornerPoints(mitk::BaseGeometry::Pointer geometry, bool visualizationOffset)
helper function for calculating corner points of the bounding object from a given geometry ...
void WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const
This method converts a 3D world index to the display point using the geometry of the renderWindow...
DataNode * GetDataNode() const
virtual void ScaleObject(StateMachineAction *, InteractionEvent *)
Performs a object shape change by influencing the scaling of the initial bounding box...
void * GetService(const ServiceReferenceBase &reference)
std::vector< int > GetHandleIndices(int index)
BaseRenderer * GetSender() const
The ColorProperty class RGB color property.
itk::SmartPointer< Self > Pointer
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
const char * selectedColorPropertyName
virtual bool CheckOverHandles(const InteractionEvent *interactionEvent)
Checks if the mouse pointer is over one of the assigned handles.
bool InitMembers(InteractionEvent *interactionEvent)
Initializes member variables.
void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName="", bool fallBackOnDefaultContext=false) override
Add new or change existent property.
virtual void TranslateObject(StateMachineAction *, InteractionEvent *)
Performs a translation of the object relative to the mouse movement.
static RenderingManager * GetInstance()
Represents an action, that is executed after a certain event (in statemachine-mechanism) TODO: implem...
virtual unsigned int GetTimeStep() const
Data class only having a BaseGeometry but not containing any specific data.
Point< ScalarType, 3 > Point3D
void UpdateOutputInformation() override
Update the information for this BaseData (the geometry in particular) so that it can be used as an ou...
std::vector< ServiceReferenceU > GetServiceReferences(const std::string &clazz, const std::string &filter=std::string())
~BoundingShapeInteractor() override
mitk::PropertyList * GetPropertyList(const mitk::BaseRenderer *renderer=nullptr) const
Get the PropertyList of the renderer. If renderer is nullptr, the BaseRenderer-independent PropertyLi...
virtual void SetDataNode(DataNode *dataNode)
#define CONNECT_CONDITION(a, f)
const mitk::TimeGeometry * GetUpdatedTimeGeometry()
Return the TimeGeometry of the data.
virtual BaseGeometry::Pointer GetGeometryForTimeStep(TimeStepType timeStep) const =0
Returns the geometry which corresponds to the given time step.
virtual void SelectHandle(StateMachineAction *, InteractionEvent *)
Called if the mouse pointer is over one of the handles indicated by a color change.
const float selectedColor[]
void SetRotationEnabled(bool rotationEnabled)
virtual void InitInteraction(StateMachineAction *, InteractionEvent *interactionEvent)
Initializes the movement, stores starting position.
#define CONNECT_FUNCTION(a, f)
const char * deselectedColorPropertyName
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
void SetDataNode(DataNode *dataNode) override
void RequestUpdateAll(RequestType type=REQUEST_UPDATE_ALL)
mitk::Point3D CalcAvgPoint(mitk::Point3D a, mitk::Point3D b)
helper function for calculating the average of two points
Class for nodes of the DataTree.
void DataNodeChanged() override
Called when a DataNode has been set/changed.
bool SetEventConfig(const std::string &filename, const us::Module *module=nullptr)
Loads a configuration from an XML resource.
virtual void RestoreNodeProperties()
Restore default properties of bounding box and handles.