iMSTK
Interactive Medical Simulation Toolkit
imstkImplicitGeometryToPointSetCD.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 "imstkImplicitGeometryToPointSetCD.h"
8 #include "imstkCollisionData.h"
9 #include "imstkImageData.h"
10 #include "imstkImplicitGeometry.h"
11 #include "imstkMath.h"
12 #include "imstkParallelUtils.h"
13 #include "imstkPointSet.h"
14 #include "imstkSignedDistanceField.h"
15 
16 namespace imstk
17 {
18 ImplicitGeometryToPointSetCD::ImplicitGeometryToPointSetCD()
19 {
20  setRequiredInputType<ImplicitGeometry>(0);
21  setRequiredInputType<PointSet>(1);
22  m_centralGrad.setDx(Vec3d(0.001, 0.001, 0.001));
23 }
24 
25 void
27  std::shared_ptr<Geometry> geomA,
28  std::shared_ptr<Geometry> geomB,
29  std::vector<CollisionElement>& elementsA,
30  std::vector<CollisionElement>& elementsB)
31 {
32  auto implicitGeom = std::dynamic_pointer_cast<ImplicitGeometry>(geomA);
33  auto pointSet = std::dynamic_pointer_cast<PointSet>(geomB);
34 
35  m_centralGrad.setFunction(implicitGeom);
36  if (auto sdf = std::dynamic_pointer_cast<SignedDistanceField>(implicitGeom))
37  {
38  m_centralGrad.setDx(sdf->getImage()->getSpacing() * 0.5);
39  }
40 
41  std::shared_ptr<VecDataArray<double, 3>> verticesPtr = pointSet->getVertexPositions();
42  const VecDataArray<double, 3>& vertices = *verticesPtr;
44  ParallelUtils::parallelFor(vertices.size(),
45  [&](const int i)
46  {
47  const Vec3d& pt = vertices[i];
48 
49  const double signedDistance = implicitGeom->getFunctionValue(pt);
50  if (signedDistance < 0.0)
51  {
52  const Vec3d n = m_centralGrad(pt).normalized(); // Contact Normal
53  const double depth = std::abs(signedDistance);
54 
56  elemA.dir = -n; // Direction to resolve SDF-based object from point
57  elemA.pt = pt + n * depth;
58  elemA.penetrationDepth = depth;
59 
61  elemB.dir = n; // Direction to resolve point from SDF
62  elemB.ptIndex = i;
63  elemB.penetrationDepth = depth;
64 
65  lock.lock();
66  elementsA.push_back(elemA);
67  elementsB.push_back(elemB);
68  lock.unlock();
69  }
70  }, vertices.size() > 100);
71 }
72 
73 void
75  std::shared_ptr<Geometry> geomA,
76  std::shared_ptr<Geometry> geomB,
77  std::vector<CollisionElement>& elementsA)
78 {
79  auto implicitGeom = std::dynamic_pointer_cast<ImplicitGeometry>(geomA);
80  auto pointSet = std::dynamic_pointer_cast<PointSet>(geomB);
81 
82  m_centralGrad.setFunction(implicitGeom);
83  if (auto sdf = std::dynamic_pointer_cast<SignedDistanceField>(implicitGeom))
84  {
85  m_centralGrad.setDx(sdf->getImage()->getSpacing() * 0.5);
86  }
87 
88  std::shared_ptr<VecDataArray<double, 3>> verticesPtr = pointSet->getVertexPositions();
89  const VecDataArray<double, 3>& vertices = *verticesPtr;
91  ParallelUtils::parallelFor(vertices.size(),
92  [&](const int i)
93  {
94  const Vec3d& pt = vertices[i];
95 
96  const double signedDistance = implicitGeom->getFunctionValue(pt);
97  if (signedDistance < 0.0)
98  {
99  const Vec3d n = m_centralGrad(pt).normalized(); // Contact Normal
100  const double depth = std::abs(signedDistance);
101 
102  PointDirectionElement elemA;
103  elemA.dir = -n; // Direction to resolve SDF-based object from point
104  elemA.pt = pt + n * depth;
105  elemA.penetrationDepth = depth;
106 
107  lock.lock();
108  elementsA.push_back(elemA);
109  lock.unlock();
110  }
111  }, vertices.size() > 100);
112 }
113 
114 void
116  std::shared_ptr<Geometry> geomA,
117  std::shared_ptr<Geometry> geomB,
118  std::vector<CollisionElement>& elementsB)
119 {
120  auto implicitGeom = std::dynamic_pointer_cast<ImplicitGeometry>(geomA);
121  auto pointSet = std::dynamic_pointer_cast<PointSet>(geomB);
122 
123  m_centralGrad.setFunction(implicitGeom);
124  if (auto sdf = std::dynamic_pointer_cast<SignedDistanceField>(implicitGeom))
125  {
126  m_centralGrad.setDx(sdf->getImage()->getSpacing() * 0.5);
127  }
128 
129  std::shared_ptr<VecDataArray<double, 3>> verticesPtr = pointSet->getVertexPositions();
130  const VecDataArray<double, 3>& vertices = *verticesPtr;
132  ParallelUtils::parallelFor(vertices.size(),
133  [&](const int i)
134  {
135  const Vec3d& pt = vertices[i];
136 
137  const double signedDistance = implicitGeom->getFunctionValue(pt);
138  if (signedDistance < 0.0)
139  {
140  const Vec3d n = m_centralGrad(pt).normalized(); // Contact Normal
141 
143  elemB.dir = n; // Direction to resolve point from SDF
144  elemB.ptIndex = i;
145  elemB.penetrationDepth = std::abs(signedDistance);
146 
147  lock.lock();
148  elementsB.push_back(elemB);
149  lock.unlock();
150  }
151  }, vertices.size() > 100);
152 }
153 } // namespace imstk
The SpinLock class.
Definition: imstkSpinLock.h:20
void unlock()
End a thread-safe region.
Definition: imstkSpinLock.h:53
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
Definition: imstkPointSet.h:25
void computeCollisionDataAB(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsA, std::vector< CollisionElement > &elementsB) override
Compute collision data for AB simultaneously.
Compound Geometry.
void lock()
Start a thread-safe region, where only one thread can execute at a time until a call to the unlock fu...
Definition: imstkSpinLock.h:45
void computeCollisionDataA(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsA) override
Compute collision data for side A.
Direclty gives a point-direction contact as its collision data, point given by index.
Class that can represent the geometry of multiple implicit geometries as boolean functions One may su...
Direclty gives a point-direction contact as its collision data.
void computeCollisionDataB(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsB) override
Compute collision data for side B.