iMSTK
Interactive Medical Simulation Toolkit
imstkPbdEdgeEdgeCCDConstraint.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 "imstkEdgeEdgeCCDState.h"
8 #include "imstkPbdEdgeEdgeCCDConstraint.h"
9 #include "imstkLineMeshToLineMeshCCD.h"
10 
11 namespace imstk
12 {
13 void
15  Vec3d* prevPtA0, Vec3d* prevPtA1,
16  Vec3d* prevPtB0, Vec3d* prevPtB1,
17  const PbdParticleId& ptA0, const PbdParticleId& ptA1,
18  const PbdParticleId& ptB0, const PbdParticleId& ptB1,
19  double stiffnessA, double stiffnessB,
20  int ccdSubsteps)
21 {
22  m_prevEdgeA[0] = prevPtA0;
23  m_prevEdgeA[1] = prevPtA1;
24  m_prevEdgeB[0] = prevPtB0;
25  m_prevEdgeB[1] = prevPtB1;
26 
27  m_particles[0] = ptA0;
28  m_particles[1] = ptA1;
29  m_particles[2] = ptB0;
30  m_particles[3] = ptB1;
31 
32  m_stiffness[0] = stiffnessA;
33  m_stiffness[1] = stiffnessB;
34  m_ccdSubsteps = ccdSubsteps;
35 }
36 
37 void
39  const double dt, const SolverType& type)
40 {
41  // The CCD constraint takes many more substeps to ensure
42  // convergence of the constraint
43  for (int k = 0; k < m_ccdSubsteps; k++)
44  {
45  PbdCollisionConstraint::projectConstraint(bodies, dt / m_ccdSubsteps, type);
46  }
47 }
48 
49 bool
51  double& c, std::vector<Vec3d>& dcdx)
52 {
53  const Vec3d& currPt0 = bodies.getPosition(m_particles[0]);
54  const Vec3d& currPt1 = bodies.getPosition(m_particles[1]);
55  const Vec3d& currPt2 = bodies.getPosition(m_particles[2]);
56  const Vec3d& currPt3 = bodies.getPosition(m_particles[3]);
57 
58  const Vec3d& prevPt0 = *m_prevEdgeA[0];
59  const Vec3d& prevPt1 = *m_prevEdgeA[1];
60  const Vec3d& prevPt2 = *m_prevEdgeB[0];
61  const Vec3d& prevPt3 = *m_prevEdgeB[1];
62 
63  EdgeEdgeCCDState prevState(prevPt0, prevPt1, prevPt2, prevPt3);
64  EdgeEdgeCCDState currState(currPt0, currPt1, currPt2, currPt3);
65 
66  double timeOfImpact = 0.0;
67  const int collisionType = EdgeEdgeCCDState::testCollision(prevState, currState, timeOfImpact);
68  if (collisionType == 0)
69  {
70  c = 0.0;
71  return false;
72  }
73 
74  const double s = currState.si();
75  const double t = currState.sj();
76  const Vec3d n0 = prevState.pi() - prevState.pj();
77  const Vec3d n1 = currState.pi() - currState.pj();
78 
79  Vec3d n = n1;
80  // invert the normal if lines are crossing:
81  bool crossing = false;
82  if (n0.dot(n1) < 0)
83  {
84  n *= -1.0;
85  crossing = true;
86  }
87 
88  const double d = n.norm();
89  if (d <= 0.0)
90  {
91  c = 0.0;
92  return false;
93  }
94  n /= d;
95 
96  // keep the prev values static by assigning zero vector as solution gradient.
97  // This can also be done by assigning invMass as zero for prev timestep vertices.
98  dcdx[0] = (1 - s) * n;
99  dcdx[1] = s * n;
100 
101  dcdx[2] = -(1 - t) * n;
102  dcdx[3] = -t * n;
103 
104  if (crossing)
105  {
106  c = d + currState.thickness();
107  }
108  else
109  {
110  c = std::abs(d - currState.thickness());
111  }
112 
113  return true;
114 }
115 } // namespace imstk
const Vec3d & pj() const
Pj is the closest point on segment xj–xj1 to segment xi–xi1.
std::pair< int, int > PbdParticleId
Index pair that refers to a particle in a PbdState. Index 0 is the body id, Index 1 is the particle i...
std::vector< PbdParticleId > m_particles
body, particle index
const Vec3d & pi() const
Pi is the closest point on segment xi–xi1 to segment xj–xj1.
Compound Geometry.
void initConstraint(Vec3d *prevPtA0, Vec3d *prevPtA1, Vec3d *prevPtB0, Vec3d *prevPtB1, const PbdParticleId &ptA0, const PbdParticleId &ptA1, const PbdParticleId &ptB0, const PbdParticleId &ptB1, double stiffnessA, double stiffnessB, int ccdSubsteps=25)
Initialize constraint.
static int testCollision(const EdgeEdgeCCDState &prev, EdgeEdgeCCDState &curr, double &relativeTimeOfImpact)
Performs a collision test based on two given timesteps that store the state of two lines each...
void projectConstraint(PbdState &bodies, const double dt, const SolverType &type) override
Performs the actual positional solve.
bool computeValueAndGradient(PbdState &bodies, double &c, std::vector< Vec3d > &dcdx) override
Compute value and gradient of constraint function.
const double sj() const
Parameterized position of closest point on segment xj–xj1 to segment xi–xi1.
SolverType
Type of solvers.
const double si() const
Parameterized position of closest point on segment xi–xi1 to segment xj–xj1.
void projectConstraint(PbdState &bodies, const double dt, const SolverType &type) override
Performs the actual positional solve.
Provides interface for accessing particles from a 2d array of PbdBody,Particles.
Definition: imstkPbdBody.h:229