iMSTK
Interactive Medical Simulation Toolkit
imstkCellPicker.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 "imstkCellPicker.h"
8 #include "imstkAbstractCellMesh.h"
9 #include "imstkCollisionDetectionAlgorithm.h"
10 #include "imstkPointSet.h"
11 
12 namespace imstk
13 {
14 CellPicker::CellPicker()
15 {
16  setRequiredInputType<Geometry>(0);
17 }
18 
19 void
21 {
22  auto geomToPick = std::dynamic_pointer_cast<Geometry>(getInput(0));
23 
24  // Perform collision detection (not for the manifold but just the intersected elements)
25  // Note: collision detection differs from intersection detection in that CD produces
26  // a manifold, not the intersected elements. So not all CDs would work.
27  CHECK(m_colDetect != nullptr) << "Trying to vertex pick but no collision detection provided";
28  m_colDetect->setInputGeometryA(geomToPick);
29  m_colDetect->setInputGeometryB(m_pickGeometry);
30  m_colDetect->update();
31 
32  // When CD reports point contacts we can assume all its connected cells are
33  // intersecting
34  if (auto cellMesh = std::dynamic_pointer_cast<AbstractCellMesh>(geomToPick))
35  {
36  cellMesh->computeVertexToCellMap();
37  }
38 
39  // Used to resolve duplicates (ordered)
40  std::map<int, PickData> resultsMap;
41 
42  const std::vector<CollisionElement>& elementsA = m_colDetect->getCollisionData()->elementsA;
43  for (size_t i = 0; i < elementsA.size(); i++)
44  {
45  // A is always the geometry to pick
46  const CollisionElement& colElemA = elementsA[i];
47  if (colElemA.m_type == CollisionElementType::CellIndex)
48  {
49  PickData data;
50  std::copy(colElemA.m_element.m_CellIndexElement.ids,
51  colElemA.m_element.m_CellIndexElement.ids + 4, data.ids);
52  data.idCount = colElemA.m_element.m_CellIndexElement.idCount;
53  data.cellType = colElemA.m_element.m_CellIndexElement.cellType;
54  data.cellId = colElemA.m_element.m_CellIndexElement.parentId;
55  resultsMap[data.cellId] = data;
56  }
57  else if (colElemA.m_type == CollisionElementType::PointIndexDirection)
58  {
59  const int vertexId = colElemA.m_element.m_PointIndexDirectionElement.ptIndex;
60 
61  // Get the connected cells to the vertex that is intersecting
62  auto cellMesh = std::dynamic_pointer_cast<AbstractCellMesh>(geomToPick);
63  if (cellMesh != nullptr)
64  {
65  const std::vector<std::unordered_set<int>>& vertexToCellMap = cellMesh->getVertexToCellMap();
66  for (auto cellId : vertexToCellMap[vertexId])
67  {
68  PickData data;
69  data.ids[0] = cellId;
70  data.idCount = 1;
71  data.cellId = cellId;
72  const int numComps = cellMesh->getAbstractCells()->getNumberOfComponents();
73  if (numComps == 1)
74  {
75  data.cellType = IMSTK_VERTEX;
76  }
77  else if (numComps == 2)
78  {
79  data.cellType = IMSTK_EDGE;
80  }
81  else if (numComps == 3)
82  {
83  data.cellType = IMSTK_TRIANGLE;
84  }
85  else if (numComps == 4)
86  {
87  data.cellType = IMSTK_TETRAHEDRON;
88  }
89  else
90  {
91  LOG(FATAL) << "Unrecognized cell type";
92  }
93  resultsMap[cellId] = data;
94  }
95  }
96  // Otherwise we have a PointSet
97  else
98  {
99  PickData data;
100  data.ids[0] = vertexId;
101  data.idCount = 1;
102  data.cellId = vertexId;
103  data.cellType = IMSTK_VERTEX;
104  m_results.push_back(data);
105  }
106  }
107  else if (colElemA.m_type == CollisionElementType::PointDirection)
108  {
109  // A cell is not picked but point specified
110  PickData data;
111  data.idCount = 0;
112  data.cellType = IMSTK_VERTEX;
113  // Yeilds the point on body
114  data.pickPoint = colElemA.m_element.m_PointDirectionElement.pt +
115  colElemA.m_element.m_PointDirectionElement.dir *
116  colElemA.m_element.m_PointDirectionElement.penetrationDepth;
117  m_results.push_back(data);
118  }
119  }
120  for (auto pickData : resultsMap)
121  {
122  m_results.push_back(pickData.second);
123  }
124 }
125 } // namespace imstk
std::shared_ptr< Geometry > getInput(size_t port=0) const
Returns input geometry given port, returns nullptr if doesn&#39;t exist.
void requestUpdate() override
Users can implement this for the logic to be run.
Compound Geometry.
int idCount
Indicates number of vertices (if 1 a cell or individual vertex)
int cellId
Supplemental cell id (when vertices are provided above and cell id is available)
Vec3d pickPoint
Some pickings may produce specific points on an element.
Union of collision elements. We use a union to avoid polymorphism. There may be many elements and acc...
Base class for any geometrical representation.
Definition: imstkGeometry.h:22
PickData provides ids to indicate what was picked These may be optionally used to indicate the select...
const std::vector< std::unordered_set< int > > & getVertexToCellMap() const
Returns map of vertices to cells that contain the vertex (reverse linkage)
CellTypeId cellType
Indicates picked cell type.
Provides non templated base for cell based meshes.
int ids[4]
Ids of the cell or vertices.