7 #include "NeedleEmbedder.h" 8 #include "EmbeddingConstraint.h" 9 #include "imstkCollisionData.h" 10 #include "imstkLineMesh.h" 11 #include "imstkPbdModel.h" 12 #include "imstkPbdObject.h" 13 #include "imstkPbdSolver.h" 14 #include "imstkPuncturable.h" 15 #include "imstkStraightNeedle.h" 16 #include "imstkTaskNode.h" 17 #include "imstkTetrahedralMesh.h" 19 using namespace imstk;
22 testPlaneLine2(
const Vec3d& p,
const Vec3d& q,
23 const Vec3d& planePt,
const Vec3d& planeNormal, Vec3d& iPt,
26 const Vec3d n = q - p;
27 const double denom = n.dot(planeNormal);
29 if (std::abs(denom) < IMSTK_DOUBLE_EPS)
34 t = (planePt - p).dot(planeNormal) / denom;
43 testSegmentTriangle2(
const Vec3d& p,
const Vec3d& q,
44 const Vec3d& a,
const Vec3d& b,
const Vec3d& c, Vec3d& uvw,
47 segmentInPlane =
false;
50 if (testPlaneLine2(p, q, a, (b - a).cross(c - a).normalized(), iPt, t))
52 uvw = baryCentric(iPt, a, b, c);
53 if (t > 0.0 && t < 1.0)
55 segmentInPlane =
true;
56 if (uvw[0] >= 0.0 && uvw[1] >= 0.0 && uvw[2] >= 0.0)
65 TissueData::TissueData(std::shared_ptr<PbdObject> obj) :
68 verticesPtr(geom->getVertexPositions()),
69 vertices(*verticesPtr),
70 indicesPtr(geom->getCells()),
75 NeedleData::NeedleData(std::shared_ptr<PbdObject> obj) :
78 verticesPtr(needle->getNeedleGeometry()->getVertexPositions()),
79 vertices(*verticesPtr),
80 cellsPtr(needle->getNeedleGeometry()->getCells()),
83 needle->getNeedleGeometry()->updatePostTransformData();
89 int v1,
int v2,
int v3,
const Vec3d& iPt)
95 if (m_faceConstraints.count(triCell) == 0)
97 const int bodyId = tissueData.obj->getPbdBody()->bodyHandle;
99 auto constraint = std::make_shared<EmbeddingConstraint>();
101 constraint->initConstraint(
102 tissueData.obj->getPbdModel()->getBodies(),
103 { needleData.obj->getPbdBody()->bodyHandle, 0 },
104 { bodyId, v1 }, { bodyId, v2 }, { bodyId, v3 },
105 &needleData.vertices[0], &needleData.vertices[1],
m_compliance);
107 constraint->setFriction(m_friction);
108 constraint->setRestitution(1.0);
111 m_faceConstraints[triCell] = constraint;
118 auto puncturable = m_tissueObject->getComponent<
Puncturable>();
126 if ((m_cdData->elementsA.size() > 0 || m_cdData->elementsB.size() > 0)
127 && needle->getState(punctureId) == Puncture::State::REMOVED)
129 needle->setState(punctureId, Puncture::State::TOUCHING);
130 puncturable->
setPuncture(punctureId, needle->getPuncture(punctureId));
134 if (needle->getState(punctureId) == Puncture::State::TOUCHING)
137 const Vec3d needleAxes = needle->getNeedleDirection();
138 const double fN = std::max(needleAxes.dot(needleData.obj->getPbdBody()->externalForce), 0.0);
141 if (fN > m_forceThreshold)
144 needle->setState(punctureId, Puncture::State::INSERTED);
145 m_pbdCHNode->setEnabled(
false);
151 m_debugEmbeddingPoints.clear();
152 m_debugEmbeddedTriangles.clear();
154 if (needle->getState(punctureId) == Puncture::State::INSERTED)
165 const double dt = m_needleObject->getPbdModel()->getTimeStep();
166 for (
int i = 0; i < needleData.cells.size(); i++)
168 const Vec2i& seg = needleData.cells[i];
170 const Vec3d& line_x0 = needleData.vertices[seg[0]];
171 const Vec3d& line_x1 = needleData.vertices[seg[1]];
173 const Vec3d& prev_line_x0 = needlePrevVertices[seg[0]];
174 const Vec3d& prev_line_x1 = needlePrevVertices[seg[1]];
176 const Vec3d diff = line_x1 - line_x0;
177 const Vec3d axes = diff.normalized();
179 for (
int j = 0; j < tissueData.indices.size(); j++)
181 const Vec4i& tet = tissueData.indices[j];
184 const Vec3d& tet_x0 = tissueData.vertices[tet[0]];
185 const Vec3d& tet_x1 = tissueData.vertices[tet[1]];
186 const Vec3d& tet_x2 = tissueData.vertices[tet[2]];
187 const Vec3d& tet_x3 = tissueData.vertices[tet[3]];
188 const Vec3d center = (tet_x0 + tet_x1 + tet_x2 + tet_x3) * 0.25;
191 const double tetSphereSqrDist =
192 std::max((tissueData.vertices[tet[0]] - center).squaredNorm(),
193 std::max((tissueData.vertices[tet[1]] - center).squaredNorm(),
194 std::max((tissueData.vertices[tet[2]] - center).squaredNorm(),
195 (tissueData.vertices[tet[3]] - center).squaredNorm())));
198 const Vec3d diffCenter = center - line_x0;
199 const double sqrDistCenterToAxes = (diffCenter - diffCenter.dot(axes) * axes).squaredNorm();
202 if (sqrDistCenterToAxes <= tetSphereSqrDist * 2.0)
206 { tet[0], tet[1], tet[2] },
207 { tet[1], tet[2], tet[3] },
208 { tet[0], tet[2], tet[3] },
209 { tet[0], tet[1], tet[3] } };
210 for (
int k = 0; k < 4; k++)
212 const Vec3d& tri_x0 = tissueData.vertices[faces[k][0]];
213 const Vec3d& tri_x1 = tissueData.vertices[faces[k][1]];
214 const Vec3d& tri_x2 = tissueData.vertices[faces[k][2]];
216 bool currInPlane =
false;
217 Vec3d curr_uvw = Vec3d::Zero();
218 const bool isCurrIntersected = testSegmentTriangle2(
220 tri_x0, tri_x1, tri_x2,
221 curr_uvw, currInPlane);
224 if (isCurrIntersected)
228 const Vec3d& prev_tri_x0 = tissuePrevVertices[faces[k][0]];
229 const Vec3d& prev_tri_x1 = tissuePrevVertices[faces[k][1]];
230 const Vec3d& prev_tri_x2 = tissuePrevVertices[faces[k][2]];
232 Vec3d prev_uvw = Vec3d::Zero();
233 bool prevInPlane =
false;
234 const bool isPrevIntersected = testSegmentTriangle2(
235 prev_line_x0, prev_line_x1,
236 prev_tri_x0, prev_tri_x1, prev_tri_x2,
237 prev_uvw, prevInPlane);
240 if (prev_uvw[0] >= 0.0 && prev_uvw[1] >= 0.0 && prev_uvw[2] >= 0.0)
242 addFaceEmbeddingConstraint(
243 tissueData, needleData,
247 curr_uvw[0] * tri_x0 + curr_uvw[1] * tri_x1 + curr_uvw[2] * tri_x2);
256 m_constraints.resize(0);
257 m_constraints.reserve(m_faceConstraints.size());
260 std::vector<TriCell> constraintsToDelete;
261 for (
auto i = m_faceConstraints.begin(); i != m_faceConstraints.end(); i++)
263 const std::vector<PbdParticleId>& particles = i->second->getParticles();
264 const Vec3d& tri_x0 = tissueData.vertices[particles[0].second];
265 const Vec3d& tri_x1 = tissueData.vertices[particles[1].second];
266 const Vec3d& tri_x2 = tissueData.vertices[particles[2].second];
268 bool currInPlane =
false;
269 Vec3d curr_uvw = Vec3d::Zero();
270 const bool isCurrIntersected = testSegmentTriangle2(
271 *i->second->getP(), *i->second->getQ(),
272 tri_x0, tri_x1, tri_x2,
273 curr_uvw, currInPlane);
278 constraintsToDelete.push_back(
TriCell(particles[0].second, particles[1].second, particles[2].second));
281 for (
auto i : constraintsToDelete)
283 m_faceConstraints.erase(i);
286 for (
auto i = m_faceConstraints.begin(); i != m_faceConstraints.end(); i++)
288 const std::vector<PbdParticleId>& particles = i->second->getParticles();
289 m_debugEmbeddingPoints.push_back(i->second->getIntersectionPoint());
290 m_debugEmbeddedTriangles.push_back(Vec3i(particles[0].second, particles[1].second, particles[2].second));
293 m_constraints.push_back(i->second.get());
295 if (m_constraints.size() == 0)
297 needle->setState(punctureId, Puncture::State::REMOVED);
298 m_pbdCHNode->setEnabled(
true);
301 tissueData.obj->getPbdModel()->getSolver()->addConstraints(&m_constraints);
305 tissuePrevVertices.resize(tissueData.vertices.size());
306 std::copy(tissueData.vertices.begin(), tissueData.vertices.end(), tissuePrevVertices.begin());
307 needlePrevVertices.resize(needleData.vertices.size());
308 std::copy(needleData.vertices.
begin(), needleData.vertices.end(), needlePrevVertices.begin());
virtual void addFaceEmbeddingConstraint(TissueData &tissueData, NeedleData &needleData, int v1, int v2, int v3, const Vec3d &iPt)
Adds embedding constraint (ie: The constraint maintained after puncture)
Utility for triangle comparison.
void update()
Add embedding constraints based off contact data We need to add the constraint once and then update i...
PunctureId getPunctureId(std::shared_ptr< Needle > needle, std::shared_ptr< Puncturable > puncturable, const int supportId)
Get puncture id between needle and puncturable.
Place this on an object to make it puncturable by a needle. This allows puncturables to know they've ...
Definition of straight, single segment needle.
iterator begin()
begin(), end() to mirror std::vector
double m_compliance
used in xPBD, inverse of Stiffness
Represents a set of tetrahedrons & vertices via an array of Vec3d double vertices & Vec4i integer ind...
void setPuncture(const PunctureId &id, std::shared_ptr< Puncture > data)
Get/Set puncture data.
std::tuple< int, int, int > PunctureId
Punctures are identified via three ints. The needle id, the puncturable id, and a local id that allow...
Flattened out with reference members.