iMSTK
Interactive Medical Simulation Toolkit
imstkCapsuleToCapsuleCD.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 "imstkCapsuleToCapsuleCD.h"
8 #include "imstkCapsule.h"
9 #include "imstkCollisionUtils.h"
10 
11 namespace imstk
12 {
13 CapsuleToCapsuleCD::CapsuleToCapsuleCD()
14 {
15  setRequiredInputType<Capsule>(0);
16  setRequiredInputType<Capsule>(1);
17 }
18 
19 void
21  std::shared_ptr<Geometry> geomA,
22  std::shared_ptr<Geometry> geomB,
23  std::vector<CollisionElement>& elementsA,
24  std::vector<CollisionElement>& elementsB)
25 {
26  std::shared_ptr<Capsule> capsule0 = std::dynamic_pointer_cast<Capsule>(geomA);
27  std::shared_ptr<Capsule> capsule1 = std::dynamic_pointer_cast<Capsule>(geomB);
28 
29  const Vec3d capsule0Pos = capsule0->getPosition();
30  const Vec3d capsule0Axis = capsule0->getOrientation().toRotationMatrix().col(1).normalized();
31  const double capsule0HalfLength = capsule0->getLength() * 0.5;
32  const Vec3d diff0 = capsule0Axis * capsule0HalfLength;
33  const double capsule0Radius = capsule0->getRadius();
34 
35  const Vec3d capsule1Pos = capsule1->getPosition();
36  const Vec3d capsule1Axis = capsule1->getOrientation().toRotationMatrix().col(1).normalized();
37  const double capsule1HalfLength = capsule1->getLength() * 0.5;
38  const Vec3d diff1 = capsule1Axis * capsule1HalfLength;
39  const double capsule1Radius = capsule1->getRadius();
40 
41  // Find the closest point on the two segments
42  Vec3d pt0, pt1;
43  CollisionUtils::edgeToEdgeClosestPoints(
44  capsule0Pos - diff0, capsule0Pos + diff0,
45  capsule1Pos - diff1, capsule1Pos + diff1,
46  pt0, pt1);
47 
48  // Skip case
49  if (pt0 == pt1)
50  {
51  return;
52  }
53 
54  // We can interpret spheres around these two points of capsule radius
55  // The point of contact should be between these two spheres
56  Vec3d sphereAContactPt, sphereBContactPt;
57  Vec3d sphereAContactNormal, sphereBContactNormal;
58  double depth;
59  if (CollisionUtils::testSphereToSphere(
60  pt0, capsule0Radius, pt1, capsule1Radius,
61  sphereAContactPt, sphereAContactNormal,
62  sphereBContactPt, sphereBContactNormal,
63  depth))
64  {
66  elemA.dir = sphereAContactNormal; // Direction to resolve capsuleA
67  elemA.pt = sphereAContactPt; // Contact point on capsuleA
68  elemA.penetrationDepth = depth;
69 
71  elemB.dir = sphereBContactNormal; // Direction to resolve capsuleB
72  elemB.pt = sphereBContactPt; // Contact point on capsuleB
73  elemB.penetrationDepth = depth;
74 
75  elementsA.push_back(elemA);
76  elementsB.push_back(elemB);
77  }
78 }
79 } // namespace imstk
Vec3d getPosition(DataType type=DataType::PostTransform)
Get the local or global position (post transformed)
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.