From 833c8ef961e68f952b5acb1d71febf400a964ea0 Mon Sep 17 00:00:00 2001 From: Frederick Roy Date: Fri, 18 Apr 2025 15:23:51 +0900 Subject: [PATCH 1/5] wip wip --- .../component/BaseBeamInterpolation.h | 2 + src/BeamAdapter/component/BeamInterpolation.h | 1 + .../component/BeamInterpolation.inl | 18 ++- .../component/WireBeamInterpolation.h | 5 + .../InterventionalRadiologyController.inl | 15 +-- .../component/engine/WireRestShape.h | 12 +- .../component/engine/WireRestShape.inl | 103 +++++++++++++----- .../AdaptiveBeamForceFieldAndMass.inl | 4 +- .../mapping/MultiAdaptiveBeamMapping.inl | 4 +- .../component/model/BaseRodSectionMaterial.h | 6 +- .../model/BaseRodSectionMaterial.inl | 5 +- 11 files changed, 124 insertions(+), 51 deletions(-) diff --git a/src/BeamAdapter/component/BaseBeamInterpolation.h b/src/BeamAdapter/component/BaseBeamInterpolation.h index f49c7522e..d7d8b7369 100644 --- a/src/BeamAdapter/component/BaseBeamInterpolation.h +++ b/src/BeamAdapter/component/BaseBeamInterpolation.h @@ -114,6 +114,8 @@ class BaseBeamInterpolation : public virtual sofa::core::objectmodel::BaseObject Real getLength(const EdgeID edgeInList); void setLength(const EdgeID edgeInList, Real& length); + virtual void getMechanicalSampling(Real& dx, const Real x_localcurv_abs) = 0; + /// Collision information using @sa d_beamCollision virtual void getCollisionSampling(Real& dx, const Real x_localcurv_abs) = 0; void addCollisionOnBeam(const sofa::Index beam); diff --git a/src/BeamAdapter/component/BeamInterpolation.h b/src/BeamAdapter/component/BeamInterpolation.h index 2be0fc5b9..a73409573 100644 --- a/src/BeamAdapter/component/BeamInterpolation.h +++ b/src/BeamAdapter/component/BeamInterpolation.h @@ -199,6 +199,7 @@ class BeamInterpolation : public BaseBeamInterpolation virtual void getSamplingParameters(type::vector& xP_noticeable, type::vector& nbP_density) override; Real getRestTotalLength() override; + void getMechanicalSampling(Real& dx, const Real x_localcurv_abs) override; void getCollisionSampling(Real &dx, const Real x_localcurv_abs) override; void getNumberOfCollisionSegment(Real &dx, unsigned int &numLines) override; diff --git a/src/BeamAdapter/component/BeamInterpolation.inl b/src/BeamAdapter/component/BeamInterpolation.inl index 9af09e6c6..e064858bc 100644 --- a/src/BeamAdapter/component/BeamInterpolation.inl +++ b/src/BeamAdapter/component/BeamInterpolation.inl @@ -420,17 +420,29 @@ typename BeamInterpolation::Real BeamInterpolation::getRes return le; } + +template +void BeamInterpolation::getMechanicalSampling(Real& dx, const Real x_localcurv_abs) +{ + SOFA_UNUSED(x_localcurv_abs); + + const auto numLines = this->m_topologyEdges->size(); + dx = getRestTotalLength()/numLines; +} + template -void BeamInterpolation::getCollisionSampling(Real &dx, const Real /*x_localcurv_abs*/) +void BeamInterpolation::getCollisionSampling(Real &dx, const Real x_localcurv_abs) { - unsigned int numLines = 30; + SOFA_UNUSED(x_localcurv_abs); + + const auto numLines = this->m_topologyEdges->size(); dx = getRestTotalLength()/numLines; } template void BeamInterpolation::getNumberOfCollisionSegment(Real &dx, unsigned int &numLines) { - numLines = 30; + numLines = static_cast(this->m_topologyEdges->size()); dx = getRestTotalLength()/numLines; } diff --git a/src/BeamAdapter/component/WireBeamInterpolation.h b/src/BeamAdapter/component/WireBeamInterpolation.h index 6e7b0ba71..592d0364e 100644 --- a/src/BeamAdapter/component/WireBeamInterpolation.h +++ b/src/BeamAdapter/component/WireBeamInterpolation.h @@ -117,6 +117,11 @@ class WireBeamInterpolation : public BaseBeamInterpolation return this->m_restShape->getLength(); } + void getMechanicalSampling(Real &dx, const Real x_localcurv_abs) override + { + this->m_restShape->getMechanicalSampling(dx,x_localcurv_abs); + } + void getCollisionSampling(Real &dx, const Real x_localcurv_abs) override { this->m_restShape->getCollisionSampling(dx,x_localcurv_abs); diff --git a/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl b/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl index fb7f8a1e9..bef1fe649 100644 --- a/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl +++ b/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl @@ -567,7 +567,7 @@ void InterventionalRadiologyController::interventionalRadiologyCollis for (int i = static_cast(xPointList.size()) - 1; i>=0; i--) { //1. we determin if the poin ument - int instrumentId = idInstrumentList[i]; + const int instrumentId = idInstrumentList[i]; // x_max for the instrument that is controlled (not dropped part) Real xMaxControlled = m_instrumentsList[instrumentId]->getRestTotalLength(); @@ -585,9 +585,9 @@ void InterventionalRadiologyController::interventionalRadiologyCollis xPointList[i] = xAbsCurv - xBegin; // provides the "local" curv absc of the point (on the instrument reference) idInstrumentList[i] = firstInstruOnx; - // 3. we look for the collision sampling of the current instrument in order to "place" the following point + // 3. we look for the mechanical sampling of the current instrument in order to "place" the following point Real xIncr; - m_instrumentsList[firstInstruOnx]->getCollisionSampling(xIncr, xPointList[i]); + m_instrumentsList[firstInstruOnx]->getMechanicalSampling(xIncr, xPointList[i]); xAbsCurv -= xIncr; // the following point could not have x_abs_curv<0; @@ -626,7 +626,7 @@ void InterventionalRadiologyController::interventionalRadiologyCollis for (unsigned int i=0; igetRestTotalLength(); @@ -709,7 +709,7 @@ void InterventionalRadiologyController::applyInterventionalRadiologyC // Create vectors with the CurvAbs of the noticiable points and the id of the corresponding instrument type::vector newCurvAbs; - type::vector> idInstrumentTable; + type::vector> idInstrumentTable; // i.e for each node -> [instID0, instID1...] // ## STEP 1: Find the total length of the COMBINED INSTRUMENTS and the one for which xtip > 0 (so the one which are simulated) helper::AdvancedTimer::stepBegin("step1"); @@ -767,10 +767,11 @@ void InterventionalRadiologyController::applyInterventionalRadiologyC // => Get write access to current nodes/dofs Data* datax = this->getMechanicalState()->write(sofa::core::vec_id::write_access::position); auto x = sofa::helper::getWriteOnlyAccessor(*datax); - VecCoord xbuf = x.ref(); + const VecCoord xbuf = x.ref(); // make a copy of the positions, as it will changed meanwhile const sofa::Size numberOfNodes = x.size(); sofa::Size numberOfSimulatedNodes = newCurvAbs.size(); // number of simulated nodes + if (numberOfSimulatedNodes > numberOfNodes) { msg_warning() << "Parameters missmatch. There are more curv abscisses '" << numberOfSimulatedNodes << "' than the number of dof: " << numberOfNodes; @@ -1012,7 +1013,7 @@ void InterventionalRadiologyController::fillInstrumentCurvAbsTable(co xBegin -= threshold; xEnd += threshold; - // check curvAbs sorted value, if value is inside [xBegin, xBegin] of the tool add it to instrumentList. + // check curvAbs sorted value, if value is inside [xBegin, xEnd] of the tool add it to instrumentList. for (unsigned int i = 0; i < curvAbs.size(); i++) { if (curvAbs[i] < xBegin) // still not inside range diff --git a/src/BeamAdapter/component/engine/WireRestShape.h b/src/BeamAdapter/component/engine/WireRestShape.h index 55dd6dc29..95041e685 100644 --- a/src/BeamAdapter/component/engine/WireRestShape.h +++ b/src/BeamAdapter/component/engine/WireRestShape.h @@ -107,10 +107,10 @@ class WireRestShape : public core::objectmodel::BaseObject Real getLength() ; - void getCollisionSampling(Real &dx, const Real x_curv); - void getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines) ; - - + + void getMechanicalSampling(Real& dx, const Real x_localcurv_abs); + void getCollisionSampling(Real &dx, const Real x_curv); + void getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines); /////////////////////////// Deprecated Methods ////////////////////////////////////////// @@ -142,9 +142,7 @@ class WireRestShape : public core::objectmodel::BaseObject private: /// Link to be set to the topology container in the component graph. - SingleLink, TopologyContainer, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology; - /// Pointer to the topology container, should be set using @sa l_topology, otherwise will search for one in current Node. - TopologyContainer* _topology{ nullptr }; + SingleLink, sofa::core::topology::BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology; }; diff --git a/src/BeamAdapter/component/engine/WireRestShape.inl b/src/BeamAdapter/component/engine/WireRestShape.inl index 61a3e1377..4d8f20eab 100644 --- a/src/BeamAdapter/component/engine/WireRestShape.inl +++ b/src/BeamAdapter/component/engine/WireRestShape.inl @@ -58,7 +58,8 @@ WireRestShape::WireRestShape() , l_sectionMaterials(initLink("wireMaterials", "link to Wire Section Materials (to be ordered according to the instrument, from handle to tip)")) , l_topology(initLink("topology", "link to the topology container")) { - + d_density.setReadOnly(true); // density is supposed to be filled using the section materials + d_keyPoints.setReadOnly(true); // key points are supposed to be filled using the section materials } @@ -70,16 +71,15 @@ void WireRestShape::init() ////////////////////////////////////////////// ////////// get and fill local topology /////// ////////////////////////////////////////////// - - // Get pointer to given topology using the link. If not found will search in current context. - _topology = l_topology.get(); - if (!_topology) - this->getContext()->get(_topology); + if (!l_topology) + { + l_topology.set(this->getContext()->getMeshTopologyLink()); + } - if(_topology != nullptr) + if (l_topology) { - msg_info() << "found topology named "<< _topology->getName() ; + msg_info() << "Found topology named "<< l_topology->getName() ; } else { @@ -94,6 +94,16 @@ void WireRestShape::init() this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } + + // Workaround around the fact that d_density and d_keyPoints are supposed to be output only + if(d_density.isSet()) + { + msg_warning() << "The density field will be ignored (output only Data)."; + } + if(d_keyPoints.isSet()) + { + msg_warning() << "The keyPoints field will be ignored (output only Data)."; + } //////////////////////////////////////////////////////// @@ -124,7 +134,7 @@ void WireRestShape::initLengths() { auto rodSection = l_sectionMaterials.get(i); keyPointList[i+1] = keyPointList[i] + rodSection->getLength(); - densityList[i] = rodSection->getNbCollisionEdges(); + densityList[i] = rodSection->getNbBeams(); } } @@ -133,8 +143,8 @@ template bool WireRestShape::initTopology() { /// fill topology : - _topology->clear(); - _topology->cleanup(); + l_topology->clear(); + l_topology->cleanup(); const type::vector& keyPts = d_keyPoints.getValue(); if (l_sectionMaterials.size() != keyPts.size() - 1) @@ -155,12 +165,12 @@ bool WireRestShape::initTopology() // add points from the material for (int i = startPtId; i < nbrVisuEdges + 1; i++) { - _topology->addPoint(prev_length + i * dx, 0, 0); + l_topology->addPoint(prev_length + i * dx, 0, 0); } // add segments from the material for (int i = prev_edges; i < prev_edges + nbrVisuEdges; i++) { - _topology->addEdge(i, i + 1); + l_topology->addEdge(i, i + 1); } prev_length = length; @@ -181,10 +191,51 @@ void WireRestShape::getSamplingParameters(type::vector& xP_noti } +template +void WireRestShape::getMechanicalSampling(Real &dx, const Real x_curv) +{ + unsigned int numLines = 0; + Real x_used = x_curv - EPSILON; + + const Real totalLength = this->getLength(); + x_used = std::clamp(x_used, 0.0, totalLength); + + const type::vector& keyPts = d_keyPoints.getValue(); + + // verify that size of number of materials == size of keyPoints-1 + if (l_sectionMaterials.size() != keyPts.size() - 1) + { + msg_error() << "Problem size of number of materials: " << l_sectionMaterials.size() + << " != size of keyPoints-1 " << keyPts.size()-1 + << ". Returning default values."; + numLines = 20; + dx = totalLength / numLines; + return; + } + + // Check in which section x_used belongs to and get access to this section material + for (sofa::Size i = 1; i< keyPts.size(); ++i) + { + if (x_used <= keyPts[i]) + { + numLines = l_sectionMaterials.get(i-1)->getNbBeams(); + + Real length = fabs(keyPts[i] - keyPts[i-1]); + dx = length / numLines; + return; + } + } + + // If x_used is out of bounds. Warn user and returns default value. + numLines = 20; + dx = totalLength / numLines; + msg_error() << " problem in getMechanicalSampling : x_curv " << x_used << " is not between keyPoints" << d_keyPoints.getValue(); +} + template void WireRestShape::getCollisionSampling(Real &dx, const Real x_curv) { - unsigned int numLines; + unsigned int numLines = 0; Real x_used = x_curv - EPSILON; const Real totalLength = this->getLength(); @@ -227,6 +278,17 @@ void WireRestShape::getCollisionSampling(Real &dx, const Real x_curv) msg_error() << " problem in getCollisionSampling : x_curv " << x_used << " is not between keyPoints" << d_keyPoints.getValue(); } +template +void WireRestShape::getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines) +{ + numLines = 0; + for (sofa::Size i = 0; i < l_sectionMaterials.size(); ++i) + { + numLines += l_sectionMaterials.get(i)->getNbCollisionEdges(); + } + dx = getLength() / numLines; +} + template void WireRestShape::getRestTransformOnX(Transform &global_H_local, const Real x) @@ -319,19 +381,6 @@ typename WireRestShape::Real WireRestShape::getLength() return d_keyPoints.getValue().back(); } - -template -void WireRestShape::getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines) -{ - numLines = 0; - for (sofa::Size i = 0; i < l_sectionMaterials.size(); ++i) - { - numLines += l_sectionMaterials.get(i)->getNbCollisionEdges(); - } - dx = getLength() / numLines; -} - - template void WireRestShape::computeOrientation(const Vec3& AB, const Quat& Q, Quat &result) { diff --git a/src/BeamAdapter/component/forcefield/AdaptiveBeamForceFieldAndMass.inl b/src/BeamAdapter/component/forcefield/AdaptiveBeamForceFieldAndMass.inl index 757b96a45..b72f54b73 100644 --- a/src/BeamAdapter/component/forcefield/AdaptiveBeamForceFieldAndMass.inl +++ b/src/BeamAdapter/component/forcefield/AdaptiveBeamForceFieldAndMass.inl @@ -60,7 +60,7 @@ AdaptiveBeamForceFieldAndMass::AdaptiveBeamForceFieldAndMass() , m_defaultMassDensity(Real(1.)) , d_massDensity(initData(&d_massDensity,type::vector(1, m_defaultMassDensity),"massDensity", "Density of the mass" )) , d_useShearStressComputation(initData(&d_useShearStressComputation, true, "shearStressComputation","if false, suppress the shear stress in the computation")) - , d_reinforceLength(initData(&d_reinforceLength, false, "reinforceLength", "if true, a separate computation for the error in elongation is peformed")) + , d_reinforceLength(initData(&d_reinforceLength, false, "reinforceLength", "if true, a separate computation for the error in elongation is performed")) , l_interpolation(initLink("interpolation","Path to the Interpolation component on scene")) { @@ -507,7 +507,7 @@ void AdaptiveBeamForceFieldAndMass::addForce (const MechanicalParams* ///* Calculer les rotation et les transformations ///* Calculer la matrice "locale" ///* Calculer la force exercée par chaque beam - ///* Calculer la force exercée par la gravitée + ///* Calculer la force exercée par la gravité for (sofa::Index beamId=0; beamId ::assignSubMappingFromControllerInfo() } else { - msg_error() << "Trying to remove baseEdge which is alreay empty. This case is not supposed to happened."; + msg_error() << "Trying to remove baseEdge which is already empty. This case is not supposed to happened."; } if (edgeToRemove.size()>0) @@ -308,7 +308,7 @@ void MultiAdaptiveBeamMapping< TIn, TOut>::init() unsigned int numSeg, numLinesInstrument; numSeg=0; InReal DX=0; - // we chose the collision parameters of the most discrestized instrument + // we chose the collision parameters of the most discretized instrument for (unsigned int i=0; i d_innerRadius; ///< Data defining the geometry internal radius of this section is hollow Data d_length; ///< Data defining the geometry length of this section + Data d_nbBeams; ///< Data defining the number of (mechanical) beams composing this section Data d_nbEdgesVisu; ///< Data defining the number of visual edges composing this section Data d_nbEdgesCollis; ///< Data defining the number of collision edges composing this section diff --git a/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl b/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl index 957363dcc..67748fb32 100644 --- a/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl +++ b/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl @@ -34,8 +34,9 @@ BaseRodSectionMaterial::BaseRodSectionMaterial() , d_radius(initData(&d_radius, (Real)1.0, "radius", "Full radius of this section")) , d_innerRadius(initData(&d_innerRadius, (Real)0.0, "innerRadius", "Inner radius of this section if hollow")) , d_length(initData(&d_length, (Real)1.0, "length", "Total length of this section")) - , d_nbEdgesVisu(initData(&d_nbEdgesVisu, (Size)10, "nbEdgesVisu", "number of Edges for the visual model")) - , d_nbEdgesCollis(initData(&d_nbEdgesCollis, (Size)20, "nbEdgesCollis", "number of Edges for the collision model")) + , d_nbBeams(initData(&d_nbBeams, (Size)5, "nbBeams", "Number of Beams for the mechanical model")) + , d_nbEdgesVisu(initData(&d_nbEdgesVisu, (Size)10, "nbEdgesVisu", "Number of Edges for the visual model")) + , d_nbEdgesCollis(initData(&d_nbEdgesCollis, (Size)20, "nbEdgesCollis", "Number of Edges for the collision model")) { } From 8f7361bfda81655c7dd0bc314ae4d68579ce2e18 Mon Sep 17 00:00:00 2001 From: Frederick Roy Date: Fri, 18 Apr 2025 15:41:32 +0900 Subject: [PATCH 2/5] make link for topo --- .../InterventionalRadiologyController.h | 4 ++++ .../InterventionalRadiologyController.inl | 23 +++++++++++++++++-- .../mapping/MultiAdaptiveBeamMapping.inl | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/BeamAdapter/component/controller/InterventionalRadiologyController.h b/src/BeamAdapter/component/controller/InterventionalRadiologyController.h index 3e2bcddd9..d01a8666b 100644 --- a/src/BeamAdapter/component/controller/InterventionalRadiologyController.h +++ b/src/BeamAdapter/component/controller/InterventionalRadiologyController.h @@ -180,6 +180,10 @@ class InterventionalRadiologyController : public sofa::component::controller::Me SingleLink< InterventionalRadiologyController, FixedProjectiveConstraint, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_fixedConstraint; + SingleLink< + InterventionalRadiologyController, sofa::core::topology::BaseMeshTopology, + BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_mechanicalTopology; + DeprecatedAndRemoved m_fixedConstraint; type::vector m_sensorMotionData; diff --git a/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl b/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl index bef1fe649..96362df09 100644 --- a/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl +++ b/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl @@ -70,6 +70,7 @@ InterventionalRadiologyController::InterventionalRadiologyController( , d_motionFilename(initData(&d_motionFilename, "motionFilename", "text file that includes tracked motion from optical sensor")) , d_indexFirstNode(initData(&d_indexFirstNode, (unsigned int) 0, "indexFirstNode", "first node (should be fixed with restshape)")) , l_fixedConstraint(initLink("fixedConstraint", "Path to the FixedProjectiveConstraint")) +, l_mechanicalTopology(initLink("topology", "Path to the mechanical topology")) { m_sensored =false; } @@ -80,6 +81,23 @@ void InterventionalRadiologyController::init() { BaseContext* context = getContext(); this->mState = nullptr; + + if(!l_mechanicalTopology) + { + msg_info() << "topology (path to the mechanical topology) has not been set, searching for one in the context."; + l_mechanicalTopology.set(this->getContext()->getMeshTopologyLink()); + } + + if (l_mechanicalTopology) + { + msg_info() << "Found topology named "<< l_mechanicalTopology->getName() ; + } + else + { + msg_error() << "Cannot find topology container. Please specify the link to the topology or insert one in the same node."; + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; + } //get the pointers of the WireBeamInterpolations const type::vector& instrumentPathList = d_instrumentsPath.getValue(); @@ -100,7 +118,8 @@ void InterventionalRadiologyController::init() } } - if (m_instrumentsList.empty()) { + if (m_instrumentsList.empty()) + { msg_error() << "No instrument found (no WireBeamInterpolation)! the component can not work and will be set to Invalid."; sofa::core::objectmodel::BaseObject::d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; @@ -1067,7 +1086,7 @@ const type::vector< type::vector >& InterventionalRadiologyController int InterventionalRadiologyController::getTotalNbEdges() const { - return getContext()->getMeshTopology()->getNbEdges(); + return l_mechanicalTopology->getNbEdges(); } diff --git a/src/BeamAdapter/component/mapping/MultiAdaptiveBeamMapping.inl b/src/BeamAdapter/component/mapping/MultiAdaptiveBeamMapping.inl index 7ff45c04d..2d8c12a28 100644 --- a/src/BeamAdapter/component/mapping/MultiAdaptiveBeamMapping.inl +++ b/src/BeamAdapter/component/mapping/MultiAdaptiveBeamMapping.inl @@ -384,7 +384,7 @@ int MultiAdaptiveBeamMapping< TIn, TOut>::addBaryPoint(const int& edgeId,const V int nbUnControlledEdges = totalNbEdges - nbControlledEdge; assert(nbUnControlledEdges>=0); - if (edgeId < (totalNbEdges-nbControlledEdge) ) + if (edgeId < nbUnControlledEdges ) { //if the edge in question is not under control, dont need to compute for collision } From 0f9732964c090a99e24259f8d0600174ba421201 Mon Sep 17 00:00:00 2001 From: Frederick Roy Date: Fri, 18 Apr 2025 20:58:43 +0900 Subject: [PATCH 3/5] compat for nbbeams --- src/BeamAdapter/component/model/BaseRodSectionMaterial.inl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl b/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl index 67748fb32..b9adaac51 100644 --- a/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl +++ b/src/BeamAdapter/component/model/BaseRodSectionMaterial.inl @@ -47,6 +47,12 @@ void BaseRodSectionMaterial::init() { this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Loading); + if(!d_nbBeams.isSet()) + { + msg_deprecated() << "nbBeams is now required but it was not set. Its value will be copied from nbEdgesCollis as a temporary compatibility solution."; + d_nbBeams.setValue(d_nbEdgesCollis.getValue()); + } + // Prepare beam sections double r = this->d_radius.getValue(); double rInner = this->d_innerRadius.getValue(); From 29f94cb7b3d49ebe745ccfd3bf1d69e1207e3cb3 Mon Sep 17 00:00:00 2001 From: Frederick Roy Date: Tue, 22 Apr 2025 16:06:15 +0900 Subject: [PATCH 4/5] fetch total number of potential beams --- src/BeamAdapter/component/BeamInterpolation.h | 2 +- src/BeamAdapter/component/BeamInterpolation.inl | 1 - src/BeamAdapter/component/WireBeamInterpolation.h | 6 ++++++ src/BeamAdapter/component/engine/WireRestShape.h | 1 + src/BeamAdapter/component/engine/WireRestShape.inl | 11 +++++++++++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/BeamAdapter/component/BeamInterpolation.h b/src/BeamAdapter/component/BeamInterpolation.h index a73409573..5da83f227 100644 --- a/src/BeamAdapter/component/BeamInterpolation.h +++ b/src/BeamAdapter/component/BeamInterpolation.h @@ -202,7 +202,7 @@ class BeamInterpolation : public BaseBeamInterpolation void getMechanicalSampling(Real& dx, const Real x_localcurv_abs) override; void getCollisionSampling(Real &dx, const Real x_localcurv_abs) override; void getNumberOfCollisionSegment(Real &dx, unsigned int &numLines) override; - + void setTransformBetweenDofAndNode(const sofa::Index beam, const Transform &DOF_H_Node, unsigned int zeroORone ); void getSplineRestTransform(const EdgeID edgeInList, Transform &local_H_local0_rest, Transform &local_H_local1_rest) override; diff --git a/src/BeamAdapter/component/BeamInterpolation.inl b/src/BeamAdapter/component/BeamInterpolation.inl index e064858bc..066f5eae4 100644 --- a/src/BeamAdapter/component/BeamInterpolation.inl +++ b/src/BeamAdapter/component/BeamInterpolation.inl @@ -446,7 +446,6 @@ void BeamInterpolation::getNumberOfCollisionSegment(Real &dx, unsigne dx = getRestTotalLength()/numLines; } - template void BeamInterpolation::getInterpolationParameters(sofa::Index beamId, Real& _L, Real& _A, Real& _Iy, Real& _Iz, Real& _Asy, Real& _Asz, Real& _J) diff --git a/src/BeamAdapter/component/WireBeamInterpolation.h b/src/BeamAdapter/component/WireBeamInterpolation.h index 592d0364e..cbdbd60bb 100644 --- a/src/BeamAdapter/component/WireBeamInterpolation.h +++ b/src/BeamAdapter/component/WireBeamInterpolation.h @@ -131,6 +131,12 @@ class WireBeamInterpolation : public BaseBeamInterpolation { this->m_restShape->getNumberOfCollisionSegment(dx,numLines); } + + // this is the number of beams which can be simulated according to the rest shape (and its sections) + sofa::Size getTotalNumberOfPossibleBeams() + { + return this->m_restShape->getTotalNumberOfBeams(); + } virtual void getRestTransform(const EdgeID edgeInList, Transform &local0_H_local1_rest); diff --git a/src/BeamAdapter/component/engine/WireRestShape.h b/src/BeamAdapter/component/engine/WireRestShape.h index 95041e685..822d76c8b 100644 --- a/src/BeamAdapter/component/engine/WireRestShape.h +++ b/src/BeamAdapter/component/engine/WireRestShape.h @@ -111,6 +111,7 @@ class WireRestShape : public core::objectmodel::BaseObject void getMechanicalSampling(Real& dx, const Real x_localcurv_abs); void getCollisionSampling(Real &dx, const Real x_curv); void getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines); + sofa::Size getTotalNumberOfBeams(); /////////////////////////// Deprecated Methods ////////////////////////////////////////// diff --git a/src/BeamAdapter/component/engine/WireRestShape.inl b/src/BeamAdapter/component/engine/WireRestShape.inl index 4d8f20eab..547c6d17f 100644 --- a/src/BeamAdapter/component/engine/WireRestShape.inl +++ b/src/BeamAdapter/component/engine/WireRestShape.inl @@ -289,6 +289,17 @@ void WireRestShape::getNumberOfCollisionSegment(Real &dx, sofa::Size& dx = getLength() / numLines; } +template +sofa::Size WireRestShape::getTotalNumberOfBeams() +{ + sofa::Size numBeams = 0; + for (sofa::Size i = 0; i < l_sectionMaterials.size(); ++i) + { + numBeams += l_sectionMaterials.get(i)->getNbBeams(); + } + + return numBeams; +} template void WireRestShape::getRestTransformOnX(Transform &global_H_local, const Real x) From aa9b355c9ab1f80a6afe9ffa35a917fb695ea8fc Mon Sep 17 00:00:00 2001 From: Frederick Roy Date: Wed, 23 Apr 2025 07:45:06 +0900 Subject: [PATCH 5/5] add warnings --- .../component/WireBeamInterpolation.h | 2 +- .../component/WireBeamInterpolation.inl | 2 +- .../InterventionalRadiologyController.inl | 32 ++++++++++++------- .../component/engine/WireRestShape.h | 2 +- .../component/engine/WireRestShape.inl | 2 +- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/BeamAdapter/component/WireBeamInterpolation.h b/src/BeamAdapter/component/WireBeamInterpolation.h index cbdbd60bb..42240b39d 100644 --- a/src/BeamAdapter/component/WireBeamInterpolation.h +++ b/src/BeamAdapter/component/WireBeamInterpolation.h @@ -133,7 +133,7 @@ class WireBeamInterpolation : public BaseBeamInterpolation } // this is the number of beams which can be simulated according to the rest shape (and its sections) - sofa::Size getTotalNumberOfPossibleBeams() + sofa::Size getTotalNumberOfPossibleBeams() const { return this->m_restShape->getTotalNumberOfBeams(); } diff --git a/src/BeamAdapter/component/WireBeamInterpolation.inl b/src/BeamAdapter/component/WireBeamInterpolation.inl index fdd3443e3..2a791aa6a 100644 --- a/src/BeamAdapter/component/WireBeamInterpolation.inl +++ b/src/BeamAdapter/component/WireBeamInterpolation.inl @@ -57,7 +57,7 @@ void WireBeamInterpolation::init() this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } - + type::vector xP_noticeable; type::vector nbP_density; diff --git a/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl b/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl index 96362df09..0005a64b7 100644 --- a/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl +++ b/src/BeamAdapter/component/controller/InterventionalRadiologyController.inl @@ -223,27 +223,35 @@ void InterventionalRadiologyController::bwdInit() stPos.getOrientation().normalize(); d_startingPos.setValue(stPos); - if (!this->mState) { + if (!this->mState) + { msg_error() << "No MechanicalState found. The component can not work and will be set to Invalid."; sofa::core::objectmodel::BaseObject::d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } + + // check if the provided mechanical state and topology can manage our tools + sofa::Size requiredNumberOfEdges = 0; + for (const auto* instrument : m_instrumentsList) + { + requiredNumberOfEdges += instrument->getTotalNumberOfPossibleBeams(); + } + + if(requiredNumberOfEdges + 1 > this->mState->getSize()) + { + msg_warning() << "The associated Mechanical Object does not contain enough nodes (" << this->mState->getSize() + << ") whereas the provided tool(s) need(s) at least " << requiredNumberOfEdges + 1 << " nodes."; + } + if(requiredNumberOfEdges > this->l_mechanicalTopology->getNbEdges()) + { + msg_warning() << "The associated Topology does not contain enough edges (" << this->l_mechanicalTopology->getNbEdges() + << ") whereas the provided tool(s) need(s) at least " << requiredNumberOfEdges << " edges."; + } WriteAccessor > x = *this->mState->write(sofa::core::vec_id::write_access::position); for(unsigned int i=0; i xP_noticeable_I; - type::vector density_I; - m_instrumentsList[i]->getSamplingParameters(xP_noticeable_I, density_I); - - for (auto nb : density_I) - nbrBeam += nb; - } - applyInterventionalRadiologyController(); sofa::core::objectmodel::BaseObject::d_componentState.setValue(sofa::core::objectmodel::ComponentState::Valid); diff --git a/src/BeamAdapter/component/engine/WireRestShape.h b/src/BeamAdapter/component/engine/WireRestShape.h index 822d76c8b..4332f7784 100644 --- a/src/BeamAdapter/component/engine/WireRestShape.h +++ b/src/BeamAdapter/component/engine/WireRestShape.h @@ -111,7 +111,7 @@ class WireRestShape : public core::objectmodel::BaseObject void getMechanicalSampling(Real& dx, const Real x_localcurv_abs); void getCollisionSampling(Real &dx, const Real x_curv); void getNumberOfCollisionSegment(Real &dx, sofa::Size& numLines); - sofa::Size getTotalNumberOfBeams(); + sofa::Size getTotalNumberOfBeams() const; /////////////////////////// Deprecated Methods ////////////////////////////////////////// diff --git a/src/BeamAdapter/component/engine/WireRestShape.inl b/src/BeamAdapter/component/engine/WireRestShape.inl index 547c6d17f..3fed22982 100644 --- a/src/BeamAdapter/component/engine/WireRestShape.inl +++ b/src/BeamAdapter/component/engine/WireRestShape.inl @@ -290,7 +290,7 @@ void WireRestShape::getNumberOfCollisionSegment(Real &dx, sofa::Size& } template -sofa::Size WireRestShape::getTotalNumberOfBeams() +sofa::Size WireRestShape::getTotalNumberOfBeams() const { sofa::Size numBeams = 0; for (sofa::Size i = 0; i < l_sectionMaterials.size(); ++i)