iMSTK
Interactive Medical Simulation Toolkit
imstkUnidirectionalPlaneToCapsuleCD.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 "imstkUnidirectionalPlaneToCapsuleCD.h"
8 #include "imstkCapsule.h"
9 #include "imstkCollisionData.h"
10 #include "imstkCollisionUtils.h"
11 #include "imstkPlane.h"
12 
13 namespace imstk
14 {
15 UnidirectionalPlaneToCapsuleCD::UnidirectionalPlaneToCapsuleCD()
16 {
17  setRequiredInputType<Plane>(0);
18  setRequiredInputType<Capsule>(1);
19 }
20 
21 void
23  std::shared_ptr<Geometry> geomA,
24  std::shared_ptr<Geometry> geomB,
25  std::vector<CollisionElement>& elementsA,
26  std::vector<CollisionElement>& elementsB)
27 {
28  std::shared_ptr<Plane> plane = std::dynamic_pointer_cast<Plane>(geomA);
29  std::shared_ptr<Capsule> capsule = std::dynamic_pointer_cast<Capsule>(geomB);
30 
31  // Get geometry properties
32  const Vec3d planePos = plane->getPosition();
33  const Vec3d n = plane->getNormal();
34 
35  const Vec3d capsule0Pos = capsule->getPosition();
36  const Vec3d capsule0Axis = capsule->getOrientation().toRotationMatrix().col(1).normalized();
37  const double capsule0HalfLength = capsule->getLength() * 0.5;
38  const Vec3d diff0 = capsule0Axis * capsule0HalfLength;
39  const double capsule0Radius = capsule->getRadius();
40 
41  // Find closest point on edge to plane
42 
43  const Vec3d p0 = capsule0Pos - diff0;
44  const Vec3d p1 = capsule0Pos + diff0;
45 
46  const double signedDist0 = plane->getFunctionValue(p0);
47  const double signedDist1 = plane->getFunctionValue(p1);
48 
49  // Find the deepest point
50  Vec3d deepestPtOnEdge = p0;
51  double deepestDist = signedDist0;
52  if (signedDist1 < signedDist0)
53  {
54  deepestPtOnEdge = p1;
55  deepestDist = signedDist1;
56  }
57 
58  // If collision
59  if (deepestDist - capsule0Radius < 0.0)
60  {
61  // If nearly coplanar use midpoint
62  if ((signedDist1 - signedDist0) < IMSTK_DOUBLE_EPS)
63  {
64  deepestPtOnEdge = (p0 + p1) * 0.5;
65  }
66 
67  const double depth = std::abs(deepestDist - capsule0Radius);
68 
70  elemA.dir = -n; // Direction to resolve plane
71  elemA.pt = deepestPtOnEdge + n * std::abs(deepestDist);
72  elemA.penetrationDepth = depth;
73 
75  elemB.dir = n; // Direction to resolve capsule
76  elemB.pt = deepestPtOnEdge - n * capsule0Radius; // Contact point on capsule
77  elemB.penetrationDepth = depth;
78 
79  elementsA.push_back(elemA);
80  elementsB.push_back(elemB);
81  }
82 }
83 } // namespace imstk
Vec3d getPosition(DataType type=DataType::PostTransform)
Get the local or global position (post transformed)
Represents and infinite plane, width can be used for visual purposes.
Definition: imstkPlane.h:19
Compound Geometry.
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.
Capsule geometry, default configuration is centered at origin with length running up and down the y a...
Definition: imstkCapsule.h:21
Direclty gives a point-direction contact as its collision data.