iMSTK
Interactive Medical Simulation Toolkit
imstkSphereToCapsuleCD.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 "imstkSphereToCapsuleCD.h"
8 #include "imstkCapsule.h"
9 #include "imstkCollisionUtils.h"
10 #include "imstkSphere.h"
11 
12 namespace imstk
13 {
14 SphereToCapsuleCD::SphereToCapsuleCD()
15 {
16  setRequiredInputType<Sphere>(0);
17  setRequiredInputType<Capsule>(1);
18 }
19 
20 void
22  std::shared_ptr<Geometry> geomA,
23  std::shared_ptr<Geometry> geomB,
24  std::vector<CollisionElement>& elementsA,
25  std::vector<CollisionElement>& elementsB)
26 {
27  std::shared_ptr<Sphere> sphere0 = std::dynamic_pointer_cast<Sphere>(geomA);
28  std::shared_ptr<Capsule> capsule1 = std::dynamic_pointer_cast<Capsule>(geomB);
29 
30  const Vec3d sphere0Pos = sphere0->getPosition();
31  const double sphere0Radius = sphere0->getRadius();
32 
33  const Vec3d capsule1Pos = capsule1->getPosition();
34  const Vec3d capsule1Axis = capsule1->getOrientation().toRotationMatrix().col(1).normalized();
35  const double capsule1HalfLength = capsule1->getLength() * 0.5;
36  const Vec3d diff1 = capsule1Axis * capsule1HalfLength;
37  const double capsule1Radius = capsule1->getRadius();
38 
39  // Find the closest point on the two segments
40  int caseType = -1;
41  const Vec3d closestPt = CollisionUtils::closestPointOnSegment(sphere0Pos,
42  capsule1Pos - diff1, capsule1Pos + diff1, caseType);
43 
44  // We can interpret spheres around these two points of capsule radius
45  // The point of contact should be between these two spheres
46  Vec3d sphereAContactPt, sphereBContactPt;
47  Vec3d sphereAContactNormal, sphereBContactNormal;
48  double depth;
49  if (CollisionUtils::testSphereToSphere(
50  sphere0Pos, sphere0Radius, closestPt, capsule1Radius,
51  sphereAContactPt, sphereAContactNormal,
52  sphereBContactPt, sphereBContactNormal,
53  depth))
54  {
56  elemA.dir = sphereAContactNormal; // Direction to resolve sphereA
57  elemA.pt = sphereAContactPt; // Contact point on sphereA
58  elemA.penetrationDepth = depth;
59 
61  elemB.dir = sphereBContactNormal; // Direction to resolve capsuleB
62  elemB.pt = sphereBContactPt; // Contact point on capsuleB
63  elemB.penetrationDepth = depth;
64 
65  elementsA.push_back(elemA);
66  elementsB.push_back(elemB);
67  }
68 }
69 } // namespace imstk
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.
Vec3d getPosition(DataType type=DataType::PostTransform)
Get the local or global position (post transformed)
Compound Geometry.
Represents a sphere via its position & radius.
Definition: imstkSphere.h:19
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.