77#include < sofa/collisionAlgorithm/operations/FindClosestProximity.h>
88#include < sofa/collisionAlgorithm/operations/Project.h>
99#include < sofa/collisionAlgorithm/proximity/EdgeProximity.h>
10+ #include < sofa/collisionAlgorithm/proximity/TetrahedronProximity.h>
1011#include < sofa/component/constraint/lagrangian/solver/ConstraintSolverImpl.h>
1112#include < sofa/component/statecontainer/MechanicalObject.h>
1213
@@ -15,7 +16,7 @@ namespace sofa::collisionAlgorithm
1516
1617class InsertionAlgorithm : public BaseAlgorithm
1718{
18- public:
19+ public:
1920 SOFA_CLASS (InsertionAlgorithm, BaseAlgorithm);
2021
2122 typedef core::behavior::MechanicalState<defaulttype::Vec3Types> MechStateTipType;
@@ -154,7 +155,8 @@ class InsertionAlgorithm : public BaseAlgorithm
154155 const auto & lambda =
155156 m_constraintSolver->getLambda ()[mstate.get ()].read ()->getValue ();
156157 SReal norm{0_sreal};
157- for (const auto & l : lambda) {
158+ for (const auto & l : lambda)
159+ {
158160 norm += l.norm ();
159161 }
160162 if (norm > punctureForceThreshold)
@@ -178,9 +180,9 @@ class InsertionAlgorithm : public BaseAlgorithm
178180 // 1.3 Collision with the shaft geometry
179181 if (collisionOutput.size ())
180182 {
181- auto createShaftProximity =
182- Operations::CreateCenterProximity::Operation::get (l_shaftGeom->getTypeInfo ());
183- auto projectOnShaft = Operations::Project::Operation::get (l_shaftGeom);
183+ auto createShaftProximity =
184+ Operations::CreateCenterProximity::Operation::get (l_shaftGeom->getTypeInfo ());
185+ auto projectOnShaft = Operations::Project::Operation::get (l_shaftGeom);
184186 for (auto itShaft = l_shaftGeom->begin (); itShaft != l_shaftGeom->end (); itShaft++)
185187 {
186188 BaseProximity::SPtr shaftProx = createShaftProximity (itShaft->element ());
@@ -190,11 +192,12 @@ class InsertionAlgorithm : public BaseAlgorithm
190192 if (surfProx)
191193 {
192194 surfProx->normalize ();
193-
195+
194196 // 1.2 If not, create a proximity pair for the tip-surface collision
195197 if (d_projective.getValue ())
196198 {
197- shaftProx = projectOnShaft (surfProx->getPosition (), itShaft->element ()).prox ;
199+ shaftProx =
200+ projectOnShaft (surfProx->getPosition (), itShaft->element ()).prox ;
198201 if (!shaftProx) continue ;
199202 shaftProx->normalize ();
200203 }
@@ -220,15 +223,30 @@ class InsertionAlgorithm : public BaseAlgorithm
220223 auto projectOnVol = Operations::Project::Operation::get (l_volGeom);
221224 const BaseProximity::SPtr volProx =
222225 findClosestProxOnVol (tipProx, l_volGeom.get (), projectOnVol, getFilterFunc ());
226+ // Proximity can be detected before the tip enters the tetra (e.g. near a boundary face)
227+ // Only accept proximities if the tip is inside the tetra during insertion
223228 if (volProx)
224229 {
225- volProx->normalize ();
226- m_couplingPts.push_back (volProx);
230+ TetrahedronProximity::SPtr tetProx =
231+ dynamic_pointer_cast<TetrahedronProximity>(volProx);
232+ if (tetProx)
233+ {
234+ double f0 (tetProx->f0 ()), f1 (tetProx->f1 ()), f2 (tetProx->f2 ()),
235+ f3 (tetProx->f3 ());
236+ bool isInTetra = toolbox::TetrahedronToolBox::isInTetra (
237+ tipProx->getPosition (), tetProx->element ()->getTetrahedronInfo (), f0,
238+ f1, f2, f3);
239+ if (isInTetra)
240+ {
241+ volProx->normalize ();
242+ m_couplingPts.push_back (volProx);
243+ }
244+ }
227245 }
228246 }
229- else // Don't bother with removing the point that was just added
247+ else // Don't bother with removing the point that was just added
230248 {
231- // 2.2. Check whether coupling point should be removed
249+ // 2.2. Check whether coupling point should be removed
232250 ElementIterator::SPtr itShaft = l_shaftGeom->begin (l_shaftGeom->getSize () - 2 );
233251 auto createShaftProximity =
234252 Operations::CreateCenterProximity::Operation::get (itShaft->getTypeInfo ());
@@ -237,7 +255,10 @@ class InsertionAlgorithm : public BaseAlgorithm
237255 const type::Vec3 normal = (edgeProx->element ()->getP1 ()->getPosition () -
238256 edgeProx->element ()->getP0 ()->getPosition ())
239257 .normalized ();
240- if (dot (tip2Pt, normal) > 0_sreal) {
258+ // If the coupling point lies ahead of the tip (positive dot product),
259+ // the needle is retreating. The last coupling point is removed
260+ if (dot (tip2Pt, normal) > 0_sreal)
261+ {
241262 m_couplingPts.pop_back ();
242263 }
243264 }
0 commit comments