![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsElasticRodKR.hpp 00003 ******************************************************************************/ 00011 /****************************************************************************** 00012 SUKITTI PUNAK (08/31/2009) 00013 UPDATE (03/23/2011) 00014 ******************************************************************************/ 00015 #ifndef TAPs_ELASTIC_ROD__KR_HPP 00016 #define TAPs_ELASTIC_ROD__KR_HPP 00017 00018 #include "TAPsElasticRodParameters.hpp" 00019 #include "TAPsElasticRodNode.hpp" 00020 00021 // Dowker Notation 00022 #include "../../Data/TAPsDatabaseDowkerNotation.hpp" 00023 #include "../../Data/TAPsKnotTrackingConstraint.hpp" 00024 00025 // For collision detection 00026 #include "../../CD/TAPsBVHTree.hpp" 00027 00028 // For drawing by OpenGL 00029 #if defined(__gl_h_) || defined(__GL_H__) 00030 #include "../../OpenGL/TAPsOpenGLUsefulObjs.hpp" 00031 #include "../../OpenGL/TAPsOpenGLObj.hpp" 00032 #endif 00033 00034 BEGIN_NAMESPACE_TAPs 00035 //============================================================================= 00036 template <typename T> 00037 class ElasticRodKR { 00038 00039 typedef std::vector< ElasticRodNode<T> > SetOfElasticRodNodes; 00040 00041 // Member Functions ------------------------------------------------------- 00043 friend std::ostream & operator<< ( std::ostream &output, ElasticRodKR<T> const &obj ) 00044 { 00045 output << obj.StrInfo(); 00046 return output; 00047 } 00048 public: 00049 00050 // Data Members ----------------------------------------------------------- 00051 enum Threshold { 00052 THRESHOLD_FOR_FIXING_KNOT, 00053 THRESHOLD_WAIT_TIME, 00054 LENGTH_THRESHOLD_0, 00055 LENGTH_THRESHOLD_1, 00056 LENGTH_THRESHOLD_2, 00057 LENGTH_THRESHOLD_3, 00058 LENGTH_THRESHOLD_4, 00059 LENGTH_THRESHOLD_5, 00060 LENGTH_THRESHOLD_6, 00061 LENGTH_THRESHOLD_7, 00062 }; 00063 00064 //------------------------------------------------------------------------- 00066 ElasticRodKR (); 00067 00069 //ElasticRodKR ( ElasticRodKR<T> const &obj ); 00070 00072 virtual ~ElasticRodKR (); 00073 00075 void CreateKR ( 00076 int * pIdxCurr, 00077 int * pIdxNext, 00078 ElasticRodParameters<T> * pParameters, 00079 SetOfElasticRodNodes * pNodeList, 00080 BVHTree<T> * bvhTree, 00081 unsigned char numOfNotAllowed 00082 ); 00083 00085 void DeleteKR (); 00086 00088 //void CDRforSelfIntersections (); 00089 00091 //void CheckIntersection (); 00092 00093 //------------------------------------------------------------------------- 00095 virtual std::string StrInfo () const; 00096 00097 //------------------------------------------------------------------------- 00098 // Operations 00099 00101 void Init ( unsigned char numKnotAllowed ); 00103 void Reset (); 00105 std::string CheckSurgeonsKnot (); 00106 00108 int KnotRecognition (); 00109 00124 void CombineTwoKnots ( 00125 int startLockedKnotID, 00126 Data::DatabaseDowkerNotation::KNOT knotType, 00127 Matrix4x4<T> const & orientation 00128 ); 00129 00130 00132 void ConstrainKnots (); 00133 00135 std::string GetStrNameForKnotCombination (); 00137 std::string GetNameOfKnot ( unsigned int i, bool withPosOrNegPostfix = false ); 00138 00142 int GetMinPtIdThatIsInRecordedKnots () const { return m_iMinPtIdThatIsInRecordedKnots; } 00146 int GetMaxPtIdThatIsInRecordedKnots () const { return m_iMaxPtIdThatIsInRecordedKnots; } 00147 00148 //void SetMinPtIdThatIsInRecordedKnots ( int i ) { m_iMinPtIdThatIsInRecordedKnots = i; } 00149 //void SetMaxPtIdThatIsInRecordedKnots ( int i ) { m_iMaxPtIdThatIsInRecordedKnots = i; } 00150 00151 //=============================================================== 00152 // Animating Knot Tying 00153 //--------------------------------------------------------------- 00154 #ifdef TAPs_ADD_ANIMATED_KNOTS 00155 00157 Matrix4x4<T> & RefToOrientationForCombinedKnot () { return m_OrientationForCombinedKnot; } 00159 Matrix4x4<T> const & RefToOrientationForCombinedKnot () const { return m_OrientationForCombinedKnot; } 00160 00162 void ProcessKnotAnimation (); 00163 00169 int ConstrainAnimatedKnots ( 00170 Data::DatabaseDowkerNotation::KNOT & knotTypeOfTheFinishTightenKnot, 00171 int & knotIDStartOfTheFinishTightenKnot, 00172 int & knotIDEndOfTheFinishTightenKnot, 00173 int & numOfCrossingsOfTheFinishTightenKnot 00174 ); 00175 00177 class AnimatedKnot { 00178 public: 00179 AnimatedKnot ( int animatedKnotID = 0 ) 00180 : NumOfCrossings(0) 00181 , KnotIDStart(-1) 00182 , KnotIDStart_Limit(-1) 00183 , KnotIDEnd_Limit(-1) 00184 , KnotIDEnd(-1) 00185 , KnotSizeLimit( 1 ) 00186 , KnotType( Data::DatabaseDowkerNotation::UNDEFINED ) 00187 , StepsLeftForSettingKnot( 0 ) 00188 , IsKnotTight( false ) 00189 , IsOrientationFixed( false ) 00190 , m_iID( animatedKnotID ) 00191 , m_bCalKnotLocation( true ) 00192 #ifdef TAPs_SPECIFIC_FOR_SUTUREAPP_02 00193 , pKnotTightenStatus( NULL ) 00194 #endif//TAPs_SPECIFIC_FOR_SUTUREAPP_02 00195 {} 00196 00197 ~AnimatedKnot () {} // Nothing to delete here 00198 00199 AnimatedKnot & operator= ( AnimatedKnot const& orig ) 00200 { 00201 m_iID = orig.m_iID; 00202 00203 KnotIDStart = orig.KnotIDStart; 00204 KnotIDStart_Limit = orig.KnotIDStart_Limit; 00205 KnotIDEnd_Limit = orig.KnotIDEnd_Limit; 00206 KnotIDEnd = orig.KnotIDEnd; 00207 KnotSizeLimit = orig.KnotSizeLimit; 00208 KnotType = orig.KnotType; 00209 NumOfCrossings = orig.NumOfCrossings; 00210 StepsLeftForSettingKnot = orig.StepsLeftForSettingKnot; 00211 Orientation = orig.Orientation; 00212 Center = orig.Center; 00213 m_bCalKnotLocation = orig.m_bCalKnotLocation; 00214 IsKnotTight = orig.IsKnotTight; 00215 IsOrientationFixed = orig.IsOrientationFixed; 00216 #ifdef TAPs_SPECIFIC_FOR_SUTUREAPP_02 00217 pKnotTightenStatus = orig.pKnotTightenStatus; 00218 #endif//TAPs_SPECIFIC_FOR_SUTUREAPP_02 00219 00220 return *this; 00221 } 00222 00223 int KnotIDStart; 00224 int KnotIDStart_Limit; 00225 int KnotIDEnd_Limit; 00226 int KnotIDEnd; 00227 int KnotSizeLimit; 00228 Data::DatabaseDowkerNotation::KNOT KnotType; 00229 int NumOfCrossings; 00230 int StepsLeftForSettingKnot; 00231 00232 Vector3<T> Center; 00233 Matrix4x4<T> Orientation; 00234 bool IsOrientationFixed; 00235 00236 bool IsKnotTight; 00237 00238 int GetID () { return m_iID; } 00239 00240 bool GetStatusCalKnotPosition () const { return m_bCalKnotLocation; } 00241 void SetStatusCalKnotPosition ( bool b ) { m_bCalKnotLocation = b; } 00242 00243 #ifdef TAPs_SPECIFIC_FOR_SUTUREAPP_02 00244 bool * pKnotTightenStatus; 00245 #endif//TAPs_SPECIFIC_FOR_SUTUREAPP_02 00246 00247 protected: 00248 int m_iID; 00249 bool m_bCalKnotLocation; 00250 }; 00251 00252 protected: 00253 std::vector< AnimatedKnot > m_ListOfAnimatedKnot; // list of animated knot 00254 public: 00255 00257 bool GetStatusKnotAnimation () const { return m_ListOfAnimatedKnot.size() > 0; } 00259 unsigned int GetNumberOfAnimatedKnots () const { return m_ListOfAnimatedKnot.size(); } 00261 AnimatedKnot * GetTheLastAnimatedKnot () 00262 { 00263 if ( KnotAnimationStatus ) return *m_ListOfAnimatedKnot.back(); 00264 else return NULL; 00265 } 00266 00271 bool AddAnimatedKnot ( 00272 #ifdef TAPs_SPECIFIC_FOR_SUTUREAPP_02 00273 bool * pKnotTightenStatus, 00274 #endif//TAPs_SPECIFIC_FOR_SUTUREAPP_02 00275 int grabbedNodeID, 00276 Data::DatabaseDowkerNotation::KNOT knot, 00277 int startNodeIDLimit = -1, 00278 int endNodeIDLimit = -1, 00279 bool bCalKnotPosition = true, 00280 bool bEndIsGrabbed = true, 00281 int offset = 5, 00282 Matrix4x4<T> * pOrientation = NULL 00283 ); 00284 00289 bool AddAnimatedKnot ( 00290 #ifdef TAPs_SPECIFIC_FOR_SUTUREAPP_02 00291 bool * pKnotTightenStatus, 00292 #endif//TAPs_SPECIFIC_FOR_SUTUREAPP_02 00293 Data::DatabaseDowkerNotation::KNOT knot, 00294 int startNodeIDLimit = -1, 00295 int startLoopNodeIDLimit = -1, 00296 int endLoopNodeIDLimit = -1, 00297 int endNodeIDLimit = -1, 00298 bool bCalKnotPosition = true, 00299 bool bEndIsGrabbed = true, 00300 Matrix4x4<T> * pOrientation = NULL 00301 ); 00302 00303 protected: 00304 AnimatedKnot m_AnimatedKnot; 00305 Matrix4x4<T> m_OrientationForCombinedKnot; 00306 00307 #endif//TAPs_ADD_ANIMATED_KNOTS 00308 //--------------------------------------------------------------- 00309 // Animating Knot Tying 00310 //=============================================================== 00311 00312 public: 00313 00315 //virtual std::vector< BVHNode<T> * > & GetListOfCollidedNodes() { return m_svCollidedNode; } 00317 //virtual std::vector< BVHNode<T> * > & GetListOfCollidedNodesThat() { return m_svCollidedNodeThat; } 00318 00320 bool SetKnotControlThreshold ( enum Threshold thdID, T val ); 00322 T GetKnotControlThreshold ( enum Threshold thdID ) const; 00323 00325 void GetCurrentTrackingKnot_StartAndEndLinkIDs ( 00326 int & startLink, 00327 int & endLink 00328 ); 00329 00331 unsigned int GetNumOfKnotsAllowed () const { return static_cast<unsigned int>( m_ucMaxNumKnotsAllowed ); } 00332 00334 unsigned int GetKnotCount () const { return static_cast<unsigned int>( m_ucKnotCount ); } 00335 00337 void GetKnotStartAndEndLinkID ( unsigned int knotID, unsigned int & start, unsigned int & end ) const 00338 { 00339 if ( knotID < GetKnotCount() ) { 00340 start = m_pListOfLockedKnots[knotID].StartLinkID; 00341 end = m_pListOfLockedKnots[knotID].EndLinkID; 00342 } 00343 } 00344 00346 void GetKnotStartLoopLinkAndEndLinkLoopLinkID ( unsigned int knotID, unsigned int & startLoopLink, unsigned int & endLoopLink ) const 00347 { 00348 if ( knotID < GetKnotCount() ) { 00349 startLoopLink = m_pListOfLockedKnots[knotID].StartLoopLinkID; 00350 endLoopLink = m_pListOfLockedKnots[knotID].EndLoopLinkID; 00351 } 00352 } 00353 00355 bool IsKnotLocationLocked ( unsigned int knotID ) const 00356 { 00357 if ( knotID < GetKnotCount() ) return m_pListOfLockedKnots[knotID].DoLockLocation; 00358 else return false; 00359 } 00360 00362 void SetStatusKnotLocationLocked ( unsigned int knotID, bool b ) 00363 { 00364 if ( knotID < GetKnotCount() ) m_pListOfLockedKnots[knotID].DoLockLocation = b; 00365 } 00366 00368 Vector3<T> GetKnotCenter ( unsigned int knotID ) const 00369 { 00370 if ( knotID < GetKnotCount() ) return m_pListOfLockedKnots[knotID].Center; 00371 else return Vector3<T>(); 00372 } 00374 void SetKnotCenter ( unsigned int knotID, Vector3<T> & center ) 00375 { 00376 if ( knotID < GetKnotCount() ) m_pListOfLockedKnots[knotID].Center = center; 00377 } 00378 00380 Quaternion<T> GetKnotOrientation ( unsigned int knotID ) const 00381 { 00382 if ( knotID < GetKnotCount() ) return m_pListOfLockedKnots[knotID].Orientation; 00383 else return Quaternion<T>(); 00384 } 00386 void SetKnotOrientation ( unsigned int knotID, Quaternion<T> & orientation ) 00387 { 00388 if ( knotID < GetKnotCount() ) return m_pListOfLockedKnots[knotID].Orientation = orientation; 00389 } 00390 00392 //void GetApproxKnotCenterAndOrientation ( unsigned int i, Vector3<T> ¢er, Quaternion<T> &orientation ); 00393 00394 // Data Members ----------------------------------------------------------- 00395 //============================================================================= 00396 protected: 00397 // Member Functions ------------------------------------------------------- 00398 // Data Members ----------------------------------------------------------- 00399 //============================================================================= 00400 private: 00401 // Member Functions ------------------------------------------------------- 00402 00404 inline void SetTheShapeOfAnimatedKnot ( AnimatedKnot & knot ); 00405 00407 inline void FinalizeTheShapeOfAnimatedKnot ( AnimatedKnot & knot ); 00408 00410 void CreateData ( unsigned char numKnotAllowed = 8 ); 00412 void DeleteData (); 00413 00416 inline Vector3<T> GetProjDirection () const; 00417 00419 int CheckSelfCrossingForKnotRecognition ( Vector3<T> const & projectionDirection ); 00420 00422 void CheckSelfCrossingsNextLevelRecursively ( 00423 BVHNode<T> * node1, BVHNode<T> * node2, 00424 Vector3<T> const & projectionDirection 00425 ); 00427 T CheckSelfCrossingsRecursively ( 00428 BVHNode<T> * node1, BVHNode<T> * node2, 00429 Vector3<T> const & projectionDirection 00430 ); 00432 T TestOverlapCircle ( 00433 BVHNode<T> * node1, BVHNode<T> * node2, 00434 Vector3<T> const & projectionDirection 00435 ); 00437 void CheckCrossings ( 00438 BVHNode<T> * node1, BVHNode<T> * node2, 00439 Vector3<T> const & projectionDirection 00440 ); 00441 00443 int GetKnotStartPt () const { return m_iKnotStartPt; }; 00445 int GetKnotEndPt () const { return m_iKnotEndPt; }; 00446 00450 void RecordKnot ( int startLink, int endLink, int knotID ); 00451 00456 void RecordKnot ( int startLink, int startLoopLink, int endLoopLink, int endLink, int knotID ); 00457 00470 int ConverseDowkerNotationToKnotName ( std::string * knotName = NULL ); 00471 00472 // The links for accessing the properties of the elastic rod 00473 int * m_pIdxCurr; 00474 int * m_pIdxNext; 00475 ElasticRodParameters<T> * m_pParameters; 00476 SetOfElasticRodNodes * m_pNodeList; 00477 //std::vector< BVHNode<T> * > m_svCollidedNode; //!< list of collided nodes for collision detection 00478 //std::vector< BVHNode<T> * > m_svCollidedNodeThat; //!< list of other object BVH tree's collided nodes for collision detection 00479 BVHTree<T> * m_BVHTree; 00480 00481 unsigned char m_ucMaxNumKnotsAllowed; 00482 unsigned char m_ucKnotCount; 00483 00484 class IC_LockedKnot { 00485 public: 00486 IC_LockedKnot () 00487 : ID(-1) 00488 , StartLinkID(-1) 00489 , StartLoopLinkID(-1) 00490 , EndLoopLinkID(-1) 00491 , EndLinkID(-1) 00492 , DoLockLocation( false ) 00493 { 00494 Center.SetXYZ( 0, 0.5, 0 ); 00495 } 00496 00497 ~IC_LockedKnot () {}; 00498 00499 IC_LockedKnot & operator= ( IC_LockedKnot const & orig ) 00500 { 00501 ID = orig.ID; 00502 StartLinkID = orig.StartLinkID; 00503 StartLoopLinkID = orig.StartLoopLinkID; 00504 EndLoopLinkID = orig.EndLoopLinkID; 00505 EndLinkID = orig.EndLinkID; 00506 DoLockLocation = orig.DoLockLocation; 00507 } 00508 00509 void Reset () 00510 { 00511 ID = -1; 00512 StartLinkID = -1; 00513 StartLoopLinkID = -1; 00514 EndLoopLinkID = -1; 00515 EndLinkID = -1; 00516 DoLockLocation = false; 00517 } 00518 00519 int ID; 00520 int StartLinkID; 00521 int StartLoopLinkID; 00522 int EndLoopLinkID; 00523 int EndLinkID; 00524 00525 Vector3<T> Center; 00526 Quaternion<T> Orientation; 00527 bool DoLockLocation; 00528 }; 00529 00530 IC_LockedKnot * m_pListOfLockedKnots; 00531 00532 int m_iMinPtIdThatIsInRecordedKnots; 00533 int m_iMaxPtIdThatIsInRecordedKnots; 00534 00537 unsigned int m_uiMinLengthThreshold; 00538 unsigned int * m_puiLengthThresholds; 00539 unsigned int m_uiLengthAccumulateTarget; 00540 00541 int m_ucTrackingKnot; 00542 int m_KnotLinkStartTempRecord; 00543 int m_KnotLinkEndTempRecord; 00544 //Data::KnotTrackingConstraint<T> m_KnotTrackingConstraint; //!< a knot tracking constraint 00545 00548 unsigned int m_uiCounterThreshold; 00549 unsigned int m_uiCounterForFixingKnot; 00550 T m_tWaitTime; 00551 T m_tAccTime; 00552 00553 ElasticRodNode<T> * m_NodesForProjPoints[3]; 00554 00555 int m_iMaxCrossingPairs, m_iNumCrossingPairs; 00556 int * m_iaDowkerNotation; 00557 int m_iKnotStartPt, m_iKnotEndPt; 00558 00608 int * m_iaCrossingCounters; 00609 class IC_Crossing { 00610 public: 00611 int number, id; 00612 IC_Crossing( int number, int id ) { this->number = number; this->id = id; } 00613 }; 00614 std::list< IC_Crossing > m_crossings; 00615 void InsertToList( int number, int id ) 00616 { 00617 // Add at the start 00618 if ( m_crossings.size() == 0 ) { 00619 m_crossings.push_back( IC_Crossing( number, id ) ); 00620 return; 00621 } 00622 // Insert in a middle 00623 std::list< IC_Crossing >::iterator it = m_crossings.begin(); 00624 while ( it != m_crossings.end() ) { 00625 if ( (*it).id > id ) { 00626 m_crossings.insert( it, IC_Crossing( number, id ) ); 00627 return; 00628 } 00629 ++it; 00630 } 00631 // Add at the end 00632 m_crossings.push_back( IC_Crossing( number, id ) ); 00633 } 00634 00635 // Manage time 00636 time_t m_StartTime; 00637 inline void ResetStartTime () 00638 { 00639 time( &m_StartTime ); // reset time 00640 } 00641 inline void ResetElapsedTime () 00642 { 00643 time( &m_StartTime ); // reset time 00644 m_tAccTime = 0.0; 00645 } 00646 inline double AddElapsedTime () 00647 { 00648 time_t prevTime = m_StartTime; 00649 time( &m_StartTime ); // new start time 00650 // difftime fn is from <ctime> 00651 m_tAccTime += difftime( m_StartTime, prevTime ); 00652 00653 return m_tAccTime; 00654 } 00655 inline bool IsTimeLimitReached () 00656 { 00657 return m_tAccTime >= m_tWaitTime; 00658 } 00659 00660 00661 //* 00662 // DEBUG 00663 std::vector<int> debug_crosses; 00664 std::vector<int> debug_crossesID; 00665 00666 std::string Debug_Str () 00667 { 00668 std::ostringstream ss; 00669 ss << "# of crossing pairs: " << m_iNumCrossingPairs << "\n"; 00670 ss << "Cross#: "; 00671 for ( int i = 0; i < static_cast<int>(debug_crosses.size()); ++i ) { 00672 ss << "\t" << debug_crosses[i]; 00673 } 00674 ss << "\n"; 00675 00676 ss << "ID#: "; 00677 for ( int i = 0; i < static_cast<int>(debug_crossesID.size()); ++i ) { 00678 ss << "\t" << debug_crossesID[i]; 00679 } 00680 ss << "\n"; 00681 00682 ss << "Dowker#:"; 00683 for ( int i = 0; i < static_cast<int>(debug_crossesID.size()); ++i ) { 00684 ss << "\t" << m_iaDowkerNotation[i]; 00685 } 00686 ss << "\n"; 00687 00688 //ss << "Recognized Knot ID: " << special_debug_knotID << "\n"; 00689 00690 ss << "Tracking Knot: " << m_ucTrackingKnot 00691 << " Accumulate: " << m_uiCounterForFixingKnot 00692 << " Knot Len: " << GetKnotEndPt() << " - " << GetKnotStartPt() << " = " << GetKnotEndPt() - GetKnotStartPt() 00693 << " Acc Length: " << m_uiLengthAccumulateTarget 00694 << " m_uiMinLengthThreshold: " << m_uiMinLengthThreshold 00695 << "\n\n"; 00696 00697 return ss.str(); 00698 } 00699 //*/ 00700 00701 //============================================================================= 00702 00703 //OpenGL 00704 //----------------------------------------------------------------------------- 00705 //#define __GL_H__ 00706 //#define TAPs_USE_GLSL 00707 //----------------------------------------------------------------------------- 00708 #if defined(__gl_h_) || defined(__GL_H__) 00709 public: 00711 inline virtual void Draw () const; 00712 00714 inline virtual void DrawForDebug () const; 00715 00716 //OpenGL::OpenGLObj Rendering; //!< OpenGL Object has material color properties 00717 protected: 00718 OpenGL::OpenGLUsefulObj<T> * m_pOGLUsefulObj; 00719 00720 #endif//defined(__gl_h_) || defined(__GL_H__) 00721 //----------------------------------------------------------------------------- 00722 //============================================================================= 00723 }; // CLASS END: ElasticRodKR 00724 //============================================================================= 00725 END_NAMESPACE_TAPs 00726 //----------------------------------------------------------------------------- 00727 #include "TAPsElasticRodKR.cpp" 00728 //----------------------------------------------------------------------------- 00729 #endif 00730 //34567890123456789012345678901234567890123456789012345678901234567890123456789 00731 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----