diff --git a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp index e10c4b2282..aedf8ae4ed 100644 --- a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp +++ b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp @@ -1,436 +1,436 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include #include #include #include #include // VTK #include #include // us #include #include mitk::InteractionTestHelper::InteractionTestHelper(const std::string &interactionXmlFilePath) : m_InteractionFilePath(interactionXmlFilePath) { this->Initialize(interactionXmlFilePath); } void mitk::InteractionTestHelper::Initialize(const std::string &interactionXmlFilePath) { tinyxml2::XMLDocument document; if (tinyxml2::XML_SUCCESS == document.LoadFile(interactionXmlFilePath.c_str())) { // get RenderingManager instance auto rm = mitk::RenderingManager::GetInstance(); // create data storage m_DataStorage = mitk::StandaloneDataStorage::New(); // for each renderer found create a render window and configure for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()); element != nullptr; element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str())) { // get name of renderer const char *rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); // get view direction mitk::SliceNavigationController::ViewDirection viewDirection = mitk::SliceNavigationController::Axial; if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str()) != nullptr) { int viewDirectionNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str())); viewDirection = static_cast(viewDirectionNum); } // get mapper slot id - mitk::BaseRenderer::MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; + MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr) { int mapperIDNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str())); - mapperID = static_cast(mapperIDNum); + mapperID = static_cast(mapperIDNum); } // Get Size of Render Windows int size[3]; size[0] = size[1] = size[2] = 0; if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str()) != nullptr) { size[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str())); } if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str()) != nullptr) { size[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str())); } if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str()) != nullptr) { size[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str())); } // create renderWindow, renderer and dispatcher auto rw = RenderWindow::New(nullptr, rendererName); // VtkRenderWindow is created within constructor if nullptr if (size[0] != 0 && size[1] != 0) { rw->SetSize(size[0], size[1]); rw->GetRenderer()->Resize(size[0], size[1]); } // set storage of renderer rw->GetRenderer()->SetDataStorage(m_DataStorage); // set view direction to axial rw->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); // set renderer to render 2D rw->GetRenderer()->SetMapperID(mapperID); rw->GetRenderer()->PrepareRender(); // Some more magic for the 3D render window case: // Camera view direction, position and focal point if (mapperID == mitk::BaseRenderer::Standard3D) { if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr) { double cameraFocalPoint[3]; cameraFocalPoint[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str())); cameraFocalPoint[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str())); cameraFocalPoint[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint); } if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr) { double cameraPosition[3]; cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str())); cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str())); cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition); } if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr) { double viewUp[3]; viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str())); viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str())); viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp); } } rw->GetVtkRenderWindow()->Render(); rw->GetVtkRenderWindow()->WaitForCompletion(); // connect SliceNavigationControllers to timestep changed event of TimeNavigationController rw->GetSliceNavigationController()->ConnectGeometryTimeEvent(rm->GetTimeNavigationController()); rm->GetTimeNavigationController()->ConnectGeometryTimeEvent(rw->GetSliceNavigationController()); // add to list of known render windows m_RenderWindowList.push_back(rw); } // TODO: check the following lines taken from QmitkStdMultiWidget and adapt them to be executed in our code here. // mitkWidget1->GetSliceNavigationController() // ->ConnectGeometrySendEvent(mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())); // register interaction event obserer to handle scroll events InitializeDisplayActionEventHandling(); } else { mitkThrow() << "Can not load interaction xml file <" << m_InteractionFilePath << ">"; } // WARNING assumes a 3D window exists !!!! this->AddDisplayPlaneSubTree(); } void mitk::InteractionTestHelper::InitializeDisplayActionEventHandling() { m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New(); m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml"); m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigMITKBase.xml"); m_DisplayActionEventBroadcast->AddEventConfig("DisplayConfigCrosshair.xml"); } mitk::InteractionTestHelper::~InteractionTestHelper() { mitk::RenderingManager *rm = mitk::RenderingManager::GetInstance(); // unregister renderers auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { rm->GetTimeNavigationController()->Disconnect((*it)->GetSliceNavigationController()); (*it)->GetSliceNavigationController()->Disconnect(rm->GetTimeNavigationController()); mitk::BaseRenderer::RemoveInstance((*it)->GetVtkRenderWindow()); } rm->RemoveAllObservers(); } mitk::DataStorage::Pointer mitk::InteractionTestHelper::GetDataStorage() { return m_DataStorage; } void mitk::InteractionTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); this->Set3dCameraSettings(); } void mitk::InteractionTestHelper::PlaybackInteraction() { mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); // load events if not loaded yet if (m_Events.empty()) this->LoadInteraction(); auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { (*it)->GetRenderer()->PrepareRender(); (*it)->GetVtkRenderWindow()->Render(); (*it)->GetVtkRenderWindow()->WaitForCompletion(); } mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); it = m_RenderWindowList.begin(); for (; it != end; ++it) { (*it)->GetVtkRenderWindow()->Render(); (*it)->GetVtkRenderWindow()->WaitForCompletion(); } // mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); // playback all events in queue for (unsigned long i = 0; i < m_Events.size(); ++i) { // let dispatcher of sending renderer process the event m_Events.at(i)->GetSender()->GetDispatcher()->ProcessEvent(m_Events.at(i)); } if (false) { it--; (*it)->GetVtkRenderWindow()->GetInteractor()->Start(); } } void mitk::InteractionTestHelper::LoadInteraction() { // load interaction pattern from xml file std::ifstream xmlStream(m_InteractionFilePath.c_str()); mitk::XML2EventParser parser(xmlStream); m_Events = parser.GetInteractions(); xmlStream.close(); // Avoid VTK warning: Trying to delete object with non-zero reference count. parser.SetReferenceCount(0); } void mitk::InteractionTestHelper::SetTimeStep(int newTimeStep) { mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); bool timeStepIsvalid = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetCreatedWorldGeometry()->IsValidTimeStep( newTimeStep); if (timeStepIsvalid) { mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->SetPos(newTimeStep); } } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByName(const std::string &name) { auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { if (name.compare((*it)->GetRenderer()->GetName()) == 0) return (*it).GetPointer(); } return nullptr; } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByDefaultViewDirection( mitk::SliceNavigationController::ViewDirection viewDirection) { auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { if (viewDirection == (*it)->GetSliceNavigationController()->GetDefaultViewDirection()) return (*it).GetPointer(); } return nullptr; } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindow(unsigned int index) { if (index < m_RenderWindowList.size()) { return m_RenderWindowList.at(index).GetPointer(); } else { return nullptr; } } void mitk::InteractionTestHelper::AddDisplayPlaneSubTree() { // add the displayed planes of the multiwidget to a node to which the subtree // @a planesSubTree points ... mitk::PlaneGeometryDataMapper2D::Pointer mapper; mitk::IntProperty::Pointer layer = mitk::IntProperty::New(1000); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetProperty("name", mitk::StringProperty::New("Widgets")); node->SetProperty("helper object", mitk::BoolProperty::New(true)); m_DataStorage->Add(node); for (auto it : m_RenderWindowList) { if (it->GetRenderer()->GetMapperID() == BaseRenderer::Standard3D) continue; // ... of widget 1 mitk::DataNode::Pointer planeNode1 = (mitk::BaseRenderer::GetInstance(it->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode(); planeNode1->SetProperty("visible", mitk::BoolProperty::New(true)); planeNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane")); planeNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); planeNode1->SetProperty("helper object", mitk::BoolProperty::New(true)); planeNode1->SetProperty("layer", layer); planeNode1->SetColor(1.0, 0.0, 0.0); mapper = mitk::PlaneGeometryDataMapper2D::New(); planeNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper); m_DataStorage->Add(planeNode1, node); } } void mitk::InteractionTestHelper::Set3dCameraSettings() { tinyxml2::XMLDocument document; if (tinyxml2::XML_SUCCESS == document.LoadFile(m_InteractionFilePath.c_str())) { // for each renderer found create a render window and configure for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()); element != nullptr; element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str())) { // get name of renderer const char *rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); // get mapper slot id - mitk::BaseRenderer::MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; + MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr) { int mapperIDNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str())); - mapperID = static_cast(mapperIDNum); + mapperID = static_cast(mapperIDNum); } if (mapperID == mitk::BaseRenderer::Standard3D) { RenderWindow *namedRenderer = nullptr; for (const auto &it : m_RenderWindowList) { if (strcmp(it->GetRenderer()->GetName(), rendererName) == 0) { namedRenderer = it.GetPointer(); break; } } if (namedRenderer == nullptr) { MITK_ERROR << "No match for render window was found."; return; } namedRenderer->GetRenderer()->PrepareRender(); if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr) { double cameraFocalPoint[3]; cameraFocalPoint[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str())); cameraFocalPoint[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str())); cameraFocalPoint[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint); } if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr) { double cameraPosition[3]; cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str())); cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str())); cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition); } if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr) { double viewUp[3]; viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str())); viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str())); viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp); } namedRenderer->GetVtkRenderWindow()->Render(); } } } } diff --git a/Modules/Core/include/mitkBaseRenderer.h b/Modules/Core/include/mitkBaseRenderer.h index adf4d40985..a8dc4ef9be 100644 --- a/Modules/Core/include/mitkBaseRenderer.h +++ b/Modules/Core/include/mitkBaseRenderer.h @@ -1,434 +1,481 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKBASERENDERER_H #define MITKBASERENDERER_H #include "mitkCameraRotationController.h" #include "mitkDataStorage.h" #include "mitkPlaneGeometry.h" #include "mitkPlaneGeometryData.h" #include "mitkSliceNavigationController.h" #include "mitkTimeGeometry.h" #include "mitkBindDispatcherInteractor.h" #include "mitkDispatcher.h" #include #include #include #include namespace mitk { class NavigationController; class SliceNavigationController; class CameraRotationController; class CameraController; class DataStorage; class Mapper; class BaseLocalStorageHandler; class KeyEvent; #pragma GCC visibility push(default) itkEventMacroDeclaration(RendererResetEvent, itk::AnyEvent); #pragma GCC visibility pop - //## @brief Organizes the rendering process - //## - //## Organizes the rendering process. A Renderer contains a reference to a - //## DataStorage and asks the mappers of the data objects to render - //## the data into the renderwindow it is associated to. - //## - //## \#Render() checks if rendering is currently allowed by calling - //## RenderWindow::PrepareRendering(). Initialization of a rendering context - //## can also be performed in this method. - //## - //## The actual rendering code has been moved to \#Repaint() - //## Both \#Repaint() and \#Update() are declared protected now. - //## - //## Note: Separation of the Repaint and Update processes (rendering vs - //## creating a vtk prop tree) still needs to be worked on. The whole - //## rendering process also should be reworked to use VTK based classes for - //## both 2D and 3D rendering. - //## @ingroup Renderer + /* + * \brief Organizes the rendering process + * + * A BaseRenderer contains a reference to a given vtkRenderWindow + * and a corresponding vtkRenderer. + * The BaseRenderer defines which mapper should be used (2D / 3D) + * and which view direction should be rendered. + * + * All existing BaseRenderer are stored in a static variable + * that can be accessed / modified via the static functions. + * VtkPropRenderer is a concrete implementation of a BaseRenderer. + */ class MITKCORE_EXPORT BaseRenderer : public itk::Object { public: - typedef std::map BaseRendererMapType; + + typedef std::map BaseRendererMapType; static BaseRendererMapType baseRendererMap; - static BaseRenderer *GetInstance(vtkRenderWindow *renWin); - static void AddInstance(vtkRenderWindow *renWin, BaseRenderer *baseRenderer); - static void RemoveInstance(vtkRenderWindow *renWin); + static BaseRenderer* GetInstance(vtkRenderWindow* renderWindow); + static void AddInstance(vtkRenderWindow* renderWindow, BaseRenderer* baseRenderer); + static void RemoveInstance(vtkRenderWindow* renderWindow); - static BaseRenderer *GetByName(const std::string &name); - static vtkRenderWindow *GetRenderWindowByName(const std::string &name); + static BaseRenderer* GetByName(const std::string& name); + static vtkRenderWindow* GetRenderWindowByName(const std::string& name); - /** Standard class typedefs. */ mitkClassMacroItkParent(BaseRenderer, itk::Object); - BaseRenderer(const char *name = nullptr, vtkRenderWindow *renWin = nullptr); - - //## @brief MapperSlotId defines which kind of mapper (e.g. 2D or 3D) should be used. - typedef int MapperSlotId; + BaseRenderer(const char* name = nullptr, vtkRenderWindow* renderWindow = nullptr); + /** + * \brief Defines which kind of mapper (e.g. 2D or 3D) should be used. + */ enum StandardMapperSlot { Standard2D = 1, Standard3D = 2 }; - //## @brief Possible view directions for render windows. + /** + * \brief Defines which view direction should be rendered. + */ enum class ViewDirection { AXIAL = 0, SAGITTAL, CORONAL, THREE_D }; void RemoveAllLocalStorages(); - void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler* lsh); - void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler* lsh); + void RegisterLocalStorageHandler(BaseLocalStorageHandler* lsh); + void UnregisterLocalStorageHandler(BaseLocalStorageHandler* lsh); + + virtual void SetDataStorage(DataStorage* storage); - virtual void SetDataStorage(DataStorage *storage); + virtual DataStorage::Pointer GetDataStorage() const + { + return m_DataStorage.GetPointer(); + } - //## return the DataStorage that is used for rendering - virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); } + vtkRenderWindow* GetRenderWindow() const + { + return m_RenderWindow; + } - //## @brief Access the RenderWindow into which this renderer renders. - vtkRenderWindow *GetRenderWindow() const { return m_RenderWindow; } - vtkRenderer *GetVtkRenderer() const { return m_VtkRenderer; } + vtkRenderer* GetVtkRenderer() const + { + return m_VtkRenderer; + } - //## @brief Returns the Dispatcher which handles Events for this BaseRenderer + /** + * \brief Get the dispatcher, which handles events for this base renderer. + */ Dispatcher::Pointer GetDispatcher() const; - //## @brief Default mapper id to use. - static const MapperSlotId defaultMapper; - - //## @brief Do the rendering and flush the result. + /** + * \brief Do the rendering and flush the result. + */ virtual void Paint(); - //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. + /** + * \brief Initialize the RenderWindow. Should only be called from RenderWindow. + */ virtual void Initialize(); - //## @brief Called to inform the renderer that the RenderWindow has been resized. + /** + * \brief Set a new size for the render window. + */ virtual void Resize(int w, int h); - //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). - virtual void InitRenderer(vtkRenderWindow *renderwindow); + /** + * \brief Initialize the base renderer with a vtk render window. + * Set the new renderer for the camera controller. + */ + virtual void InitRenderer(vtkRenderWindow* renderwindow); - //## @brief Set the initial size. Called by RenderWindow after it has become - //## visible for the first time. + /** + * \brief Set the initial size for the render window. + */ virtual void InitSize(int w, int h); - //## @brief Draws a point on the widget. - //## Should be used during conferences to show the position of the remote mouse - virtual void DrawOverlayMouse(Point2D &p2d); - - //## @brief Set/Get the WorldGeometry (m_WorldGeometry) for 3D and 2D rendering, that describing the - //## (maximal) area to be rendered. - //## - //## Depending of the type of the passed BaseGeometry more or less information can be extracted: - //## \li if it is a PlaneGeometry (which is a sub-class of BaseGeometry), m_CurrentWorldPlaneGeometry is - //## also set to point to it. m_WorldTimeGeometry is set to nullptr. - //## \li if it is a TimeGeometry, m_WorldTimeGeometry is also set to point to it. - //## If m_WorldTimeGeometry contains instances of SlicedGeometry3D, m_CurrentWorldPlaneGeometry is set to - //## one of geometries stored in the SlicedGeometry3D according to the value of m_Slice; otherwise - //## a PlaneGeometry describing the top of the bounding-box of the BaseGeometry is set as the - //## m_CurrentWorldPlaneGeometry. - //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the BaseGeometry - //## is set as the m_CurrentWorldPlaneGeometry. m_WorldTimeGeometry is set to nullptr. - //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the BaseGeometry - //## when the passed BaseGeometry is not sliced. - //## \sa m_WorldGeometry - //## \sa m_WorldTimeGeometry - //## \sa m_CurrentWorldPlaneGeometry - virtual void SetWorldTimeGeometry(const mitk::TimeGeometry *geometry); + virtual void DrawOverlayMouse(Point2D&) + { + MITK_INFO << "BaseRenderer::DrawOverlayMouse() should be in concret implementation OpenGLRenderer." << std::endl; + } + /** + * \brief Set the world time geometry using the given TimeGeometry. + * + * Setting a new world time geometry updates the current world geometry and the + * curent world plane geometry, using the currently selected slice and timestep. + */ + virtual void SetWorldTimeGeometry(const mitk::TimeGeometry* geometry); itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry); - //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering + /** + * \brief Get the current time-extracted 3D-geometry. + */ itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry); - //## @brief Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering - itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry) + /** + * \brief Get the current slice-extracted 2D-geometry. + */ + itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry); - //## Calculates the bounds of the DataStorage (if it contains any valid data), - //## creates a geometry from these bounds and sets it as world geometry of the renderer. - //## - //## Call this method to re-initialize the renderer to the current DataStorage - //## (e.g. after loading an additional dataset), to ensure that the view is - //## aligned correctly. - //## \warning This is not implemented yet. - virtual bool SetWorldGeometryToDataStorageBounds() { return false; } + virtual bool SetWorldGeometryToDataStorageBounds() + { + return false; + } - //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry - //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry + /** + * \brief Set the slice that should be used for geometry extraction. + * + * The slice defines the current slice-extracted 2D-geometry (CurrentWorldPlaneGeometry). + * Setting a new slice will update the current world geometry and the + * curent world plane geometry. + */ virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int); - //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry - //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry + /** + * \brief Set the timestep that should be used for geometry extraction. + * + * The timestep defines the current time-extracted 3D-geometry (CurrentWorldGeometry). + * Setting a new timestep will update the current world geometry and the + * curent world plane geometry. + */ virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int); - //## @brief Get the time-step of a BaseData object which - //## exists at the time of the currently displayed content - //## - //## Returns -1 or mitk::BaseData::m_TimeSteps if there - //## is no data at the current time. - TimeStepType GetTimeStep(const BaseData *data) const; - - //## @brief Get the time in ms of the currently displayed content - //## + /** + * \brief Get the timestep of a BaseData object which + * exists at the time of the currently displayed content. + * + * Returns -1 if there is no data at the current time. + */ + TimeStepType GetTimeStep(const BaseData* data) const; + + /** + * \brief Get the time in ms of the currently display content (geometry). + */ ScalarType GetTime() const; - //## @brief SetWorldGeometry is called according to the geometrySliceEvent, - //## which is supposed to be a SliceNavigationController::GeometrySendEvent - virtual void SetGeometry(const itk::EventObject &geometrySliceEvent); - - //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the - //## slice navigation controller - virtual void UpdateGeometry(const itk::EventObject &geometrySliceEvent); - - //## @brief SetSlice is called according to the geometrySliceEvent, - //## which is supposed to be a SliceNavigationController::GeometrySliceEvent - virtual void SetGeometrySlice(const itk::EventObject &geometrySliceEvent); - - //## @brief SetTimeStep is called according to the geometrySliceEvent, - //## which is supposed to be a SliceNavigationController::GeometryTimeEvent - virtual void SetGeometryTime(const itk::EventObject &geometryTimeEvent); - - //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry - // m_CurrentWorldPlaneGeometry (for 2D rendering) - itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode) - - //## @brief Sets timestamp of CurrentWorldPlaneGeometry and forces so reslicing in that renderwindow + /** + * \brief Set the world time geometry using the geometry of the given event. + * + * The function is triggered by a SliceNavigationController::GeometrySendEvent. + */ + virtual void SetGeometry(const itk::EventObject& geometrySliceEvent); + + /** + * \brief Set the current world plane geometry using the existing current world geometry. + * + * The function is triggered by a SliceNavigationController::GeometryUpdateEvent. + */ + virtual void UpdateGeometry(const itk::EventObject& geometrySliceEvent); + + /** + * \brief Set the current slice using "SetSlice" and update the current world geometry + * and the current world plane geometry. + * + * The function is triggered by a SliceNavigationController::GeometrySliceEvent. + */ + virtual void SetGeometrySlice(const itk::EventObject& geometrySliceEvent); + + /** + * \brief Set the current time using "SetTimeStep" and update the current world geometry + * and the current world plane geometry. + * + * The function is triggered by a TimeNavigationController::TimeEvent. + */ + virtual void SetGeometryTime(const itk::EventObject& geometryTimeEvent); + + itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode); + + /** + * \brief Modify the update time of the current world plane geometry and force reslicing. + */ void SendUpdateSlice(); - //## @brief Get timestamp of last call of SetCurrentWorldPlaneGeometry + /** + * \brief Get timestamp of the update time of the current world plane geometry. + */ itkGetMacro(CurrentWorldPlaneGeometryUpdateTime, unsigned long); - //## @brief Get timestamp of last change of current TimeStep + /** + * \brief Get timestamp of the update time of the current timestep. + */ itkGetMacro(TimeStepUpdateTime, unsigned long); - //## @brief Perform a picking: find the x,y,z world coordinate of a - //## display x,y coordinate. - //## @warning Has to be overwritten in subclasses for the 3D-case. - //## - //## Implemented here only for 2D-rendering - virtual void PickWorldPoint(const Point2D &diplayPosition, Point3D &worldPosition) const = 0; - - /** \brief Determines the object (mitk::DataNode) closest to the current - * position by means of picking - * - * \warning Implementation currently empty for 2D rendering; intended to be - * implemented for 3D renderers */ - virtual DataNode *PickObject(const Point2D & /*displayPosition*/, Point3D & /*worldPosition*/) const + /** + * \brief Pick a world coordinate (x,y,z) given a display coordinate (x,y). + * + * \warning Not implemented; has to be overwritten in subclasses. + */ + virtual void PickWorldPoint(const Point2D& diplayPosition, Point3D& worldPosition) const = 0; + + /** + * \brief Determines the object (mitk::DataNode) closest to the current + * position by means of picking. + * + * \warning Implementation currently empty for 2D rendering; intended to be + * implemented for 3D renderers. + */ + virtual DataNode* PickObject(const Point2D& /*displayPosition*/, Point3D& /*worldPosition*/) const { return nullptr; } - //## @brief Get the MapperSlotId to use. + /** + * \brief Get the currently used mapperID. + */ itkGetMacro(MapperID, MapperSlotId); itkGetConstMacro(MapperID, MapperSlotId); - //## @brief Set the MapperSlotId to use. + /** + * \brief Set the used mapperID. + */ virtual void SetMapperID(MapperSlotId id); - virtual int *GetSize() const; - virtual int *GetViewportSize() const; + virtual int* GetSize() const; + virtual int* GetViewportSize() const; - void SetSliceNavigationController(SliceNavigationController *SlicenavigationController); + void SetSliceNavigationController(SliceNavigationController* SlicenavigationController); itkGetObjectMacro(CameraController, CameraController); itkGetObjectMacro(SliceNavigationController, SliceNavigationController); itkGetObjectMacro(CameraRotationController, CameraRotationController); itkGetMacro(EmptyWorldGeometry, bool); - //## @brief Tells if the displayed region is shifted and rescaled if the render window is resized. - itkGetMacro(KeepDisplayedRegion, bool) - - //## @brief Tells if the displayed region should be shifted and rescaled if the render window is resized. + /** + * \brief Getter/Setter for defining if the displayed region should be shifted + * or rescaled if the render window is resized. + */ + itkGetMacro(KeepDisplayedRegion, bool); itkSetMacro(KeepDisplayedRegion, bool); - //## @brief get the name of the Renderer - //## @note - const char *GetName() const + /** + * \brief Return the name of the base renderer + */ + const char* GetName() const { return m_Name.c_str(); } - //## @brief get the x_size of the RendererWindow - //## @note - int GetSizeX() const { return GetSize()[0]; } + /** + * \brief Return the size in x-direction of the base renderer. + */ + int GetSizeX() const + { + return this->GetSize()[0]; + } + + /** + * \brief Return the size in y-direction of the base renderer. + */ + int GetSizeY() const + { + return this->GetSize()[1]; + } - //## @brief get the y_size of the RendererWindow - //## @note - int GetSizeY() const { return GetSize()[1]; } - const double *GetBounds() const; + /** + * \brief Return the bounds of the bounding box of the + * current world geometry (time-extracted 3D-geometry). + * + * If the geometry is empty, the bounds are set to zero. + */ + const double* GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); - /** Returns number of mappers which are visible and have level-of-detail - * rendering enabled */ + /** + * \brief Return the number of mappers which are visible and have + * level-of-detail rendering enabled. + */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; - //## @brief This method converts a display point to the 3D world index - //## using the geometry of the renderWindow. - void DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const; - - //## @brief This method converts a display point to the 2D world index, mapped onto the display plane - //## using the geometry of the renderWindow. - void DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const; - - //## @brief This method converts a 3D world index to the display point - //## using the geometry of the renderWindow. - void WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const; - - //## @brief This method converts a 3D world index to the point on the viewport - //## using the geometry of the renderWindow. - void WorldToView(const Point3D &worldIndex, Point2D &viewPoint) const; - - //## @brief This method converts a 2D plane coordinate to the display point - //## using the geometry of the renderWindow. - void PlaneToDisplay(const Point2D &planePointInMM, Point2D &displayPoint) const; - - //## @brief This method converts a 2D plane coordinate to the point on the viewport - //## using the geometry of the renderWindow. - void PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const; + /** + * \brief Convert a display point to the 3D world index + * using the geometry of the renderWindow. + */ + void DisplayToWorld(const Point2D& displayPoint, Point3D& worldIndex) const; + + /** + * \brief Convert a display point to the 2D world index, mapped onto the display plane + * using the geometry of the renderWindow. + */ + void DisplayToPlane(const Point2D& displayPoint, Point2D& planePointInMM) const; + + /** + * \brief Convert a 3D world index to the display point + * using the geometry of the renderWindow. + */ + void WorldToDisplay(const Point3D& worldIndex, Point2D& displayPoint) const; + + /** + * \brief Convert a 3D world index to the point on the viewport + * using the geometry of the renderWindow. + */ + void WorldToView(const Point3D& worldIndex, Point2D& viewPoint) const; + + /** + * \brief Convert a 2D plane coordinate to the display point + * using the geometry of the renderWindow. + */ + void PlaneToDisplay(const Point2D& planePointInMM, Point2D& displayPoint) const; + + /** + * \brief Convert a 2D plane coordinate to the point on the viewport + * using the geometry of the renderWindow. + */ + void PlaneToView(const Point2D& planePointInMM, Point2D& viewPoint) const; double GetScaleFactorMMPerDisplayUnit() const; Point2D GetDisplaySizeInMM() const; Point2D GetViewportSizeInMM() const; Point2D GetOriginInMM() const; itkGetConstMacro(ConstrainZoomingAndPanning, bool) virtual void SetConstrainZoomingAndPanning(bool constrain); protected: ~BaseRenderer() override; - //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; - vtkRenderWindow *m_RenderWindow; - vtkRenderer *m_VtkRenderer; + vtkRenderWindow* m_RenderWindow; + vtkRenderer* m_VtkRenderer; - //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; - - //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; - - //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; - //## @brief CameraController for 3D rendering - //## @note preliminary. itk::SmartPointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; void UpdateCurrentGeometries(); - - //## @brief Sets m_CurrentWorldPlaneGeometry - virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry *geometry2d); - - //## @brief Sets m_CurrentWorldGeometry + virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry* geometry2d); virtual void SetCurrentWorldGeometry(const BaseGeometry *geometry); private: - //## m_WorldTimeGeometry is set by SetWorldGeometry if the passed BaseGeometry is a - //## TimeGeometry (or a sub-class of it). If it contains instances of SlicedGeometry3D, - //## m_Slice and m_TimeStep (set via SetSlice and SetTimeStep, respectively) define - //## which 2D geometry stored in m_WorldTimeGeometry (if available) - //## is used as m_CurrentWorldPlaneGeometry. - //## \sa m_CurrentWorldPlaneGeometry + /** + * \brief Pointer to the current TimeGeometry. + * + * This WorldTimeGeometry is used to extract a SlicedGeometry3D, + * using the current timestep (set via SetTimeStep). + * The time-extracted 3D-geometry is used as the "CurrentWorldgeometry". + * It will be set using the "SetCurrentWorldGeometry"-function. + * A PlaneGeometry can further be extracted using the current slice (set via SetSlice). + * The slice-extracted 2D-geometry is used as the "CurrentWorldPlaneGeometry". + * It will be set using the "SetCurrentWorldPlaneGeometry"-function. + */ TimeGeometry::ConstPointer m_WorldTimeGeometry; - //## Pointer to the current 3D-worldgeometry. + /** + * \brief Pointer to the current time-extracted 3D-geometry. + * + * This CurrentWorldGeometry is used to define the bounds for this + * BaseRenderer. + * It will be set using the "SetCurrentWorldGeometry"-function. + */ BaseGeometry::ConstPointer m_CurrentWorldGeometry; - //## Pointer to the current 2D-worldgeometry. The 2D-worldgeometry - //## describes the maximal area (2D manifold) to be rendered in case we - //## are doing 2D-rendering. - //## It is const, since we are not allowed to change it (it may be taken - //## directly from the geometry of an image-slice and thus it would be - //## very strange when suddenly the image-slice changes its geometry). + /** + * \brief Pointer to the current slice-extracted 2D-geometry. + * + * This CurrentWorldPlaneGeometry is used to define the maximal + * area (2D manifold) to be rendered in case we are doing 2D-rendering. + * It will be set using the "SetCurrentWorldPlaneGeometry"-function. + */ PlaneGeometry::Pointer m_CurrentWorldPlaneGeometry; - //## Defines together with m_TimeStep which 2D geometry stored in m_WorldTimeGeometry - //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep). - //## \sa m_WorldTimeGeometry unsigned int m_Slice; - - //## Defines together with m_Slice which 2D geometry stored in m_WorldTimeGeometry - //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep). - //## \sa m_WorldTimeGeometry unsigned int m_TimeStep; - //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime; - - //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; - //## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage. - BindDispatcherInteractor *m_BindDispatcherInteractor; + BindDispatcherInteractor* m_BindDispatcherInteractor; - //## @brief Tells if the displayed region should be shifted or rescaled if the render window is resized. bool m_KeepDisplayedRegion; protected: - void PrintSelf(std::ostream &os, itk::Indent indent) const override; + void PrintSelf(std::ostream& os, itk::Indent indent) const override; - //## Data object containing the m_CurrentWorldPlaneGeometry defined above. PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData; - - //## DataNode objects containing the m_CurrentWorldPlaneGeometryData defined above. DataNode::Pointer m_CurrentWorldPlaneGeometryNode; - - //## @brief test only unsigned long m_CurrentWorldPlaneGeometryTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; - typedef std::set LODEnabledMappersType; + typedef std::set LODEnabledMappersType; - /** Number of mappers which are visible and have level-of-detail - * rendering enabled */ unsigned int m_NumberOfVisibleLODEnabledMappers; - // Local Storage Handling for mappers - std::list m_RegisteredLocalStorageHandlers; + std::list m_RegisteredLocalStorageHandlers; bool m_ConstrainZoomingAndPanning; - }; } // namespace mitk #endif // MITKBASERENDERER_H diff --git a/Modules/Core/src/Interactions/mitkEventRecorder.cpp b/Modules/Core/src/Interactions/mitkEventRecorder.cpp index 11bdf36c00..429f00c5bd 100644 --- a/Modules/Core/src/Interactions/mitkEventRecorder.cpp +++ b/Modules/Core/src/Interactions/mitkEventRecorder.cpp @@ -1,188 +1,188 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkEventRecorder.h" #include "mitkEventFactory.h" #include "mitkInteractionEvent.h" #include "mitkInteractionEventConst.h" #include "vtkCamera.h" #include "mitkBaseRenderer.h" static void WriteEventXMLHeader(std::ofstream &stream) { stream << mitk::InteractionEventConst::xmlHead() << "\n"; } static void WriteEventXMLConfig(std::ofstream &stream) { // stream << " <" << mitk::InteractionEventConst::xmlTagConfigRoot() << ">\n"; // write renderer config // for all registered 2D renderers write name and viewdirection. auto rendererIterator = mitk::BaseRenderer::baseRendererMap.begin(); auto end = mitk::BaseRenderer::baseRendererMap.end(); for (; rendererIterator != end; ++rendererIterator) { std::string rendererName = (*rendererIterator).second->GetName(); mitk::SliceNavigationController::ViewDirection viewDirection = (*rendererIterator).second->GetSliceNavigationController()->GetDefaultViewDirection(); - mitk::BaseRenderer::MapperSlotId mapperID = (*rendererIterator).second->GetMapperID(); + MapperSlotId mapperID = (*rendererIterator).second->GetMapperID(); // stream << " <" << mitk::InteractionEventConst::xmlTagRenderer() << " " << mitk::InteractionEventConst::xmlEventPropertyRendererName() << "=\"" << rendererName << "\" " << mitk::InteractionEventConst::xmlEventPropertyViewDirection() << "=\"" << viewDirection << "\" " << mitk::InteractionEventConst::xmlEventPropertyMapperID() << "=\"" << mapperID << "\" " << mitk::InteractionEventConst::xmlRenderSizeX() << "=\"" << (*rendererIterator).second->GetSize()[0] << "\" " << mitk::InteractionEventConst::xmlRenderSizeY() << "=\"" << (*rendererIterator).second->GetSize()[1] << "\" " << mitk::InteractionEventConst::xmlRenderSizeZ() << "=\"" << (*rendererIterator).second->GetSize()[2] << "\" "; ; if ((*rendererIterator).second->GetMapperID() == mitk::BaseRenderer::Standard3D) { // For a 3D render window, rotation and zoom settings are determined by the vtkCamera parameters // these are recorded here: stream << mitk::InteractionEventConst::xmlViewUpX() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetViewUp()[0] << "\" " << mitk::InteractionEventConst::xmlViewUpY() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetViewUp()[1] << "\" " << mitk::InteractionEventConst::xmlViewUpZ() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetViewUp()[2] << "\" " << mitk::InteractionEventConst::xmlCameraFocalPointX() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint()[0] << "\" " << mitk::InteractionEventConst::xmlCameraFocalPointY() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint()[1] << "\" " << mitk::InteractionEventConst::xmlCameraFocalPointZ() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint()[2] << "\" " << mitk::InteractionEventConst::xmlCameraPositionX() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetPosition()[0] << "\" " << mitk::InteractionEventConst::xmlCameraPositionY() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetPosition()[1] << "\" " << mitk::InteractionEventConst::xmlCameraPositionZ() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetPosition()[2] << "\" "; } stream << "/>\n"; } // stream << " \n"; } static void WriteEventXMLEventsOpen(std::ofstream &stream) { stream << " <" << mitk::InteractionEventConst::xmlTagEvents() << ">\n"; } static void WriteEventXMLEventsClose(std::ofstream &stream) { stream << " \n"; } static void WriteEventXMLInteractionsOpen(std::ofstream &stream) { stream << "<" << mitk::InteractionEventConst::xmlTagInteractions() << ">\n"; } static void WriteEventXMLInteractionsClose(std::ofstream &stream) { stream << ""; } static void WriteEventXMLClose(std::ofstream &stream) { WriteEventXMLEventsClose(stream); WriteEventXMLInteractionsClose(stream); } mitk::EventRecorder::EventRecorder() : m_Active(false) { } mitk::EventRecorder::~EventRecorder() { if (m_FileStream.is_open()) { m_FileStream.flush(); m_FileStream.close(); } } void mitk::EventRecorder::Notify(mitk::InteractionEvent *interactionEvent, bool /*isHandled*/) { if (m_FileStream.is_open()) m_FileStream << EventFactory::EventToXML(interactionEvent) << "\n"; } void mitk::EventRecorder::SetEventIgnoreList(std::vector list) { m_IgnoreList = list; } void mitk::EventRecorder::StartRecording() { if (m_FileName == "") { MITK_ERROR << "EventRecorder::StartRecording - Filename needs to be set first."; return; } if (m_FileStream.is_open()) { MITK_ERROR << "EventRecorder::StartRecording - Still recording. Stop recording before starting it again."; return; } m_FileStream.open(m_FileName.c_str(), std::ofstream::out); if (!m_FileStream.good()) { MITK_ERROR << "File " << m_FileName << " could not be opened!"; m_FileStream.close(); return; } m_Active = true; // write head and config // // // // // // ... // // WriteEventXMLHeader(m_FileStream); WriteEventXMLInteractionsOpen(m_FileStream); WriteEventXMLConfig(m_FileStream); WriteEventXMLEventsOpen(m_FileStream); } void mitk::EventRecorder::StopRecording() { if (m_FileStream.is_open()) { // write end tag // // WriteEventXMLClose(m_FileStream); m_FileStream.flush(); m_FileStream.close(); m_Active = false; } }