diff --git a/Modules/Simulation/mitkPlaneIntersectionVisitor.cpp b/Modules/Simulation/mitkPlaneIntersectionVisitor.cpp index 0cb4e5dbcd..47e4c06c27 100644 --- a/Modules/Simulation/mitkPlaneIntersectionVisitor.cpp +++ b/Modules/Simulation/mitkPlaneIntersectionVisitor.cpp @@ -1,42 +1,136 @@ /*=================================================================== 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 "mitkPlaneIntersectionVisitor.h" #include mitk::PlaneIntersectionVisitor::PlaneIntersectionVisitor(const Point3D& point, const Vector3D& normal, const sofa::core::ExecParams* params) : Visitor(params), m_Point(point), m_Normal(normal) { } mitk::PlaneIntersectionVisitor::~PlaneIntersectionVisitor() { } +const std::vector& mitk::PlaneIntersectionVisitor::GetIntersections() const +{ + return m_Intersections; +} + sofa::simulation::Visitor::Result mitk::PlaneIntersectionVisitor::processNodeTopDown(sofa::simulation::Node* node) { for_each(this, node, node->visualModel, &PlaneIntersectionVisitor::processVisualModel); return RESULT_CONTINUE; } void mitk::PlaneIntersectionVisitor::processVisualModel(sofa::simulation::Node*, sofa::core::visual::VisualModel* visualModel) { using sofa::component::visualmodel::VisualModelImpl; + using sofa::core::topology::Triangle; + using sofa::core::topology::Quad; + using sofa::defaulttype::ResizableExtVector; + + typedef VisualModelImpl::VecCoord VecCoord; VisualModelImpl* visualModelImpl = dynamic_cast(visualModel); + + if (visualModelImpl == NULL) + return; + + const VecCoord& verts = visualModelImpl->getVertices(); + const ResizableExtVector& tris = visualModelImpl->getTriangles(); + const ResizableExtVector& quads = visualModelImpl->getQuads(); + + float n[3] = { static_cast(m_Normal[0]), static_cast(m_Normal[1]), static_cast(m_Normal[2]) }; + float p[3] = { static_cast(m_Point[0]), static_cast(m_Point[1]), static_cast(m_Point[2]) }; + float d[3]; + size_t index; + const float* t0; + const float* t1; + const float* t2; + float s; + Edge edge; + Intersection intersection; + + const size_t numTriangles = tris.size(); + + for (size_t i = 0; i < numTriangles; ++i) + { + t0 = verts[tris[i][0]].data(); + t1 = verts[tris[i][1]].data(); + t2 = verts[tris[i][2]].data(); + + d[0] = n[0] * (p[0] - t0[0]) + n[1] * (p[1] - t0[1]) + n[2] * (p[2] - t0[2]); + d[1] = n[0] * (p[0] - t1[0]) + n[1] * (p[1] - t1[1]) + n[2] * (p[2] - t1[2]); + d[2] = n[0] * (p[0] - t2[0]) + n[1] * (p[1] - t2[1]) + n[2] * (p[2] - t2[2]); + + if (d[0] * d[1] < 0.0f) + { + index = d[0] * d[2] < 0.0f + ? 0 + : 1; + } + else if (d[0] * d[2] < 0.0f) + { + index = 2; + } + else + { + continue; + } + + t0 = verts[tris[i][index]].data(); + t1 = verts[tris[i][(index + 1) % 3]].data(); + t2 = verts[tris[i][(index + 2) % 3]].data(); + + s = (n[0] * (p[0] - t0[0]) + n[1] * (p[1] - t0[1]) + n[2] * (p[2] - t0[2])) / (n[0] * (t1[0] - t0[0]) + n[1] * (t1[1] - t0[1]) + n[2] * (t1[2] - t0[2])); + + edge.v0[0] = static_cast(t0[0] + s * (t1[0] - t0[0])); + edge.v0[1] = static_cast(t0[1] + s * (t1[1] - t0[1])); + edge.v0[2] = static_cast(t0[2] + s * (t1[2] - t0[2])); + + s = (n[0] * (p[0] - t0[0]) + n[1] * (p[1] - t0[1]) + n[2] * (p[2] - t0[2])) / (n[0] * (t2[0] - t0[0]) + n[1] * (t2[1] - t0[1]) + n[2] * (t2[2] - t0[2])); + + edge.v1[0] = static_cast(t0[0] + s * (t2[0] - t0[0])); + edge.v1[1] = static_cast(t0[1] + s * (t2[1] - t0[1])); + edge.v1[2] = static_cast(t0[2] + s * (t2[2] - t0[2])); + + intersection.edges.push_back(edge); + } + + if (!intersection.edges.empty()) + { + const sofa::core::loader::Material& material = visualModelImpl->material.getValue(); + + if (material.useDiffuse) + { + intersection.color[0] = static_cast(material.diffuse[0]); + intersection.color[1] = static_cast(material.diffuse[1]); + intersection.color[2] = static_cast(material.diffuse[2]); + } + else + { + intersection.color[0] = 1.0f; + intersection.color[1] = 1.0f; + intersection.color[2] = 1.0f; + } + + m_Intersections.push_back(intersection); + } } diff --git a/Modules/Simulation/mitkPlaneIntersectionVisitor.h b/Modules/Simulation/mitkPlaneIntersectionVisitor.h index 487eb8860f..52ff75e1e3 100644 --- a/Modules/Simulation/mitkPlaneIntersectionVisitor.h +++ b/Modules/Simulation/mitkPlaneIntersectionVisitor.h @@ -1,46 +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 mitkPlaneIntersectionVisitor_h #define mitkPlaneIntersectionVisitor_h #include #include #include #include namespace mitk { class MitkSimulation_EXPORT PlaneIntersectionVisitor : public sofa::simulation::Visitor { public: + struct Edge + { + Point3D v0; + Point3D v1; + }; + + struct Intersection + { + ScalarType color[3]; + std::vector edges; + }; + PlaneIntersectionVisitor(const Point3D& point, const Vector3D& normal, const sofa::core::ExecParams* params = sofa::core::ExecParams::defaultInstance()); ~PlaneIntersectionVisitor(); + const std::vector& GetIntersections() const; + Result processNodeTopDown(sofa::simulation::Node* node); private: PlaneIntersectionVisitor(const PlaneIntersectionVisitor&); PlaneIntersectionVisitor& operator=(const PlaneIntersectionVisitor&); void processVisualModel(sofa::simulation::Node*, sofa::core::visual::VisualModel* visualModel); Point3D m_Point; Vector3D m_Normal; + + std::vector m_Intersections; }; } #endif diff --git a/Modules/Simulation/mitkSimulationGLMapper2D.cpp b/Modules/Simulation/mitkSimulationGLMapper2D.cpp index 2996ba5a0d..ac0d4e0ca2 100644 --- a/Modules/Simulation/mitkSimulationGLMapper2D.cpp +++ b/Modules/Simulation/mitkSimulationGLMapper2D.cpp @@ -1,68 +1,102 @@ /*=================================================================== 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 #include "mitkPlaneIntersectionVisitor.h" #include "mitkSimulation.h" #include "mitkSimulationGLMapper2D.h" void mitk::SimulationGLMapper2D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer, bool overwrite) { if (node != NULL) { Superclass::SetDefaultProperties(node, renderer, overwrite); } } mitk::SimulationGLMapper2D::SimulationGLMapper2D() { } mitk::SimulationGLMapper2D::~SimulationGLMapper2D() { } void mitk::SimulationGLMapper2D::ApplyColorAndOpacityProperties(BaseRenderer*, vtkActor*) { } void mitk::SimulationGLMapper2D::Paint(BaseRenderer* renderer) { + typedef PlaneIntersectionVisitor::Edge Edge; + typedef PlaneIntersectionVisitor::Intersection Intersection; + if (renderer == NULL) return; SliceNavigationController* sliceNavigationController = renderer->GetSliceNavigationController(); if (sliceNavigationController == NULL) return; const PlaneGeometry* planeGeometry = sliceNavigationController->GetCurrentPlaneGeometry(); if (planeGeometry == NULL) return; DataNode* dataNode = this->GetDataNode(); if (dataNode == NULL) return; Simulation* simulation = static_cast(dataNode->GetData()); if (simulation == NULL) return; PlaneIntersectionVisitor planeIntersectionVisitor(planeGeometry->GetOrigin(), planeGeometry->GetNormal()); simulation->GetRootNode()->executeVisitor(&planeIntersectionVisitor); + + mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); + Point2D point2D; + + const std::vector& intersections = planeIntersectionVisitor.GetIntersections(); + std::vector::const_iterator intersectionsEnd = intersections.end(); + + for (std::vector::const_iterator intersectionIt = intersections.begin(); intersectionIt != intersectionsEnd; ++intersectionIt) + { + const std::vector& edges = intersectionIt->edges; + std::vector::const_iterator edgesEnd = edges.end(); + + glColor3dv(intersectionIt->color); + glBegin(GL_LINES); + + for (std::vector::const_iterator edgeIt = edges.begin(); edgeIt != edgesEnd; ++edgeIt) + { + displayGeometry->Map(edgeIt->v0, point2D); + displayGeometry->WorldToDisplay(point2D, point2D); + + glVertex2dv(point2D.GetDataPointer()); + + displayGeometry->Map(edgeIt->v1, point2D); + displayGeometry->WorldToDisplay(point2D, point2D); + + glVertex2dv(point2D.GetDataPointer()); + } + + glEnd(); + } } 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 07b79e9e8b..7d0673fa2a 100644 --- a/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp +++ b/Plugins/org.mitk.gui.qt.simulation/src/internal/QmitkSimulationView.cpp @@ -1,301 +1,301 @@ /*=================================================================== 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 "QmitkBaseItemDelegate.h" #include "QmitkNoEditItemDelegate.h" #include "QmitkSimulationView.h" #include #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; } static mitk::SimulationInteractor::Pointer CreateSimulationInteractor() { const us::Module* simulationModule = us::ModuleRegistry::GetModule("MitkSimulation"); mitk::SimulationInteractor::Pointer interactor = mitk::SimulationInteractor::New(); interactor->LoadStateMachine("Simulation.xml", simulationModule); interactor->SetEventConfig("SimulationConfig.xml", simulationModule); return interactor; } QmitkSimulationView::QmitkSimulationView() : m_SimulationService(GetService()), m_Interactor(CreateSimulationInteractor()), 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))); connect(m_Controls.sceneTreeWidget, SIGNAL(itemSelectionChanged()), this, SLOT(OnSelectedBaseChanged())); connect(m_Controls.pushButton, SIGNAL(clicked()), this, SLOT(OnButtonClicked())); if (m_Controls.simulationComboBox->GetSelectedNode().IsNotNull()) { this->OnSelectedSimulationChanged(m_Controls.simulationComboBox->GetSelectedNode()); } else { this->SetSimulationControlsEnabled(false); } } void QmitkSimulationView::OnAnimateButtonToggled(bool toggled) { mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); if (toggled) { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); simulation->SetAnimationFlag(true); scheduler->AddProcess(simulation); m_Controls.stepButton->setEnabled(false); } else if (m_Selection.IsNotNull()) { mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); scheduler->RemoveProcess(simulation); simulation->SetAnimationFlag(false); m_Controls.stepButton->setEnabled(true); } if (!scheduler->IsEmpty()) { if (!m_Timer.isActive()) m_Timer.start(0); } else { m_Timer.stop(); } } void QmitkSimulationView::OnDtChanged(double dt) { if (m_Selection.IsNull()) return; 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()); if (simulation.IsNotNull()) { mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); scheduler->RemoveProcess(simulation); if (scheduler->IsEmpty() && m_Timer.isActive()) m_Timer.stop(); if (m_SimulationService->GetActiveSimulation() == simulation) m_SimulationService->SetActiveSimulation(NULL); } } 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); + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } 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()); this->SetSimulationControlsEnabled(true); } else { m_Selection = NULL; this->SetSimulationControlsEnabled(false); m_Controls.animateButton->setChecked(false); m_Controls.dtSpinBox->setValue(0.0); } m_Interactor->SetDataNode(m_Selection); this->ResetSceneTreeWidget(); } void QmitkSimulationView::OnSelectedBaseChanged() { QList selectedBaseItems = m_Controls.sceneTreeWidget->selectedItems(); m_Controls.baseTreeWidget->OnSelectedBaseChanged(!selectedBaseItems.isEmpty() ? m_Controls.sceneTreeWidget->GetBaseFromItem(selectedBaseItems[0]) : NULL); } void QmitkSimulationView::OnStep(bool renderWindowUpdate) { mitk::Scheduler* scheduler = m_SimulationService->GetScheduler(); mitk::Simulation::Pointer simulation = dynamic_cast(scheduler->GetNextProcess()); m_SimulationService->SetActiveSimulation(simulation); if (simulation.IsNotNull()) simulation->Animate(); if (renderWindowUpdate) - this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } void QmitkSimulationView::OnStepButtonClicked() { if (m_Selection.IsNull()) return; mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_SimulationService->SetActiveSimulation(simulation); simulation->Animate(); - this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); + this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_ALL); } 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::ResetSceneTreeWidget() { m_Controls.sceneTreeWidget->clear(); if (m_Selection.IsNull()) return; mitk::Simulation::Pointer simulation = static_cast(m_Selection->GetData()); m_Controls.sceneTreeWidget->addChild(NULL, simulation->GetRootNode().get()); m_Controls.sceneTreeWidget->expandItem(m_Controls.sceneTreeWidget->topLevelItem(0)); } void QmitkSimulationView::SetSimulationControlsEnabled(bool enabled) { m_Controls.animateButton->setEnabled(enabled); m_Controls.stepButton->setEnabled(enabled); m_Controls.resetButton->setEnabled(enabled); m_Controls.dtLabel->setEnabled(enabled); m_Controls.dtSpinBox->setEnabled(enabled); } void QmitkSimulationView::SetFocus() { m_Controls.animateButton->setFocus(); } void QmitkSimulationView::OnButtonClicked() { } /*#include #include #include #include #include void QmitkSimulationView::OnButtonClicked() { vtkRenderWindow* renderWindow = this->GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetVtkRenderWindow(); vtkSmartPointer windowToImageFilter = vtkSmartPointer::New(); windowToImageFilter->SetInput(renderWindow); windowToImageFilter->SetInputBufferTypeToZBuffer(); vtkSmartPointer imageShiftScaleFilter = vtkSmartPointer::New(); imageShiftScaleFilter->SetInputConnection(windowToImageFilter->GetOutputPort()); imageShiftScaleFilter->SetOutputScalarTypeToUnsignedChar(); imageShiftScaleFilter->SetShift(0); imageShiftScaleFilter->SetScale(-255); vtkSmartPointer pngWriter = vtkSmartPointer::New(); pngWriter->SetInputConnection(imageShiftScaleFilter->GetOutputPort()); pngWriter->SetFileName("C:\\Users\\Stefan\\Desktop\\DepthBuffer.png"); pngWriter->Write(); }*/