Skip to content

Commit efacdc8

Browse files
authored
[Wire Shape] Fix the confusion between the nbEdgesCollision and the number of mechanical Beams (#177)
* make link for topo * compat for nbbeams
1 parent d019b69 commit efacdc8

12 files changed

Lines changed: 156 additions & 54 deletions

src/BeamAdapter/component/BaseBeamInterpolation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ class BaseBeamInterpolation : public virtual sofa::core::objectmodel::BaseObject
114114
Real getLength(const EdgeID edgeInList);
115115
void setLength(const EdgeID edgeInList, Real& length);
116116

117+
virtual void getMechanicalSampling(Real& dx, const Real x_localcurv_abs) = 0;
118+
117119
/// Collision information using @sa d_beamCollision
118120
virtual void getCollisionSampling(Real& dx, const Real x_localcurv_abs) = 0;
119121
void addCollisionOnBeam(const sofa::Index beam);

src/BeamAdapter/component/BeamInterpolation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ class BeamInterpolation : public BaseBeamInterpolation<DataTypes>
199199
virtual void getSamplingParameters(type::vector<Real>& xP_noticeable,
200200
type::vector<sofa::Size>& nbP_density) override;
201201
Real getRestTotalLength() override;
202+
void getMechanicalSampling(Real& dx, const Real x_localcurv_abs) override;
202203
void getCollisionSampling(Real &dx, const Real x_localcurv_abs) override;
203204
void getNumberOfCollisionSegment(Real &dx, unsigned int &numLines) override;
204205

src/BeamAdapter/component/BeamInterpolation.inl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,17 +420,29 @@ typename BeamInterpolation<DataTypes>::Real BeamInterpolation<DataTypes>::getRes
420420
return le;
421421
}
422422

423+
424+
template <class DataTypes>
425+
void BeamInterpolation<DataTypes>::getMechanicalSampling(Real& dx, const Real x_localcurv_abs)
426+
{
427+
SOFA_UNUSED(x_localcurv_abs);
428+
429+
const auto numLines = this->m_topologyEdges->size();
430+
dx = getRestTotalLength()/numLines;
431+
}
432+
423433
template <class DataTypes>
424-
void BeamInterpolation<DataTypes>::getCollisionSampling(Real &dx, const Real /*x_localcurv_abs*/)
434+
void BeamInterpolation<DataTypes>::getCollisionSampling(Real &dx, const Real x_localcurv_abs)
425435
{
426-
unsigned int numLines = 30;
436+
SOFA_UNUSED(x_localcurv_abs);
437+
438+
const auto numLines = this->m_topologyEdges->size();
427439
dx = getRestTotalLength()/numLines;
428440
}
429441

430442
template <class DataTypes>
431443
void BeamInterpolation<DataTypes>::getNumberOfCollisionSegment(Real &dx, unsigned int &numLines)
432444
{
433-
numLines = 30;
445+
numLines = static_cast<unsigned int>(this->m_topologyEdges->size());
434446
dx = getRestTotalLength()/numLines;
435447
}
436448

src/BeamAdapter/component/WireBeamInterpolation.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@ class WireBeamInterpolation : public BaseBeamInterpolation<DataTypes>
117117
return this->m_restShape->getLength();
118118
}
119119

