diff --git a/Modules/Simulation/mitkISimulationService.h b/Modules/Simulation/mitkISimulationService.h index c916e2467d..3406ce7827 100644 --- a/Modules/Simulation/mitkISimulationService.h +++ b/Modules/Simulation/mitkISimulationService.h @@ -1,44 +1,47 @@ /*=================================================================== 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 mitkISimulationService_h #define mitkISimulationService_h #include #include #include namespace mitk { + class Scheduler; + class MitkSimulation_EXPORT ISimulationService { public: virtual Simulation::Pointer GetActiveSimulation() const = 0; virtual void SetActiveSimulation(Simulation::Pointer activeSimulation) = 0; + virtual Scheduler* GetScheduler() = 0; protected: ISimulationService(); virtual ~ISimulationService(); private: ISimulationService(const ISimulationService&); ISimulationService& operator=(const ISimulationService&); }; } US_DECLARE_SERVICE_INTERFACE(mitk::ISimulationService, "org.mitk.ISimulationService"); #endif diff --git a/Modules/Simulation/mitkSchedulableProcess.h b/Modules/Simulation/mitkSchedulableProcess.h index 97bf80b1ff..4c26c26022 100644 --- a/Modules/Simulation/mitkSchedulableProcess.h +++ b/Modules/Simulation/mitkSchedulableProcess.h @@ -1,47 +1,49 @@ /*=================================================================== 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 mitkSchedulableProcess_h #define mitkSchedulableProcess_h #include #include namespace mitk { class MitkSimulation_EXPORT SchedulableProcess { public: explicit SchedulableProcess(int priority = 0); virtual ~SchedulableProcess(); int GetPriority() const; boost::chrono::nanoseconds GetTotalElapsedTime() const; void ResetTotalElapsedTime(boost::chrono::nanoseconds carryover = boost::chrono::nanoseconds::zero()); boost::chrono::nanoseconds GetElapsedTime() const; + + protected: void SetElapsedTime(boost::chrono::nanoseconds elapsedTime); private: SchedulableProcess(const SchedulableProcess&); SchedulableProcess& operator=(const SchedulableProcess&); int m_Priority; boost::chrono::nanoseconds m_TotalElapsedTime; boost::chrono::nanoseconds m_ElapsedTime; }; } #endif diff --git a/Modules/Simulation/mitkSimulation.cpp b/Modules/Simulation/mitkSimulation.cpp index 5127918867..a42c8594b9 100644 --- a/Modules/Simulation/mitkSimulation.cpp +++ b/Modules/Simulation/mitkSimulation.cpp @@ -1,165 +1,167 @@ /*=================================================================== 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 "mitkSimulation.h" #include #include "mitkGeometry3D.h" static sofa::simulation::Simulation::SPtr CreateSimulation() { const std::string key = "MultiMappingObject"; if (sofa::simulation::xml::BaseElement::NodeFactory::HasKey(key)) sofa::simulation::xml::BaseElement::NodeFactory::ResetEntry(key); return sofa::core::objectmodel::New(); } mitk::Simulation::Simulation() : m_SOFASimulation(CreateSimulation()) { } mitk::Simulation::~Simulation() { if (m_RootNode) { if (m_SOFASimulation) m_SOFASimulation->unload(m_RootNode); } } void mitk::Simulation::Animate() { if (!m_RootNode || !m_SOFASimulation) return; + boost::chrono::high_resolution_clock::time_point t0 = boost::chrono::high_resolution_clock::now(); m_SOFASimulation->animate(m_RootNode.get(), m_RootNode->getDt()); + this->SetElapsedTime(boost::chrono::high_resolution_clock::now() - t0); } sofa::core::visual::DrawTool* mitk::Simulation::GetDrawTool() { return &m_DrawTool; } sofa::simulation::Node::SPtr mitk::Simulation::GetRootNode() const { return m_RootNode; } sofa::simulation::Simulation::SPtr mitk::Simulation::GetSOFASimulation() const { return m_SOFASimulation; } void mitk::Simulation::Reset() { if (!m_RootNode || !m_SOFASimulation) return; m_SOFASimulation->reset(m_RootNode.get()); m_RootNode->setTime(0.0); m_SOFASimulation->updateContext(m_RootNode.get()); } bool mitk::Simulation::GetAnimationFlag() const { return m_RootNode ? m_RootNode->getContext()->getAnimate() : false; } void mitk::Simulation::SetAnimationFlag(bool animate) { if (m_RootNode) m_RootNode->getContext()->setAnimate(animate); } void mitk::Simulation::SetDt(double dt) { if (m_RootNode) m_RootNode->setDt(dt); } void mitk::Simulation::SetRootNode(sofa::simulation::Node::SPtr rootNode) { m_RootNode = rootNode; } bool mitk::Simulation::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } void mitk::Simulation::SetRequestedRegion(const itk::DataObject*) { } void mitk::Simulation::SetRequestedRegionToLargestPossibleRegion() { } void mitk::Simulation::UpdateOutputInformation() { using sofa::defaulttype::BoundingBox; using sofa::defaulttype::Vector3; if (this->GetSource().IsNotNull()) this->GetSource()->UpdateOutputInformation(); if (m_RootNode) { const BoundingBox& boundingBox = m_RootNode->f_bbox.getValue(); mitk::Geometry3D::BoundsArrayType bounds; if (boundingBox.isValid()) { const Vector3& min = boundingBox.minBBox(); const Vector3& max = boundingBox.maxBBox(); bounds[0] = static_cast(min.x()); bounds[1] = static_cast(max.x()); bounds[2] = static_cast(min.y()); bounds[3] = static_cast(max.y()); bounds[4] = static_cast(min.z()); bounds[5] = static_cast(max.z()); } else { bounds.Fill(0.0f); } mitk::BaseGeometry::Pointer geometry = this->GetGeometry(); if (geometry.IsNull()) { geometry = Geometry3D::New(); geometry->SetBounds(bounds); this->SetGeometry(geometry); } else { geometry->SetBounds(bounds); } } this->GetTimeGeometry()->Update(); } bool mitk::Simulation::VerifyRequestedRegion() { return true; } diff --git a/Modules/Simulation/mitkSimulationService.cpp b/Modules/Simulation/mitkSimulationService.cpp index b9bc9efc66..280870de9f 100644 --- a/Modules/Simulation/mitkSimulationService.cpp +++ b/Modules/Simulation/mitkSimulationService.cpp @@ -1,56 +1,62 @@ /*=================================================================== 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 "mitkSimulationService.h" #include static void SwitchSimuluationContext(mitk::Simulation::Pointer activeSimulation) { if (activeSimulation.IsNull()) { sofa::simulation::setSimulation(NULL); sofa::core::visual::VisualParams::defaultInstance()->drawTool() = NULL; } else { sofa::simulation::Simulation::SPtr sofaSimulation = activeSimulation->GetSOFASimulation(); if (sofaSimulation != sofa::simulation::getSimulation()) { sofa::simulation::setSimulation(sofaSimulation.get()); sofa::core::visual::VisualParams::defaultInstance()->drawTool() = activeSimulation->GetDrawTool(); } } } mitk::SimulationService::SimulationService() + : m_Scheduler(SchedulingAlgorithm::WeightedRoundRobin) { } mitk::SimulationService::~SimulationService() { } mitk::Simulation::Pointer mitk::SimulationService::GetActiveSimulation() const { return m_ActiveSimulation; } void mitk::SimulationService::SetActiveSimulation(Simulation::Pointer activeSimulation) { SwitchSimuluationContext(activeSimulation); m_ActiveSimulation = activeSimulation; } + +mitk::Scheduler* mitk::SimulationService::GetScheduler() +{ + return &m_Scheduler; +} diff --git a/Modules/Simulation/mitkSimulationService.h b/Modules/Simulation/mitkSimulationService.h index 58f412e18f..9c0796d728 100644 --- a/Modules/Simulation/mitkSimulationService.h +++ b/Modules/Simulation/mitkSimulationService.h @@ -1,38 +1,41 @@ /*=================================================================== 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 mitkSimulationService_h #define mitkSimulationService_h #include +#include namespace mitk { class SimulationService : public ISimulationService { public: SimulationService(); ~SimulationService(); Simulation::Pointer GetActiveSimulation() const; void SetActiveSimulation(Simulation::Pointer activeSimulation); + Scheduler* GetScheduler(); private: Simulation::Pointer m_ActiveSimulation; + Scheduler m_Scheduler; }; } #endif diff --git a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp index 4a718b60a2..1e0e3973b8 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp @@ -1,196 +1,195 @@ /*=================================================================== 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_simulation_Activator.h" #include "QmitkSimulationView.h" #include #include +#include #include template static T* GetService() { ctkPluginContext* context = mitk::org_mitk_gui_qt_simulation_Activator::GetContext(); if (context == NULL) return NULL; ctkServiceReference serviceReference = context->getServiceReference(); return serviceReference ? context->getService(serviceReference) : NULL; } QmitkSimulationView::QmitkSimulationView() : m_SimulationService(GetService()), - m_Scheduler(mitk::SchedulingAlgorithm::WeightedRoundRobin), m_Timer(this) { this->GetDataStorage()->RemoveNodeEvent.AddListener( mitk::MessageDelegate1(this, &QmitkSimulationView::OnNodeRemovedFromDataStorage)); connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimeout())); } QmitkSimulationView::~QmitkSimulationView() { this->GetDataStorage()->RemoveNodeEvent.RemoveListener( mitk::MessageDelegate1(this, &QmitkSimulationView::OnNodeRemovedFromDataStorage)); } void QmitkSimulationView::CreateQtPartControl(QWidget* parent) { m_Controls.setupUi(parent); m_Controls.simulationComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.simulationComboBox->SetPredicate(mitk::NodePredicateDataType::New("Simulation")); connect(m_Controls.simulationComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnSelectedSimulationChanged(const mitk::DataNode*))); connect(m_Controls.animateButton, SIGNAL(toggled(bool)), this, SLOT(OnAnimateButtonToggled(bool))); connect(m_Controls.stepButton, SIGNAL(clicked()), this, SLOT(OnStepButtonClicked())); connect(m_Controls.resetButton, SIGNAL(clicked()), this, SLOT(OnResetButtonClicked())); connect(m_Controls.dtSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDtChanged(double))); if (m_Controls.simulationComboBox->GetSelectedNode().IsNotNull()) this->OnSelectedSimulationChanged(m_Controls.simulationComboBox->GetSelectedNode()); } void QmitkSimulationView::OnAnimateButtonToggled(bool toggled) { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); + mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); if (toggled) { simulation->SetAnimationFlag(true); - m_Scheduler.AddProcess(simulation); + scheduler->AddProcess(simulation); m_Controls.stepButton->setEnabled(false); } else { - m_Scheduler.RemoveProcess(simulation); + scheduler->RemoveProcess(simulation); simulation->SetAnimationFlag(false); m_Controls.stepButton->setEnabled(true); } - if (!m_Scheduler.IsEmpty()) + if (!scheduler->IsEmpty()) { if (!m_Timer.isActive()) m_Timer.start(0); } else { m_Timer.stop(); } } void QmitkSimulationView::OnDtChanged(double dt) { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); simulation->SetDt(std::max(0.0, dt)); } void QmitkSimulationView::OnNodeRemovedFromDataStorage(const mitk::DataNode* node) { mitk::Simulation::Pointer simulation = dynamic_cast(node->GetData()); + mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); if (simulation.IsNotNull()) { - m_Scheduler.RemoveProcess(simulation); + scheduler->RemoveProcess(simulation); - if (m_Scheduler.IsEmpty() && m_Timer.isActive()) + if (scheduler->IsEmpty() && m_Timer.isActive()) m_Timer.stop(); } } void QmitkSimulationView::OnResetButtonClicked() { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_SimulationService->SetActiveSimulation(simulation); m_Controls.dtSpinBox->setValue(simulation->GetRootNode()->getDt()); simulation->Reset(); this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); } void QmitkSimulationView::OnSelectedSimulationChanged(const mitk::DataNode* node) { if (node != NULL) { m_Selection = m_Controls.simulationComboBox->GetSelectedNode(); mitk::Simulation* simulation = static_cast(m_Selection->GetData()); m_Controls.animateButton->setChecked(simulation->GetAnimationFlag()); m_Controls.dtSpinBox->setValue(simulation->GetRootNode()->getDt()); m_Controls.simulationGroupBox->setEnabled(true); } else { m_Controls.simulationGroupBox->setEnabled(false); m_Controls.animateButton->setChecked(false); m_Controls.dtSpinBox->setValue(0.0); } } void QmitkSimulationView::OnStep(bool renderWindowUpdate) { - mitk::Simulation::Pointer simulation = dynamic_cast(m_Scheduler.GetNextProcess()); + mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); + mitk::Simulation::Pointer simulation = dynamic_cast(scheduler->GetNextProcess()); m_SimulationService->SetActiveSimulation(simulation); if (simulation.IsNotNull()) - { - boost::chrono::high_resolution_clock::time_point t0 = boost::chrono::high_resolution_clock::now(); simulation->Animate(); - simulation->SetElapsedTime(boost::chrono::high_resolution_clock::now() - t0); - } if (renderWindowUpdate) this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); } void QmitkSimulationView::OnStepButtonClicked() { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_SimulationService->SetActiveSimulation(simulation); simulation->Animate(); this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); } void QmitkSimulationView::OnTimeout() { QTime currentTime = QTime::currentTime(); if (currentTime.msecsTo(m_NextRenderWindowUpdate) > 0) { this->OnStep(false); } else { m_NextRenderWindowUpdate = currentTime.addMSecs(MSecsPerFrame); this->OnStep(true); } } void QmitkSimulationView::SetFocus() { m_Controls.animateButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.h b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.h index 306f2a7286..0de564fc8a 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.h +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.h @@ -1,64 +1,62 @@ /*=================================================================== 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 QmitkSimulationView_h #define QmitkSimulationView_h -#include #include #include #include #include namespace mitk { class ISimulationService; } class QmitkSimulationView : public QmitkAbstractView { Q_OBJECT public: QmitkSimulationView(); ~QmitkSimulationView(); void CreateQtPartControl(QWidget* parent); void SetFocus(); private slots: void OnAnimateButtonToggled(bool toggled); void OnDtChanged(double dt); void OnResetButtonClicked(); void OnSelectedSimulationChanged(const mitk::DataNode* node); void OnStep(bool renderWindowUpdate); void OnStepButtonClicked(); void OnTimeout(); private: void OnNodeRemovedFromDataStorage(const mitk::DataNode* node); static const int MSecsPerFrame = 17; Ui::QmitkSimulationViewControls m_Controls; mitk::ISimulationService* m_SimulationService; mitk::DataNode::Pointer m_Selection; - mitk::Scheduler m_Scheduler; QTimer m_Timer; QTime m_NextRenderWindowUpdate; }; #endif