From 0c15a9ecdd664f72cbaf660e5cc765580ba87273 Mon Sep 17 00:00:00 2001 From: Themis Skamagkis Date: Fri, 29 May 2026 16:42:38 +0200 Subject: [PATCH 1/3] [operations] Robustify retraction detection check using tip velocity --- src/CollisionAlgorithm/operations/NeedleOperations.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/CollisionAlgorithm/operations/NeedleOperations.cpp b/src/CollisionAlgorithm/operations/NeedleOperations.cpp index a36a6869..14be9ab0 100644 --- a/src/CollisionAlgorithm/operations/NeedleOperations.cpp +++ b/src/CollisionAlgorithm/operations/NeedleOperations.cpp @@ -6,7 +6,7 @@ namespace sofa::collisionalgorithm::Operations::Needle bool prunePointsUsingEdges(std::vector& couplingPts, const EdgeElement::SPtr& edge) { - if (!edge) + if (!edge) { msg_warning("Needle::PrunePointsAheadOfTip") << "Null element pointer in prunePointsUsingEdges; returning false"; @@ -16,6 +16,12 @@ bool prunePointsUsingEdges(std::vector& couplingPts, const type::Vec3 tip(edge->getP1()->getPosition()); const type::Vec3 edgeDirection = tip - edgeBase; + // Only prune if the tip is retracting (moving against the insertion direction). + // NOTE: This uses the needle tip velocity only. If retraction results from needle-tissue + // relative movement, retraction is not detected. + const type::Vec3 tipVelocity = edge->getP1()->getVelocity(); + if (dot(tipVelocity, edgeDirection) >= 0_sreal) return true; + const int initSize = couplingPts.size(); while(!couplingPts.empty()) From 25d0db3a07364d60f29f3f1dc1c870b055bcc097 Mon Sep 17 00:00:00 2001 From: Themis Skamagkis Date: Fri, 29 May 2026 18:00:51 +0200 Subject: [PATCH 2/3] [operations] Invert bool return from pruning operations --- .../operations/NeedleOperations.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/CollisionAlgorithm/operations/NeedleOperations.cpp b/src/CollisionAlgorithm/operations/NeedleOperations.cpp index 14be9ab0..77290493 100644 --- a/src/CollisionAlgorithm/operations/NeedleOperations.cpp +++ b/src/CollisionAlgorithm/operations/NeedleOperations.cpp @@ -3,6 +3,9 @@ namespace sofa::collisionalgorithm::Operations::Needle { +// Returns true when at least one coupling point was popped from the back, +// false when the set was left unchanged (including the null-edge error path +// and the non-retracting early-exit). bool prunePointsUsingEdges(std::vector& couplingPts, const EdgeElement::SPtr& edge) { @@ -16,11 +19,11 @@ bool prunePointsUsingEdges(std::vector& couplingPts, const type::Vec3 tip(edge->getP1()->getPosition()); const type::Vec3 edgeDirection = tip - edgeBase; - // Only prune if the tip is retracting (moving against the insertion direction). - // NOTE: This uses the needle tip velocity only. If retraction results from needle-tissue + // Only prune if the tip is retracting (moving against the insertion direction). + // NOTE: This uses the needle tip velocity only. If retraction results from needle-tissue // relative movement, retraction is not detected. const type::Vec3 tipVelocity = edge->getP1()->getVelocity(); - if (dot(tipVelocity, edgeDirection) >= 0_sreal) return true; + if (dot(tipVelocity, edgeDirection) >= 0_sreal) return false; const int initSize = couplingPts.size(); @@ -32,7 +35,7 @@ bool prunePointsUsingEdges(std::vector& couplingPts, if(dot(tip2Pt, edgeDirection) < 0_sreal) break; couplingPts.pop_back(); } - return (initSize == couplingPts.size()); + return (couplingPts.size() < initSize); } int register_PrunePointsAheadOfTip_Edge = From 1222f7e797f4bf40120bf459c73c49d717e31f4a Mon Sep 17 00:00:00 2001 From: epernod Date: Fri, 29 May 2026 18:25:12 +0200 Subject: [PATCH 3/3] Put method description into header file --- src/CollisionAlgorithm/operations/NeedleOperations.cpp | 7 ++----- src/CollisionAlgorithm/operations/NeedleOperations.h | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/CollisionAlgorithm/operations/NeedleOperations.cpp b/src/CollisionAlgorithm/operations/NeedleOperations.cpp index 77290493..7c51c08c 100644 --- a/src/CollisionAlgorithm/operations/NeedleOperations.cpp +++ b/src/CollisionAlgorithm/operations/NeedleOperations.cpp @@ -3,9 +3,6 @@ namespace sofa::collisionalgorithm::Operations::Needle { -// Returns true when at least one coupling point was popped from the back, -// false when the set was left unchanged (including the null-edge error path -// and the non-retracting early-exit). bool prunePointsUsingEdges(std::vector& couplingPts, const EdgeElement::SPtr& edge) { @@ -38,6 +35,6 @@ bool prunePointsUsingEdges(std::vector& couplingPts, return (couplingPts.size() < initSize); } -int register_PrunePointsAheadOfTip_Edge = - PrunePointsAheadOfTip::register_func(&prunePointsUsingEdges); +int register_PrunePointsAheadOfTip_Edge = PrunePointsAheadOfTip::register_func(&prunePointsUsingEdges); + } // namespace sofa::collisionalgorithm::Operations::Needle diff --git a/src/CollisionAlgorithm/operations/NeedleOperations.h b/src/CollisionAlgorithm/operations/NeedleOperations.h index 184677a4..1c39f1c8 100644 --- a/src/CollisionAlgorithm/operations/NeedleOperations.h +++ b/src/CollisionAlgorithm/operations/NeedleOperations.h @@ -29,6 +29,11 @@ class SOFA_COLLISIONALGORITHM_API PrunePointsAheadOfTip } }; +/** +* Returns true when at least one coupling point was popped from the back, +* false when the set was left unchanged (including the null-edge error path +* and the non-retracting early-exit). +*/ bool prunePointsUsingEdges(std::vector& couplingPts, const EdgeElement::SPtr& edgeProx);