120+
void getMechanicalSampling(Real &dx, const Real x_localcurv_abs) override
121+
{
122+
this->m_restShape->getMechanicalSampling(dx,x_localcurv_abs);
123+
}
124+
120125
void getCollisionSampling(Real &dx, const Real x_localcurv_abs) override
121126
{
122127
this->m_restShape->getCollisionSampling(dx,x_localcurv_abs);

src/BeamAdapter/component/controller/InterventionalRadiologyController.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ class InterventionalRadiologyController : public sofa::component::controller::Me
180180
SingleLink<
181181
InterventionalRadiologyController, FixedProjectiveConstraint<DataTypes>,
182182
BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_fixedConstraint;
183+
SingleLink<
184+
InterventionalRadiologyController, sofa::core::topology::BaseMeshTopology,
185+
BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_mechanicalTopology;
186+
183187
DeprecatedAndRemoved m_fixedConstraint;
184188

185189
type::vector<Vec3d> m_sensorMotionData;

src/BeamAdapter/component/controller/InterventionalRadiologyController.inl

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ InterventionalRadiologyController<DataTypes>::InterventionalRadiologyController(
7070
, d_motionFilename(initData(&d_motionFilename, "motionFilename", "text file that includes tracked motion from optical sensor"))
7171
, d_indexFirstNode(initData(&d_indexFirstNode, (unsigned int) 0, "indexFirstNode", "first node (should be fixed with restshape)"))
7272
, l_fixedConstraint(initLink("fixedConstraint", "Path to the FixedProjectiveConstraint"))
73+
, l_mechanicalTopology(initLink("topology", "Path to the mechanical topology"))
7374
{
7475
m_sensored =false;
7576
}
@@ -80,6 +81,23 @@ void InterventionalRadiologyController<DataTypes>::init()
8081
{
8182
BaseContext* context = getContext();
8283
this->mState = nullptr;
84+
85+
if(!l_mechanicalTopology)
86+
{
87+
msg_info() << "topology (path to the mechanical topology) has not been set, searching for one in the context.";
88+
l_mechanicalTopology.set(this->getContext()->getMeshTopologyLink());
89+
}
90+
91+
if (l_mechanicalTopology)
92+
{
93+
msg_info() << "Found topology named "<< l_mechanicalTopology->getName() ;
94+
}
95+
else
96+
{
97+
msg_error() << "Cannot find topology container. Please specify the link to the topology or insert one in the same node.";
98+
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
99+
return;
100+
}
83101

84102
//get the pointers of the WireBeamInterpolations
85103
const type::vector<std::string>& instrumentPathList = d_instrumentsPath.getValue();
@@ -100,7 +118,8 @@ void InterventionalRadiologyController<DataTypes>::init()
100118
}
101119
}
102120

103-
if (m_instrumentsList.empty()) {
121+
if (m_instrumentsList.empty())
122+
{
104123
msg_error() << "No instrument found (no WireBeamInterpolation)! the component can not work and will be set to Invalid.";
105124
sofa::core::objectmodel::BaseObject::d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
106125
return;
@@ -567,7 +586,7 @@ void InterventionalRadiologyController<DataTypes>::interventionalRadiologyCollis
567586
for (int i = static_cast<int>(xPointList.size()) - 1; i>=0; i--)
568587
{
569588
//1. we determin if the poin ument
570-
int instrumentId = idInstrumentList[i];
589+
const int instrumentId = idInstrumentList[i];
571590

572591
// x_max for the instrument that is controlled (not dropped part)
573592
Real xMaxControlled = m_instrumentsList[instrumentId]->getRestTotalLength();
@@ -585,9 +604,9 @@ void InterventionalRadiologyController<DataTypes>::interventionalRadiologyCollis
585604
xPointList[i] = xAbsCurv - xBegin; // provides the "local" curv absc of the point (on the instrument reference)
586605
idInstrumentList[i] = firstInstruOnx;
587606

588-
// 3. we look for the collision sampling of the current instrument in order to "place" the following point
607+
// 3. we look for the mechanical sampling of the current instrument in order to "place" the following point
589608
Real xIncr;
590-
m_instrumentsList[firstInstruOnx]->getCollisionSampling(xIncr, xPointList[i]);
609+
m_instrumentsList[firstInstruOnx]->getMechanicalSampling(xIncr, xPointList[i]);
591610
xAbsCurv -= xIncr;
592611

593612
// the following point could not have x_abs_curv<0;
@@ -626,7 +645,7 @@ void InterventionalRadiologyController<DataTypes>::interventionalRadiologyCollis
626645

627646
for (unsigned int i=0; i<xPointList.size(); i++)
628647
{
629-
int instrumentId = idInstrumentList[i];
648+
const int instrumentId = idInstrumentList[i];
630649

631650
// x_max for the instrument that is controlled (not dropped part)
632651
Real xMaxInstrument = m_instrumentsList[instrumentId]->getRestTotalLength();
@@ -709,7 +728,7 @@ void InterventionalRadiologyController<DataTypes>::applyInterventionalRadiologyC
709728

710729
// Create vectors with the CurvAbs of the noticiable points and the id of the corresponding instrument
711730
type::vector<Real> newCurvAbs;
712-
type::vector<type::vector<int>> idInstrumentTable;
731+
type::vector<type::vector<int>> idInstrumentTable; // i.e for each node -> [instID0, instID1...]
713732

714733
// ## STEP 1: Find the total length of the COMBINED INSTRUMENTS and the one for which xtip > 0 (so the one which are simulated)
715734
helper::AdvancedTimer::stepBegin("step1");
@@ -767,10 +786,11 @@ void InterventionalRadiologyController<DataTypes>::applyInterventionalRadiologyC
767786
// => Get write access to current nodes/dofs
768787
Data<VecCoord>* datax = this->getMechanicalState()->write(sofa::core::vec_id::write_access::position);
769788
auto x = sofa::helper::getWriteOnlyAccessor(*datax);
770-
VecCoord xbuf = x.ref();
789+
const VecCoord xbuf = x.ref(); // make a copy of the positions, as it will changed meanwhile
771790

772791
const sofa::Size numberOfNodes = x.size();
773792
sofa::Size numberOfSimulatedNodes = newCurvAbs.size(); // number of simulated nodes
793+
774794
if (numberOfSimulatedNodes > numberOfNodes)
775795
{
776796
msg_warning() << "Parameters missmatch. There are more curv abscisses '" << numberOfSimulatedNodes << "' than the number of dof: " << numberOfNodes;
@@ -1012,7 +1032,7 @@ void InterventionalRadiologyController<DataTypes>::fillInstrumentCurvAbsTable(co
10121032
xBegin -= threshold;
10131033
xEnd += threshold;
10141034

1015-
// check curvAbs sorted value, if value is inside [xBegin, xBegin] of the tool add it to instrumentList.
1035+
// check curvAbs sorted value, if value is inside [xBegin, xEnd] of the tool add it to instrumentList.
10161036
for (unsigned int i = 0; i < curvAbs.size(); i++)
10171037
{
10181038
if (curvAbs[i] < xBegin) // still not inside range
@@ -1066,7 +1086,7 @@ const type::vector< type::vector<int> >& InterventionalRadiologyController<DataT
10661086
template <class DataTypes>
10671087
int InterventionalRadiologyController<DataTypes>::getTotalNbEdges() const
10681088
{
1069-
return getContext()->getMeshTopology()->getNbEdges();
1089+
return l_mechanicalTopology->getNbEdges();
10701090
}
10711091

10721092

src/BeamAdapter/component/engine/WireRestShape.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ class WireRestShape : public core::objectmodel::BaseObject
107107

108108

109109
Real getLength() ;
110-
void getCollisionSampling(Real &dx, const Real x_curv);
111-
void getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines) ;
112-
113-
110+
111+
void getMechanicalSampling(Real& dx, const Real x_localcurv_abs);
112+
void getCollisionSampling(Real &dx, const Real x_curv);
113+
void getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines);
114114

115115
/////////////////////////// Deprecated Methods //////////////////////////////////////////
116116

@@ -142,9 +142,7 @@ class WireRestShape : public core::objectmodel::BaseObject
142142

143143
private:
144144
/// Link to be set to the topology container in the component graph.
145-
SingleLink<WireRestShape<DataTypes>, TopologyContainer, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;
146-
/// Pointer to the topology container, should be set using @sa l_topology, otherwise will search for one in current Node.
147-
TopologyContainer* _topology{ nullptr };
145+
SingleLink<WireRestShape<DataTypes>, sofa::core::topology::BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;
148146
};
149147

150148

src/BeamAdapter/component/engine/WireRestShape.inl

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ WireRestShape<DataTypes>::WireRestShape()
5858
, l_sectionMaterials(initLink("wireMaterials", "link to Wire Section Materials (to be ordered according to the instrument, from handle to tip)"))
5959
, l_topology(initLink("topology", "link to the topology container"))
6060
{
61-
61+
d_density.setReadOnly(true); // density is supposed to be filled using the section materials
62+
d_keyPoints.setReadOnly(true); // key points are supposed to be filled using the section materials
6263
}
6364

6465

@@ -70,16 +71,15 @@ void WireRestShape<DataTypes>::init()
7071
//////////////////////////////////////////////
7172
////////// get and fill local topology ///////
7273
//////////////////////////////////////////////
73-
74-
// Get pointer to given topology using the link. If not found will search in current context.
75-
_topology = l_topology.get();
7674

77-
if (!_topology)
78-
this->getContext()->get(_topology);
75+
if (!l_topology)
76+
{
77+
l_topology.set(this->getContext()->getMeshTopologyLink());
78+
}
7979

80-
if(_topology != nullptr)
80+
if (l_topology)
8181
{
82-
msg_info() << "found topology named "<< _topology->getName() ;
82+
msg_info() << "Found topology named "<< l_topology->getName() ;
8383
}
8484
else
8585
{
@@ -94,6 +94,16 @@ void WireRestShape<DataTypes>::init()
9494
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
9595
return;
9696
}
97+
98+
// Workaround around the fact that d_density and d_keyPoints are supposed to be output only
99+
if(d_density.isSet())
100+
{
101+
msg_warning() << "The density field will be ignored (output only Data).";
102+
}
103+
if(d_keyPoints.isSet())
104+
{
105+
msg_warning() << "The keyPoints field will be ignored (output only Data).";
106+
}
97107

98108

99109
////////////////////////////////////////////////////////
@@ -124,7 +134,7 @@ void WireRestShape<DataTypes>::initLengths()
124134
{
125135
auto rodSection = l_sectionMaterials.get(i);
126136
keyPointList[i+1] = keyPointList[i] + rodSection->getLength();
127-
densityList[i] = rodSection->getNbCollisionEdges();
137+
densityList[i] = rodSection->getNbBeams();
128138
}
129139
}
130140

@@ -133,8 +143,8 @@ template <class DataTypes>
133143
bool WireRestShape<DataTypes>::initTopology()
134144
{
135145
/// fill topology :
136-
_topology->clear();
137-
_topology->cleanup();
146+
l_topology->clear();
147+
l_topology->cleanup();
138148

139149
const type::vector<Real>& keyPts = d_keyPoints.getValue();
140150
if (l_sectionMaterials.size() != keyPts.size() - 1)
@@ -155,12 +165,12 @@ bool WireRestShape<DataTypes>::initTopology()
155165

156166
// add points from the material
157167
for (int i = startPtId; i < nbrVisuEdges + 1; i++) {
158-
_topology->addPoint(prev_length + i * dx, 0, 0);
168+
l_topology->addPoint(prev_length + i * dx, 0, 0);
159169
}
160170

161171
// add segments from the material
162172
for (int i = prev_edges; i < prev_edges + nbrVisuEdges; i++) {
163-
_topology->addEdge(i, i + 1);
173+
l_topology->addEdge(i, i + 1);
164174
}
165175

166176
prev_length = length;
@@ -181,10 +191,51 @@ void WireRestShape<DataTypes>::getSamplingParameters(type::vector<Real>& xP_noti
181191
}
182192

183193

194+
template <class DataTypes>
195+
void WireRestShape<DataTypes>::getMechanicalSampling(Real &dx, const Real x_curv)
196+
{
197+
unsigned int numLines = 0;
198+
Real x_used = x_curv - EPSILON;
199+
200+
const Real totalLength = this->getLength();
201+
x_used = std::clamp(x_used, 0.0, totalLength);
202+
203+
const type::vector<Real>& keyPts = d_keyPoints.getValue();
204+
205+
// verify that size of number of materials == size of keyPoints-1
206+
if (l_sectionMaterials.size() != keyPts.size() - 1)
207+
{
208+
msg_error() << "Problem size of number of materials: " << l_sectionMaterials.size()
209+
<< " != size of keyPoints-1 " << keyPts.size()-1
210+
<< ". Returning default values.";
211+
numLines = 20;
212+
dx = totalLength / numLines;
213+
return;
214+
}
215+
216+
// Check in which section x_used belongs to and get access to this section material
217+
for (sofa::Size i = 1; i< keyPts.size(); ++i)
218+
{
219+
if (x_used <= keyPts[i])
220+
{
221+
numLines = l_sectionMaterials.get(i-1)->getNbBeams();
222+
223+
Real length = fabs(keyPts[i] - keyPts[i-1]);
224+
dx = length / numLines;
225+
return;
226+
}
227+
}
228+
229+
// If x_used is out of bounds. Warn user and returns default value.
230+
numLines = 20;
231+
dx = totalLength / numLines;
232+
msg_error() << " problem in getMechanicalSampling : x_curv " << x_used << " is not between keyPoints" << d_keyPoints.getValue();
233+
}
234+
184235
template <class DataTypes>
185236
void WireRestShape<DataTypes>::getCollisionSampling(Real &dx, const Real x_curv)
186237
{
187-
unsigned int numLines;
238+
unsigned int numLines = 0;
188239
Real x_used = x_curv - EPSILON;
189240

190241
const Real totalLength = this->getLength();
@@ -227,6 +278,17 @@ void WireRestShape<DataTypes>::getCollisionSampling(Real &dx, const Real x_curv)
227278
msg_error() << " problem in getCollisionSampling : x_curv " << x_used << " is not between keyPoints" << d_keyPoints.getValue();
228279
}
229280

281+
template <class DataTypes>
282+
void WireRestShape<DataTypes>::getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines)
283+
{
284+
numLines = 0;
285+
for (sofa::Size i = 0; i < l_sectionMaterials.size(); ++i)
286+
{
287+
numLines += l_sectionMaterials.get(i)->getNbCollisionEdges();
288+
}
289+
dx = getLength() / numLines;
290+
}
291+
230292

231293
template <class DataTypes>
232294
void WireRestShape<DataTypes>::getRestTransformOnX(Transform &global_H_local, const Real x)
@@ -319,19 +381,6 @@ typename WireRestShape<DataTypes>::Real WireRestShape<DataTypes>::getLength()
319381
return d_keyPoints.getValue().back();
320382
}
321383

322-
323-
template <class DataTypes>
324-
void WireRestShape<DataTypes>::getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines)
325-
{
326-
numLines = 0;
327-
for (sofa::Size i = 0; i < l_sectionMaterials.size(); ++i)
328-
{
329-
numLines += l_sectionMaterials.get(i)->getNbCollisionEdges();
330-
}
331-
dx = getLength() / numLines;
332-
}
333-
334-
335384
template <class DataTypes>
336385
void WireRestShape<DataTypes>::computeOrientation(const Vec3& AB, const Quat& Q, Quat &result)
337386
{

0 commit comments

Comments
 (0)