Skip to content

Commit 57df238

Browse files
authored
[operation] A new Operation class (needle-explicit specialization) to enable coupling point removal from the top-level algorithm (#89)
* [operations] Added a namespace for NeedleOperations and a function to remove points ahead of the tip * [operations] Implemented a custom function for removing points based on edge direction * [algorithm] Use custom operation for point removal - avoid dynamic casts to edge element types * [operations] Message warning for empty element pointer or empty coupling points vector
1 parent ebd68b8 commit 57df238

File tree

3 files changed

+70
-31
lines changed

3 files changed

+70
-31
lines changed

src/sofa/collisionAlgorithm/algorithm/InsertionAlgorithm.h

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <sofa/collisionAlgorithm/operations/CreateCenterProximity.h>
77
#include <sofa/collisionAlgorithm/operations/FindClosestProximity.h>
88
#include <sofa/collisionAlgorithm/operations/Project.h>
9+
#include <sofa/collisionAlgorithm/operations/NeedleOperations.h>
910
#include <sofa/collisionAlgorithm/proximity/EdgeProximity.h>
1011
#include <sofa/collisionAlgorithm/proximity/TetrahedronProximity.h>
1112
#include <sofa/component/constraint/lagrangian/solver/ConstraintSolverImpl.h>
@@ -247,38 +248,11 @@ class InsertionAlgorithm : public BaseAlgorithm
247248
}
248249
else // Don't bother with removing the point that was just added
249250
{
250-
// 2.2. Check whether coupling point should be removed
251+
// Remove coupling points that are ahead of the tip in the insertion direction
251252
ElementIterator::SPtr itShaft = l_shaftGeom->begin(l_shaftGeom->getSize() - 2);
252-
auto createShaftProximity =
253-
Operations::CreateCenterProximity::Operation::get(itShaft->getTypeInfo());
254-
const BaseProximity::SPtr shaftProx = createShaftProximity(itShaft->element());
255-
if (shaftProx)
256-
{
257-
const EdgeProximity::SPtr edgeProx =
258-
dynamic_pointer_cast<EdgeProximity>(shaftProx);
259-
if (edgeProx)
260-
{
261-
const type::Vec3 normal = (edgeProx->element()->getP1()->getPosition() -
262-
edgeProx->element()->getP0()->getPosition())
263-
.normalized();
264-
// If the (last) coupling point lies ahead of the tip (positive dot product),
265-
// the needle is retreating. Thus, that point is removed.
266-
if (dot(tip2Pt, normal) > 0_sreal)
267-
{
268-
m_couplingPts.pop_back();
269-
}
270-
}
271-
else
272-
{
273-
msg_warning() << "shaftGeom: " << l_shaftGeom->getName()
274-
<< " is not an EdgeGeometry. Point removal is disabled";
275-
}
276-
}
277-
else
278-
{
279-
msg_warning() << "Cannot create proximity from shaftGeom: "
280-
<< l_shaftGeom->getName() << " - point removal is disabled";
281-
}
253+
auto prunePointsAheadOfTip =
254+
Operations::Needle::PrunePointsAheadOfTip::get(itShaft->getTypeInfo());
255+
prunePointsAheadOfTip(m_couplingPts, itShaft->element());
282256
}
283257
}
284258

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <sofa/collisionAlgorithm/operations/NeedleOperations.h>
2+
3+
namespace sofa::collisionAlgorithm::Operations::Needle
4+
{
5+
6+
bool prunePointsUsingEdges(std::vector<BaseProximity::SPtr>& couplingPts,
7+
const EdgeElement::SPtr& edge)
8+
{
9+
if (!edge)
10+
{
11+
msg_warning("Needle::PrunePointsAheadOfTip")
12+
<< "Null element pointer in prunePointsUsingEdges; returning false";
13+
return false;
14+
}
15+
const type::Vec3 edgeBase(edge->getP0()->getPosition());
16+
const type::Vec3 tip(edge->getP1()->getPosition());
17+
18+
const type::Vec3 edgeDirection = tip - edgeBase;
19+
20+
if (couplingPts.empty()) return true;
21+
const type::Vec3 tip2Pt = couplingPts.back()->getPosition() - tip;
22+
23+
// Positive dot product means the point is ahead of the tip
24+
if (dot(tip2Pt, edgeDirection) > 0_sreal) couplingPts.pop_back();
25+
26+
return true;
27+
}
28+
29+
int register_PrunePointsAheadOfTip_Edge =
30+
PrunePointsAheadOfTip::register_func<EdgeElement>(&prunePointsUsingEdges);
31+
} // namespace sofa::collisionAlgorithm::Operations::Needle
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma once
2+
3+
#include <sofa/collisionAlgorithm/BaseOperation.h>
4+
#include <sofa/collisionAlgorithm/BaseProximity.h>
5+
#include <sofa/collisionAlgorithm/elements/EdgeElement.h>
6+
7+
namespace sofa::collisionAlgorithm::Operations::Needle
8+
{
9+
10+
class PrunePointsAheadOfTip
11+
: public GenericOperation<PrunePointsAheadOfTip, // Type of the operation
12+
bool, // Default return type
13+
std::vector<BaseProximity::SPtr>&,
14+
const BaseElement::SPtr& // Parameters
15+
>
16+
{
17+
public:
18+
bool defaultFunc(std::vector<BaseProximity::SPtr>&, const BaseElement::SPtr&) const override
19+
{
20+
return false;
21+
}
22+
23+
void notFound(const std::type_info& id) const override
24+
{
25+
msg_error("Needle::PrunePointsAheadOfTip")
26+
<< "The operation PrunePointsAheadOfTipOperation is not registered with for type = "
27+
<< sofa::helper::NameDecoder::decodeFullName(id);
28+
}
29+
};
30+
31+
bool prunePointsUsingEdges(std::vector<BaseProximity::SPtr>& couplingPts,
32+
const EdgeElement::SPtr& edgeProx);
33+
34+
} // namespace sofa::collisionAlgorithm::Operations::Needle

0 commit comments

Comments
 (0)