iMSTK
Interactive Medical Simulation Toolkit
imstkBurner.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkAnalyticalGeometry.h"
8 #include "imstkBurner.h"
9 #include "imstkCDObjectFactory.h"
10 #include "imstkCellMesh.h"
11 #include "imstkCellPicker.h"
12 #include "imstkParallelUtils.h"
13 #include "imstkPbdObject.h"
14 #include "imstkPbdModel.h"
15 #include "imstkPbdModelConfig.h"
16 #include "imstkPickingAlgorithm.h"
17 #include "imstkTaskGraph.h"
18 #include "imstkTaskNode.h"
19 #include "imstkParallelFor.h"
20 
21 namespace imstk
22 {
23 Burner::Burner(const std::string& name) : SceneBehaviour(true, name)
24 {
25  m_burningHandleNode = std::make_shared<TaskNode>([this]()
26  {
27  handle();
28  }, "Handle_" + m_name);
29 }
30 
31 void
33 {
34  m_burningObj = std::dynamic_pointer_cast<PbdObject>(getEntity().lock());
35 
36  CHECK(m_burningObj != nullptr) << "Burner requires an object to do the burning";
37 
38  if (m_burnGeometry == nullptr)
39  {
40  m_burnGeometry = std::dynamic_pointer_cast<AnalyticalGeometry>(m_burningObj->getPhysicsGeometry());
41  CHECK(m_burnGeometry != nullptr) << "Burner requires analytical geometry for physics geometry";
42  }
43 
44  // Verify that some objects are burnable
45  if (m_burnableObjects.empty())
46  {
47  LOG(INFO) << "There are no burnable objects for the burning tool to burn.";
48  }
49 
50  // Add task nodes
51  m_taskGraph->addNode(m_burningHandleNode);
52  m_taskGraph->addNode(m_burningObj->getPbdModel()->getTaskGraph()->getSink());
53  m_taskGraph->addNode(m_burningObj->getPbdModel()->getIntegratePositionNode());
54  m_taskGraph->addNode(m_burningObj->getPbdModel()->getSolveNode());
55 }
56 
57 void
58 Burner::visualUpdate(const double& dt)
59 {
60  m_burnOnce = true;
61  m_didBurnLastPhysics = m_didBurn;
62  m_didBurn = false;
63  m_burnTime = dt;
64 }
65 
66 bool
67 Burner::getDidBurn() const
68 {
69  return m_didBurnLastPhysics;
70 }
71 
72 void
73 Burner::handle()
74 {
75  // Check tool state
76  if (m_onState && m_burnOnce)
77  {
78  m_burnOnce = false;
79  ParallelUtils::parallelFor(m_burnableObjects.size(), [this](const int index) {
80  handleBurnable(index);
81  }, m_burnableObjects.size() > 1);
82  }
83 }
84 
85 void
86 Burner::handleBurnable(int burnableId)
87 {
88  if (m_burnableObjects[burnableId].object == nullptr)
89  {
90  return;
91  }
92 
93  if (m_burnableObjects[burnableId].picker == nullptr)
94  {
95  // Create Picking Algorithms
96  auto cellPicker = std::make_shared<CellPicker>();
97  cellPicker->setPickingGeometry(m_burnGeometry);
98 
99  std::shared_ptr<Geometry> pbdPhysicsGeom = m_burnableObjects[burnableId].object->getPhysicsGeometry();
100  CHECK(pbdPhysicsGeom != nullptr) << "Physics geometry of burnable object: " << m_burnableObjects[burnableId].object->getName() << " is null in Burner";
101 
102  auto cdType = CDObjectFactory::getCDType(*m_burnGeometry, *pbdPhysicsGeom);
103 
104  // TODO check if we can make the COllision remove burnable if not
105 
106  cellPicker->setCollisionDetection(CDObjectFactory::makeCollisionDetection(cdType));
107 
108  m_burnableObjects[burnableId].picker = cellPicker;
109  }
110 
111  // Perform the picking on the burnable object
112  std::shared_ptr<Geometry> geometryToPick = m_burnableObjects[burnableId].object->getPhysicsGeometry();
113  const std::vector<PickData>& pickData = m_burnableObjects[burnableId].picker->pick(geometryToPick);
114 
115  for (size_t i = 0; i < pickData.size(); i++)
116  {
117  const PickData& data = pickData[i];
118 
119  // If no cell is grabbed, go to next PickData
120  if (data.cellId == -1)
121  {
122  continue;
123  }
124 
125  // Integrate the burn state with time
126  applyBurn(burnableId, data.cellId);
127  }
128 }
129 
130 void
131 Burner::applyBurn(int burnableId, int cellId)
132 {
133  // Get model data
134  // double dt = m_burnableObjects[burnableId].object->getPbdModel()->getConfig()->m_dt;
135 
136  // Mesh state data
137  auto cellMesh = std::dynamic_pointer_cast<AbstractCellMesh>(m_burnableObjects[burnableId].object->getPhysicsGeometry());
138  auto burnDamagePtr = std::dynamic_pointer_cast<DataArray<double>>(cellMesh->getCellAttribute("BurnDamage"));
139  DataArray<double>& burnDamage = *burnDamagePtr;
140 
141  auto burnVisualPtr = std::dynamic_pointer_cast<DataArray<double>>(cellMesh->getCellAttribute("BurnVisual"));
142  DataArray<double>& burnVisual = *burnVisualPtr;
143 
144  monopolarToolModel(burnDamage[cellId], burnVisual[cellId], m_burnTime);
145  m_didBurn = true;
146 }
147 
148 void
149 Burner::monopolarToolModel(double& burnDmg, double& burnVis, double dt)
150 {
151  burnDmg += m_onTime * m_q * m_normWattage * dt;
152  burnVis += (1.0 - m_onTime) * m_q * m_normWattage * dt;
153 }
154 
155 void
156 Burner::initGraphEdges(std::shared_ptr<TaskNode> source, std::shared_ptr<TaskNode> sink)
157 {
158  m_taskGraph->addEdge(source, m_burningObj->getPbdModel()->getIntegratePositionNode());
159  m_taskGraph->addEdge(m_burningObj->getPbdModel()->getIntegratePositionNode(), m_burningHandleNode);
160  m_taskGraph->addEdge(m_burningHandleNode, m_burningObj->getPbdModel()->getSolveNode());
161  m_taskGraph->addEdge(m_burningObj->getPbdModel()->getSolveNode(), m_burningObj->getPbdModel()->getTaskGraph()->getSink());
162  m_taskGraph->addEdge(m_burningObj->getPbdModel()->getTaskGraph()->getSink(), sink);
163 }
164 } // namespace imstk
Base class for any analytical geometrical representation.
void init() override
Initialize the component, called at a later time after all component construction is complete...
Definition: imstkBurner.cpp:32
Compound Geometry.
std::weak_ptr< Entity > getEntity() const
Get parent entity.
int cellId
Supplemental cell id (when vertices are provided above and cell id is available)
static std::shared_ptr< CollisionDetectionAlgorithm > makeCollisionDetection(const std::string collisionTypeName)
attempts to create a new CD algorithm
PickData provides ids to indicate what was picked These may be optionally used to indicate the select...
Base class for scene objects that move and/or deform under position based dynamics formulation...
static std::string getCDType(const Geometry &obj1, const Geometry &obj2)
Get the CD type from the types of objects colliding.
Provides non templated base for cell based meshes.