diff --git a/Modules/Simulation/mitkSimulation.cpp b/Modules/Simulation/mitkSimulation.cpp index 9f0e45fa4b..c499c7b059 100644 --- a/Modules/Simulation/mitkSimulation.cpp +++ b/Modules/Simulation/mitkSimulation.cpp @@ -1,231 +1,238 @@ /*=================================================================== 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 "mitkSimulationPropAssemblyVisitor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include const float mitk::Simulation::ScaleFactor = 1000.0f; static sofa::simulation::Simulation::SPtr CreateSimulation(mitk::Simulation::SimulationType type = mitk::Simulation::Tree) { if (type == mitk::Simulation::DAG) return sofa::core::objectmodel::New(); else if (type == mitk::Simulation::Bgl) return sofa::core::objectmodel::New(); else return sofa::core::objectmodel::New(); } void mitk::Simulation::SetActiveSimulation(mitk::Simulation* simulation) { if (simulation == NULL) { sofa::simulation::setSimulation(NULL); sofa::core::visual::VisualParams::defaultInstance()->drawTool() = NULL; } else { sofa::simulation::Simulation* sofaSimulation = simulation->m_Simulation.get(); if (sofa::simulation::getSimulation() != sofaSimulation) { sofa::simulation::setSimulation(sofaSimulation); sofa::core::visual::VisualParams::defaultInstance()->drawTool() = &simulation->m_DrawTool; } } } mitk::Simulation::Simulation() : m_Simulation(CreateSimulation()), m_DefaultDT(0.0) { } mitk::Simulation::~Simulation() { if (m_Simulation != NULL) { if (m_RootNode != NULL) m_Simulation->unload(m_RootNode); if (sofa::simulation::getSimulation() == m_Simulation.get()) SetActiveSimulation(NULL); } } void mitk::Simulation::AppendSnapshot(mitk::Surface::Pointer surface) const { if (surface.IsNull()) return; vtkSmartPointer snapshot = this->CreateSnapshot(); if (snapshot != NULL) - surface->SetVtkPolyData(snapshot, surface->GetTimeSteps()); + { + unsigned int timeStep = surface->GetSizeOfPolyDataSeries(); + + if (timeStep != 0 && surface->GetVtkPolyData(timeStep - 1) == NULL) + --timeStep; + + surface->SetVtkPolyData(snapshot, timeStep); + } } vtkSmartPointer mitk::Simulation::CreateSnapshot() const { if (m_RootNode == NULL) return NULL; vtkSmartPointer propAssembly = vtkSmartPointer::New(); SimulationPropAssemblyVisitor propAssemblyVisitor(propAssembly); m_RootNode->executeVisitor(&propAssemblyVisitor); vtkSmartPointer appendFilter = vtkSmartPointer::New(); vtkPropCollection* propCollection = propAssembly->GetParts(); vtkProp* prop = NULL; for (propCollection->InitTraversal(); (prop = propCollection->GetNextProp()) != NULL; ) { vtkActor* actor = vtkActor::SafeDownCast(prop); vtkPolyData* polyData = vtkPolyData::SafeDownCast(actor->GetMapper()->GetInput()); appendFilter->AddInput(polyData); } vtkSmartPointer scaleTransform = vtkSmartPointer::New(); scaleTransform->Scale(ScaleFactor, ScaleFactor, ScaleFactor); vtkSmartPointer transformFilter = vtkSmartPointer::New(); transformFilter->SetInputConnection(appendFilter->GetOutputPort()); transformFilter->SetTransform(scaleTransform); transformFilter->Update(); vtkSmartPointer snapshot = vtkSmartPointer::New(); snapshot->ShallowCopy(transformFilter->GetOutputDataObject(0)); return snapshot; } double mitk::Simulation::GetDefaultDT() const { return m_DefaultDT; } mitk::SimulationDrawTool* mitk::Simulation::GetDrawTool() { return &m_DrawTool; } sofa::simulation::Node::SPtr mitk::Simulation::GetRootNode() const { return m_RootNode; } sofa::simulation::Simulation::SPtr mitk::Simulation::GetSimulation() const { return m_Simulation; } bool mitk::Simulation::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } void mitk::Simulation::SetAsActiveSimulation() { SetActiveSimulation(this); } void mitk::Simulation::SetDefaultDT(double dt) { m_DefaultDT = std::max(0.0, dt); } void mitk::Simulation::SetRequestedRegion(itk::DataObject*) { } void mitk::Simulation::SetRequestedRegionToLargestPossibleRegion() { } void mitk::Simulation::SetRootNode(sofa::simulation::Node* rootNode) { m_RootNode.reset(rootNode); } mitk::Surface::Pointer mitk::Simulation::TakeSnapshot() const { vtkSmartPointer snapshot = this->CreateSnapshot(); if (snapshot == NULL) return NULL; Surface::Pointer surface = Surface::New(); surface->SetVtkPolyData(snapshot); return surface; } void mitk::Simulation::UpdateOutputInformation() { if (this->GetSource().IsNotNull()) this->GetSource()->UpdateOutputInformation(); if (m_RootNode != NULL) { const sofa::defaulttype::BoundingBox& boundingBox = m_RootNode->f_bbox.getValue(); const sofa::defaulttype::Vector3& min = boundingBox.minBBox(); const sofa::defaulttype::Vector3& max = boundingBox.maxBBox(); mitk::Geometry3D::BoundsArrayType bounds; bounds[0] = static_cast(min.x() * ScaleFactor); bounds[1] = static_cast(max.x() * ScaleFactor); bounds[2] = static_cast(min.y() * ScaleFactor); bounds[3] = static_cast(max.y() * ScaleFactor); bounds[4] = static_cast(min.z() * ScaleFactor); bounds[5] = static_cast(max.z() * ScaleFactor); if(this->GetGeometry() != NULL) { this->GetGeometry()->SetBounds(bounds); } else { Geometry3D::Pointer geometry = Geometry3D::New(); geometry->SetBounds(bounds); this->SetGeometry(geometry); } } this->GetTimeSlicedGeometry()->UpdateInformation(); } bool mitk::Simulation::VerifyRequestedRegion() { return true; } 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 bacd38cfd8..8f8f66f3ae 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp @@ -1,184 +1,233 @@ /*=================================================================== 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 "QmitkSimulationPreferencePage.h" #include "QmitkSimulationView.h" #include #include #include #include #include QmitkSimulationView::QmitkSimulationView() : m_Timer(this) { connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimerTimeout())); initSOFAPlugins(); } QmitkSimulationView::~QmitkSimulationView() { } void QmitkSimulationView::CreateQtPartControl(QWidget* parent) { m_Controls.setupUi(parent); m_Controls.simulationComboBox->SetDataStorage(this->GetDataStorage()); m_Controls.simulationComboBox->SetPredicate(mitk::NodePredicateDataType::New("Simulation")); + m_Controls.stepsRecordedLabel->hide(); + connect(m_Controls.animateButton, SIGNAL(toggled(bool)), this, SLOT(OnAnimateButtonToggled(bool))); + connect(m_Controls.recordButton, SIGNAL(toggled(bool)), this, SLOT(OnRecordButtonToggled(bool))); connect(m_Controls.resetButton, SIGNAL(clicked()), this, SLOT(OnResetButtonClicked())); connect(m_Controls.stepButton, SIGNAL(clicked()), this, SLOT(OnStepButtonClicked())); connect(m_Controls.simulationComboBox, SIGNAL(OnSelectionChanged(const mitk::DataNode*)), this, SLOT(OnSimulationComboBoxSelectionChanged(const mitk::DataNode*))); connect(m_Controls.dtSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnDTSpinBoxValueChanged(double))); connect(m_Controls.snapshotButton, SIGNAL(clicked()), this, SLOT(OnSnapshotButtonClicked())); } void QmitkSimulationView::OnAnimateButtonToggled(bool toggled) { if (this->SetSelectionAsCurrentSimulation()) { - mitk::Simulation::Pointer simulation = dynamic_cast(m_Controls.simulationComboBox->GetSelectedNode()->GetData()); + mitk::Simulation::Pointer simulation = dynamic_cast(m_Selection->GetData()); sofa::simulation::Simulation::SPtr sofaSimulation = simulation->GetSimulation(); sofa::simulation::Node::SPtr rootNode = simulation->GetRootNode(); rootNode->getContext()->setAnimate(toggled); if (toggled) { m_Controls.stepButton->setEnabled(false); m_Timer.start(0); } } if (!toggled) { m_Timer.stop(); m_Controls.stepButton->setEnabled(true); } } void QmitkSimulationView::OnDTSpinBoxValueChanged(double value) { if (!this->SetSelectionAsCurrentSimulation()) return; - mitk::Simulation::Pointer simulation = dynamic_cast(m_Controls.simulationComboBox->GetSelectedNode()->GetData()); + mitk::Simulation::Pointer simulation = dynamic_cast(m_Selection->GetData()); sofa::simulation::Node::SPtr rootNode = simulation->GetRootNode(); rootNode->setDt(value == 0.0 ? simulation->GetDefaultDT() : value); } +void QmitkSimulationView::OnRecordButtonToggled(bool toggled) +{ + if (!toggled) + { + if (m_Record.IsNotNull()) + { + mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); + dataNode->SetData(m_Record); + dataNode->SetName(m_Record->GetTimeSteps() == 1 ? "Snapshot" : "Record"); + + m_Record = NULL; + + this->GetDataStorage()->Add(dataNode, m_Selection); + } + + m_Controls.stepsRecordedLabel->hide(); + m_Controls.stepsRecordedLabel->setText("0 steps recorded"); + } + else if (toggled) + { + m_Controls.stepsRecordedLabel->show(); + } +} + void QmitkSimulationView::OnResetButtonClicked() { if (!this->SetSelectionAsCurrentSimulation()) return; - mitk::Simulation::Pointer simulation = dynamic_cast(m_Controls.simulationComboBox->GetSelectedNode()->GetData()); + if (m_Controls.recordButton->isChecked()) + m_Controls.recordButton->setChecked(false); + + mitk::Simulation::Pointer simulation = dynamic_cast(m_Selection->GetData()); sofa::simulation::Simulation::SPtr sofaSimulation = simulation->GetSimulation(); sofa::simulation::Node::SPtr rootNode = simulation->GetRootNode(); m_Controls.dtSpinBox->setValue(0.0); sofaSimulation->reset(rootNode.get()); rootNode->setTime(0.0); rootNode->execute(sofa::core::ExecParams::defaultInstance()); simulation->GetDrawTool()->Reset(); this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); } void QmitkSimulationView::OnSimulationComboBoxSelectionChanged(const mitk::DataNode* node) { + // TODO: Assign NULL to m_Selection in case it was just removed from data storage. + if (m_Controls.animateButton->isChecked()) m_Controls.animateButton->setChecked(false); + if (m_Controls.recordButton->isChecked()) + m_Controls.recordButton->setChecked(false); + if (node != NULL) { + m_Selection = m_Controls.simulationComboBox->GetSelectedNode(); m_Controls.sceneGroupBox->setEnabled(true); m_Controls.snapshotButton->setEnabled(true); static_cast(node->GetData())->SetAsActiveSimulation(); } else { + m_Selection = NULL; m_Controls.sceneGroupBox->setEnabled(false); m_Controls.snapshotButton->setEnabled(false); mitk::Simulation::SetActiveSimulation(NULL); } } void QmitkSimulationView::OnSnapshotButtonClicked() { if (!this->SetSelectionAsCurrentSimulation()) return; - mitk::DataNode::Pointer simulationDataNode = m_Controls.simulationComboBox->GetSelectedNode(); - mitk::Simulation::Pointer simulation = dynamic_cast(simulationDataNode->GetData()); + mitk::Simulation::Pointer simulation = dynamic_cast(m_Selection->GetData()); mitk::Surface::Pointer snapshot = simulation->TakeSnapshot(); if (snapshot.IsNull()) return; mitk::DataNode::Pointer snapshotDataNode = mitk::DataNode::New(); snapshotDataNode->SetData(snapshot); snapshotDataNode->SetName("Snapshot"); - this->GetDataStorage()->Add(snapshotDataNode, simulationDataNode); + this->GetDataStorage()->Add(snapshotDataNode, m_Selection); } void QmitkSimulationView::OnStepButtonClicked() { if (!this->SetSelectionAsCurrentSimulation()) return; mitk::Simulation::Pointer simulation = dynamic_cast(m_Controls.simulationComboBox->GetSelectedNode()->GetData()); sofa::simulation::Simulation::SPtr sofaSimulation = simulation->GetSimulation(); sofa::simulation::Node::SPtr rootNode = simulation->GetRootNode(); simulation->GetDrawTool()->Reset(); sofaSimulation->animate(rootNode.get(), rootNode->getDt()); this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); + + if (m_Controls.recordButton->isChecked()) + { + if (m_Record.IsNull()) + m_Record = mitk::Surface::New(); + + simulation->AppendSnapshot(m_Record); + + unsigned int numSteps = m_Record->GetTimeSteps(); + QString plural = numSteps != 1 ? "s" : ""; + + m_Controls.stepsRecordedLabel->setText(QString("%1 step%2 recorded").arg(numSteps).arg(plural)); + } } void QmitkSimulationView::SetFocus() { m_Controls.animateButton->setFocus(); } bool QmitkSimulationView::SetSelectionAsCurrentSimulation() const { mitk::DataNode::Pointer selectedNode = m_Controls.simulationComboBox->GetSelectedNode(); if (selectedNode.IsNotNull()) { static_cast(m_Controls.simulationComboBox->GetSelectedNode()->GetData())->SetAsActiveSimulation(); return true; } return false; } void QmitkSimulationView::OnTimerTimeout() { this->OnStepButtonClicked(); } 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 8bcdd8def0..50aa9ca06b 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.h +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.h @@ -1,54 +1,58 @@ /*=================================================================== 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 class QmitkSimulationView : public QmitkAbstractView { Q_OBJECT public: QmitkSimulationView(); ~QmitkSimulationView(); void CreateQtPartControl(QWidget* parent); void SetFocus(); -private: - QmitkSimulationView(const QmitkSimulationView&); - QmitkSimulationView& operator=(const QmitkSimulationView&); - - bool SetSelectionAsCurrentSimulation() const; - - Ui::QmitkSimulationViewControls m_Controls; - QTimer m_Timer; - private slots: void OnAnimateButtonToggled(bool toggled); void OnDTSpinBoxValueChanged(double value); + void OnRecordButtonToggled(bool toggled); void OnResetButtonClicked(); void OnSimulationComboBoxSelectionChanged(const mitk::DataNode* node); void OnSnapshotButtonClicked(); void OnStepButtonClicked(); void OnTimerTimeout(); + +private: + QmitkSimulationView(const QmitkSimulationView&); + QmitkSimulationView& operator=(const QmitkSimulationView&); + + bool SetSelectionAsCurrentSimulation() const; + + Ui::QmitkSimulationViewControls m_Controls; + QTimer m_Timer; + mitk::DataNode::Pointer m_Selection; + mitk::Surface::Pointer m_Record; }; #endif diff --git a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationViewControls.ui b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationViewControls.ui index 9d88c0eba6..12a7bd372f 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationViewControls.ui @@ -1,169 +1,179 @@ QmitkSimulationViewControls true 0 0 301 548 Simulation false Scene 0 0 0 0 Animate true false 0 0 Step 0 0 Reset 0 0 dt 0 0 s 3 0.010000000000000 Surface Recording - - - + + + - Enable Recording + Record + + + true - + false Take Snapshot + + + + 0 step(s) recorded + + + Qt::Vertical 20 421 QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h