![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsAdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle.cpp 00003 ******************************************************************************/ 00007 /****************************************************************************** 00008 SUKITTI PUNAK (09/29/2010) 00009 UPDATE (01/07/2011) 00010 ******************************************************************************/ 00011 #include "TAPsAdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle.hpp" 00012 // Using Inclusion Model (i.e. definitions are included in declarations) 00013 // (this name.cpp is included in name.hpp) 00014 // Each friend is defined directly inside its declaration. 00015 00016 BEGIN_NAMESPACE_TAPs 00017 //============================================================================= 00018 // Constructors 00019 //----------------------------------------------------------------------------- 00020 template <typename T, typename DATA> 00021 AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle ( 00022 unsigned int size_IPs, // number of interactive points (IPs) on the head needle 00023 unsigned int size_Intp, // number of interpolated points on the head needle's circle path 00024 unsigned int RBDModelAsSutureHeadNeedle, 00025 unsigned int ERModelAsSutureThread 00026 ) 00027 : m_RBDModelAsSutureHeadNeedle( RBDModelAsSutureHeadNeedle ) 00028 , m_ERModelAsSutureThread( ERModelAsSutureThread ) 00029 , m_size_ForIPG( size_IPs ) 00030 , m_NumberOfSutureHeadNeedlePointsPuncturedIn( 0 ) 00031 , m_NumberOfSutureThreadPointsPuncturedIn( 0 ) 00032 00033 // For the head needle's circle path 00034 , m_size_ForCirclePath( size_Intp ) 00035 , m_uiNumOfLockedCirclePaths( 0 ) 00036 { 00037 m_SetOfInteractions_ForIPG.resize( size_IPs ); 00038 m_SetOfInteractionAssociatedModelID_ForIPG.resize( size_IPs, -1 ); 00039 m_PuncturedLocations_ForIPG.resize( size_IPs ); 00040 for ( unsigned int i = 0; i < size_IPs; ++i ) { 00041 m_SetOfInteractions_ForIPG[i].SetVertexIDFromModel_1( i ); 00042 } 00043 00044 // For the head needle's circle path 00045 m_SetOfInteractions_ForCirclePath.resize( size_Intp ); 00046 m_SetOfInteractionAssociatedModelID_ForCirclePath.resize( size_Intp, -1 ); 00047 for ( unsigned int i = 0; i < size_Intp; ++i ) { 00048 m_SetOfInteractions_ForCirclePath[i].SetVertexIDFromModel_1( i ); 00049 } 00050 } 00051 //----------------------------------------------------------------------------- 00052 template <typename T, typename DATA> 00053 AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::~AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle () 00054 { 00055 ResetPunctureController(); 00056 ClearAllConstraints_ForIPG(); 00057 ClearAllConstraints_ForCirclePath(); 00058 } 00059 //----------------------------------------------------------------------------- 00060 template <typename T, typename DATA> 00061 std::string AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::StrInfo () const 00062 { 00063 std::ostringstream ss; 00064 ss << "AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<" << typeid(T).name() << ">"; 00065 ss << " has size of " << m_size_ForIPG << " for IPs on the head needle"; 00066 ss << " and has size of " << m_size_ForCirclePath << " for the interpolated points on the head needle's circle path."; 00067 return ss.str(); 00068 } 00069 //----------------------------------------------------------------------------- 00070 template <typename T, typename DATA> 00071 HEVertex<T> * AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ProcessPuncturingOfHeadNeedleRepresentedByIPGWithFEMModel ( 00072 unsigned int FEMModel, 00073 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 00074 typename AdvSimSupport_DATA<T,DATA>::ModelLists & ListOfModelObjects, 00075 //std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, //!< list of suture models based on elastic rod (belongs to ER-based model group) 00076 //std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, //!< list of deformable models based on FEM (belongs to FEM-based model group) 00077 //std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, //!< list of models based on rigid body dynamics (belongs to IPG-based model group) 00078 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 00079 bool & bPunctureIn, 00080 bool & bPunctureOut, 00081 bool & bAborted 00082 ) 00083 { 00084 bPunctureIn = false; 00085 bPunctureOut = false; 00086 bAborted = false; 00087 00088 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER = ListOfModelObjects.BasedOnER; 00089 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM = ListOfModelObjects.BasedOnFEM; 00090 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD = ListOfModelObjects.BasedOnRBD; 00091 00092 m_PunctureController.StrInfo = ""; 00093 00094 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 00095 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 00096 00097 ModelDefBasedOnFEMHex<T,DATA> * pFEMHex = dynamic_cast< ModelDefBasedOnFEMHex<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 00098 ModelDefBasedOnFEMTet<T,DATA> * pFEMTet = dynamic_cast< ModelDefBasedOnFEMTet<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 00099 00100 if ( pFEMHex ) 00101 { 00102 InteractionPointGroup<T> & IPG = ListOfModelsBasedOnRBD[RBDloc]->RefToInteractionPointGroup(); 00103 if ( IPG.GetNumOfInteractionPoints() == 0 ) return NULL; 00104 std::vector< Vector3<T> > IPs = ListOfModelsBasedOnRBD[RBDloc]->GetAllInteractionPointPositionsInWorldSpace(); 00105 //if ( IPs.size() == 0 ) return; 00106 00107 //T distConstraint = 10E5; 00108 T distConstraint = ( IPs[2] - IPs[0] ).Length(); // this length is fixed 00109 00110 // 00111 unsigned int start = 0; 00112 00113 // Check intersection 00114 AdvSimSupport_DATA<T,DATA>::TEMP_ListOfPoints.clear(); 00115 AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEFaces.clear(); 00116 AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEVertices.clear(); 00117 AdvSimSupport_DATA<T,DATA>::TEMP_ListOfRatios.clear(); 00118 AdvSimSupport_DATA<T,DATA>::TEMP_ListOfIntersectionAngles.clear(); 00119 CD::Fn::CD_PolygonalMesh_vs_LineSegment( 00120 &ListOfModelsBasedOnFEM[FEMloc]->RefToSurfaceMesh(), // HE-based mesh model 00121 &IPs[start], &IPs[start+1], // line segment 00122 &AdvSimSupport_DATA<T,DATA>::TEMP_ListOfPoints, // list of intersected points 00123 &AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEFaces, // list of intersected HE-based faces 00124 &AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEVertices, // list of closest HE-based vertices to the intersected points 00125 &AdvSimSupport_DATA<T,DATA>::TEMP_ListOfRatios, // list of ratios of the closest vertices relative to the line segment [0(ptA)-1(ptB)] 00126 &AdvSimSupport_DATA<T,DATA>::TEMP_ListOfIntersectionAngles // list of intersected angles of the needle of Tyco Endo Stitch device with triangle faces 00127 ); 00128 00129 /* 00130 // DEBUG -- print out the intersection angles 00131 for ( unsigned int i = 0; i < AdvSimSupport_DATA<T,DATA>::TEMP_ListOfIntersectionAngles.size(); ++i ) { 00132 std::cout << i << "\tintersection angle\t" << AdvSimSupport_DATA<T,DATA>::TEMP_ListOfIntersectionAngles[i] << "\n"; 00133 } 00134 std::cout << "#of puncture-in pts created: " << m_PunctureController.NumOfPunctureInPointsCreated << "\n"; 00135 std::cout << "#of puncture-Out pts created: " << m_PunctureController.NumOfPunctureOutPointsCreated << "\n"; 00136 //*/ 00137 00138 //------------------------------------------------- 00139 // START: CASE FOR PUNCTURE-IN OR -OUT 00140 if ( AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEVertices.size() > 0 ) { 00141 00142 // (FIRST) PUNCTURE-IN 00143 // Check if the sharp point is not currently punturing ( i.e. < 0 ) 00144 if ( m_SetOfInteractionAssociatedModelID_ForIPG[start] < 0 ) { 00145 00146 if ( m_PunctureController.ReachNumOfPunctureInPointsLimit() ) { 00147 m_PunctureController.StrInfo = "Number of created puncture-in points has reached the limit!"; 00148 return NULL; 00149 } 00150 00151 if ( AdvSimSupport_DATA<T,DATA>::TEMP_ListOfIntersectionAngles[0] > m_PunctureController.PunctureInAngleThreshold ) { 00152 m_PunctureController.StrInfo = "The angle is too small for the head needle to puncture into the wound!"; 00153 return NULL; 00154 } 00155 00156 // DEBUG -- Protection 00157 if ( m_NumberOfSutureHeadNeedlePointsPuncturedIn > 0 ) return NULL; 00158 00159 //std::cout << "NEXT PUNCTURE IN\n"; 00160 00161 unsigned int id = start; 00162 HEVertex<T> * pHEVertex = AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEVertices[0]; 00163 00164 // Set simulation flags of the interaction point at id 00165 IPG.GetInteractionPointAtIndex( id ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00166 //IPG.GetInteractionPointAtIndex( id ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00167 //IPG.GetInteractionPointAtIndex( id ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00168 00169 // Set simulation flags of the HEVertex 00170 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00171 00172 // 00173 // Set the constraint number at id 00174 // 00175 m_SetOfInteractionAssociatedModelID_ForIPG[id] = FEMModel; 00176 //m_SetOfInteractions[id].SetVertexIDFromModel_1( id ); // already set and it is invariant 00177 m_SetOfInteractions_ForIPG[id].SetPtrToVertexFromModel_2( pHEVertex ); 00178 m_SetOfInteractions_ForIPG[id].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 00179 m_SetOfInteractions_ForIPG[id].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 00180 m_SetOfInteractions_ForIPG[id].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 00181 m_SetOfInteractions_ForIPG[id].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 00182 m_SetOfInteractions_ForIPG[id].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 00183 m_SetOfInteractions_ForIPG[id].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 00184 m_SetOfInteractions_ForIPG[id].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 00185 00186 00187 ListOfModelsBasedOnRBD[RBDloc]->LockPosition(); // lock the head needle 00188 m_PuncturedLocations_ForIPG[id] = IPs[start]; // save the first punctured location 00189 m_SharpPointPrevPos_ForIPG = IPs[0]; // save the location of the sharp point 00190 ++m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00191 00192 //std::cout << "m_NumberOfSutureHeadNeedlePointsPuncturedIn: " << m_NumberOfSutureHeadNeedlePointsPuncturedIn << "\n"; 00193 00194 bPunctureIn = true; 00195 m_PunctureController.WaitForTransfer = true; 00196 m_PunctureController.IncreaseNumOfPunctureInPointsCreated(); 00197 return pHEVertex; 00198 } 00199 // PUNCTURE-OUT 00200 else { 00201 00202 if ( m_PunctureController.ReachNumOfPunctureOutPointsLimit() ) { 00203 m_PunctureController.StrInfo = "Number of created puncture-out points has reached the limit!"; 00204 return NULL; 00205 } 00206 00207 if ( AdvSimSupport_DATA<T,DATA>::TEMP_ListOfIntersectionAngles[0] < 180 - m_PunctureController.PunctureOutAngleThreshold ) { 00208 m_PunctureController.StrInfo = "The angle is too small for the head needle to puncture out from the wound!"; 00209 return NULL; 00210 } 00211 00212 Matrix4x4<T> TrxFEMModel = ListOfModelsBasedOnFEM[FEMloc]->RefToTransformationSupport().RefToMatrixTransform(); 00213 Vector3<T> pos1 = TrxFEMModel * m_SetOfInteractions_ForIPG[start].GetPtrToVertexFromModel_2()->GetBarycentricPtr()->GetNewVertexLocation(); 00214 00215 T distThreshold = ( IPs[start] - IPs[start+1] ).Length(); 00216 T dist = (IPs[0] - m_SharpPointPrevPos_ForIPG).Length(); 00217 00218 if ( dist >= distThreshold && dist < distConstraint ) { 00219 00220 //std::cout << "NEXT PUNCTURE OUT\n"; 00221 00222 unsigned int next = 1; 00223 for ( ; next < m_size_ForIPG; ++next ) { 00224 if ( m_SetOfInteractionAssociatedModelID_ForIPG[next] < 0 ) break; 00225 } 00226 00227 //------------------------------------- 00228 // Make the next two points puncture in 00229 if ( next < m_size_ForIPG-1 ) { 00230 00231 // Set simulation flags of the HEVertex 00232 HEVertex<T> * pHEVertex = AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEVertices[0]; 00233 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00234 00235 // Set simulation flags of the interaction point at next and next+1 00236 IPG.GetInteractionPointAtIndex( next ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00237 //IPG.GetInteractionPointAtIndex( next ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00238 //IPG.GetInteractionPointAtIndex( next ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00239 IPG.GetInteractionPointAtIndex( next+1 ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00240 //IPG.GetInteractionPointAtIndex( next+1 ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00241 //IPG.GetInteractionPointAtIndex( next+1 ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00242 00243 // Save the punctured out location 00244 //m_PuncturedLocations_ForIPG[next+1] = IPs[start]; 00245 00246 // Shift the old point back one step, and put the new one at the sharp point. 00247 for ( unsigned int i = next+1; i > 1; --i ) { 00248 // The interaction is shifted by two 00249 m_SetOfInteractionAssociatedModelID_ForIPG[i] = m_SetOfInteractionAssociatedModelID_ForIPG[i-2]; 00250 //m_SetOfInteractions[i].SetVertexIDFromModel_1( i ); // already set and it is invariant 00251 m_SetOfInteractions_ForIPG[i].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForIPG[i-2].GetPtrToVertexFromModel_2() ); 00252 m_SetOfInteractions_ForIPG[i].SetForceRatio( m_SetOfInteractions_ForIPG[i-2].GetForceRatio() ); 00253 m_SetOfInteractions_ForIPG[i].SetForceScaleA( m_SetOfInteractions_ForIPG[i-2].GetForceScaleA() ); 00254 m_SetOfInteractions_ForIPG[i].SetForceScaleB( m_SetOfInteractions_ForIPG[i-2].GetForceScaleB() ); 00255 m_SetOfInteractions_ForIPG[i].SetForceThresholdA( m_SetOfInteractions_ForIPG[i-2].GetForceThresholdA() ); 00256 m_SetOfInteractions_ForIPG[i].SetForceThresholdB( m_SetOfInteractions_ForIPG[i-2].GetForceThresholdB() ); 00257 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusA( m_SetOfInteractions_ForIPG[i-2].GetEnforcePositionStatusA() ); 00258 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusB( m_SetOfInteractions_ForIPG[i-2].GetEnforcePositionStatusB() ); 00259 00260 // Shift the punctured location (is shifted by two) 00261 m_PuncturedLocations_ForIPG[i] = m_PuncturedLocations_ForIPG[i-2]; 00262 } 00263 00264 // 00265 // Set the constraint number at the 2nd point -- the first point after the sharp point 00266 // 00267 m_SetOfInteractionAssociatedModelID_ForIPG[start+1] = FEMModel; 00268 //m_SetOfInteractions_ForIPG[start].SetVertexIDFromModel_1( start+1 ); // already set and it is invariant 00269 m_SetOfInteractions_ForIPG[start+1].SetPtrToVertexFromModel_2( pHEVertex ); 00270 m_SetOfInteractions_ForIPG[start+1].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 00271 m_SetOfInteractions_ForIPG[start+1].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 00272 m_SetOfInteractions_ForIPG[start+1].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 00273 m_SetOfInteractions_ForIPG[start+1].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 00274 m_SetOfInteractions_ForIPG[start+1].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 00275 m_SetOfInteractions_ForIPG[start+1].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 00276 m_SetOfInteractions_ForIPG[start+1].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 00277 // Save the punctured location(s) 00278 m_PuncturedLocations_ForIPG[start+1] = IPs[start]; 00279 m_PuncturedLocations_ForIPG[start] = IPs[start]; 00280 00281 // 00282 // Clear the sharp point 00283 // 00284 IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::SLIDABLE ); 00285 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::ATTACHED ); 00286 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00287 m_SetOfInteractionAssociatedModelID_ForIPG[start] = -1; 00288 00289 m_SharpPointPrevPos_ForIPG = IPs[0]; // save the location of the sharp point 00290 ++m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00291 00292 //std::cout << "m_NumberOfSutureHeadNeedlePointsPuncturedIn: " << m_NumberOfSutureHeadNeedlePointsPuncturedIn << "\n"; 00293 } 00294 //------------------------------------- 00295 // Make the 1st point of suture thread puncture in 00296 else { 00297 00298 // Save the location of the sharp point 00299 //m_SharpPointPrevPos_ForIPG = IPs[0]; 00300 00301 //--m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00302 } 00303 //------------------------------------- 00304 00305 bPunctureOut = true; 00306 //m_PunctureController.WaitForTransfer = true; 00307 m_PunctureController.IncreaseNumOfPunctureOutPointsCreated(); 00308 return AdvSimSupport_DATA<T,DATA>::TEMP_ListOfHEVertices[0]; 00309 } 00310 } 00311 }// END: CASE FOR PUNCTURE-IN OR -OUT 00312 //------------------------------------------------- 00313 // START: CASE FOR STILL PUNCTURING INSIDE, WITH NO PUNCTURE-OUT YET 00314 // The sharp point is currently punturing ( i.e. >= 0 ) 00315 else if ( m_SetOfInteractionAssociatedModelID_ForIPG[start] >= 0 ) { 00316 00317 //std::cout << "m_SetOfInteractionAssociatedModelID[start] >= 0\n"; 00318 00319 unsigned int next = 1; 00320 for ( ; next < m_size_ForIPG; ++next ) { 00321 if ( m_SetOfInteractionAssociatedModelID_ForIPG[next] < 0 ) break; 00322 } 00323 00324 if ( next < m_size_ForIPG ) { 00325 00326 //std::cout << "NEXT: " << next << "\n"; 00327 00328 Matrix4x4<T> TrxFEMModel = ListOfModelsBasedOnFEM[FEMloc]->RefToTransformationSupport().RefToMatrixTransform(); 00329 Vector3<T> pos1 = TrxFEMModel * m_SetOfInteractions_ForIPG[start].GetPtrToVertexFromModel_2()->GetBarycentricPtr()->GetNewVertexLocation(); 00330 00331 T distThreshold = ( IPs[next] - IPs[next-1] ).Length();// * 2; 00332 T dist = (IPs[0] - m_SharpPointPrevPos_ForIPG).Length(); 00333 00334 //* 00335 // Before puncture out, check for abortion of the puncture if the head needle is moved to far from the path 00336 T distAbort = distThreshold * 5; 00337 if ( next < 2 && dist > distAbort ) { // next is the point number in the IPG 00338 bAborted = true; 00339 ClearAllConstraints_ForIPG(); 00340 return NULL; 00341 } 00342 //*/ 00343 00344 if ( dist >= distThreshold && dist < distConstraint ) { 00345 00346 // FIND THE VERTEX AT INTERACTION POINT#0 00347 bool bFound = false; 00348 unsigned int elementID; 00349 //Vector3<T> position = IPs[start]; 00350 Vector3<T> position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * IPs[start]; // start is 0 00351 Vector3<unsigned int> gridLocations; 00352 Vector3<T> coordinates; 00353 bFound = pFEMHex->FindElementThatContainsPointInLocalSpace( position, elementID, gridLocations, coordinates ); 00354 00355 // Replace the surface HEVertex with a created inner HEVertex inside the FEMModel 00356 if ( bFound ) { 00357 00358 HEVertex<T> * pNewHEVertex = pFEMHex->AddExtraVertexInLocalSpace( 00359 position, elementID, &pFEMHex->RefToFEMMesh().RefToElement( elementID ), gridLocations, coordinates ); 00360 00361 // Set simulation flags of the interaction point at id 00362 IPG.GetInteractionPointAtIndex( next ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00363 //IPG.GetInteractionPointAtIndex( next ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00364 //IPG.GetInteractionPointAtIndex( next ).GetSimFlags().SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00365 00366 // Set simulation flags of the HEVertex 00367 pNewHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00368 00369 // Save the punctured location 00370 //PuncturedLocations.push_back( IPs[start] ); 00371 00372 // Shift the old point back one step, and put the new one at the sharp point. 00373 for ( unsigned int i = next; i > 0; --i ) { 00374 m_SetOfInteractionAssociatedModelID_ForIPG[i] = m_SetOfInteractionAssociatedModelID_ForIPG[i-1]; 00375 //m_SetOfInteractions_ForIPG[i].SetVertexIDFromModel_1( i ); // already set and it is invariant 00376 m_SetOfInteractions_ForIPG[i].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForIPG[i-1].GetPtrToVertexFromModel_2() ); 00377 m_SetOfInteractions_ForIPG[i].SetForceRatio( m_SetOfInteractions_ForIPG[i-1].GetForceRatio() ); 00378 m_SetOfInteractions_ForIPG[i].SetForceScaleA( m_SetOfInteractions_ForIPG[i-1].GetForceScaleA() ); 00379 m_SetOfInteractions_ForIPG[i].SetForceScaleB( m_SetOfInteractions_ForIPG[i-1].GetForceScaleB() ); 00380 m_SetOfInteractions_ForIPG[i].SetForceThresholdA( m_SetOfInteractions_ForIPG[i-1].GetForceThresholdA() ); 00381 m_SetOfInteractions_ForIPG[i].SetForceThresholdB( m_SetOfInteractions_ForIPG[i-1].GetForceThresholdB() ); 00382 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusA( m_SetOfInteractions_ForIPG[i-1].GetEnforcePositionStatusA() ); 00383 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusB( m_SetOfInteractions_ForIPG[i-1].GetEnforcePositionStatusB() ); 00384 // Shift the punctured location 00385 m_PuncturedLocations_ForIPG[i] = m_PuncturedLocations_ForIPG[i-1]; 00386 } 00387 // 00388 // Set the constraint number at the sharp point 00389 // 00390 m_SetOfInteractionAssociatedModelID_ForIPG[start] = FEMModel; 00391 //m_SetOfInteractions_ForIPG[start].SetVertexIDFromModel_1( start ); // already set and it is invariant 00392 m_SetOfInteractions_ForIPG[start].SetPtrToVertexFromModel_2( pNewHEVertex ); 00393 m_SetOfInteractions_ForIPG[start].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 00394 m_SetOfInteractions_ForIPG[start].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 00395 m_SetOfInteractions_ForIPG[start].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 00396 m_SetOfInteractions_ForIPG[start].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 00397 m_SetOfInteractions_ForIPG[start].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 00398 m_SetOfInteractions_ForIPG[start].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 00399 m_SetOfInteractions_ForIPG[start].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 00400 // Save the punctured location 00401 m_PuncturedLocations_ForIPG[start] = IPs[start]; 00402 00403 m_SharpPointPrevPos_ForIPG = IPs[0]; // save the location of the sharp point 00404 ++m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00405 00406 //std::cout << "HEVertex's position: " << pNewHEVertex->GetPosition() << "\n"; 00407 //std::cout << "pConstraint: " << *pConstraint << std::endl; 00408 //std::cout << "pConstraint: " << pConstraint << std::endl; 00409 00410 //std::cout << "m_NumberOfSutureHeadNeedlePointsPuncturedIn: " << m_NumberOfSutureHeadNeedlePointsPuncturedIn << "\n"; 00411 } 00412 } 00413 } 00414 // Case the whole needle stays inside an FEM-based model 00415 else { 00416 } 00417 }//END: CASE FOR STILL PUNCTURING INSIDE 00418 //------------------------------------------------- 00419 // START: CASE FOR THE SHARP POINT HAS PUNCTURED OUT 00420 // The sharp point is currently punturing ( i.e. >= 0 ) 00421 else { 00422 start = 1; 00423 for ( ; start < m_size_ForIPG; ++start ) { 00424 if ( m_SetOfInteractionAssociatedModelID_ForIPG[start] >= 0 ) break; 00425 } 00426 // Case two or more points of head needle still inside an FEM-based model 00427 if ( start < m_size_ForIPG-1 ) { 00428 unsigned int next = start + 1; 00429 for ( ; next < m_size_ForIPG; ++next ) { 00430 if ( m_SetOfInteractionAssociatedModelID_ForIPG[next] < 0 ) break; 00431 } 00432 if ( next < m_size_ForIPG ) { 00433 00434 //std::cout << "next < m_size --> next: " << next << ", start: " << start << std::endl; 00435 00436 Matrix4x4<T> TrxFEMModel = ListOfModelsBasedOnFEM[FEMloc]->RefToTransformationSupport().RefToMatrixTransform(); 00437 Vector3<T> pos1 = TrxFEMModel * m_SetOfInteractions_ForIPG[start].GetPtrToVertexFromModel_2()->GetBarycentricPtr()->GetNewVertexLocation(); 00438 00439 T distThreshold = ( IPs[next] - IPs[next-1] ).Length(); 00440 T dist = (IPs[0] - m_SharpPointPrevPos_ForIPG).Length(); 00441 00442 if ( dist >= distThreshold && dist < distConstraint ) { 00443 // Shift every point by one 00444 for ( unsigned int i = next; i > start; --i ) { 00445 00446 m_SetOfInteractionAssociatedModelID_ForIPG[i] = m_SetOfInteractionAssociatedModelID_ForIPG[i-1]; 00447 //m_SetOfInteractions_ForIPG[i].SetVertexIDFromModel_1( i ); // already set and it is invariant 00448 m_SetOfInteractions_ForIPG[i].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForIPG[i-1].GetPtrToVertexFromModel_2() ); 00449 m_SetOfInteractions_ForIPG[i].SetForceRatio( m_SetOfInteractions_ForIPG[i-1].GetForceRatio() ); 00450 m_SetOfInteractions_ForIPG[i].SetForceScaleA( m_SetOfInteractions_ForIPG[i-1].GetForceScaleA() ); 00451 m_SetOfInteractions_ForIPG[i].SetForceScaleB( m_SetOfInteractions_ForIPG[i-1].GetForceScaleB() ); 00452 m_SetOfInteractions_ForIPG[i].SetForceThresholdA( m_SetOfInteractions_ForIPG[i-1].GetForceThresholdA() ); 00453 m_SetOfInteractions_ForIPG[i].SetForceThresholdB( m_SetOfInteractions_ForIPG[i-1].GetForceThresholdB() ); 00454 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusA( m_SetOfInteractions_ForIPG[i-1].GetEnforcePositionStatusA() ); 00455 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusB( m_SetOfInteractions_ForIPG[i-1].GetEnforcePositionStatusB() ); 00456 // Shift the punctured location 00457 m_PuncturedLocations_ForIPG[i] = m_PuncturedLocations_ForIPG[i-1]; 00458 } 00459 // 00460 // Clear the start point 00461 // 00462 IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::SLIDABLE ); 00463 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::ATTACHED ); 00464 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00465 m_SetOfInteractionAssociatedModelID_ForIPG[start] = -1; 00466 00467 m_PuncturedLocations_ForIPG[start] = IPs[start]; 00468 m_SharpPointPrevPos_ForIPG = IPs[0]; // save the location of the sharp point 00469 //m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00470 00471 //std::cout << "m_NumberOfSutureHeadNeedlePointsPuncturedIn: " << m_NumberOfSutureHeadNeedlePointsPuncturedIn << "\n"; 00472 } 00473 } 00474 else { // CASE: next == m_size 00475 00476 //std::cout << "next >= m_size --> next: " << next << ", start: " << start << std::endl; 00477 --next; 00478 00479 Matrix4x4<T> TrxFEMModel = ListOfModelsBasedOnFEM[FEMloc]->RefToTransformationSupport().RefToMatrixTransform(); 00480 Vector3<T> pos1 = TrxFEMModel * m_SetOfInteractions_ForIPG[start].GetPtrToVertexFromModel_2()->GetBarycentricPtr()->GetNewVertexLocation(); 00481 00482 T distThreshold = ( IPs[next] - IPs[next-1] ).Length(); 00483 T dist = (IPs[0] - m_SharpPointPrevPos_ForIPG).Length(); 00484 00485 if ( dist >= distThreshold && dist < distConstraint ) { 00486 00487 // 00488 // Add the constraint of suture thread 00489 // 00490 { 00491 //std::cout << "ADD SUTURE THREAD" << std::endl; 00492 00493 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 00494 unsigned int ERModelVertexID = 1; 00495 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 00496 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00497 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00498 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00499 // 00500 //unsigned int HEloc = m_SetOfInteractionAssociatedModelID_ForIPG[next]; 00501 HEVertex<T> * pVertexHEModel = m_SetOfInteractions_ForIPG[next].GetPtrToVertexFromModel_2(); 00502 00503 ++m_NumberOfSutureThreadPointsPuncturedIn; 00504 00505 //std::cout << "m_NumberOfSutureThreadPointsPuncturedIn: " << m_NumberOfSutureThreadPointsPuncturedIn << "\n"; 00506 00507 // Shift all suture points by one (FORWARD ATTACHMENT OF SUTURE'S THREAD WITH FEMMODEL) 00508 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForIPG.begin(); 00509 while ( it != m_ListOfSutureThreadVsFEMModels_ForIPG.end() ) { 00510 unsigned int ptID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1() + 1; 00511 it->pAdvSimConstraint_VertexIdVsHEVertex->SetVertexIDFromModel_1( ptID ); 00512 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00513 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00514 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00515 ++it; 00516 } 00517 00518 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 00519 new AdvSimConstraint_VertexIdVsHEVertex<T>( 00520 ERModelVertexID, 00521 pVertexHEModel, 00522 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 00523 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 00524 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 00525 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 00526 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 00527 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 00528 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 00529 ); 00530 m_ListOfSutureThreadVsFEMModels_ForIPG.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 00531 pConstraint->RefToSavedPositionB() = pVertexHEModel->GetPosition(); 00532 00533 //std::cout << "HEVertex's position: " << pVertexHEModel->GetPosition() << "\n"; 00534 //std::cout << "pConstraint: " << pConstraint << std::endl; 00535 //std::cout << "pConstraint: " << *pConstraint << std::endl; 00536 00537 } 00538 00539 // Shift every point by one 00540 for ( unsigned int i = next; i > start; --i ) { 00541 00542 m_SetOfInteractionAssociatedModelID_ForIPG[i] = m_SetOfInteractionAssociatedModelID_ForIPG[i-1]; 00543 //m_SetOfInteractions_ForIPG[i].SetVertexIDFromModel_1( i ); // already set and it is invariant 00544 m_SetOfInteractions_ForIPG[i].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForIPG[i-1].GetPtrToVertexFromModel_2() ); 00545 m_SetOfInteractions_ForIPG[i].SetForceRatio( m_SetOfInteractions_ForIPG[i-1].GetForceRatio() ); 00546 m_SetOfInteractions_ForIPG[i].SetForceScaleA( m_SetOfInteractions_ForIPG[i-1].GetForceScaleA() ); 00547 m_SetOfInteractions_ForIPG[i].SetForceScaleB( m_SetOfInteractions_ForIPG[i-1].GetForceScaleB() ); 00548 m_SetOfInteractions_ForIPG[i].SetForceThresholdA( m_SetOfInteractions_ForIPG[i-1].GetForceThresholdA() ); 00549 m_SetOfInteractions_ForIPG[i].SetForceThresholdB( m_SetOfInteractions_ForIPG[i-1].GetForceThresholdB() ); 00550 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusA( m_SetOfInteractions_ForIPG[i-1].GetEnforcePositionStatusA() ); 00551 m_SetOfInteractions_ForIPG[i].SetEnforcePositionStatusB( m_SetOfInteractions_ForIPG[i-1].GetEnforcePositionStatusB() ); 00552 // Shift the punctured location 00553 m_PuncturedLocations_ForIPG[i] = m_PuncturedLocations_ForIPG[i-1]; 00554 } 00555 // 00556 // Clear the start point 00557 // 00558 IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::SLIDABLE ); 00559 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::ATTACHED ); 00560 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00561 m_SetOfInteractionAssociatedModelID_ForIPG[start] = -1; 00562 00563 m_PuncturedLocations_ForIPG[start] = IPs[start]; 00564 m_SharpPointPrevPos_ForIPG = IPs[0]; // save the location of the sharp point 00565 --m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00566 00567 //std::cout << "m_NumberOfSutureHeadNeedlePointsPuncturedIn: " << m_NumberOfSutureHeadNeedlePointsPuncturedIn << "\n"; 00568 } 00569 } 00570 } 00571 // Case the last point of head needle still inside an FEM-based model 00572 else if ( start == m_size_ForIPG-1 ) { 00573 00574 //unsigned int next = start + 1; 00575 //std::cout << "next == m_size & start == m_size-1 --> next: " << next << ", start: " << start << ", m_size: " << m_size << std::endl; 00576 00577 Matrix4x4<T> TrxFEMModel = ListOfModelsBasedOnFEM[FEMloc]->RefToTransformationSupport().RefToMatrixTransform(); 00578 Vector3<T> pos1 = TrxFEMModel * m_SetOfInteractions_ForIPG[start].GetPtrToVertexFromModel_2()->GetBarycentricPtr()->GetNewVertexLocation(); 00579 00580 T distThreshold = ( IPs[start] - IPs[start-1] ).Length(); 00581 T dist = (IPs[0] - m_SharpPointPrevPos_ForIPG).Length(); 00582 00583 if ( dist >= distThreshold && dist < distConstraint ) { 00584 00585 // 00586 // Add the constraint of suture thread 00587 // 00588 { 00589 //std::cout << "ADD SUTURE THREAD (last connection)" << std::endl; 00590 00591 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 00592 unsigned int ERModelVertexID = 1; 00593 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 00594 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00595 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00596 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00597 // 00598 //unsigned int HEloc = m_SetOfInteractionAssociatedModelID_ForIPG[start]; 00599 HEVertex<T> * pVertexHEModel = m_SetOfInteractions_ForIPG[start].GetPtrToVertexFromModel_2(); 00600 00601 ++m_NumberOfSutureThreadPointsPuncturedIn; 00602 00603 //std::cout << "m_NumberOfSutureThreadPointsPuncturedIn: " << m_NumberOfSutureThreadPointsPuncturedIn << "\n"; 00604 00605 // Shift all suture points by one (FORWARD ATTACHMENT OF SUTURE'S THREAD WITH FEMMODEL) 00606 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForIPG.begin(); 00607 while ( it != m_ListOfSutureThreadVsFEMModels_ForIPG.end() ) { 00608 unsigned int ptID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1() + 1; 00609 it->pAdvSimConstraint_VertexIdVsHEVertex->SetVertexIDFromModel_1( ptID ); 00610 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 00611 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 00612 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00613 ++it; 00614 } 00615 00616 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 00617 new AdvSimConstraint_VertexIdVsHEVertex<T>( 00618 ERModelVertexID, 00619 pVertexHEModel, 00620 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 00621 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 00622 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 00623 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 00624 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 00625 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 00626 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 00627 ); 00628 pConstraint->RefToSavedPositionB() = pVertexHEModel->GetPosition(); 00629 m_ListOfSutureThreadVsFEMModels_ForIPG.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 00630 00631 //std::cout << "HEVertex's position: " << pVertexHEModel->GetPosition() << "\n"; 00632 //std::cout << "pConstraint: " << pConstraint << std::endl; 00633 //std::cout << "pConstraint: " << *pConstraint << std::endl; 00634 } 00635 // 00636 // Clear the start point 00637 // 00638 IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::SLIDABLE ); 00639 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::ATTACHED ); 00640 //IPG.GetInteractionPointAtIndex( start ).GetSimFlags().ClearSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 00641 m_SetOfInteractionAssociatedModelID_ForIPG[start] = -1; 00642 00643 ListOfModelsBasedOnRBD[RBDloc]->UnlockPosition(); // lock the head needle 00644 m_PuncturedLocations_ForIPG[start] = IPs[start]; 00645 m_SharpPointPrevPos_ForIPG = IPs[0]; // save the location of the sharp point 00646 --m_NumberOfSutureHeadNeedlePointsPuncturedIn; 00647 00648 //std::cout << "last point out\n"; 00649 //std::cout << "m_NumberOfSutureHeadNeedlePointsPuncturedIn: " << m_NumberOfSutureHeadNeedlePointsPuncturedIn << "\n"; 00650 00651 // Transfer the constraints to the main constraint data structure 00652 { 00653 TransferConstraintsToMainConstraintDS( 00654 m_ListOfSutureThreadVsFEMModels_ForIPG, 00655 ListOf_ERModelVsHEModelInteractions, 00656 ListOfModelObjects, 00657 ListOfModels[m_ERModelAsSutureThread].Slot 00658 ); 00659 00660 m_PunctureController.WaitForTransfer = false; 00661 00662 // Clear 00663 m_NumberOfSutureThreadPointsPuncturedIn = 0; 00664 m_ListOfSutureThreadVsFEMModels_ForIPG.clear(); 00665 } 00666 } 00667 } 00668 }//END: CASE FOR THE SHARP POINT HAS PUNCTURED OUT 00669 } 00670 00671 else if ( pFEMTet ) 00672 { 00673 PrtNotImplementedYet( "ProcessPuncturingOfHeadNeedleRepresentedByIPGWithFEMModel for FEMTet" ); 00674 } 00675 00676 00677 /* 00678 // DEBUG 00679 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 00680 unsigned int HEloc = 0; 00681 for ( unsigned int i = 0; i < ListOf_ERModelVsHEModelInteractions[ERloc][HEloc].size(); ++i ) { 00682 std::cout << i << ": ER vertID: " << ListOf_ERModelVsHEModelInteractions[ERloc][HEloc][i]->GetVertexIDFromModel_1() << "\n"; 00683 } 00684 //*/ 00685 00686 return NULL; 00687 } 00688 //----------------------------------------------------------------------------- 00689 template <typename T, typename DATA> 00690 HEVertex<T> * AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ProcessPuncturingOfHeadNeedleUsingCirclePathWithFEMModel ( 00691 typename ModelSurgicalSutureWithHeadNeedle<T>::CirclePath & CirclePathCtrl, 00692 unsigned int FEMModel, 00693 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 00694 typename AdvSimSupport_DATA<T,DATA>::ModelLists & ListOfModelObjects, 00695 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 00696 bool & bPunctureIn, 00697 bool & bPunctureOut, 00698 bool & bAborted, 00699 bool & bSuccess 00700 ) 00701 { 00702 //return NULL; 00703 00704 // Easy puncturing 00705 00706 00707 bPunctureIn = false; 00708 bPunctureOut = false; 00709 bAborted = false; 00710 bSuccess = false; 00711 00712 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER = ListOfModelObjects.BasedOnER; 00713 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM = ListOfModelObjects.BasedOnFEM; 00714 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD = ListOfModelObjects.BasedOnRBD; 00715 00716 /* 00717 // DEBUG LIMIT THE NUMBER OF LOCKED CIRCLE PATH 00718 if ( m_uiNumOfLockedCirclePaths >= 3 ) { 00719 CirclePathCtrl.pListOfCDNodes.clear(); 00720 ClearAllConstraints_ForCirclePath(); 00721 return NULL; 00722 } 00723 //*/ 00724 00725 //--------------------------------------------------------------- 00726 // Process puncturing of the locked puncture path 00727 if ( m_LockedCirclePath.IsLocked ) { 00728 HEVertex<T> * pVertex = ProcessLockedPuncturePath( 00729 m_LockedCirclePath, 00730 CirclePathCtrl, 00731 ListOfModels, 00732 ListOfModelObjects, 00733 ListOf_ERModelVsHEModelInteractions, 00734 bPunctureIn, 00735 bPunctureOut, 00736 bAborted, 00737 bSuccess 00738 ); 00739 00740 if ( bAborted ) { 00741 ClearAllConstraints_ForCirclePath(); 00742 CirclePathCtrl.pListOfCDNodes.clear(); 00743 return NULL; 00744 } 00745 00746 if ( bPunctureOut ) { 00747 CirclePathCtrl.pListOfCDNodes.clear(); 00748 } 00749 00750 return pVertex; 00751 //*/ 00752 00753 return NULL; 00754 } 00755 00756 //std::cout << "find puncture path" << std::endl; // DEBUG 00757 00758 //--------------------------------------------------------------- 00759 // 00760 // Find puncture path 00761 // 00762 00763 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 00764 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 00765 00766 ModelDefBasedOnFEMHex<T,DATA> * pFEMHex = dynamic_cast< ModelDefBasedOnFEMHex<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 00767 ModelDefBasedOnFEMTet<T,DATA> * pFEMTet = dynamic_cast< ModelDefBasedOnFEMTet<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 00768 00769 RigidBodyDynamics<T> * pHeadNeedle = ListOfModelsBasedOnRBD[RBDloc]; 00770 Matrix4x4<T> TrxRBD( pHeadNeedle->CalMatrixTransform() ); 00771 BVHNodeLeaf<T> cdNode( Enum::BVH_NODE_LEAF_SPHERE ); 00772 cdNode.SetCenter( TrxRBD * CirclePathCtrl.Center ); 00773 cdNode.SetRadius( CirclePathCtrl.Radius ); 00774 00775 Vector3<T> circleCenter = TrxRBD * CirclePathCtrl.Center; 00776 Vector3<T> circleNormalPlane = TrxRBD * (CirclePathCtrl.NormalPlane + CirclePathCtrl.Center) - circleCenter; 00777 00778 if ( pFEMHex ) 00779 { 00780 // Broad-phase collision detection of the model's binary sphere tree with the needle's circle path 00781 //bool bCD = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->TestOverlapWithTillLeafNodes( CirclePathCtrl.pCDSphereNode ); 00782 bool bCD = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->TestIntersectionWithCircleTillLeafNodes( &circleNormalPlane, &circleCenter, CirclePathCtrl.Radius ); 00783 if ( bCD ) { 00784 00785 // Narrow-phase collision detection of the triangles bounded by spheres 00786 // detected from the broad-phase collision detection with the needle's circle path 00787 std::vector< BVHNode<T> * > pBVHNodeList = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->GetListOfCollidedNodes(); 00788 std::vector< BVHNode<T> * >::iterator it = pBVHNodeList.begin(); 00789 00790 Matrix4x4<T> TrxFEM( pFEMHex->PtrToBVHTreeOfSurfaceMesh()->GetTransform().GetMatrixTransform() ); 00791 CirclePathCtrl.Trx = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->GetTransform(); 00792 CirclePathCtrl.pListOfCDNodes.clear(); 00793 00794 // Transform the interpolated points along the circle path to the world space 00795 std::vector< Vector3<T> > points; 00796 unsigned int numOfSegments = CirclePathCtrl.InterpolatedPts.size() - 1; 00797 for ( unsigned int i = 0; i <= numOfSegments; ++i ) { 00798 points.push_back( TrxRBD * CirclePathCtrl.InterpolatedPts[i] ); 00799 } 00800 00801 std::vector< unsigned int > interpolatedPointIDs; 00802 std::vector< HEFace<T> * > triangles; 00803 std::vector< unsigned int > listOfFEMModelIDs; 00804 00805 while ( it != pBVHNodeList.end() ) { 00806 int id = CDCirclePathVsTriangle( points, numOfSegments, (*it)->GetAPrimitiveHalfEdgeFace(), TrxFEM ); 00807 if ( id >= 0 ) { 00808 interpolatedPointIDs.push_back( id ); 00809 triangles.push_back( (*it)->GetAPrimitiveHalfEdgeFace() ); 00810 listOfFEMModelIDs.push_back( FEMModel ); 00811 CirclePathCtrl.pListOfCDNodes.push_back( *it ); 00812 } 00813 ++it; 00814 } 00815 00816 if ( interpolatedPointIDs.size() > 0 ) { 00817 00818 std::vector< unsigned int > interpolatedPointIDs_sorted; 00819 std::vector< HEFace<T> * > triangles_sorted; 00820 std::vector< unsigned int > listOfFEMModelIDs_sorted; 00821 std::vector< bool > checks( interpolatedPointIDs.size(), false ); 00822 00823 // Sort the data 00824 unsigned int minID, address; 00825 for ( unsigned int i = 0; i < interpolatedPointIDs.size(); ++i ) { 00826 minID = INT_MAX; 00827 address = INT_MAX; 00828 for ( unsigned int j = 0; j < interpolatedPointIDs.size(); ++j ) { 00829 if ( !checks[j] && minID > interpolatedPointIDs[j] ) { 00830 minID = interpolatedPointIDs[j]; 00831 address = j; 00832 } 00833 } 00834 if ( minID < INT_MAX ) { 00835 interpolatedPointIDs_sorted.push_back( minID ); 00836 triangles_sorted.push_back( triangles[address] ); 00837 listOfFEMModelIDs_sorted.push_back( listOfFEMModelIDs[address] ); 00838 checks[address] = true; 00839 } 00840 } 00841 00842 //return NULL; 00843 00844 if ( RecordAndLockThePuncturePath( 00845 CirclePathCtrl, 00846 ListOfModels, 00847 ListOfModelsBasedOnER, 00848 ListOfModelsBasedOnFEM, 00849 ListOfModelsBasedOnRBD, 00850 ListOf_ERModelVsHEModelInteractions, 00851 bPunctureIn, 00852 bPunctureOut, 00853 interpolatedPointIDs_sorted, 00854 triangles_sorted, 00855 listOfFEMModelIDs_sorted 00856 ) 00857 ) 00858 { 00859 } 00860 }//END: if ( interpolatedPointIDs.size() > 0 ) 00861 }//END: Narrow-phase CD 00862 }//END: if ( pFEMHex ) 00863 00864 else if ( pFEMTet ) 00865 { 00866 PrtNotImplementedYet( "ProcessPuncturingOfHeadNeedleUsingCirclePathWithFEMModel for FEMTet" ); 00867 }//END: if ( pFEMTet ) 00868 00869 return NULL; 00870 } 00871 //----------------------------------------------------------------------------- 00872 template <typename T, typename DATA> 00873 HEVertex<T> * AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ProcessPuncturingOfHeadNeedleUsingCirclePathWithFEMModel_MoreAccuButUnfinishYet ( 00874 typename ModelSurgicalSutureWithHeadNeedle<T>::CirclePath & CirclePathCtrl, 00875 unsigned int FEMModel, 00876 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 00877 typename AdvSimSupport_DATA<T,DATA>::ModelLists & ListOfModelObjects, 00878 //std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, //!< list of suture models based on elastic rod (belongs to ER-based model group) 00879 //std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, //!< list of deformable models based on FEM (belongs to FEM-based model group) 00880 //std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, //!< list of models based on rigid body dynamics (belongs to IPG-based model group) 00881 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 00882 bool & bPunctureIn, 00883 bool & bPunctureOut, 00884 bool & bAborted 00885 ) 00886 { 00887 bPunctureIn = false; 00888 bPunctureOut = false; 00889 bAborted = false; 00890 00891 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER = ListOfModelObjects.BasedOnER; 00892 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM = ListOfModelObjects.BasedOnFEM; 00893 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD = ListOfModelObjects.BasedOnRBD; 00894 00895 /* 00896 // DEBUG LIMIT THE NUMBER OF LOCKED CIRCLE PATH 00897 if ( m_uiNumOfLockedCirclePaths >= 3 ) { 00898 CirclePathCtrl.pListOfCDNodes.clear(); 00899 ClearAllConstraints_ForCirclePath(); 00900 return NULL; 00901 } 00902 //*/ 00903 00904 //--------------------------------------------------------------- 00905 // Process puncturing of the locked puncture path 00906 if ( m_LockedCirclePath.IsLocked ) { 00907 HEVertex<T> * pVertex = ProcessLockedPuncturePath_MoreAccuButUnfinishYet( 00908 m_LockedCirclePath, 00909 CirclePathCtrl, 00910 ListOfModels, 00911 ListOfModelObjects, 00912 ListOf_ERModelVsHEModelInteractions, 00913 bPunctureIn, 00914 bPunctureOut, 00915 bAborted 00916 ); 00917 00918 if ( bAborted ) { 00919 ClearAllConstraints_ForCirclePath(); 00920 CirclePathCtrl.pListOfCDNodes.clear(); 00921 return NULL; 00922 } 00923 00924 if ( bPunctureOut ) { 00925 CirclePathCtrl.pListOfCDNodes.clear(); 00926 } 00927 00928 return pVertex; 00929 } 00930 00931 //std::cout << "find puncture path" << std::endl; // DEBUG 00932 00933 //--------------------------------------------------------------- 00934 // 00935 // Find puncture path 00936 // 00937 00938 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 00939 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 00940 00941 ModelDefBasedOnFEMHex<T,DATA> * pFEMHex = dynamic_cast< ModelDefBasedOnFEMHex<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 00942 ModelDefBasedOnFEMTet<T,DATA> * pFEMTet = dynamic_cast< ModelDefBasedOnFEMTet<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 00943 00944 RigidBodyDynamics<T> * pHeadNeedle = ListOfModelsBasedOnRBD[RBDloc]; 00945 Matrix4x4<T> TrxRBD( pHeadNeedle->CalMatrixTransform() ); 00946 BVHNodeLeaf<T> cdNode( Enum::BVH_NODE_LEAF_SPHERE ); 00947 cdNode.SetCenter( TrxRBD * CirclePathCtrl.Center ); 00948 cdNode.SetRadius( CirclePathCtrl.Radius ); 00949 00950 Vector3<T> circleCenter = TrxRBD * CirclePathCtrl.Center; 00951 Vector3<T> circleNormalPlane = TrxRBD * (CirclePathCtrl.NormalPlane + CirclePathCtrl.Center) - circleCenter; 00952 00953 if ( pFEMHex ) 00954 { 00955 // Broad-phase collision detection of the model's binary sphere tree with the needle's circle path 00956 //bool bCD = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->TestOverlapWithTillLeafNodes( CirclePathCtrl.pCDSphereNode ); 00957 bool bCD = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->TestIntersectionWithCircleTillLeafNodes( &circleNormalPlane, &circleCenter, CirclePathCtrl.Radius ); 00958 if ( bCD ) { 00959 00960 // Narrow-phase collision detection of the triangles bounded by spheres 00961 // detected from the broad-phase collision detection with the needle's circle path 00962 std::vector< BVHNode<T> * > pBVHNodeList = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->GetListOfCollidedNodes(); 00963 std::vector< BVHNode<T> * >::iterator it = pBVHNodeList.begin(); 00964 00965 Matrix4x4<T> TrxFEM( pFEMHex->PtrToBVHTreeOfSurfaceMesh()->GetTransform().GetMatrixTransform() ); 00966 CirclePathCtrl.Trx = pFEMHex->PtrToBVHTreeOfSurfaceMesh()->GetTransform(); 00967 CirclePathCtrl.pListOfCDNodes.clear(); 00968 00969 // Transform the interpolated points along the circle path to the world space 00970 std::vector< Vector3<T> > points; 00971 unsigned int numOfSegments = CirclePathCtrl.InterpolatedPts.size() - 1; 00972 for ( unsigned int i = 0; i <= numOfSegments; ++i ) { 00973 points.push_back( TrxRBD * CirclePathCtrl.InterpolatedPts[i] ); 00974 } 00975 00976 std::vector< unsigned int > interpolatedPointIDs; 00977 std::vector< HEFace<T> * > triangles; 00978 std::vector< unsigned int > listOfFEMModelIDs; 00979 00980 while ( it != pBVHNodeList.end() ) { 00981 int id = CDCirclePathVsTriangle( points, numOfSegments, (*it)->GetAPrimitiveHalfEdgeFace(), TrxFEM ); 00982 if ( id >= 0 ) { 00983 interpolatedPointIDs.push_back( id ); 00984 triangles.push_back( (*it)->GetAPrimitiveHalfEdgeFace() ); 00985 listOfFEMModelIDs.push_back( FEMModel ); 00986 CirclePathCtrl.pListOfCDNodes.push_back( *it ); 00987 } 00988 ++it; 00989 } 00990 00991 if ( interpolatedPointIDs.size() > 0 ) { 00992 00993 std::vector< unsigned int > interpolatedPointIDs_sorted; 00994 std::vector< HEFace<T> * > triangles_sorted; 00995 std::vector< unsigned int > listOfFEMModelIDs_sorted; 00996 std::vector< bool > checks( interpolatedPointIDs.size(), false ); 00997 00998 // Sort the data 00999 unsigned int minID, address; 01000 for ( unsigned int i = 0; i < interpolatedPointIDs.size(); ++i ) { 01001 minID = INT_MAX; 01002 address = INT_MAX; 01003 for ( unsigned int j = 0; j < interpolatedPointIDs.size(); ++j ) { 01004 if ( !checks[j] && minID > interpolatedPointIDs[j] ) { 01005 minID = interpolatedPointIDs[j]; 01006 address = j; 01007 } 01008 } 01009 if ( minID < INT_MAX ) { 01010 interpolatedPointIDs_sorted.push_back( minID ); 01011 triangles_sorted.push_back( triangles[address] ); 01012 listOfFEMModelIDs_sorted.push_back( listOfFEMModelIDs[address] ); 01013 checks[address] = true; 01014 } 01015 } 01016 01017 /* 01018 // DEBUG 01019 std::cout << "Size of unsorted triangles: " << triangles.size() << std::endl; 01020 std::cout << "Size of sorted triangles: " << triangles_sorted.size() << std::endl; 01021 for ( unsigned int i = 0; i < triangles_sorted.size(); ++i ) { 01022 std::cout << i << "\t" << *triangles_sorted[i] << std::endl; 01023 } 01024 //*/ 01025 01026 /* 01027 // DEBUG 01028 std::cout << "IDs\n"; 01029 for ( unsigned int i = 0; i < interpolatedPointIDs_sorted.size(); ++i ) { 01030 std::cout << interpolatedPointIDs_sorted[i] << "\n"; 01031 std::cout << "FEMModel: " << listOfFEMModelIDs_sorted[i] << "\n"; 01032 std::cout << "Triangles: " << triangles_sorted[i] << "\n"; 01033 } 01034 //*/ 01035 01036 // The sorted data are interpolatedPointIDs_sorted and triangles_sorted 01037 // points still contains the interpolated point in world space along the circle path 01038 // point#0 is the end point of the needle 01039 // and point#[CirclePathCtrl.IDOfFirstInterpolatedPtBeforeSharpPt] is the first interpolated point before the needle's sharp point 01040 // 01041 // Record the punctured path 01042 // 01043 //m_LockedCirclePath.Clear(); // m_LockedCirclePath has to be cleared before calling RecordAndLockThePuncturePath_MoreAccuButUnfinishYet fn 01044 // Currently, tt is cleared in ProcessLockedPuncturePath_MoreAccuButUnfinishYet fn 01045 01046 //std::cout << "Try RecordAndLockThePuncturePath_MoreAccuButUnfinishYet" << std::endl; // DEBUG 01047 01048 if ( RecordAndLockThePuncturePath_MoreAccuButUnfinishYet( 01049 CirclePathCtrl, 01050 ListOfModels, 01051 ListOfModelsBasedOnER, 01052 ListOfModelsBasedOnFEM, 01053 ListOfModelsBasedOnRBD, 01054 ListOf_ERModelVsHEModelInteractions, 01055 bPunctureIn, 01056 bPunctureOut, 01057 interpolatedPointIDs_sorted, 01058 triangles_sorted, 01059 listOfFEMModelIDs_sorted 01060 ) 01061 ) 01062 { 01063 //bPunctureIn = true; 01064 //return m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.back().pHEVertex; 01065 } 01066 }//END: if ( interpolatedPointIDs.size() > 0 ) 01067 }//END: Narrow-phase CD 01068 }//END: if ( pFEMHex ) 01069 01070 else if ( pFEMTet ) 01071 { 01072 PrtNotImplementedYet( "ProcessPuncturingOfHeadNeedleUsingCirclePathWithFEMModel_MoreAccuButUnfinishYet for FEMTet" ); 01073 }//END: if ( pFEMTet ) 01074 01075 return NULL; 01076 } 01077 //----------------------------------------------------------------------------- 01078 template <typename T, typename DATA> 01079 int AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::CDCirclePathVsTriangle ( 01080 std::vector< Vector3<T> > points, 01081 unsigned int numOfSegments, 01082 HEFace<T> const * const pHEFace, 01083 Matrix4x4<T> const & TrxTriangle 01084 ) 01085 { 01086 //std::cout << *pHEFace << "\n"; 01087 01088 bool result; 01089 T ratio; 01090 Vector3<T> projPt; 01091 01092 std::vector< HEVertex<T> const * const > pHEVertices = pHEFace->GetPtrsToVertices(); 01093 for ( unsigned int i = 0; i < numOfSegments; ++i ) { 01094 result = CGMath<T>::FindIntersectionLineSegmentTriangle( 01095 points[i], points[i+1], 01096 TrxTriangle * pHEVertices[0]->GetPosition(), 01097 TrxTriangle * pHEVertices[1]->GetPosition(), 01098 TrxTriangle * pHEVertices[2]->GetPosition(), 01099 ratio, 01100 projPt 01101 ); 01102 if ( result ) { 01103 //std::cout << "InterpolatedPt ID: " << i << "\n"; 01104 return i; 01105 } 01106 } 01107 01108 return -1; 01109 } 01110 //----------------------------------------------------------------------------- 01111 template <typename T, typename DATA> 01112 bool AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::RecordAndLockThePuncturePath ( 01113 typename ModelSurgicalSutureWithHeadNeedle<T>::CirclePath & CirclePathCtrl, 01114 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 01115 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, 01116 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, 01117 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, 01118 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 01119 bool & bPunctureIn, 01120 bool & bPunctureOut, 01121 std::vector< unsigned int > & interpolatedPointIDs, 01122 std::vector< HEFace<T> * > & triangles, 01123 std::vector< unsigned int > & listOfFEMModelIDs 01124 ) 01125 { 01126 //PunctureInOutList punctureList; 01127 01128 // The head needle's sharp point has to be penetrated the FEM-based model 01129 if ( interpolatedPointIDs[0] > CirclePathCtrl.IDOfFirstInterpolatedPtBeforeSharpPt ) { 01130 return false; 01131 } 01132 01133 //return false; 01134 01135 unsigned int sutureThreadID = 20; 01136 unsigned int numOfPts = interpolatedPointIDs.size(); 01137 01138 01139 // Even number of punctured points 01140 if ( numOfPts >= 2 && numOfPts % 2 == 0 ) { 01141 01142 Vector3<T> position; 01143 Vector3<unsigned int> gridLocations; 01144 Vector3<T> coordinates; 01145 01146 // For all pairs of two points -- puncture out and in 01147 //for ( int i = numOfPts-1; i > 0; i-=2 ) 01148 // Only the first two points -- puncture out and in 01149 int i = 1; 01150 { 01151 01152 // plus two for skipping the first point after the punctured-in point 01153 // because the point can be close to the punctured in point 01154 // and make the suture thread turn sharply. 01155 int outID = interpolatedPointIDs[i]; 01156 int inID = interpolatedPointIDs[i-1] + 1; 01157 //int inID = interpolatedPointIDs[i-1]; 01158 01159 // Locate FEM-based model 01160 unsigned int elementID; 01161 unsigned int FEMModel = listOfFEMModelIDs[i-1]; 01162 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 01163 01164 /* 01165 // DEBUG 01166 std::cout << "outID: " << outID << std::endl; 01167 std::cout << "inID: " << inID << std::endl; 01168 std::cout << "FEMModel = " << FEMModel << std::endl; 01169 std::cout << "FEMloc = " << FEMloc << std::endl; 01170 //*/ 01171 01172 ModelDefBasedOnFEMHex<T,DATA> * pFEMHex = dynamic_cast< ModelDefBasedOnFEMHex<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 01173 ModelDefBasedOnFEMTet<T,DATA> * pFEMTet = dynamic_cast< ModelDefBasedOnFEMTet<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 01174 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 01175 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 01176 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 01177 01178 RigidBodyDynamics<T> * pHeadNeedle = ListOfModelsBasedOnRBD[RBDloc]; 01179 Matrix4x4<T> TrxRBD( pHeadNeedle->CalMatrixTransform() ); 01180 //Vector3<T> circleCenter = TrxRBD * CirclePathCtrl.Center; 01181 //Vector3<T> circleNormalPlane = TrxRBD * (CirclePathCtrl.NormalPlane + CirclePathCtrl.Center) - circleCenter; 01182 01183 // Store the FEM's location id of this punctured pair (of punctured-in and punctured-out points) 01184 m_LockedCirclePath.ListOfFEMModelBasedOnPuncturedPair.push_back( FEMModel ); 01185 01186 //* 01187 // 01188 // Find and store punctured-in vertex 01189 // 01190 //std::cout << "Find and store punctured-in vertex" << std::endl; 01191 { 01192 Vector3<T> position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD * CirclePathCtrl.InterpolatedPts[i-1]; 01193 std::vector< HEVertex<T> * const > pListOfTriVertices = triangles[i-1]->GetPtrsToVertices(); 01194 01195 /* 01196 // DEBUG 01197 std::cout << "pListOfTriVertices[0]: " << pListOfTriVertices[0] << std::endl; 01198 std::cout << "pListOfTriVertices[1]: " << pListOfTriVertices[1] << std::endl; 01199 std::cout << "pListOfTriVertices[2]: " << pListOfTriVertices[2] << std::endl; 01200 //*/ 01201 01202 T len0 = (position - pListOfTriVertices[0]->GetPosition()).Length(); 01203 T len1 = (position - pListOfTriVertices[1]->GetPosition()).Length(); 01204 T len2 = (position - pListOfTriVertices[2]->GetPosition()).Length(); 01205 if ( len0 < len1 ) { 01206 if ( len0 < len2 ) { // len0 is minimum 01207 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[0] ) ); 01208 } 01209 else { // len2 is minimum 01210 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[2] ) ); 01211 } 01212 } 01213 else { 01214 if ( len1 < len2 ) { // len1 is minimum 01215 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[1] ) ); 01216 } 01217 else { // len2 is minimum 01218 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[2] ) ); 01219 } 01220 } 01221 } 01222 01223 01224 // 01225 // Find and store punctured-out vertex 01226 // 01227 //std::cout << "Find and store punctured-out vertex" << std::endl; 01228 { 01229 Vector3<T> position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD * CirclePathCtrl.InterpolatedPts[i]; 01230 std::vector< HEVertex<T> * const > pListOfTriVertices = triangles[i]->GetPtrsToVertices(); 01231 T len0 = (position - pListOfTriVertices[0]->GetPosition()).Length(); 01232 T len1 = (position - pListOfTriVertices[1]->GetPosition()).Length(); 01233 T len2 = (position - pListOfTriVertices[2]->GetPosition()).Length(); 01234 if ( len0 < len1 ) { 01235 if ( len0 < len2 ) { // len0 is minimum 01236 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[0] ) ); 01237 } 01238 else { // len2 is minimum 01239 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[2] ) ); 01240 } 01241 } 01242 else { 01243 if ( len1 < len2 ) { // len1 is minimum 01244 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[1] ) ); 01245 } 01246 else { // len2 is minimum 01247 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[2] ) ); 01248 } 01249 } 01250 } 01251 //*/ 01252 01253 // From high to low ID numbers 01254 //std::cout << "From high to low ID numbers" << std::endl; 01255 for ( int p = outID; p > inID; --p ) { 01256 if ( pFEMHex ) { 01257 01258 //std::cout << "pFEMHex: " << pFEMHex << std::endl; // DEBUG 01259 01260 position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD * CirclePathCtrl.InterpolatedPts[p]; 01261 01262 //std::cout << "before FindElementThatContainsPointInLocalSpace" << std::endl; 01263 01264 bool bFound = pFEMHex->FindElementThatContainsPointInLocalSpace( position, elementID, gridLocations, coordinates ); 01265 01266 //std::cout << "p: " << p << std::endl; 01267 01268 if ( bFound ) { 01269 //std::cout << "FOUND element: " << elementID << ",\t" << gridLocations << ",\t" << coordinates << "\n"; // DEBUG 01270 01271 // Create the punctured point inside the found element 01272 HEVertex<T> * pNewHEVertex = pFEMHex->AddExtraVertexInLocalSpace( 01273 position, elementID, &pFEMHex->RefToFEMMesh().RefToElement( elementID ), gridLocations, coordinates ); 01274 01275 // push from high to low ID numbers 01276 m_LockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.push_back( IData( pNewHEVertex ) ); 01277 01278 /* 01279 // ADD CONNECTION RIGHT AWAY 01280 //-------------------------- 01281 // Set simulation flags of the HEVertex 01282 pNewHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01283 // Create the constraint 01284 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 01285 new AdvSimConstraint_VertexIdVsHEVertex<T>( 01286 sutureThreadID, 01287 pNewHEVertex, 01288 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 01289 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 01290 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 01291 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 01292 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 01293 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 01294 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 01295 ); 01296 // Set simulation flags of the suture thread point 01297 pSutureThread->GetListOfNodes()[sutureThreadID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 01298 pSutureThread->GetListOfNodes()[sutureThreadID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01299 pSutureThread->GetListOfNodes()[sutureThreadID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01300 // Add the constraint 01301 m_ListOfSutureThreadVsFEMModels_ForCirclePath.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 01302 pConstraint->RefToSavedPositionB() = pNewHEVertex->GetPosition(); 01303 // Update the suture thread point id 01304 ++sutureThreadID; 01305 // DEBUG 01306 std::cout << "HEVertex's position: " << pNewHEVertex->GetPosition() << "\n"; 01307 std::cout << "pConstraint: " << *pConstraint << std::endl; 01308 std::cout << "pConstraint: " << pConstraint << std::endl; 01309 //*/ 01310 } 01311 } 01312 else if ( pFEMTet ) 01313 { 01314 PrtNotImplementedYet( "RecordAndLockThePuncturePath for FEMTet" ); 01315 } 01316 } 01317 } 01318 m_pCirclePathCtrl = &CirclePathCtrl; 01319 m_LockedCirclePath.NumOfPointsToBeProcessed = m_LockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(); 01320 m_LockedCirclePath.IsLocked = true; 01321 ++m_uiNumOfLockedCirclePaths; 01322 01323 //std::cout << "End RecordAndLockThePuncturePath" << std::endl; // DEBUG 01324 01325 return true; 01326 } 01327 01328 // Odd number of punctured points 01329 else { 01330 } 01331 01332 return false; 01333 }//END: RecordAndLockThePuncturePath Function 01334 //----------------------------------------------------------------------------- 01335 template <typename T, typename DATA> 01336 bool AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::RecordAndLockThePuncturePath_MoreAccuButUnfinishYet ( 01337 typename ModelSurgicalSutureWithHeadNeedle<T>::CirclePath & CirclePathCtrl, 01338 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 01339 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, 01340 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, 01341 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, 01342 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 01343 bool & bPunctureIn, 01344 bool & bPunctureOut, 01345 std::vector< unsigned int > & interpolatedPointIDs, 01346 std::vector< HEFace<T> * > & triangles, 01347 std::vector< unsigned int > & listOfFEMModelIDs 01348 ) 01349 { 01350 //PunctureInOutList punctureList; 01351 01352 // The head needle's sharp point has to be penetrated the FEM-based model 01353 if ( interpolatedPointIDs[0] > CirclePathCtrl.IDOfFirstInterpolatedPtBeforeSharpPt ) { 01354 return false; 01355 } 01356 01357 //return false; 01358 01359 unsigned int sutureThreadID = 20; 01360 unsigned int numOfPts = interpolatedPointIDs.size(); 01361 01362 01363 // Even number of punctured points 01364 if ( numOfPts >= 2 && numOfPts % 2 == 0 ) { 01365 01366 Vector3<T> position; 01367 Vector3<unsigned int> gridLocations; 01368 Vector3<T> coordinates; 01369 01370 // For all pairs of two points -- puncture out and in 01371 //for ( int i = numOfPts-1; i > 0; i-=2 ) 01372 // Only the first two points -- puncture out and in 01373 int i = 1; 01374 { 01375 01376 // plus two for skipping the first point after the punctured-in point 01377 // because the point can be close to the punctured in point 01378 // and make the suture thread turn sharply. 01379 int outID = interpolatedPointIDs[i]; 01380 int inID = interpolatedPointIDs[i-1] + 1; 01381 //int inID = interpolatedPointIDs[i-1]; 01382 01383 // Locate FEM-based model 01384 unsigned int elementID; 01385 unsigned int FEMModel = listOfFEMModelIDs[i-1]; 01386 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 01387 01388 /* 01389 // DEBUG 01390 std::cout << "outID: " << outID << std::endl; 01391 std::cout << "inID: " << inID << std::endl; 01392 std::cout << "FEMModel = " << FEMModel << std::endl; 01393 std::cout << "FEMloc = " << FEMloc << std::endl; 01394 //*/ 01395 01396 ModelDefBasedOnFEMHex<T,DATA> * pFEMHex = dynamic_cast< ModelDefBasedOnFEMHex<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 01397 ModelDefBasedOnFEMTet<T,DATA> * pFEMTet = dynamic_cast< ModelDefBasedOnFEMTet<T,DATA> * >( ListOfModelsBasedOnFEM[FEMloc] ); 01398 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 01399 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 01400 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 01401 01402 RigidBodyDynamics<T> * pHeadNeedle = ListOfModelsBasedOnRBD[RBDloc]; 01403 Matrix4x4<T> TrxRBD( pHeadNeedle->CalMatrixTransform() ); 01404 //Vector3<T> circleCenter = TrxRBD * CirclePathCtrl.Center; 01405 //Vector3<T> circleNormalPlane = TrxRBD * (CirclePathCtrl.NormalPlane + CirclePathCtrl.Center) - circleCenter; 01406 01407 // Store the FEM's location id of this punctured pair (of punctured-in and punctured-out points) 01408 m_LockedCirclePath.ListOfFEMModelBasedOnPuncturedPair.push_back( FEMModel ); 01409 01410 //* 01411 // 01412 // Find and store punctured-in vertex 01413 // 01414 //std::cout << "Find and store punctured-in vertex" << std::endl; 01415 { 01416 Vector3<T> position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD * CirclePathCtrl.InterpolatedPts[i-1]; 01417 std::vector< HEVertex<T> * const > pListOfTriVertices = triangles[i-1]->GetPtrsToVertices(); 01418 01419 /* 01420 // DEBUG 01421 std::cout << "pListOfTriVertices[0]: " << pListOfTriVertices[0] << std::endl; 01422 std::cout << "pListOfTriVertices[1]: " << pListOfTriVertices[1] << std::endl; 01423 std::cout << "pListOfTriVertices[2]: " << pListOfTriVertices[2] << std::endl; 01424 //*/ 01425 01426 T len0 = (position - pListOfTriVertices[0]->GetPosition()).Length(); 01427 T len1 = (position - pListOfTriVertices[1]->GetPosition()).Length(); 01428 T len2 = (position - pListOfTriVertices[2]->GetPosition()).Length(); 01429 if ( len0 < len1 ) { 01430 if ( len0 < len2 ) { // len0 is minimum 01431 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[0] ) ); 01432 } 01433 else { // len2 is minimum 01434 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[2] ) ); 01435 } 01436 } 01437 else { 01438 if ( len1 < len2 ) { // len1 is minimum 01439 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[1] ) ); 01440 } 01441 else { // len2 is minimum 01442 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.push_back( IData( pListOfTriVertices[2] ) ); 01443 } 01444 } 01445 } 01446 01447 01448 // 01449 // Find and store punctured-out vertex 01450 // 01451 //std::cout << "Find and store punctured-out vertex" << std::endl; 01452 { 01453 Vector3<T> position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD * CirclePathCtrl.InterpolatedPts[i]; 01454 std::vector< HEVertex<T> * const > pListOfTriVertices = triangles[i]->GetPtrsToVertices(); 01455 T len0 = (position - pListOfTriVertices[0]->GetPosition()).Length(); 01456 T len1 = (position - pListOfTriVertices[1]->GetPosition()).Length(); 01457 T len2 = (position - pListOfTriVertices[2]->GetPosition()).Length(); 01458 if ( len0 < len1 ) { 01459 if ( len0 < len2 ) { // len0 is minimum 01460 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[0] ) ); 01461 } 01462 else { // len2 is minimum 01463 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[2] ) ); 01464 } 01465 } 01466 else { 01467 if ( len1 < len2 ) { // len1 is minimum 01468 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[1] ) ); 01469 } 01470 else { // len2 is minimum 01471 m_LockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.push_back( IData( pListOfTriVertices[2] ) ); 01472 } 01473 } 01474 } 01475 //*/ 01476 01477 // From high to low ID numbers 01478 //std::cout << "From high to low ID numbers" << std::endl; 01479 for ( int p = outID; p > inID; --p ) { 01480 if ( pFEMHex ) { 01481 01482 //std::cout << "pFEMHex: " << pFEMHex << std::endl; // DEBUG 01483 01484 position = pFEMHex->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD * CirclePathCtrl.InterpolatedPts[p]; 01485 01486 //std::cout << "before FindElementThatContainsPointInLocalSpace" << std::endl; 01487 01488 bool bFound = pFEMHex->FindElementThatContainsPointInLocalSpace( position, elementID, gridLocations, coordinates ); 01489 01490 //std::cout << "p: " << p << std::endl; 01491 01492 if ( bFound ) { 01493 //std::cout << "FOUND element: " << elementID << ",\t" << gridLocations << ",\t" << coordinates << "\n"; // DEBUG 01494 01495 // Create the punctured point inside the found element 01496 HEVertex<T> * pNewHEVertex = pFEMHex->AddExtraVertexInLocalSpace( 01497 position, elementID, &pFEMHex->RefToFEMMesh().RefToElement( elementID ), gridLocations, coordinates ); 01498 01499 // push from high to low ID numbers 01500 m_LockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.push_back( IData( pNewHEVertex ) ); 01501 01502 /* 01503 // ADD CONNECTION RIGHT AWAY 01504 //-------------------------- 01505 // Set simulation flags of the HEVertex 01506 pNewHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01507 // Create the constraint 01508 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 01509 new AdvSimConstraint_VertexIdVsHEVertex<T>( 01510 sutureThreadID, 01511 pNewHEVertex, 01512 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 01513 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 01514 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 01515 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 01516 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 01517 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 01518 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 01519 ); 01520 // Set simulation flags of the suture thread point 01521 pSutureThread->GetListOfNodes()[sutureThreadID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 01522 pSutureThread->GetListOfNodes()[sutureThreadID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01523 pSutureThread->GetListOfNodes()[sutureThreadID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01524 // Add the constraint 01525 m_ListOfSutureThreadVsFEMModels_ForCirclePath.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 01526 pConstraint->RefToSavedPositionB() = pNewHEVertex->GetPosition(); 01527 // Update the suture thread point id 01528 ++sutureThreadID; 01529 // DEBUG 01530 std::cout << "HEVertex's position: " << pNewHEVertex->GetPosition() << "\n"; 01531 std::cout << "pConstraint: " << *pConstraint << std::endl; 01532 std::cout << "pConstraint: " << pConstraint << std::endl; 01533 //*/ 01534 } 01535 } 01536 else if ( pFEMTet ) 01537 { 01538 PrtNotImplementedYet( "RecordAndLockThePuncturePath_MoreAccuButUnfinishYet for FEMTet" ); 01539 } 01540 } 01541 } 01542 m_pCirclePathCtrl = &CirclePathCtrl; 01543 m_LockedCirclePath.NumOfPointsToBeProcessed = m_LockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(); 01544 m_LockedCirclePath.IsLocked = true; 01545 ++m_uiNumOfLockedCirclePaths; 01546 01547 //std::cout << "End RecordAndLockThePuncturePath_MoreAccuButUnfinishYet" << std::endl; // DEBUG 01548 01549 return true; 01550 } 01551 01552 // Odd number of punctured points 01553 else { 01554 } 01555 01556 return false; 01557 }//END: RecordAndLockThePuncturePath_MoreAccuButUnfinishYet Function 01558 //----------------------------------------------------------------------------- 01559 template <typename T, typename DATA> 01560 HEVertex<T> * AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ProcessLockedPuncturePath ( 01561 LockedCirclePath & TheLockedCirclePath, 01562 typename ModelSurgicalSutureWithHeadNeedle<T>::CirclePath & CirclePathCtrl, 01563 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 01564 typename AdvSimSupport_DATA<T,DATA>::ModelLists & ListOfModelObjects, 01565 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 01566 bool & bPunctureIn, 01567 bool & bPunctureOut, 01568 bool & bAborted, 01569 bool & bSuccess 01570 ) 01571 { 01572 /* 01573 // DEBUG 01574 std::cout << "TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(): " << TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() << "\n"; 01575 std::cout << "TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.size(): " << TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.size() << "\n"; 01576 std::cout << "TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.size(): " << TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.size() << "\n"; 01577 std::cout << "TheLockedCirclePath.ListOfFEMModelBasedOnPuncturedPair.size(): " << TheLockedCirclePath.ListOfFEMModelBasedOnPuncturedPair.size() << "\n"; 01578 //*/ 01579 01580 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER = ListOfModelObjects.BasedOnER; 01581 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM = ListOfModelObjects.BasedOnFEM; 01582 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD = ListOfModelObjects.BasedOnRBD; 01583 01584 static unsigned int s_NumberOfPuncturePtsLeft; 01585 static unsigned int s_LeadPtID; 01586 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 01587 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 01588 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 01589 RigidBodyDynamics<T> * pHeadNeedle = ListOfModelsBasedOnRBD[RBDloc]; 01590 Matrix4x4<T> TrxRBD( pHeadNeedle->CalMatrixTransform() ); 01591 unsigned int FEMModel = TheLockedCirclePath.ListOfFEMModelBasedOnPuncturedPair[0]; 01592 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 01593 ModelDefBasedOnFEM<T,DATA> * pFEM = ListOfModelsBasedOnFEM[FEMloc]; 01594 Matrix4x4<T> TrxTotal( pFEM->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD ); 01595 01596 unsigned int idSharpPt = CirclePathCtrl.IDOfFirstInterpolatedPtBeforeSharpPt + 1; 01597 Vector3<T> beforeSharpPt = CirclePathCtrl.InterpolatedPts[idSharpPt-1]; 01598 bool & bIn = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].bProcessed; 01599 bool & bOut = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].bProcessed; 01600 01601 // With a higher value, this one makes it easier to puncture the wound. 01602 int distOffsetSize = 1; 01603 T distConstraint = ( CirclePathCtrl.InterpolatedPts[idSharpPt+distOffsetSize] - CirclePathCtrl.InterpolatedPts[idSharpPt-distOffsetSize] ).Length(); // this length is fixed 01604 distConstraint *= 4; 01605 01606 T distAbort = ( CirclePathCtrl.InterpolatedPts[idSharpPt+3] - CirclePathCtrl.InterpolatedPts[idSharpPt-3] ).Length(); // this length is fixed 01607 01608 if ( !bIn ) { // Puncture In 01609 01610 //std::cout << "Try Puncture In" << std::endl; // DEBUG 01611 01612 Vector3<T> point = TrxTotal * beforeSharpPt; 01613 01614 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex->GetPosition()).Length(); 01615 01616 //std::cout << "len2: " << len2 << std::endl; 01617 //std::cout << "distAbort: " << distAbort << std::endl; 01618 01619 // Before puncture out, check for abortion of the path if the head needle is moved to far from the path 01620 if ( len2 > distAbort ) { 01621 bAborted = true; 01622 return NULL; 01623 } 01624 01625 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 01626 01627 if ( len2 < len1 && len2 < distConstraint ) { 01628 // Set simulation flags of the HEVertex 01629 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex; 01630 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01631 // 01632 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 01633 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 01634 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 01635 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 01636 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 01637 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 01638 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 01639 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 01640 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 01641 // 01642 pHeadNeedle->LockPosition(); 01643 // Set return data 01644 bIn = bPunctureIn = true; 01645 01646 //std::cout << "Done puncture in" << std::endl; 01647 01648 return TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex; 01649 } 01650 else { 01651 return NULL; 01652 } 01653 } 01654 else { // Already Puncture In 01655 if ( !bOut ) { // Not Puncture Out Yet 01656 01657 // Check for abort 01658 T dist = ( TrxRBD*CirclePathCtrl.Center - pFEM->RefToTransformationSupport().GetMatrixTransform()*TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex->GetPosition() ).Length(); 01659 if ( dist > CirclePathCtrl.Radius * 2 ) { 01660 bAborted = true; 01661 return NULL; 01662 } 01663 01664 if ( TheLockedCirclePath.NumOfPointsToBeProcessed > 0 ) { // Puncture Inside 01665 01666 // The HEVertex pointers stored in TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside 01667 // are associatedly stored from high to low ID numbers of path circle. 01668 unsigned int vertexID = TheLockedCirclePath.NumOfPointsToBeProcessed - 1; 01669 01670 //std::cout << "TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(): " << TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() << std::endl; 01671 //std::cout << "TheLockedCirclePath.NumOfPointsToBeProcessed: " << TheLockedCirclePath.NumOfPointsToBeProcessed << std::endl; 01672 //std::cout << "vertexID: " << vertexID << std::endl; 01673 01674 if ( vertexID == TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - 1 ) { // the first point after the punctured-in point 01675 Vector3<T> point = TrxTotal * beforeSharpPt; 01676 01677 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex->GetPosition()).Length(); 01678 01679 //std::cout << "len2: " << len2 << "\n"; 01680 //std::cout << "distAbort: " << distAbort << "\n"; 01681 // Before puncture out, check for abortion of the path if the head needle is moved to far from the path 01682 if ( len2 > distAbort ) { 01683 bAborted = true; 01684 return NULL; 01685 } 01686 01687 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex->GetPosition()).Length(); 01688 01689 if ( len2 < len1 && len2 < distConstraint ) { 01690 // Transfer the first constraint 01691 unsigned int c = idSharpPt - 1; 01692 01693 //std::cout << "idSharpPt: " << idSharpPt << "\n"; 01694 //std::cout << "c: " << c << "\n"; 01695 01696 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01697 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[idSharpPt].GetPtrToVertexFromModel_2() ); 01698 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceRatio() ); 01699 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleA() ); 01700 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleB() ); 01701 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdA() ); 01702 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdB() ); 01703 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusA() ); 01704 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusB() ); 01705 01706 // Set simulation flags of the HEVertex 01707 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 01708 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01709 // Set the next constraint 01710 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 01711 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 01712 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 01713 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 01714 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 01715 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 01716 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 01717 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 01718 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 01719 01720 //m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( false ); 01721 // Set return data 01722 --TheLockedCirclePath.NumOfPointsToBeProcessed; 01723 return TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 01724 } 01725 } 01726 else { // all the points after the first point after the punctured-in point 01727 Vector3<T> point = TrxTotal * beforeSharpPt; 01728 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID+1].pHEVertex->GetPosition()).Length(); 01729 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex->GetPosition()).Length(); 01730 if ( len2 < len1 && len2 < distConstraint ) { 01731 // Transfer all constraints except the first one 01732 unsigned int numberOfTransferredPoints = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - TheLockedCirclePath.NumOfPointsToBeProcessed; 01733 unsigned int c = idSharpPt - numberOfTransferredPoints - 1; 01734 01735 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 01736 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 01737 //std::cout << "c: " << c << std::endl; 01738 01739 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01740 for ( unsigned int i = 0; i < numberOfTransferredPoints; ++i, ++c ) { 01741 unsigned int d = c + 1; 01742 01743 //std::cout << "transfer from " << d << " to " << c << std::endl; 01744 01745 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 01746 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 01747 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 01748 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 01749 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 01750 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 01751 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 01752 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 01753 } 01754 // Transfer the first constraint 01755 c = idSharpPt - 1; 01756 01757 //std::cout << "Transfer the first point" << std::endl; 01758 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 01759 //std::cout << "c: " << c << std::endl; 01760 //std::cout << "transfer from " << idSharpPt << " to " << c << std::endl; 01761 01762 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01763 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[idSharpPt].GetPtrToVertexFromModel_2() ); 01764 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceRatio() ); 01765 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleA() ); 01766 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleB() ); 01767 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdA() ); 01768 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdB() ); 01769 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusA() ); 01770 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusB() ); 01771 // Set simulation flags of the HEVertex 01772 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 01773 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01774 // Set the next constraint 01775 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 01776 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 01777 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 01778 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 01779 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 01780 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 01781 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 01782 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 01783 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 01784 //m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( false ); 01785 // Set return data 01786 --TheLockedCirclePath.NumOfPointsToBeProcessed; 01787 return TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 01788 } 01789 } 01790 //unsigned int idPtOnNeedle = idSharpPt - ( TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - TheLockedCirclePath.NumOfPointsToBeProcessed ); 01791 } 01792 else 01793 { // Pucture Out 01794 Vector3<T> point = TrxTotal * beforeSharpPt; 01795 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 01796 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 01797 01798 //if ( false ) { // DEBUG 01799 if ( len2 < len1 && len2 < distConstraint ) { 01800 01801 // Transfer all constraints except the first one 01802 unsigned int numberOfTransferredPoints = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - TheLockedCirclePath.NumOfPointsToBeProcessed; 01803 unsigned int c = idSharpPt - numberOfTransferredPoints - 1; 01804 01805 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 01806 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 01807 //std::cout << "c: " << c << std::endl; 01808 01809 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01810 for ( unsigned int i = 0; i < numberOfTransferredPoints; ++i, ++c ) { 01811 unsigned int d = c + 1; 01812 01813 //std::cout << "transfer from " << d << " to " << c << std::endl; 01814 01815 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 01816 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 01817 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 01818 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 01819 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 01820 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 01821 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 01822 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 01823 } 01824 // Transfer the first constraint 01825 c = idSharpPt - 1; 01826 01827 //std::cout << "Transfer the first point" << std::endl; 01828 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 01829 //std::cout << "c: " << c << std::endl; 01830 //std::cout << "transfer from " << idSharpPt << " to " << c << std::endl; 01831 01832 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01833 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[idSharpPt].GetPtrToVertexFromModel_2() ); 01834 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceRatio() ); 01835 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleA() ); 01836 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleB() ); 01837 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdA() ); 01838 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdB() ); 01839 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusA() ); 01840 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusB() ); 01841 // Set simulation flags of the HEVertex 01842 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex; 01843 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01844 // Set the next constraint 01845 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 01846 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 01847 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 01848 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 01849 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 01850 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 01851 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 01852 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 01853 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 01854 //m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( false ); 01855 01856 // Set return data 01857 bOut = bPunctureOut = true; 01858 s_NumberOfPuncturePtsLeft = 2 + TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(); 01859 s_LeadPtID = idSharpPt; 01860 return TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex; 01861 } 01862 else { 01863 return NULL; 01864 } 01865 } 01866 } 01867 else { // Already Puncture Out 01868 01869 // Check for abort 01870 T dist = ( TrxRBD*CirclePathCtrl.Center - pFEM->RefToTransformationSupport().GetMatrixTransform()*TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex->GetPosition() ).Length(); 01871 if ( dist > CirclePathCtrl.Radius * 2 ) { 01872 bAborted = true; 01873 return NULL; 01874 } 01875 01876 if ( s_NumberOfPuncturePtsLeft > 0 ) { // Head needle sliding forward inside the punctured path 01877 01878 //std::cout << "s_NumberOfPuncturePtsLeft: " << s_NumberOfPuncturePtsLeft << std::endl; 01879 //std::cout << "m_SetOfInteractionAssociatedModelID_ForCirclePath[0]: " << m_SetOfInteractionAssociatedModelID_ForCirclePath[0] << std::endl; 01880 01881 if ( m_SetOfInteractionAssociatedModelID_ForCirclePath[0] < 0 ) { // The end of head needle is still outside the puncture path (not going in the puncture path yet) 01882 01883 Vector3<T> point = TrxTotal * CirclePathCtrl.InterpolatedPts[s_LeadPtID-1]; 01884 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 01885 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 01886 01887 //if ( false ) { // DEBUG 01888 if ( len2 < len1 && len2 < distConstraint ) { 01889 01890 // Transfer all constraints 01891 unsigned int numberOfTransferredPoints = s_NumberOfPuncturePtsLeft; 01892 unsigned int c = s_LeadPtID - numberOfTransferredPoints; 01893 01894 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 01895 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 01896 //std::cout << "c: " << c << std::endl; 01897 01898 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01899 for ( unsigned int i = 0; i < numberOfTransferredPoints; ++i, ++c ) { 01900 unsigned int d = c + 1; 01901 01902 //std::cout << "transfer from " << d << " to " << c << std::endl; 01903 01904 //* 01905 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 01906 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 01907 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 01908 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 01909 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 01910 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 01911 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 01912 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 01913 //*/ 01914 } 01915 01916 m_SetOfInteractionAssociatedModelID_ForCirclePath[s_LeadPtID] = -1; // clear the lead point's constraint state 01917 01918 // Set return data 01919 --s_LeadPtID; 01920 return NULL; 01921 } 01922 }//END: The end of head needle is still outside the puncture path (not going in the puncture path yet) 01923 else { // The end of head needle is still inside the puncture path 01924 if ( s_LeadPtID > 0 ) { // not the last point out 01925 01926 //std::cout << "CASE: not the last point out" << std::endl; 01927 01928 Vector3<T> point = TrxTotal * CirclePathCtrl.InterpolatedPts[s_LeadPtID-1]; 01929 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 01930 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 01931 01932 //if ( false ) { // DEBUG 01933 if ( len2 < len1 && len2 < distConstraint ) { 01934 01935 // Transfer all constraints except the first constraint 01936 unsigned int numberOfTransferredPoints = s_NumberOfPuncturePtsLeft; 01937 unsigned int c = s_LeadPtID - numberOfTransferredPoints + 1; 01938 01939 //* 01940 // 01941 // Transfer the first constraint to the suture's thread 01942 // 01943 // Add the constraint of suture thread 01944 // 01945 { 01946 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 01947 unsigned int ERModelVertexID = 1; 01948 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 01949 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 01950 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01951 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01952 // 01953 //unsigned int HEloc = m_SetOfInteractionAssociatedModelID_ForIPG[start]; 01954 HEVertex<T> * pVertexHEModel = m_SetOfInteractions_ForCirclePath[c].GetPtrToVertexFromModel_2(); 01955 01956 ++m_NumberOfSutureThreadPointsPuncturedIn; 01957 01958 //std::cout << "m_NumberOfSutureThreadPointsPuncturedIn: " << m_NumberOfSutureThreadPointsPuncturedIn << "\n"; 01959 01960 // Shift all suture points by one (FORWARD ATTACHMENT OF SUTURE'S THREAD WITH FEMMODEL) 01961 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForCirclePath.begin(); 01962 while ( it != m_ListOfSutureThreadVsFEMModels_ForCirclePath.end() ) { 01963 unsigned int ptID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1() + 1; 01964 it->pAdvSimConstraint_VertexIdVsHEVertex->SetVertexIDFromModel_1( ptID ); 01965 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 01966 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 01967 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 01968 ++it; 01969 } 01970 01971 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 01972 new AdvSimConstraint_VertexIdVsHEVertex<T>( 01973 ERModelVertexID, 01974 pVertexHEModel, 01975 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 01976 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 01977 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 01978 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 01979 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 01980 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 01981 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 01982 ); 01983 pConstraint->RefToSavedPositionB() = pVertexHEModel->GetPosition(); 01984 m_ListOfSutureThreadVsFEMModels_ForCirclePath.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 01985 01986 //std::cout << "HEVertex's position: " << pVertexHEModel->GetPosition() << "\n"; 01987 //std::cout << "pConstraint: " << pConstraint << std::endl; 01988 //std::cout << "pConstraint: " << *pConstraint << std::endl; 01989 } 01990 //*/ 01991 01992 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 01993 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 01994 //std::cout << "s_LeadPtID: " << s_LeadPtID << std::endl; 01995 //std::cout << "c: " << c << std::endl; 01996 01997 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 01998 for ( unsigned int i = 1; i < numberOfTransferredPoints; ++i, ++c ) { 01999 unsigned int d = c + 1; 02000 02001 //std::cout << "transfer from " << d << " to " << c << std::endl; 02002 02003 //* 02004 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 02005 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 02006 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 02007 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 02008 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 02009 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 02010 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 02011 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 02012 //*/ 02013 } 02014 02015 m_SetOfInteractionAssociatedModelID_ForCirclePath[s_LeadPtID] = -1; // clear the lead point's constraint state 02016 02017 // Set return data 02018 --s_NumberOfPuncturePtsLeft; 02019 --s_LeadPtID; 02020 return NULL; 02021 } 02022 } 02023 else { // the last point out 02024 //std::cout << "CASE: the last point out" << std::endl; 02025 02026 Vector3<T> point = TrxTotal * CirclePathCtrl.InterpolatedPts[0]; 02027 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 02028 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 02029 02030 //if ( false ) { // DEBUG 02031 if ( len2 < len1 && len2 < distConstraint ) { 02032 02033 // Transfer all constraints except the first constraint 02034 //unsigned int numberOfTransferredPoints = s_NumberOfPuncturePtsLeft; 02035 //unsigned int c = s_LeadPtID - numberOfTransferredPoints + 1; // will always be zero 02036 unsigned int c = 0; 02037 02038 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << "\n"; 02039 //std::cout << "c: " << c << "\n"; 02040 02041 //* 02042 // Transfer the first constraint to the suture's thread 02043 // 02044 // Add the constraint of suture thread 02045 // 02046 { 02047 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 02048 unsigned int ERModelVertexID = 1; 02049 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 02050 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 02051 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02052 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 02053 // 02054 //unsigned int HEloc = m_SetOfInteractionAssociatedModelID_ForIPG[start]; 02055 HEVertex<T> * pVertexHEModel = m_SetOfInteractions_ForCirclePath[c].GetPtrToVertexFromModel_2(); 02056 02057 ++m_NumberOfSutureThreadPointsPuncturedIn; 02058 02059 //std::cout << "m_NumberOfSutureThreadPointsPuncturedIn: " << m_NumberOfSutureThreadPointsPuncturedIn << "\n"; 02060 02061 // Shift all suture points by one (FORWARD ATTACHMENT OF SUTURE'S THREAD WITH FEMMODEL) 02062 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForCirclePath.begin(); 02063 while ( it != m_ListOfSutureThreadVsFEMModels_ForCirclePath.end() ) { 02064 unsigned int ptID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1() + 1; 02065 it->pAdvSimConstraint_VertexIdVsHEVertex->SetVertexIDFromModel_1( ptID ); 02066 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 02067 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02068 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 02069 ++it; 02070 } 02071 02072 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 02073 new AdvSimConstraint_VertexIdVsHEVertex<T>( 02074 ERModelVertexID, 02075 pVertexHEModel, 02076 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 02077 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 02078 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 02079 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 02080 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 02081 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 02082 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 02083 ); 02084 pConstraint->RefToSavedPositionB() = pVertexHEModel->GetPosition(); 02085 m_ListOfSutureThreadVsFEMModels_ForCirclePath.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 02086 02087 //std::cout << "HEVertex's position: " << pVertexHEModel->GetPosition() << "\n"; 02088 //std::cout << "pConstraint: " << pConstraint << std::endl; 02089 //std::cout << "pConstraint: " << *pConstraint << std::endl; 02090 } 02091 //*/ 02092 02093 m_SetOfInteractionAssociatedModelID_ForCirclePath[0] = -1; // clear the lead point's constraint state 02094 02095 // Set return data 02096 --s_NumberOfPuncturePtsLeft; 02097 //--s_LeadPtID; 02098 02099 // Transfer the constraints to the main constraint data structure 02100 { 02101 TransferConstraintsToMainConstraintDS( 02102 m_ListOfSutureThreadVsFEMModels_ForCirclePath, 02103 ListOf_ERModelVsHEModelInteractions, 02104 ListOfModelObjects, 02105 ListOfModels[m_ERModelAsSutureThread].Slot 02106 ); 02107 02108 bSuccess = true; 02109 02110 // Clear 02111 m_NumberOfSutureThreadPointsPuncturedIn = 0; 02112 m_ListOfSutureThreadVsFEMModels_ForCirclePath.clear(); 02113 } 02114 02115 return NULL; 02116 } 02117 } 02118 }//END: The end of head needle is still inside the puncture path 02119 } 02120 else { // Head needle is completely out from the puncture path 02121 m_LockedCirclePath.Clear(); 02122 } 02123 } 02124 } 02125 return NULL; 02126 }//END: ProcessLockedPuncturePath Function 02127 //----------------------------------------------------------------------------- 02128 template <typename T, typename DATA> 02129 HEVertex<T> * AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ProcessLockedPuncturePath_MoreAccuButUnfinishYet ( 02130 LockedCirclePath & TheLockedCirclePath, 02131 typename ModelSurgicalSutureWithHeadNeedle<T>::CirclePath & CirclePathCtrl, 02132 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 02133 typename AdvSimSupport_DATA<T,DATA>::ModelLists & ListOfModelObjects, 02134 //std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, //!< list of suture models based on elastic rod (belongs to ER-based model group) 02135 //std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, //!< list of deformable models based on FEM (belongs to FEM-based model group) 02136 //std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, //!< list of models based on rigid body dynamics (belongs to IPG-based model group) 02137 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 02138 bool & bPunctureIn, 02139 bool & bPunctureOut, 02140 bool & bAborted 02141 ) 02142 { 02143 /* 02144 // DEBUG 02145 std::cout << "TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(): " << TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() << "\n"; 02146 std::cout << "TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.size(): " << TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn.size() << "\n"; 02147 std::cout << "TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.size(): " << TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut.size() << "\n"; 02148 std::cout << "TheLockedCirclePath.ListOfFEMModelBasedOnPuncturedPair.size(): " << TheLockedCirclePath.ListOfFEMModelBasedOnPuncturedPair.size() << "\n"; 02149 //*/ 02150 02151 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER = ListOfModelObjects.BasedOnER; 02152 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM = ListOfModelObjects.BasedOnFEM; 02153 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD = ListOfModelObjects.BasedOnRBD; 02154 02155 static unsigned int s_NumberOfPuncturePtsLeft; 02156 static unsigned int s_LeadPtID; 02157 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 02158 unsigned int RBDloc = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 02159 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 02160 RigidBodyDynamics<T> * pHeadNeedle = ListOfModelsBasedOnRBD[RBDloc]; 02161 Matrix4x4<T> TrxRBD( pHeadNeedle->CalMatrixTransform() ); 02162 unsigned int FEMModel = TheLockedCirclePath.ListOfFEMModelBasedOnPuncturedPair[0]; 02163 unsigned int FEMloc = ListOfModels[FEMModel].Slot; 02164 ModelDefBasedOnFEM<T,DATA> * pFEM = ListOfModelsBasedOnFEM[FEMloc]; 02165 Matrix4x4<T> TrxTotal( pFEM->RefToTransformationSupport().GetInverseMatrixTransform() * TrxRBD ); 02166 02167 unsigned int idSharpPt = CirclePathCtrl.IDOfFirstInterpolatedPtBeforeSharpPt + 1; 02168 Vector3<T> beforeSharpPt = CirclePathCtrl.InterpolatedPts[idSharpPt-1]; 02169 bool & bIn = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].bProcessed; 02170 bool & bOut = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].bProcessed; 02171 02172 // With a higher value, this one makes it easier to puncture the wound. 02173 int distOffsetSize = 1; 02174 T distConstraint = ( CirclePathCtrl.InterpolatedPts[idSharpPt+distOffsetSize] - CirclePathCtrl.InterpolatedPts[idSharpPt-distOffsetSize] ).Length(); // this length is fixed 02175 //distConstraint *= 2; 02176 02177 T distAbort = ( CirclePathCtrl.InterpolatedPts[idSharpPt+3] - CirclePathCtrl.InterpolatedPts[idSharpPt-3] ).Length(); // this length is fixed 02178 02179 if ( !bIn ) { // Puncture In 02180 02181 //std::cout << "Try Puncture In" << std::endl; // DEBUG 02182 02183 Vector3<T> point = TrxTotal * beforeSharpPt; 02184 02185 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex->GetPosition()).Length(); 02186 02187 //std::cout << "len2: " << len2 << std::endl; 02188 //std::cout << "distAbort: " << distAbort << std::endl; 02189 02190 // Before puncture out, check for abortion of the path if the head needle is moved to far from the path 02191 if ( len2 > distAbort ) { 02192 bAborted = true; 02193 return NULL; 02194 } 02195 02196 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 02197 02198 if ( len2 < len1 && len2 < distConstraint ) { 02199 // Set simulation flags of the HEVertex 02200 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex; 02201 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02202 // 02203 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 02204 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 02205 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 02206 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 02207 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 02208 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 02209 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 02210 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 02211 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 02212 // 02213 pHeadNeedle->LockPosition(); 02214 // Set return data 02215 bIn = bPunctureIn = true; 02216 02217 //std::cout << "Done puncture in" << std::endl; 02218 02219 return TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex; 02220 } 02221 else { 02222 return NULL; 02223 } 02224 } 02225 else { // Already Puncture In 02226 if ( !bOut ) { // Not Puncture Out Yet 02227 if ( TheLockedCirclePath.NumOfPointsToBeProcessed > 0 ) { // Puncture Inside 02228 02229 // The HEVertex pointers stored in TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside 02230 // are associatedly stored from high to low ID numbers of path circle. 02231 unsigned int vertexID = TheLockedCirclePath.NumOfPointsToBeProcessed - 1; 02232 02233 //std::cout << "TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(): " << TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() << std::endl; 02234 //std::cout << "TheLockedCirclePath.NumOfPointsToBeProcessed: " << TheLockedCirclePath.NumOfPointsToBeProcessed << std::endl; 02235 //std::cout << "vertexID: " << vertexID << std::endl; 02236 02237 if ( vertexID == TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - 1 ) { // the first point after the punctured-in point 02238 Vector3<T> point = TrxTotal * beforeSharpPt; 02239 02240 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex->GetPosition()).Length(); 02241 02242 //std::cout << "len2: " << len2 << "\n"; 02243 //std::cout << "distAbort: " << distAbort << "\n"; 02244 // Before puncture out, check for abortion of the path if the head needle is moved to far from the path 02245 if ( len2 > distAbort ) { 02246 bAborted = true; 02247 return NULL; 02248 } 02249 02250 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedIn[0].pHEVertex->GetPosition()).Length(); 02251 02252 if ( len2 < len1 && len2 < distConstraint ) { 02253 // Transfer the first constraint 02254 unsigned int c = idSharpPt - 1; 02255 02256 //std::cout << "idSharpPt: " << idSharpPt << "\n"; 02257 //std::cout << "c: " << c << "\n"; 02258 02259 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02260 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[idSharpPt].GetPtrToVertexFromModel_2() ); 02261 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceRatio() ); 02262 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleA() ); 02263 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleB() ); 02264 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdA() ); 02265 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdB() ); 02266 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusA() ); 02267 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusB() ); 02268 02269 // Set simulation flags of the HEVertex 02270 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 02271 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02272 // Set the next constraint 02273 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 02274 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 02275 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 02276 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 02277 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 02278 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 02279 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 02280 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 02281 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 02282 02283 //m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( false ); 02284 // Set return data 02285 --TheLockedCirclePath.NumOfPointsToBeProcessed; 02286 return TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 02287 } 02288 } 02289 else { // all the points after the first point after the punctured-in point 02290 Vector3<T> point = TrxTotal * beforeSharpPt; 02291 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID+1].pHEVertex->GetPosition()).Length(); 02292 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex->GetPosition()).Length(); 02293 if ( len2 < len1 && len2 < distConstraint ) { 02294 // Transfer all constraints except the first one 02295 unsigned int numberOfTransferredPoints = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - TheLockedCirclePath.NumOfPointsToBeProcessed; 02296 unsigned int c = idSharpPt - numberOfTransferredPoints - 1; 02297 02298 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 02299 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 02300 //std::cout << "c: " << c << std::endl; 02301 02302 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02303 for ( unsigned int i = 0; i < numberOfTransferredPoints; ++i, ++c ) { 02304 unsigned int d = c + 1; 02305 02306 //std::cout << "transfer from " << d << " to " << c << std::endl; 02307 02308 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 02309 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 02310 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 02311 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 02312 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 02313 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 02314 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 02315 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 02316 } 02317 // Transfer the first constraint 02318 c = idSharpPt - 1; 02319 02320 //std::cout << "Transfer the first point" << std::endl; 02321 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 02322 //std::cout << "c: " << c << std::endl; 02323 //std::cout << "transfer from " << idSharpPt << " to " << c << std::endl; 02324 02325 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02326 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[idSharpPt].GetPtrToVertexFromModel_2() ); 02327 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceRatio() ); 02328 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleA() ); 02329 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleB() ); 02330 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdA() ); 02331 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdB() ); 02332 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusA() ); 02333 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusB() ); 02334 // Set simulation flags of the HEVertex 02335 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 02336 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02337 // Set the next constraint 02338 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 02339 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 02340 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 02341 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 02342 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 02343 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 02344 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 02345 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 02346 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 02347 //m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( false ); 02348 // Set return data 02349 --TheLockedCirclePath.NumOfPointsToBeProcessed; 02350 return TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[vertexID].pHEVertex; 02351 } 02352 } 02353 //unsigned int idPtOnNeedle = idSharpPt - ( TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - TheLockedCirclePath.NumOfPointsToBeProcessed ); 02354 } 02355 else 02356 { // Pucture Out 02357 Vector3<T> point = TrxTotal * beforeSharpPt; 02358 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 02359 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 02360 02361 //if ( false ) { // DEBUG 02362 if ( len2 < len1 && len2 < distConstraint ) { 02363 02364 // Transfer all constraints except the first one 02365 unsigned int numberOfTransferredPoints = TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size() - TheLockedCirclePath.NumOfPointsToBeProcessed; 02366 unsigned int c = idSharpPt - numberOfTransferredPoints - 1; 02367 02368 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 02369 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 02370 //std::cout << "c: " << c << std::endl; 02371 02372 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02373 for ( unsigned int i = 0; i < numberOfTransferredPoints; ++i, ++c ) { 02374 unsigned int d = c + 1; 02375 02376 //std::cout << "transfer from " << d << " to " << c << std::endl; 02377 02378 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 02379 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 02380 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 02381 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 02382 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 02383 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 02384 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 02385 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 02386 } 02387 // Transfer the first constraint 02388 c = idSharpPt - 1; 02389 02390 //std::cout << "Transfer the first point" << std::endl; 02391 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 02392 //std::cout << "c: " << c << std::endl; 02393 //std::cout << "transfer from " << idSharpPt << " to " << c << std::endl; 02394 02395 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02396 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[idSharpPt].GetPtrToVertexFromModel_2() ); 02397 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceRatio() ); 02398 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleA() ); 02399 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceScaleB() ); 02400 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdA() ); 02401 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetForceThresholdB() ); 02402 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusA() ); 02403 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[idSharpPt].GetEnforcePositionStatusB() ); 02404 // Set simulation flags of the HEVertex 02405 HEVertex<T> * pHEVertex = TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex; 02406 pHEVertex->SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02407 // Set the next constraint 02408 m_SetOfInteractionAssociatedModelID_ForCirclePath[idSharpPt] = FEMModel; 02409 m_SetOfInteractions_ForCirclePath[idSharpPt].SetPtrToVertexFromModel_2( pHEVertex ); 02410 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceRatio( AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio ); 02411 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleA( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA ); 02412 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceScaleB( AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB ); 02413 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdA( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA ); 02414 m_SetOfInteractions_ForCirclePath[idSharpPt].SetForceThresholdB( AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB ); 02415 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusA( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA ); 02416 m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB ); 02417 //m_SetOfInteractions_ForCirclePath[idSharpPt].SetEnforcePositionStatusB( false ); 02418 02419 // Set return data 02420 bOut = bPunctureOut = true; 02421 s_NumberOfPuncturePtsLeft = 2 + TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside.size(); 02422 s_LeadPtID = idSharpPt; 02423 return TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex; 02424 } 02425 else { 02426 return NULL; 02427 } 02428 } 02429 } 02430 else { // Already Puncture Out 02431 if ( s_NumberOfPuncturePtsLeft > 0 ) { // Head needle sliding forward inside the punctured path 02432 02433 //std::cout << "s_NumberOfPuncturePtsLeft: " << s_NumberOfPuncturePtsLeft << std::endl; 02434 //std::cout << "m_SetOfInteractionAssociatedModelID_ForCirclePath[0]: " << m_SetOfInteractionAssociatedModelID_ForCirclePath[0] << std::endl; 02435 02436 if ( m_SetOfInteractionAssociatedModelID_ForCirclePath[0] < 0 ) { // The end of head needle is still outside the puncture path (not going in the puncture path yet) 02437 02438 Vector3<T> point = TrxTotal * CirclePathCtrl.InterpolatedPts[s_LeadPtID-1]; 02439 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 02440 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 02441 02442 //if ( false ) { // DEBUG 02443 if ( len2 < len1 && len2 < distConstraint ) { 02444 02445 // Transfer all constraints 02446 unsigned int numberOfTransferredPoints = s_NumberOfPuncturePtsLeft; 02447 unsigned int c = s_LeadPtID - numberOfTransferredPoints; 02448 02449 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 02450 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 02451 //std::cout << "c: " << c << std::endl; 02452 02453 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02454 for ( unsigned int i = 0; i < numberOfTransferredPoints; ++i, ++c ) { 02455 unsigned int d = c + 1; 02456 02457 //std::cout << "transfer from " << d << " to " << c << std::endl; 02458 02459 //* 02460 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 02461 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 02462 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 02463 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 02464 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 02465 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 02466 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 02467 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 02468 //*/ 02469 } 02470 02471 m_SetOfInteractionAssociatedModelID_ForCirclePath[s_LeadPtID] = -1; // clear the lead point's constraint state 02472 02473 // Set return data 02474 --s_LeadPtID; 02475 return NULL; 02476 } 02477 }//END: The end of head needle is still outside the puncture path (not going in the puncture path yet) 02478 else { // The end of head needle is still inside the puncture path 02479 if ( s_LeadPtID > 0 ) { // not the last point out 02480 02481 //std::cout << "CASE: not the last point out" << std::endl; 02482 02483 Vector3<T> point = TrxTotal * CirclePathCtrl.InterpolatedPts[s_LeadPtID-1]; 02484 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 02485 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 02486 02487 //if ( false ) { // DEBUG 02488 if ( len2 < len1 && len2 < distConstraint ) { 02489 02490 // Transfer all constraints except the first constraint 02491 unsigned int numberOfTransferredPoints = s_NumberOfPuncturePtsLeft; 02492 unsigned int c = s_LeadPtID - numberOfTransferredPoints + 1; 02493 02494 //* 02495 // 02496 // Transfer the first constraint to the suture's thread 02497 // 02498 // Add the constraint of suture thread 02499 // 02500 { 02501 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 02502 unsigned int ERModelVertexID = 1; 02503 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 02504 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 02505 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02506 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 02507 // 02508 //unsigned int HEloc = m_SetOfInteractionAssociatedModelID_ForIPG[start]; 02509 HEVertex<T> * pVertexHEModel = m_SetOfInteractions_ForCirclePath[c].GetPtrToVertexFromModel_2(); 02510 02511 ++m_NumberOfSutureThreadPointsPuncturedIn; 02512 02513 //std::cout << "m_NumberOfSutureThreadPointsPuncturedIn: " << m_NumberOfSutureThreadPointsPuncturedIn << "\n"; 02514 02515 // Shift all suture points by one (FORWARD ATTACHMENT OF SUTURE'S THREAD WITH FEMMODEL) 02516 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForCirclePath.begin(); 02517 while ( it != m_ListOfSutureThreadVsFEMModels_ForCirclePath.end() ) { 02518 unsigned int ptID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1() + 1; 02519 it->pAdvSimConstraint_VertexIdVsHEVertex->SetVertexIDFromModel_1( ptID ); 02520 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 02521 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02522 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 02523 ++it; 02524 } 02525 02526 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 02527 new AdvSimConstraint_VertexIdVsHEVertex<T>( 02528 ERModelVertexID, 02529 pVertexHEModel, 02530 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 02531 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 02532 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 02533 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 02534 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 02535 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 02536 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 02537 ); 02538 pConstraint->RefToSavedPositionB() = pVertexHEModel->GetPosition(); 02539 m_ListOfSutureThreadVsFEMModels_ForCirclePath.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 02540 02541 //std::cout << "HEVertex's position: " << pVertexHEModel->GetPosition() << "\n"; 02542 //std::cout << "pConstraint: " << pConstraint << std::endl; 02543 //std::cout << "pConstraint: " << *pConstraint << std::endl; 02544 } 02545 //*/ 02546 02547 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << std::endl; 02548 //std::cout << "idSharpPt: " << idSharpPt << std::endl; 02549 //std::cout << "s_LeadPtID: " << s_LeadPtID << std::endl; 02550 //std::cout << "c: " << c << std::endl; 02551 02552 m_SetOfInteractionAssociatedModelID_ForCirclePath[c] = FEMModel; 02553 for ( unsigned int i = 1; i < numberOfTransferredPoints; ++i, ++c ) { 02554 unsigned int d = c + 1; 02555 02556 //std::cout << "transfer from " << d << " to " << c << std::endl; 02557 02558 //* 02559 m_SetOfInteractions_ForCirclePath[c].SetPtrToVertexFromModel_2( m_SetOfInteractions_ForCirclePath[d].GetPtrToVertexFromModel_2() ); 02560 m_SetOfInteractions_ForCirclePath[c].SetForceRatio( m_SetOfInteractions_ForCirclePath[d].GetForceRatio() ); 02561 m_SetOfInteractions_ForCirclePath[c].SetForceScaleA( m_SetOfInteractions_ForCirclePath[d].GetForceScaleA() ); 02562 m_SetOfInteractions_ForCirclePath[c].SetForceScaleB( m_SetOfInteractions_ForCirclePath[d].GetForceScaleB() ); 02563 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdA( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdA() ); 02564 m_SetOfInteractions_ForCirclePath[c].SetForceThresholdB( m_SetOfInteractions_ForCirclePath[d].GetForceThresholdB() ); 02565 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusA( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusA() ); 02566 m_SetOfInteractions_ForCirclePath[c].SetEnforcePositionStatusB( m_SetOfInteractions_ForCirclePath[d].GetEnforcePositionStatusB() ); 02567 //*/ 02568 } 02569 02570 m_SetOfInteractionAssociatedModelID_ForCirclePath[s_LeadPtID] = -1; // clear the lead point's constraint state 02571 02572 // Set return data 02573 --s_NumberOfPuncturePtsLeft; 02574 --s_LeadPtID; 02575 return NULL; 02576 } 02577 } 02578 else { // the last point out 02579 //std::cout << "CASE: the last point out" << std::endl; 02580 02581 Vector3<T> point = TrxTotal * CirclePathCtrl.InterpolatedPts[0]; 02582 T len1 = (point - TheLockedCirclePath.ListOfFEMMeshPuncturedVerticesInside[0].pHEVertex->GetPosition()).Length(); 02583 T len2 = (point - TheLockedCirclePath.ListOfFEMMeshSurfaceVertexPuncturedOut[0].pHEVertex->GetPosition()).Length(); 02584 02585 //if ( false ) { // DEBUG 02586 if ( len2 < len1 && len2 < distConstraint ) { 02587 02588 // Transfer all constraints except the first constraint 02589 //unsigned int numberOfTransferredPoints = s_NumberOfPuncturePtsLeft; 02590 //unsigned int c = s_LeadPtID - numberOfTransferredPoints + 1; // will always be zero 02591 unsigned int c = 0; 02592 02593 //std::cout << "numberOfTransferredPoints: " << numberOfTransferredPoints << "\n"; 02594 //std::cout << "c: " << c << "\n"; 02595 02596 //* 02597 // Transfer the first constraint to the suture's thread 02598 // 02599 // Add the constraint of suture thread 02600 // 02601 { 02602 unsigned int ERloc = ListOfModels[m_ERModelAsSutureThread].Slot; 02603 unsigned int ERModelVertexID = 1; 02604 ModelElasticRod<T> * pSutureThread = ListOfModelsBasedOnER[ERloc]; 02605 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 02606 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02607 pSutureThread->GetListOfNodes()[ERModelVertexID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 02608 // 02609 //unsigned int HEloc = m_SetOfInteractionAssociatedModelID_ForIPG[start]; 02610 HEVertex<T> * pVertexHEModel = m_SetOfInteractions_ForCirclePath[c].GetPtrToVertexFromModel_2(); 02611 02612 ++m_NumberOfSutureThreadPointsPuncturedIn; 02613 02614 //std::cout << "m_NumberOfSutureThreadPointsPuncturedIn: " << m_NumberOfSutureThreadPointsPuncturedIn << "\n"; 02615 02616 // Shift all suture points by one (FORWARD ATTACHMENT OF SUTURE'S THREAD WITH FEMMODEL) 02617 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForCirclePath.begin(); 02618 while ( it != m_ListOfSutureThreadVsFEMModels_ForCirclePath.end() ) { 02619 unsigned int ptID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1() + 1; 02620 it->pAdvSimConstraint_VertexIdVsHEVertex->SetVertexIDFromModel_1( ptID ); 02621 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::SLIDABLE ); 02622 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::ATTACHED ); 02623 pSutureThread->GetListOfNodes()[ptID].SimFlags.SetSimulationConstraints( Enum::AddOn::IGNORE_CD_FORCE ); 02624 ++it; 02625 } 02626 02627 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint = 02628 new AdvSimConstraint_VertexIdVsHEVertex<T>( 02629 ERModelVertexID, 02630 pVertexHEModel, 02631 AdvSimSupport_DATA<T,DATA>::STATE_ForceRatio_2, 02632 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleA_2, 02633 AdvSimSupport_DATA<T,DATA>::STATE_ForceScaleB_2, 02634 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdA_2, 02635 AdvSimSupport_DATA<T,DATA>::STATE_ForceThresholdB_2, 02636 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionA_2, 02637 AdvSimSupport_DATA<T,DATA>::STATE_EnforcePositionB_2 02638 ); 02639 pConstraint->RefToSavedPositionB() = pVertexHEModel->GetPosition(); 02640 m_ListOfSutureThreadVsFEMModels_ForCirclePath.push_front( InteractionSutureThreadVsFEMModel<T>( pConstraint, ERloc ) ); 02641 02642 //std::cout << "HEVertex's position: " << pVertexHEModel->GetPosition() << "\n"; 02643 //std::cout << "pConstraint: " << pConstraint << std::endl; 02644 //std::cout << "pConstraint: " << *pConstraint << std::endl; 02645 } 02646 //*/ 02647 02648 m_SetOfInteractionAssociatedModelID_ForCirclePath[0] = -1; // clear the lead point's constraint state 02649 02650 // Set return data 02651 --s_NumberOfPuncturePtsLeft; 02652 //--s_LeadPtID; 02653 02654 // Transfer the constraints to the main constraint data structure 02655 { 02656 TransferConstraintsToMainConstraintDS( 02657 m_ListOfSutureThreadVsFEMModels_ForCirclePath, 02658 ListOf_ERModelVsHEModelInteractions, 02659 ListOfModelObjects, 02660 ListOfModels[m_ERModelAsSutureThread].Slot 02661 ); 02662 02663 // Clear 02664 m_NumberOfSutureThreadPointsPuncturedIn = 0; 02665 m_ListOfSutureThreadVsFEMModels_ForCirclePath.clear(); 02666 } 02667 02668 return NULL; 02669 } 02670 } 02671 }//END: The end of head needle is still inside the puncture path 02672 } 02673 else { // Head needle is completely out from the puncture path 02674 m_LockedCirclePath.Clear(); 02675 } 02676 } 02677 } 02678 return NULL; 02679 }//END: ProcessLockedPuncturePath_MoreAccuButUnfinishYet Function 02680 //----------------------------------------------------------------------------- 02681 02682 02683 //----------------------------------------------------------------------------- 02684 template <typename T, typename DATA> 02685 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::TransferConstraintsToMainConstraintDS ( 02686 std::list< InteractionSutureThreadVsFEMModel<T> > & listOfConstraints, 02687 typename AdvSimSupport_DATA<T,DATA>::ListOfInteractions_ERModelVsHEModel & ListOf_ERModelVsHEModelInteractions, 02688 typename AdvSimSupport_DATA<T,DATA>::ModelLists & ListOfModelObjects, 02689 unsigned int ERloc 02690 ) 02691 { 02692 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = listOfConstraints.begin(); 02693 while ( it != listOfConstraints.end() ) { 02694 02695 // For controlling forward/backward movement of suture 02696 unsigned int ERModelVertexID = it->pAdvSimConstraint_VertexIdVsHEVertex->GetVertexIDFromModel_1(); 02697 ListOfModelObjects.AllERNodePropsList[ERloc][ERModelVertexID].IsConstrained = true; 02698 02699 //ListOf_ERModelVsHEModelInteractions[ERloc][it->FEMloc].push_back( it->pAdvSimConstraint_VertexIdVsHEVertex ); 02700 02701 // Insert to the list (sorted from low to high) 02702 unsigned int size = ListOf_ERModelVsHEModelInteractions[ERloc][it->FEMloc].Constraints.size(); 02703 if ( size == 0 ) { 02704 ListOf_ERModelVsHEModelInteractions[ERloc][it->FEMloc].Constraints.push_back( it->pAdvSimConstraint_VertexIdVsHEVertex ); 02705 } 02706 else { 02707 std::vector< AdvSimConstraint_VertexIdVsHEVertex<T> * > & List = ListOf_ERModelVsHEModelInteractions[ERloc][it->FEMloc].Constraints; 02708 std::vector< AdvSimConstraint_VertexIdVsHEVertex<T> * >::iterator itMDS = List.begin(); 02709 02710 //----------------------------------------------------------- 02711 // (binary) insert from low to high 02712 unsigned int start = 0, middle = size/2, end = size; 02713 while ( end - start > 0 ) { 02714 02715 if ( List[middle]->GetVertexIDFromModel_1() > ERModelVertexID ) { 02716 end = middle; 02717 middle = (end - start)/2 + start; 02718 } 02719 else if ( List[middle]->GetVertexIDFromModel_1() < ERModelVertexID ) { 02720 start = middle+1; 02721 middle = (end - start)/2 + start; 02722 } 02723 else { 02724 break; 02725 } 02726 } 02727 List.insert( itMDS + middle, it->pAdvSimConstraint_VertexIdVsHEVertex ); 02728 //----------------------------------------------------------- 02729 02730 /* 02731 // DEBUG 02732 std::cout << "Sorted List:"; 02733 for ( itMDS = List.begin(); itMDS != List.end(); ++itMDS ) { 02734 std::cout << "\t" << (*itMDS)->GetVertexIDFromModel_1(); 02735 } 02736 std::cout << "\n"; 02737 //*/ 02738 } 02739 02740 it->pAdvSimConstraint_VertexIdVsHEVertex->RefToSavedPositionB() = it->pAdvSimConstraint_VertexIdVsHEVertex->GetPtrToVertexFromModel_2()->GetPosition(); 02741 ++it; 02742 } 02743 } 02744 //----------------------------------------------------------------------------- 02745 02746 02747 //============================================================================= 02748 // FOR IPG 02749 //----------------------------------------------------------------------------- 02750 template <typename T, typename DATA> 02751 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAllConstraints_ForIPG ( 02752 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 02753 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, 02754 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, 02755 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, 02756 typename AdvSimSupport_DATA<T,DATA>::ListOfPointForces & ListOfPointForces 02757 ) 02758 { 02759 // The head needle model type must be MODEL_BASED_ON_IPG_RBD 02760 Enum::ModelType HeadNeedleModelType = ListOfModels[m_RBDModelAsSutureHeadNeedle].Type; 02761 if ( HeadNeedleModelType != Enum::MODEL_BASED_ON_IPG_RBD ) return; 02762 02763 // Get the head needle's transformation matrix and its inverse 02764 unsigned int locRBD = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 02765 RigidBodyDynamics<T> * pRBDModel = ListOfModelsBasedOnRBD[locRBD]; 02766 Matrix4x4<T> TrxModelRBD = pRBDModel->CalMatrixTransform(); 02767 Matrix4x4<T> InvTrxModelRBD = TrxModelRBD.GetInverse(); 02768 02769 // Suture's head needle with FEM-based models 02770 for ( unsigned int i = 0; i < m_size_ForIPG; ++i ) { 02771 int modelID = m_SetOfInteractionAssociatedModelID_ForIPG[i]; 02772 // A model is linked to the i(th) constraint 02773 if ( modelID >= 0 ) { 02774 Enum::ModelType modelType = ListOfModels[modelID].Type; 02775 if ( modelType == Enum::MODEL_BASED_ON_FEM ) { 02776 // MODEL_BASED_ON_IPG_RBD vs MODEL_BASED_ON_FEM at the i(th) constraint 02777 EnforceAConstraintOfSutureHeadNeedleTiedWithFEMModel_ForIPG( 02778 i, TrxModelRBD, InvTrxModelRBD, pRBDModel, 02779 ListOfModelsBasedOnFEM[ListOfModels[modelID].Slot], 02780 ListOfPointForces 02781 ); 02782 } 02783 } 02784 } 02785 02786 // Suture's thread with FEM-based models 02787 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForIPG.begin(); 02788 while ( it != m_ListOfSutureThreadVsFEMModels_ForIPG.end() ) { 02789 EnforceAConstraintOfSutureThreadTiedWithFEMModel_ForIPG( 02790 it->pAdvSimConstraint_VertexIdVsHEVertex, 02791 ListOfModelsBasedOnER[ListOfModels[m_ERModelAsSutureThread].Slot], 02792 ListOfModelsBasedOnFEM[it->FEMloc], 02793 ListOfPointForces 02794 ); 02795 ++it; 02796 } 02797 } 02798 //----------------------------------------------------------------------------- 02799 template <typename T, typename DATA> 02800 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ResetPunctureController () 02801 { 02802 m_PunctureController.Reset(); 02803 } 02804 //----------------------------------------------------------------------------- 02805 template <typename T, typename DATA> 02806 std::string AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::GetPunctureControllerCurrentInfo () 02807 { 02808 return m_PunctureController.StrInfo; 02809 } 02810 //----------------------------------------------------------------------------- 02811 template <typename T, typename DATA> 02812 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ClearAllConstraints_ForIPG () 02813 { 02814 // Since all values of each constraint will be set explicitly, except VertexId with invariant. 02815 // And m_SetOfInteractionAssociatedModelID less than zero signifies that the constraint is voided or cancelled. 02816 // Therefore, only m_SetOfInteractionAssociatedModelID needs to be cleared. 02817 for ( unsigned int i = 0; i < m_size_ForIPG; ++i ) { 02818 m_SetOfInteractionAssociatedModelID_ForIPG[i] = -1; 02819 } 02820 02821 // Unlock the head needle 02822 //ListOfModelsBasedOnRBD[RBDloc].UnlockHeadNeedlePosition(); 02823 02824 m_NumberOfSutureThreadPointsPuncturedIn = 0; 02825 m_NumberOfSutureHeadNeedlePointsPuncturedIn = 0; 02826 } 02827 //----------------------------------------------------------------------------- 02828 template <typename T, typename DATA> 02829 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAllConsistentPositions_ForIPG ( 02830 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 02831 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, 02832 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, 02833 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD 02834 ) 02835 { 02836 // Suture's head needle with FEM-based models 02837 SetOfInteractions::iterator it = m_SetOfInteractions_ForIPG.begin(); 02838 int i = 0; 02839 while ( it != m_SetOfInteractions_ForIPG.end() ) { 02840 if ( m_SetOfInteractionAssociatedModelID_ForIPG[i] >= 0 ) { 02841 if ( it->GetEnforcePositionStatusB() ) { 02842 //it->RefToSavedPositionA() = it->GetPtrToVertexFromModel_1()->GetProtectedPosition(); 02843 it->RefToSavedPositionB() = it->GetPtrToVertexFromModel_2()->GetProtectedPosition(); 02844 //it->GetPtrToVertexFromModel_1()->GetProtectedPosition() = it->RefToTargetPositionA(); 02845 02846 #ifdef TAPs_USE_VERTEX_POSITION_AVERAGING 02847 std::vector< HEVertex<T> * > firstRing = it->GetPtrToVertexFromModel_2()->FindTheFirstRingOfVertices(); 02848 unsigned int size = firstRing.size(); 02849 if ( size > 0 ) { 02850 Vector3<T> avgPos; 02851 for ( unsigned int i = 0; i < size; ++i ) { 02852 avgPos += firstRing[i]->GetPosition(); 02853 } 02854 T scale = size / T(2); 02855 avgPos = ( avgPos + it->RefToTargetPositionB()*scale ) / ( size + scale ); 02856 it->GetPtrToVertexFromModel_2()->GetProtectedPosition() = avgPos; 02857 for ( unsigned int i = 0; i < size; ++i ) { 02858 firstRing[i]->GetProtectedPosition() = ( firstRing[i]->GetPosition() + avgPos ) / 2; 02859 } 02860 } 02861 else { 02862 it->GetPtrToVertexFromModel_2()->GetProtectedPosition() = it->RefToTargetPositionB(); 02863 } 02864 #else //TAPs_USE_VERTEX_POSITION_AVERAGING 02865 it->GetPtrToVertexFromModel_2()->GetProtectedPosition() = it->RefToTargetPositionB(); 02866 #endif//TAPs_USE_VERTEX_POSITION_AVERAGING 02867 } 02868 } 02869 ++it; 02870 ++i; 02871 } 02872 02873 // Suture's thread with FEM-based models 02874 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator itc = m_ListOfSutureThreadVsFEMModels_ForIPG.begin(); 02875 while ( itc != m_ListOfSutureThreadVsFEMModels_ForIPG.end() ) { 02876 EnforceAConsistentPositionSutureThreadTiedWithFEMModel_ForIPG( 02877 itc->pAdvSimConstraint_VertexIdVsHEVertex, 02878 ListOfModelsBasedOnER[ListOfModels[m_ERModelAsSutureThread].Slot], 02879 ListOfModelsBasedOnFEM[itc->FEMloc] 02880 ); 02881 ++itc; 02882 } 02883 } 02884 //----------------------------------------------------------------------------- 02885 template <typename T, typename DATA> 02886 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAConstraintOfSutureHeadNeedleTiedWithFEMModel_ForIPG ( 02887 unsigned int constraintNumber, 02888 Matrix4x4<T> const & HeadNeedleTrx, 02889 Matrix4x4<T> const & HeadNeedleTrxInv, 02890 RigidBodyDynamics<T> * pRBDModel, 02891 ModelDefBasedOnFEM<T,DATA> * pFEMModel, 02892 typename AdvSimSupport_DATA<T,DATA>::ListOfPointForces & ListOfPointForces 02893 ) 02894 { 02895 Matrix4x4<T> TrxModelFEM = pFEMModel->RefToTransformationSupport().RefToMatrixTransform(); 02896 Matrix4x4<T> InvTrxModelFEM = TrxModelFEM.GetInverse(); 02897 02898 AdvSimConstraint_VertexIdVsHEVertex<T> & Constraint = m_SetOfInteractions_ForIPG[constraintNumber]; 02899 02900 unsigned int vertID = Constraint.GetVertexIDFromModel_1(); 02901 HEVertex<T> * pHEvert = Constraint.GetPtrToVertexFromModel_2(); 02902 Vector3<T> V1 = pRBDModel->RefToInteractionPointGroup().GetInteractionPointAtIndex( vertID ).GetPosition(); 02903 Vector3<T> V2 = pHEvert->GetProtectedPosition() = Constraint.RefToSavedPositionB(); 02904 V1 = HeadNeedleTrx * V1; 02905 V2 = TrxModelFEM * V2; 02906 T ratio = Constraint.GetForceRatio(); 02907 Constraint.RefToTargetPositionA() = Constraint.RefToTargetPositionB() = ratio*V1 + (1-ratio)*V2; 02908 V1 = HeadNeedleTrxInv * Constraint.RefToTargetPositionA(); 02909 V2 = InvTrxModelFEM * Constraint.RefToTargetPositionB(); 02910 Constraint.RefToTargetPositionA() = V1; 02911 Constraint.RefToTargetPositionB() = V2; 02912 02913 // RBD-based, add the connection as a point force. 02914 { 02915 } 02916 // FEM-based, add the connection as a point force. 02917 { 02918 Vector3<T> Fb = V2 - pHEvert->GetProtectedPosition(); 02919 PointForce<T> * pF = new PointForce<T>(); 02920 ListOfPointForces.push_back( pF ); 02921 02922 // Set connection (i.e. point) force 02923 pF->SetID( pHEvert->GetID() ); 02924 pF->RefToPosition() = pHEvert->GetBarycentricPtr()->RetGenBaryCoords(); 02925 pF->RefToForce() = Fb * Constraint.GetForceScaleB(); 02926 02927 pFEMModel->AddConnectionForceInLocalCoordinates( ListOfPointForces.back() ); 02928 } 02929 } 02930 //----------------------------------------------------------------------------- 02931 template <typename T, typename DATA> 02932 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAConstraintOfSutureThreadTiedWithFEMModel_ForIPG ( 02933 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint, 02934 ModelElasticRod<T> * pERModel, 02935 ModelDefBasedOnFEM<T,DATA> * pFEMModel, 02936 typename AdvSimSupport_DATA<T,DATA>::ListOfPointForces & ListOfPointForces 02937 ) 02938 { 02939 int ERModelPt = pConstraint->GetVertexIDFromModel_1(); 02940 Matrix4x4<T> TrxFEMModel = pFEMModel->RefToTransformationSupport().RefToMatrixTransform(); 02941 Matrix4x4<T> InvTrxFEMModel = TrxFEMModel.GetInverse(); 02942 02943 Vector3<T> & S = pERModel->RefToCurrentVertexPositionOfNodeNumber( ERModelPt ); 02944 HEVertex<T> * he = pConstraint->GetPtrToVertexFromModel_2(); 02945 Vector3<T> V = he->GetProtectedPosition() = pConstraint->RefToSavedPositionB(); 02946 V = TrxFEMModel * V; 02947 T ratio = pConstraint->GetForceRatio(); 02948 pConstraint->RefToTargetPositionA() = 02949 pConstraint->RefToTargetPositionB() = ratio*S + (1-ratio)*V; 02950 //S = pConstraint->RefToTargetPositionA(); // ERModel's point's current position 02951 V = InvTrxFEMModel * pConstraint->RefToTargetPositionB(); 02952 pConstraint->RefToTargetPositionB() = V; 02953 02954 // FEM-based model, add the connection as a point force. 02955 { 02956 Vector3<T> F = V - he->GetProtectedPosition(); 02957 PointForce<T> * pF = new PointForce<T>(); 02958 ListOfPointForces.push_back( pF ); 02959 02960 pF->SetID( he->GetID() ); 02961 pF->RefToPosition() = he->GetBarycentricPtr()->RetGenBaryCoords(); 02962 // Scale pF by the timestep 02963 pF->RefToForce() = F * pConstraint->GetForceScaleB() / pFEMModel->GetTimeStep(); 02964 pFEMModel->AddConnectionForceInLocalCoordinates( ListOfPointForces.back() ); 02965 } 02966 02967 // Calculate the external force apply to Suture 02968 Vector3<T> Fs = pConstraint->RefToTargetPositionA() - S; 02969 02970 bool bLinearForce = true; 02971 T scaleNonlinearForce = 0.5; 02972 02973 if ( bLinearForce ) 02974 { 02975 // LINEAR FORCE 02976 Fs *= pConstraint->GetForceScaleA(); 02977 } 02978 else 02979 { 02980 // NONLINEAR FORCE 02981 T ERModel_link_length = pERModel->GetLinkLength(); 02982 T magnitude = Fs.Magnitude(); 02983 T scale = pow( pConstraint->GetForceScaleA(), magnitude/ERModel_link_length ); 02984 if ( scale*magnitude <= pERModel->GetStretchModulus()*scaleNonlinearForce ) { 02985 Fs *= scale; 02986 } 02987 else { 02988 Fs *= pERModel->GetStretchModulus(); 02989 } 02990 } 02991 02992 // Scale Fs by the timestep, iteration times, and mass 02993 pERModel->GetListOfNodes()[ERModelPt].ExternalForce_ForAdvSimCtrl = Fs / pERModel->GetSimTimeStep() / pERModel->GetSimIterationTimes() / pERModel->GetListOfNodes()[ERModelPt].GetMass(); 02994 } 02995 //----------------------------------------------------------------------------- 02996 template <typename T, typename DATA> 02997 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAConsistentPositionSutureThreadTiedWithFEMModel_ForIPG ( 02998 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint, 02999 ModelElasticRod<T> * pERModel, 03000 ModelDefBasedOnFEM<T,DATA> * pFEMModel 03001 ) 03002 { 03003 int ERModelPt = pConstraint->GetVertexIDFromModel_1(); 03004 Matrix4x4<T> TrxFEMModel = pFEMModel->RefToTransformationSupport().RefToMatrixTransform(); 03005 Matrix4x4<T> InvTrxFEMModel = TrxFEMModel.GetInverse(); 03006 03007 unsigned int nodeID = pConstraint->GetVertexIDFromModel_1(); 03008 03009 // Enforce ER-based model's Position 03010 if ( pConstraint->GetEnforcePositionStatusA() ) { 03011 pERModel->GetListOfNodes()[nodeID].UseEnforcedPosition = true; 03012 pERModel->GetListOfNodes()[nodeID].EnforcedPosition = pConstraint->RefToTargetPositionA(); 03013 } 03014 else { 03015 } 03016 03017 pConstraint->RefToSavedPositionB() = pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition(); 03018 03019 // Move the model's constrained point to the target point 03020 if ( false ) 03021 { 03022 // TO THE TARGET POSITION B 03023 if ( pConstraint->GetEnforcePositionStatusB() ) { 03024 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = pConstraint->RefToTargetPositionB(); 03025 } 03026 } 03027 else { 03028 // TO THE SUTURE POINT 03029 if ( pConstraint->GetEnforcePositionStatusB() ) { 03030 #ifdef TAPs_USE_VERTEX_POSITION_AVERAGING 03031 std::vector< HEVertex<T> * > firstRing = pConstraint->GetPtrToVertexFromModel_2()->FindTheFirstRingOfVertices(); 03032 unsigned int size = firstRing.size(); 03033 Vector3<T> targetPos = InvTrxFEMModel * pERModel->RefToCurrentVertexPositionOfNodeNumber( pConstraint->GetVertexIDFromModel_1() ); 03034 if ( size > 0 ) { 03035 Vector3<T> avgPos; 03036 for ( unsigned int i = 0; i < size; ++i ) { 03037 avgPos += firstRing[i]->GetPosition(); 03038 } 03039 T scale = size / T(2); 03040 avgPos = ( avgPos + targetPos*scale ) / ( size + scale ); 03041 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = avgPos; 03042 for ( unsigned int i = 0; i < size; ++i ) { 03043 firstRing[i]->GetProtectedPosition() = ( firstRing[i]->GetPosition() + avgPos ) / 2; 03044 } 03045 } 03046 else { 03047 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = targetPos; 03048 } 03049 #else //TAPs_USE_VERTEX_POSITION_AVERAGING 03050 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = InvTrxFEMModel * 03051 pERModel->RefToCurrentVertexPositionOfNodeNumber( 03052 pConstraint->GetVertexIDFromModel_1() ); 03053 #endif//TAPs_USE_VERTEX_POSITION_AVERAGING 03054 } 03055 } 03056 } 03057 //----------------------------------------------------------------------------- 03058 // FOR IPG 03059 //============================================================================= 03060 03061 03062 03063 03064 //============================================================================= 03065 // FOR CIRCLE PATH 03066 //----------------------------------------------------------------------------- 03067 template <typename T, typename DATA> 03068 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAllConstraints_ForCirclePath ( 03069 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 03070 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, 03071 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, 03072 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD, 03073 typename AdvSimSupport_DATA<T,DATA>::ListOfPointForces & ListOfPointForces 03074 ) 03075 { 03076 // The head needle model type must be MODEL_BASED_ON_IPG_RBD 03077 Enum::ModelType HeadNeedleModelType = ListOfModels[m_RBDModelAsSutureHeadNeedle].Type; 03078 if ( HeadNeedleModelType != Enum::MODEL_BASED_ON_IPG_RBD ) return; 03079 03080 // Get the head needle's transformation matrix and its inverse 03081 unsigned int locRBD = ListOfModels[m_RBDModelAsSutureHeadNeedle].Slot; 03082 RigidBodyDynamics<T> * pRBDModel = ListOfModelsBasedOnRBD[locRBD]; 03083 Matrix4x4<T> TrxModelRBD = pRBDModel->CalMatrixTransform(); 03084 Matrix4x4<T> InvTrxModelRBD = TrxModelRBD.GetInverse(); 03085 03086 // Suture's head needle with FEM-based models 03087 for ( unsigned int i = 0; i < m_size_ForCirclePath; ++i ) { 03088 03089 int modelID = m_SetOfInteractionAssociatedModelID_ForCirclePath[i]; 03090 03091 // A model is linked to the i(th) constraint 03092 if ( modelID >= 0 ) { 03093 Enum::ModelType modelType = ListOfModels[modelID].Type; 03094 if ( modelType == Enum::MODEL_BASED_ON_FEM ) { 03095 // MODEL_BASED_ON_IPG_RBD vs MODEL_BASED_ON_FEM at the i(th) constraint 03096 EnforceAConstraintOfSutureHeadNeedleTiedWithFEMModel_ForCirclePath( 03097 i, TrxModelRBD, InvTrxModelRBD, pRBDModel, 03098 ListOfModelsBasedOnFEM[ListOfModels[modelID].Slot], 03099 ListOfPointForces 03100 ); 03101 } 03102 } 03103 } 03104 03105 // Suture's thread with FEM-based models 03106 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator it = m_ListOfSutureThreadVsFEMModels_ForCirclePath.begin(); 03107 while ( it != m_ListOfSutureThreadVsFEMModels_ForCirclePath.end() ) { 03108 EnforceAConstraintOfSutureThreadTiedWithFEMModel_ForCirclePath( 03109 it->pAdvSimConstraint_VertexIdVsHEVertex, 03110 ListOfModelsBasedOnER[ListOfModels[m_ERModelAsSutureThread].Slot], 03111 ListOfModelsBasedOnFEM[it->FEMloc], 03112 ListOfPointForces 03113 ); 03114 ++it; 03115 } 03116 } 03117 //----------------------------------------------------------------------------- 03118 template <typename T, typename DATA> 03119 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::ClearAllConstraints_ForCirclePath () 03120 { 03121 // Since all values of each constraint will be set explicitly, except VertexId with invariant. 03122 // And m_SetOfInteractionAssociatedModelID less than zero signifies that the constraint is voided or cancelled. 03123 // Therefore, only m_SetOfInteractionAssociatedModelID needs to be cleared. 03124 for ( unsigned int i = 0; i < m_size_ForCirclePath; ++i ) { 03125 m_SetOfInteractionAssociatedModelID_ForCirclePath[i] = -1; 03126 } 03127 03128 m_ListOfSutureThreadVsFEMModels_ForCirclePath.clear(); 03129 03130 m_LockedCirclePath.Clear(); 03131 03132 m_uiNumOfLockedCirclePaths = 0; 03133 03134 // Unlock the head needle 03135 //ListOfModelsBasedOnRBD[RBDloc].UnlockHeadNeedlePosition(); 03136 03137 m_NumberOfSutureThreadPointsPuncturedIn = 0; 03138 m_NumberOfSutureHeadNeedlePointsPuncturedIn = 0; 03139 } 03140 //----------------------------------------------------------------------------- 03141 template <typename T, typename DATA> 03142 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAllConsistentPositions_ForCirclePath ( 03143 typename AdvSimSupport_DATA<T,DATA>::ModelIDs const & ListOfModels, 03144 std::vector< ModelElasticRod<T> * > & ListOfModelsBasedOnER, 03145 std::vector< ModelDefBasedOnFEM<T,DATA> * > & ListOfModelsBasedOnFEM, 03146 std::vector< RigidBodyDynamics<T> * > & ListOfModelsBasedOnRBD 03147 ) 03148 { 03149 // Suture's head needle with FEM-based models 03150 SetOfInteractions::iterator it = m_SetOfInteractions_ForCirclePath.begin(); 03151 int i = 0; 03152 while ( it != m_SetOfInteractions_ForCirclePath.end() ) { 03153 if ( m_SetOfInteractionAssociatedModelID_ForCirclePath[i] >= 0 ) { 03154 if ( it->GetEnforcePositionStatusB() ) { 03155 //it->RefToSavedPositionA() = it->GetPtrToVertexFromModel_1()->GetProtectedPosition(); 03156 it->RefToSavedPositionB() = it->GetPtrToVertexFromModel_2()->GetProtectedPosition(); 03157 //it->GetPtrToVertexFromModel_1()->GetProtectedPosition() = it->RefToTargetPositionA(); 03158 03159 #ifdef TAPs_USE_VERTEX_POSITION_AVERAGING 03160 std::vector< HEVertex<T> * > firstRing = it->GetPtrToVertexFromModel_2()->FindTheFirstRingOfVertices(); 03161 unsigned int size = firstRing.size(); 03162 if ( size > 0 ) { 03163 Vector3<T> avgPos; 03164 for ( unsigned int i = 0; i < size; ++i ) { 03165 avgPos += firstRing[i]->GetPosition(); 03166 } 03167 T scale = size;// / T(2); 03168 avgPos = ( avgPos + it->RefToTargetPositionB()*scale ) / ( size + scale ); 03169 it->GetPtrToVertexFromModel_2()->GetProtectedPosition() = avgPos; 03170 for ( unsigned int i = 0; i < size; ++i ) { 03171 firstRing[i]->GetProtectedPosition() = ( firstRing[i]->GetPosition() + avgPos ) / 2; 03172 } 03173 } 03174 else { 03175 it->GetPtrToVertexFromModel_2()->GetProtectedPosition() = it->RefToTargetPositionB(); 03176 } 03177 #else //TAPs_USE_VERTEX_POSITION_AVERAGING 03178 it->GetPtrToVertexFromModel_2()->GetProtectedPosition() = it->RefToTargetPositionB(); 03179 #endif//TAPs_USE_VERTEX_POSITION_AVERAGING 03180 } 03181 } 03182 ++it; 03183 ++i; 03184 } 03185 03186 // Suture's thread with FEM-based models 03187 std::list< InteractionSutureThreadVsFEMModel<T> >::iterator itc = m_ListOfSutureThreadVsFEMModels_ForCirclePath.begin(); 03188 while ( itc != m_ListOfSutureThreadVsFEMModels_ForCirclePath.end() ) { 03189 EnforceAConsistentPositionSutureThreadTiedWithFEMModel_ForCirclePath( 03190 itc->pAdvSimConstraint_VertexIdVsHEVertex, 03191 ListOfModelsBasedOnER[ListOfModels[m_ERModelAsSutureThread].Slot], 03192 ListOfModelsBasedOnFEM[itc->FEMloc] 03193 ); 03194 ++itc; 03195 } 03196 } 03197 //----------------------------------------------------------------------------- 03198 template <typename T, typename DATA> 03199 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAConstraintOfSutureHeadNeedleTiedWithFEMModel_ForCirclePath ( 03200 unsigned int constraintNumber, 03201 Matrix4x4<T> const & HeadNeedleTrx, 03202 Matrix4x4<T> const & HeadNeedleTrxInv, 03203 RigidBodyDynamics<T> * pRBDModel, 03204 ModelDefBasedOnFEM<T,DATA> * pFEMModel, 03205 typename AdvSimSupport_DATA<T,DATA>::ListOfPointForces & ListOfPointForces 03206 ) 03207 { 03208 Matrix4x4<T> TrxModelFEM = pFEMModel->RefToTransformationSupport().RefToMatrixTransform(); 03209 Matrix4x4<T> InvTrxModelFEM = TrxModelFEM.GetInverse(); 03210 03211 AdvSimConstraint_VertexIdVsHEVertex<T> & Constraint = m_SetOfInteractions_ForCirclePath[constraintNumber]; 03212 03213 unsigned int vertID = Constraint.GetVertexIDFromModel_1(); 03214 HEVertex<T> * pHEvert = Constraint.GetPtrToVertexFromModel_2(); 03215 //Vector3<T> V1 = pRBDModel->RefToInteractionPointGroup().GetInteractionPointAtIndex( vertID ).GetPosition(); 03216 Vector3<T> V1 = m_pCirclePathCtrl->InterpolatedPts[vertID]; 03217 Vector3<T> V2 = pHEvert->GetProtectedPosition() = Constraint.RefToSavedPositionB(); 03218 V1 = HeadNeedleTrx * V1; 03219 V2 = TrxModelFEM * V2; 03220 T ratio = Constraint.GetForceRatio(); 03221 Constraint.RefToTargetPositionA() = Constraint.RefToTargetPositionB() = ratio*V1 + (1-ratio)*V2; 03222 V1 = HeadNeedleTrxInv * Constraint.RefToTargetPositionA(); 03223 V2 = InvTrxModelFEM * Constraint.RefToTargetPositionB(); 03224 Constraint.RefToTargetPositionA() = V1; 03225 Constraint.RefToTargetPositionB() = V2; 03226 03227 // RBD-based, add the connection as a point force. 03228 { 03229 } 03230 // FEM-based, add the connection as a point force. 03231 { 03232 Vector3<T> Fb = V2 - pHEvert->GetProtectedPosition(); 03233 PointForce<T> * pF = new PointForce<T>(); 03234 ListOfPointForces.push_back( pF ); 03235 03236 // Set connection (i.e. point) force 03237 pF->SetID( pHEvert->GetID() ); 03238 pF->RefToPosition() = pHEvert->GetBarycentricPtr()->RetGenBaryCoords(); 03239 pF->RefToForce() = Fb * Constraint.GetForceScaleB(); 03240 pFEMModel->AddConnectionForceInLocalCoordinates( ListOfPointForces.back() ); 03241 } 03242 } 03243 //----------------------------------------------------------------------------- 03244 template <typename T, typename DATA> 03245 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAConstraintOfSutureThreadTiedWithFEMModel_ForCirclePath ( 03246 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint, 03247 ModelElasticRod<T> * pERModel, 03248 ModelDefBasedOnFEM<T,DATA> * pFEMModel, 03249 typename AdvSimSupport_DATA<T,DATA>::ListOfPointForces & ListOfPointForces 03250 ) 03251 { 03252 int ERModelPt = pConstraint->GetVertexIDFromModel_1(); 03253 Matrix4x4<T> TrxFEMModel = pFEMModel->RefToTransformationSupport().RefToMatrixTransform(); 03254 Matrix4x4<T> InvTrxFEMModel = TrxFEMModel.GetInverse(); 03255 03256 Vector3<T> & S = pERModel->RefToCurrentVertexPositionOfNodeNumber( ERModelPt ); 03257 HEVertex<T> * he = pConstraint->GetPtrToVertexFromModel_2(); 03258 Vector3<T> V = he->GetProtectedPosition() = pConstraint->RefToSavedPositionB(); 03259 V = TrxFEMModel * V; 03260 T ratio = pConstraint->GetForceRatio(); 03261 pConstraint->RefToTargetPositionA() = 03262 pConstraint->RefToTargetPositionB() = ratio*S + (1-ratio)*V; 03263 //S = pConstraint->RefToTargetPositionA(); // ERModel's point's current position 03264 V = InvTrxFEMModel * pConstraint->RefToTargetPositionB(); 03265 pConstraint->RefToTargetPositionB() = V; 03266 03267 // FEM-based model, add the connection as a point force. 03268 { 03269 Vector3<T> F = V - he->GetProtectedPosition(); 03270 PointForce<T> * pF = new PointForce<T>(); 03271 ListOfPointForces.push_back( pF ); 03272 03273 pF->SetID( he->GetID() ); 03274 pF->RefToPosition() = he->GetBarycentricPtr()->RetGenBaryCoords(); 03275 pF->RefToForce() = F * pConstraint->GetForceScaleB(); 03276 pFEMModel->AddConnectionForceInLocalCoordinates( ListOfPointForces.back() ); 03277 } 03278 03279 // Calculate the external force apply to Suture 03280 Vector3<T> Fs = pConstraint->RefToTargetPositionA() - S; 03281 03282 bool bLinearForce = true; 03283 T scaleNonlinearForce = 0.5; 03284 03285 if ( bLinearForce ) 03286 { 03287 // LINEAR FORCE 03288 Fs *= pConstraint->GetForceScaleA(); 03289 } 03290 else 03291 { 03292 // NONLINEAR FORCE 03293 T ERModel_link_length = pERModel->GetLinkLength(); 03294 T magnitude = Fs.Magnitude(); 03295 T scale = pow( pConstraint->GetForceScaleA(), magnitude/ERModel_link_length ); 03296 if ( scale*magnitude <= pERModel->GetStretchModulus()*scaleNonlinearForce ) { 03297 Fs *= scale; 03298 } 03299 else { 03300 Fs *= pERModel->GetStretchModulus(); 03301 } 03302 } 03303 03304 pERModel->GetListOfNodes()[ERModelPt].ExternalForce_ForAdvSimCtrl = Fs; 03305 } 03306 //----------------------------------------------------------------------------- 03307 template <typename T, typename DATA> 03308 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::EnforceAConsistentPositionSutureThreadTiedWithFEMModel_ForCirclePath ( 03309 AdvSimConstraint_VertexIdVsHEVertex<T> * pConstraint, 03310 ModelElasticRod<T> * pERModel, 03311 ModelDefBasedOnFEM<T,DATA> * pFEMModel 03312 ) 03313 { 03314 int ERModelPt = pConstraint->GetVertexIDFromModel_1(); 03315 Matrix4x4<T> TrxFEMModel = pFEMModel->RefToTransformationSupport().RefToMatrixTransform(); 03316 Matrix4x4<T> InvTrxFEMModel = TrxFEMModel.GetInverse(); 03317 03318 unsigned int nodeID = pConstraint->GetVertexIDFromModel_1(); 03319 03320 // Enforce ER-based model's Position 03321 if ( pConstraint->GetEnforcePositionStatusA() ) { 03322 pERModel->GetListOfNodes()[nodeID].UseEnforcedPosition = true; 03323 pERModel->GetListOfNodes()[nodeID].EnforcedPosition = pConstraint->RefToTargetPositionA(); 03324 } 03325 else { 03326 } 03327 03328 pConstraint->RefToSavedPositionB() = pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition(); 03329 03330 // Move the model's constrained point to the target point 03331 if ( false ) 03332 { 03333 // TO THE TARGET POSITION B 03334 if ( pConstraint->GetEnforcePositionStatusB() ) { 03335 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = pConstraint->RefToTargetPositionB(); 03336 } 03337 } 03338 else { 03339 // TO THE SUTURE POINT 03340 if ( pConstraint->GetEnforcePositionStatusB() ) { 03341 #ifdef TAPs_USE_VERTEX_POSITION_AVERAGING 03342 std::vector< HEVertex<T> * > firstRing = pConstraint->GetPtrToVertexFromModel_2()->FindTheFirstRingOfVertices(); 03343 unsigned int size = firstRing.size(); 03344 Vector3<T> targetPos = InvTrxFEMModel * pERModel->RefToCurrentVertexPositionOfNodeNumber( pConstraint->GetVertexIDFromModel_1() ); 03345 if ( size > 0 ) { 03346 Vector3<T> avgPos; 03347 for ( unsigned int i = 0; i < size; ++i ) { 03348 avgPos += firstRing[i]->GetPosition(); 03349 //firstRing[i]->GetProtectedPosition() = ( firstRing[i]->GetPosition() + targetPos ) / 2; 03350 } 03351 T scale = size;// / T(2); 03352 avgPos = ( avgPos + targetPos*scale ) / ( size + scale ); 03353 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = avgPos; 03354 } 03355 else { 03356 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = targetPos; 03357 } 03358 #else //TAPs_USE_VERTEX_POSITION_AVERAGING 03359 pConstraint->GetPtrToVertexFromModel_2()->GetProtectedPosition() = InvTrxFEMModel * 03360 pERModel->RefToCurrentVertexPositionOfNodeNumber( 03361 pConstraint->GetVertexIDFromModel_1() ); 03362 #endif//TAPs_USE_VERTEX_POSITION_AVERAGING 03363 } 03364 } 03365 } 03366 //----------------------------------------------------------------------------- 03367 // FOR CIRCLE PATH 03368 //============================================================================= 03369 03370 03371 03372 03373 //============================================================================= 03374 #if defined(__gl_h_) || defined(__GL_H__) 03375 //----------------------------------------------------------------------------- 03376 template <typename T, typename DATA> 03377 void AdvSimConstraint_ForModelSurgicalSutureWithHeadNeedle<T,DATA>::Draw () const 03378 { 03379 for ( unsigned int i = 0; i < m_size_ForIPG; ++i ) { 03380 if ( m_SetOfInteractionAssociatedModelID_ForIPG[i] >= 0 ) { 03381 // ... 03382 //DRAW SOMETHING IN HERE 03383 m_SetOfInteractions_ForIPG[i].Draw(); 03384 03385 //std::cout << 03386 //... 03387 } 03388 } 03389 03390 // Draw saved punctured locations 03391 glPushAttrib( GL_ALL_ATTRIB_BITS ); 03392 glDisable( GL_LIGHTING ); 03393 glPointSize( 25 ); 03394 glBegin( GL_POINTS ); 03395 glColor3f( 1, 1, 1 ); 03396 for ( unsigned int i = 0; i < m_size_ForIPG; ++i ) { 03397 if ( m_SetOfInteractionAssociatedModelID_ForIPG[i] >= 0 ) { 03398 glVertex3fv( m_PuncturedLocations_ForIPG[i].GetDataFloat() ); 03399 } 03400 } 03401 glEnd(); 03402 glPopAttrib(); 03403 03404 /* 03405 // Draw suture's punctured thread points 03406 glPushAttrib( GL_ALL_ATTRIB_BITS ); 03407 std::list< InteractionSutureThreadVsFEMModel<T> >::const_iterator it = m_ListOfSutureThreadVsFEMModels.begin(); 03408 int count = 0; 03409 while ( it != m_ListOfSutureThreadVsFEMModels.end() ) { 03410 std::cout << ++count << ": " << *it->pAdvSimConstraint_VertexIdVsHEVertex << "\n"; 03411 03412 glBegin( GL_POINTS ); 03413 glEnd(); 03414 ++it; 03415 } 03416 glPopAttrib(); 03417 //*/ 03418 03419 } 03420 03421 //----------------------------------------------------------------------------- 03422 #endif // #if defined(__gl_h_) || defined(__GL_H__) 03423 //============================================================================= 03424 03425 03426 //============================================================================= 03427 END_NAMESPACE_TAPs 03428 //34567890123456789012345678901234567890123456789012345678901234567890123456789 03429 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----