Skip to content

Commit 9f40bff

Browse files
authored
[algorithm] Check whether the needle tip is inside the detected tetrahedron proximity before adding it (#64)
* [algorithm] check whether the tip is inside tetra before adding the detected tetrahedron to the insertionOutput * [algorithm] Check tetProx after downcasting to TetrahedronProximity * [algorithm] Added comments
1 parent 5b468ea commit 9f40bff

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

src/sofa/collisionAlgorithm/algorithm/InsertionAlgorithm.h

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
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

1617
class 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

Comments
 (0)