iMSTK
Interactive Medical Simulation Toolkit
imstkCollisionDetectionAlgorithm.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 "imstkCollisionDetectionAlgorithm.h"
8 #include "imstkAnalyticalGeometry.h"
9 #include "imstkCollisionData.h"
10 #include "imstkSurfaceMesh.h"
11 
12 namespace imstk
13 {
14 CollisionDetectionAlgorithm::CollisionDetectionAlgorithm() : GeometryAlgorithm(),
15  m_collisionDataVector(std::make_shared<std::vector<std::shared_ptr<CollisionData>>>())
16 {
17  m_collisionDataVector->push_back(std::make_shared<CollisionData>());
18  setNumInputPorts(2);
19 }
20 
21 bool
23 {
24  // We allow subclasses to not use input requirements
25  if (m_requiredTypeChecks.size() == 0)
26  {
27  return true;
28  }
29  // Otherwise there must be 2 input ports for CD
30  if (getInput(0) == nullptr)
31  {
32  LOG(WARNING) << "CollisionDetectionAlgorithm missing input A/input 0";
33  return false;
34  }
35  if (getInput(1) == nullptr)
36  {
37  LOG(WARNING) << "CollisionDetectionAlgorithm missing input B/input 1";
38  return false;
39  }
40 
41  // Now type check, CollisionDetection allows reversible inputs
42  GeometryCheck req1 = m_requiredTypeChecks.at(0);
43  GeometryCheck req2 = m_requiredTypeChecks.at(1);
44 
45  if ((req1(getInput(0).get()) && req2(getInput(1).get()))
46  || (req2(getInput(0).get()) && req1(getInput(1).get())))
47  {
48  return true;
49  }
50  else
51  {
52  LOG(WARNING) << "CollisionDetectionAlgorithm invalid input types. Received: ("
53  << getInput(0)->getTypeName() << ", " << getInput(1)->getTypeName() << ")";
54  return false;
55  }
56 }
57 
58 void
60 {
61  // Determine if the input is flipped
62  GeometryCheck req1 = m_requiredTypeChecks.at(0);
63  GeometryCheck req2 = m_requiredTypeChecks.at(1);
64  if ((req1(getInput(0).get()) && req2(getInput(1).get()))
65  || (req2(getInput(0).get()) && req1(getInput(1).get())))
66  {
67  // Determine if the input is flipped so we can flip the output
68  if ((req1(getInput(0).get()) && req2(getInput(1).get())))
69  {
70  m_flipOutput = false;
71  }
72  else if ((req2(getInput(0).get()) && req1(getInput(1).get())))
73  {
74  m_flipOutput = true;
75  }
76  }
77 
78  std::shared_ptr<Geometry> geomA = (*m_collisionDataVector)[0]->geomA = getInput(0);
79  std::shared_ptr<Geometry> geomB = (*m_collisionDataVector)[0]->geomB = getInput(1);
80 
81  std::vector<CollisionElement>* a = &(*m_collisionDataVector)[0]->elementsA;
82  std::vector<CollisionElement>* b = &(*m_collisionDataVector)[0]->elementsB;
83 
84  a->resize(0);
85  b->resize(0);
86 
87  bool genA = m_generateCD_A;
88  bool genB = m_generateCD_B;
89 
90  // If the input geometry is flipped, pass the element vectors and geometry
91  // in flipped so the subclass doesn't have to worry about implementing flipping
92  // and can assume A=type1 and B=type2
93  // Ex: PlaneToSphere has A=Plane, B=Sphere, if user provides flipped input PlaneToSphere
94  // does not need to worry about if A is sphere and B is plane instead
95  if (m_flipOutput)
96  {
97  // Locally swap, output will still be in the order given by input
98  std::swap(a, b);
99  std::swap(geomA, geomB);
100  std::swap(genA, genB);
101  }
102 
103  // If user asked for both A and B
104  if (genA && genB)
105  {
106  // If not implemented it will call A and B separately
107  computeCollisionDataAB(geomA, geomB, *a, *b);
108  }
109  else
110  {
111  // If user asked for just A or just B
112  if (genA)
113  {
114  computeCollisionDataA(geomA, geomB, *a);
115  }
116  if (genB)
117  {
118  computeCollisionDataB(geomA, geomB, *b);
119  }
120 
121  // If asked for A or B but not implemented try AB
122  if ((genA && !m_computeColDataAImplemented)
123  || (genB && !m_computeColDataBImplemented))
124  {
125  computeCollisionDataAB(geomA, geomB, *a, *b);
126  }
127  }
128 }
129 } // namespace imstk
virtual bool areInputsValid() override
Check inputs are correct (always works reversibly)
Compound Geometry.
virtual void requestUpdate() override
Compute the collision data.