MeVisLabToolboxReference
|
00001 // **InsertLicense** code 00002 //---------------------------------------------------------------------------------- 00004 00009 //---------------------------------------------------------------------------------- 00010 #ifndef __GraphAnalyser_H 00011 #define __GraphAnalyser_H 00012 00013 00014 // Include dll-specific settings. 00015 #include "mlVesselGraphSystem.h" 00016 00017 // Include ml Macros for implementation support. 00018 #include "mlDebug.h" 00019 00020 // Include vessel graph class. 00021 #include "mlSystemWarningsDisable.h" 00022 #include <map> 00023 #include <memory.h> 00024 #include "mlSystemWarningsRestore.h" 00025 #include "mlGraph.h" 00026 #include "mlGraphComponents.h" 00027 #include "mlFloatingPointVector.h" 00028 #include "mlMatrixTemplate.h" 00029 #include "AssocGraph.h" 00030 00031 00032 00033 // Be sure that all your modules are part of the ml. So collisions 00034 // with names in system files or other libraries are minimized. 00035 ML_START_NAMESPACE 00036 00037 // ------------------------------------------------------------------ 00039 00040 // ------------------------------------------------------------------ 00043 typedef enum 00044 { 00045 DATA_NO = 0, 00046 DATA_SCL, 00047 DATA_BARYCENTER, 00048 DATA_DISTANCE, 00049 DATA_FLAG, 00050 DATA_NODE, 00051 DATA_GET_FKT, 00052 DATA_SET_FKT, 00053 DATA_AV_LEN, 00054 OUTDATA_CLUSTER, 00055 OUTDATA_LENGTH, 00056 OUTDATA_VOLUME, 00057 OUTDATA_POS, 00058 OUTDATA_GLOBAL_MIN_DIST, 00059 OUTDATA_AV_MIN_DIST, 00060 OUTDATA_ROOT, 00061 } NData; 00062 00063 typedef std::map<NData, void *> DataMap; 00065 00066 //---------------------------------------------------------- 00068 00069 //---------------------------------------------------------- 00072 typedef enum 00073 { 00074 PROC_NONE = 0x000, 00075 PROC_LENGTH = 0x001, 00076 PROC_VOLUME = 0x002, 00077 PROC_WEIGHTED_POS = 0x004, 00078 PROC_AV_MIN_DIST = 0x008, 00079 PROC_SCL = 0x010, 00080 PROC_SKELETON_AREA= 0x020, 00081 PROC_ROOT = 0x100, 00082 PROC_ST_VOLUME = 0x202, 00083 PROC_ST_POS = 0x204, 00084 PROC_ST_NODE_SUM = 0x208, 00085 PROC_CLUSTER = 0x400 00086 } NProcessMode; 00087 00088 00089 00090 00092 00093 // ------------------------------------------------------------------ 00095 00096 // ------------------------------------------------------------------ 00102 struct CIdxFloat{ 00103 int _nIdx; 00104 float _fValue; 00105 00106 00107 CIdxFloat(const CIdxFloat & oIF) : _nIdx(oIF._nIdx), _fValue(oIF._fValue) {}; 00108 CIdxFloat(int nIdx = 0, float fValue = 0.0) : _nIdx(nIdx), _fValue(fValue) {}; 00109 CIdxFloat& operator=(const CIdxFloat &oIF) {if (this != &oIF){ this->_nIdx = oIF._nIdx; this->_fValue=oIF._fValue;} return *this; } 00110 00111 00113 inline bool operator> (const CIdxFloat& oIF) const { if(_fValue != oIF._fValue){return _fValue > oIF._fValue;} else {return _nIdx > oIF._nIdx;} } 00114 inline bool operator< (const CIdxFloat& oIF) const { if(_fValue != oIF._fValue){return _fValue < oIF._fValue;} else {return _nIdx < oIF._nIdx;} } 00115 inline bool operator==(const CIdxFloat& oIF) const { return ((_nIdx == oIF._nIdx) && (_fValue == oIF._fValue)); } 00117 }; 00118 00122 struct CIdxIdx{ 00123 int _n1; 00124 int _n2; 00125 CIdxIdx(const CIdxIdx & oII) : _n1(oII._n1), _n2(oII._n2) {}; 00126 CIdxIdx& operator=(const CIdxIdx &oII) {if (this != &oII){ this->_n1 = oII._n1; this->_n2=oII._n2;} return *this; } 00128 inline bool operator< (const CIdxIdx& oII) const { if(_n1 != oII._n1){return _n1 < oII._n1;} else {return _n2 < oII._n2;} } 00129 inline bool operator==(const CIdxIdx& oII) const { return ((_n1 == oII._n1) && (_n2 == oII._n2)); } 00131 }; 00133 00134 00135 00136 // ------------------------------------------------------------------ 00138 // ------------------------------------------------------------------ 00143 class VESSELGRAPH_EXPORT GraphAnalyser 00144 { 00145 public: 00146 //-------------------------------------------------------- 00148 00149 //-------------------------------------------------------- 00152 explicit GraphAnalyser (Graph * pGraph) : _pGraph(pGraph) {}; 00154 00155 //---------------------------------------------------------- 00157 00158 //---------------------------------------------------------- 00161 void measureLength(); 00162 00165 void measureVolume(); 00166 00170 void measureST_Volume(bool bIgnoreOrientation=false 00171 00172 ); 00173 00176 float measureAvMinDistance(); 00177 00179 void measureSkeletonArea(int nAvLength=5); 00180 00182 Vector3 measureBarycenter(); 00183 00187 void measureST_Barycenter(bool bIgnoreOrientation=false 00188 00189 ); 00190 00192 inline void sumupST_DrainVolume(bool bIgnoreOrientation=false 00193 00194 ) 00195 { sumupST_Value (&VesselNode::getDrainVolume, &VesselNode::setDrainVolume, bIgnoreOrientation); } 00196 00197 void sumupST_Value(VesselNode::NodeGetFkt getFkt, 00198 VesselNode::NodeSetFkt setFkt, 00199 bool bIgnoreOrientation=false 00200 00201 ); 00202 00204 void measureMaxPathValue(VesselNode* pRootNode, VesselEdge::EdgeGetFkt edgeGetFkt, VesselNode::NodeGetFkt nodeGetFkt, VesselNode::NodeSetFkt nodeSetFkt); 00205 00208 void searchMaxSubTrees(std::vector<VesselEdge *>::iterator iBegin, 00209 std::vector<VesselEdge *>::iterator iEnd, 00210 int nNum, 00211 std::vector<VesselEdge *> * pvMaxEdges, 00212 float * pfActValue, 00213 float * pfActSum 00214 ); 00215 00218 inline void searchMaxSubTrees(std::vector<VesselEdge *> vStartEdges, 00219 unsigned int nNum, 00220 std::vector<VesselEdge *> * pvMaxEdges, 00221 float * pfActValue, 00222 float * pfActSum 00223 ) 00224 { 00225 searchMaxSubTrees(vStartEdges.begin(), vStartEdges.end(), (int) nNum, pvMaxEdges, pfActValue, pfActSum); 00226 } 00227 00230 inline void searchMaxSubTrees(std::vector<VesselEdge *> vStartEdges, 00231 int nPos, 00232 unsigned int nNum, 00233 std::vector<VesselEdge *> * pvMaxEdges, 00234 float * pfActValue, 00235 float * pfActSum 00236 ) 00237 { 00238 searchMaxSubTrees(vStartEdges.begin()+nPos, vStartEdges.begin()+nPos+1, (int) nNum, pvMaxEdges, pfActValue, pfActSum); 00239 } 00240 00241 // Starting at node pRoot, search for two subtrees (originating from a common node) with barycenters at a large distance 00242 // in separationDirection and large volumes. Push_back() them to vClassifiedEdges ordered by descending position in separationDirection. 00243 // If (pRoot==NULL) all nodes in the graph are considered. 00244 void searchSubTreeSeparation(VesselNode* pRoot, const Vector3& separationDirection, std::vector<VesselEdge*>& vClassifiedEdges); 00245 00249 void searchST_MajorBifurcation(VesselEdge *pStartEdge, 00250 float fMinorLimit, 00251 std::vector<VesselEdge *> *pvEdges, 00252 bool bClear = true 00253 ); 00254 00259 void searchST_MajorBifurcation(VesselEdge *pStartEdge, 00260 float fMinorLimitStart, 00261 float fMinorLimitStep, 00262 int nMinorLimitNumber, 00263 std::vector<VesselEdge *> *pvEdges, 00264 bool bClear = true 00265 ); 00266 00267 00274 bool calcDistanceMatrix(MatrixTemplate<double>& dm, std::vector<int>& vId, int nMaxNodes); 00275 00276 00295 bool calcNodeClassifikator(CDoubleArray * pArAssoc, std::vector<int>* pvId, int nMaxNodes); 00296 00297 00301 bool calcNodeBaseFromPosition(const Vector3 & vPosition, const std::vector<int> & vId, std::vector<CIdxFloat> * pvResult); 00302 00306 bool calcPositionFromNodeBase(std::vector<CIdxFloat> vBase, Vector3 * pvResult); 00307 00309 double calcSpannedVolume(const std::vector<int> & vId); 00311 00312 00313 00314 //---------------------------------------------------------- 00316 00317 //---------------------------------------------------------- 00320 VesselNode* suggestRoot(float fSignificanceLevel = 0.7, int nPreferedDirection = 0); 00321 00322 00325 short sampleConnectedCluster(); 00326 00328 const VesselNode * getParent(const VesselNode *pN1, const VesselNode *pN2) const; 00329 const VesselNode * getParent(const VesselEdge *pE1, const VesselEdge *pE2) const; 00330 VesselNode* getParent(VesselNode* pN1, VesselNode* pN2); 00331 VesselNode* getParent(VesselEdge *pE1, VesselEdge* pE2); 00333 00335 void tansferLabels(Skeleton::LABELTYPE NType, float fThresh = 0.1); 00337 void tansferLabelsInverse(void); 00339 void scanSkeletonLabelMinMax( float *min, float *max ); 00340 00342 void collectLeafs(VesselNode *pRoot, std::vector<VesselNode*>& pLeafs); 00343 00344 private: 00345 //---------------------------------------------------------- 00347 00348 //---------------------------------------------------------- 00352 void calcRootPath(int nParentStart, int nParentEnd, int * pFreeIdx, std::vector<PathInfo>::iterator iPathBase, std::vector<PathInfo>::iterator iPathEnd); 00354 00355 00356 00357 //---------------------------------------------------------- 00359 00360 //---------------------------------------------------------- 00362 Graph * _pGraph; 00363 00365 DataMap _MData; 00367 00368 }; 00369 00370 00371 00372 00373 00374 // ------------------------------------------------------------------ 00376 // ------------------------------------------------------------------ 00381 class VESSELGRAPH_EXPORT EdgeAnalyser 00382 { 00383 public: 00384 00385 //-------------------------------------------------------- 00387 00388 //-------------------------------------------------------- 00391 explicit EdgeAnalyser (long NMode, DataMap * pData = NULL); 00393 00394 00395 00396 //-------------------------------------------------------- 00398 00399 //-------------------------------------------------------- 00400 // function \c operator() provide singular outer access point 00401 inline void operator() (VesselEdge *pEdge){(this->*_actMeasure)(pEdge);} 00403 00404 00405 private: 00406 //-------------------------------------------------------- 00408 00409 //-------------------------------------------------------- 00411 void measureNothing(VesselEdge * /*pEdge*/) {} 00412 00415 void measureLength (VesselEdge *pEdge); 00416 00419 void measureVolume (VesselEdge *pEdge); 00420 00422 void measurePosition (VesselEdge *pEdge); 00423 00425 void averageMinDistance (VesselEdge *pEdge); 00426 00429 void measureST_Volume(VesselEdge *pEdge); 00430 00433 void measureST_Barycenter(VesselEdge *pEdge); 00434 00436 void measure_avSkeletonArea(VesselEdge *pEdge); 00437 00438 00441 void sumupST_NodeValue(VesselEdge *pEdge); 00442 00444 00445 //---------------------------------------------------------- 00447 00448 //---------------------------------------------------------- 00450 void (EdgeAnalyser::*_actMeasure) (VesselEdge *pEdge); 00451 00453 float _fVoxVolume; 00455 DataMap * _pData; 00457 long _NMode; 00459 }; 00460 00461 00462 00463 typedef enum { 00464 CMP_LENGTH, 00465 CMP_VOLUME, 00466 CMP_STVOLUME, 00467 CMP_STCENTER_X, 00468 CMP_STCENTER_Y, 00469 CMP_STCENTER_Z, 00470 CMP_STCENTER_PLANE, 00471 CMP_LABEL 00472 } CMP_FEATURE; 00473 00474 // ------------------------------------------------------------------ 00476 // ------------------------------------------------------------------ 00480 class compareEdges{ 00481 public: 00484 explicit compareEdges (CMP_FEATURE NFeature, Vector3 planeNormal = Vector3(0)){ 00485 _planeNormal = planeNormal; 00486 switch(NFeature){ 00487 case (CMP_LENGTH): 00488 _actComperator = &compareEdges::compareLength; 00489 break; 00490 case (CMP_VOLUME): 00491 _actComperator = &compareEdges::compareVolume; 00492 break; 00493 case (CMP_STVOLUME): 00494 _actComperator = &compareEdges::compareSTVolume; 00495 break; 00496 case (CMP_STCENTER_X): 00497 _actComperator = &compareEdges::compareSTCenterX; 00498 break; 00499 case (CMP_STCENTER_Y): 00500 _actComperator = &compareEdges::compareSTCenterY; 00501 break; 00502 case (CMP_STCENTER_Z): 00503 _actComperator = &compareEdges::compareSTCenterZ; 00504 break; 00505 case (CMP_STCENTER_PLANE): 00506 _actComperator = &compareEdges::compareSTCenterPlane; 00507 break; 00508 case (CMP_LABEL): 00509 default: 00510 _actComperator = &compareEdges::compareLabel; 00511 break; 00512 } 00513 } 00514 00515 int operator() (const VesselEdge *pE1, const VesselEdge *pE2) const 00516 { return (this->*_actComperator)(pE1, pE2); } 00517 00518 private: 00520 int (compareEdges::*_actComperator) (const VesselEdge *pE1, const VesselEdge *pE2) const; 00521 Vector3 _planeNormal; 00522 00523 int compareLabel (const VesselEdge *pE1, const VesselEdge *pE2) const { return pE1->getLabel() > pE2->getLabel(); } 00524 int compareLength (const VesselEdge *pE1, const VesselEdge *pE2) const { return pE1->getLength() > pE2->getLength(); } 00525 int compareVolume (const VesselEdge *pE1, const VesselEdge *pE2) const { return pE1->getVolume() > pE2->getVolume(); } 00526 int compareSTVolume (const VesselEdge *pE1, const VesselEdge *pE2) const { return pE1->getSTVolume() > pE2->getSTVolume(); } 00527 int compareSTCenterX (const VesselEdge *pE1, const VesselEdge *pE2) const { return (pE1->getSTBarycenter())[0] > (pE2->getSTBarycenter())[0]; } 00528 int compareSTCenterY (const VesselEdge *pE1, const VesselEdge *pE2) const { return (pE1->getSTBarycenter())[1] > (pE2->getSTBarycenter())[1]; } 00529 int compareSTCenterZ (const VesselEdge *pE1, const VesselEdge *pE2) const { return (pE1->getSTBarycenter())[2] > (pE2->getSTBarycenter())[2]; } 00530 int compareSTCenterPlane (const VesselEdge *pE1, const VesselEdge *pE2) const { return (pE1->getSTBarycenter()-pE2->getSTBarycenter()).dot(_planeNormal) > 0; } 00531 00532 }; 00533 00534 00535 // ------------------------------------------------------------------ 00537 // ------------------------------------------------------------------ 00542 class VESSELGRAPH_EXPORT NodeAnalyser 00543 { 00544 public: 00545 00546 //-------------------------------------------------------- 00548 00549 //-------------------------------------------------------- 00552 explicit NodeAnalyser (long NMode, DataMap * pData = NULL) : 00553 _actMeasure (&NodeAnalyser::doNothing), 00554 _pData(pData) 00555 { 00556 switch(NMode){ 00557 case PROC_ROOT: 00558 if(_pData != NULL){ 00559 if((*pData)[OUTDATA_ROOT] != NULL){ 00560 *((long *) (*pData)[OUTDATA_ROOT]) = 0; 00561 _fDist = 0.0; 00562 _actMeasure = &NodeAnalyser::suggestRoot; 00563 } 00564 } else { 00565 _actMeasure = &NodeAnalyser::doNothing; 00566 } 00567 break; 00568 case PROC_CLUSTER: 00569 if(_pData != NULL){ 00570 if((*pData)[OUTDATA_CLUSTER] != NULL){ 00571 _actMeasure = &NodeAnalyser::setClusterLabel; 00572 } 00573 } else { 00574 _actMeasure = &NodeAnalyser::doNothing; 00575 } 00576 break; 00577 default: 00578 _actMeasure = &NodeAnalyser::doNothing; 00579 } 00580 } 00582 00583 00584 //-------------------------------------------------------- 00586 00587 //-------------------------------------------------------- 00588 // function \c operator() provide singular outer access point 00589 inline void operator() (VesselNode *pNode){(this->*_actMeasure)(pNode);} 00591 00592 00593 private: 00594 //-------------------------------------------------------- 00596 00597 //-------------------------------------------------------- 00599 void doNothing (VesselNode * /*pNode*/) {} 00600 00602 void suggestRoot (VesselNode *pNode); 00603 00605 void setClusterLabel (VesselNode *pNode); 00607 00608 //---------------------------------------------------------- 00610 00611 //---------------------------------------------------------- 00613 void (NodeAnalyser::*_actMeasure) (VesselNode *pNode); 00614 00616 DataMap * _pData; 00617 00618 float _fDist; 00620 }; 00621 00622 // ------------------------------------------------------------------ 00624 // ------------------------------------------------------------------ 00631 class measureSkeletonAgent 00632 { 00633 00635 class Process 00636 { 00638 typedef void (measureSkeletonAgent::*ProcessFkt) (const Skeleton & oSkeleton, Process * pProcess); 00639 public: 00641 Process () : oProcess (&measureSkeletonAgent::doNothing), pResult (NULL) {} 00642 Process(const Process & oP) : oProcess (oP.oProcess), pResult(oP.pResult) {} 00643 00644 ProcessFkt oProcess; 00645 void *pResult; 00646 }; 00647 00649 friend class Process; 00650 00652 typedef std::map<NProcessMode, Process>::iterator IProcess; 00653 00654 public: 00655 00656 00657 //-------------------------------------------------------- 00659 00660 //-------------------------------------------------------- 00663 measureSkeletonAgent(int nMode, DataMap * pData = NULL) : 00664 _fLastLength(0.0), 00665 _pScale(NULL), 00666 _pData(pData) 00667 { 00668 _MProcess.erase(_MProcess.begin(), _MProcess.end()); 00669 00670 if(_pData != NULL){ 00671 if(nMode & PROC_LENGTH) 00672 { 00673 Process oProcess; 00674 oProcess.pResult = (*_pData)[OUTDATA_LENGTH]; 00675 if(nMode & PROC_SCL){ 00676 _pScale = (Vector3 *) (*_pData)[DATA_SCL]; 00677 oProcess.oProcess = &measureSkeletonAgent::ProcessL1Scale; 00678 } 00679 else { 00680 oProcess.oProcess =&measureSkeletonAgent::ProcessL1; 00681 } 00682 _MProcess[PROC_LENGTH] = oProcess; 00683 } 00684 00685 if(nMode & PROC_VOLUME) 00686 { 00687 Process oProcess; 00688 oProcess.pResult = (*_pData)[OUTDATA_VOLUME]; 00689 oProcess.oProcess = &measureSkeletonAgent::ProcessV1; 00690 _MProcess[PROC_VOLUME] = oProcess; 00691 } 00692 00693 if(nMode & PROC_WEIGHTED_POS) 00694 { 00695 Process oProcess; 00696 oProcess.pResult = (*_pData)[OUTDATA_POS]; 00697 oProcess.oProcess = &measureSkeletonAgent::ProcessP1; 00698 _MProcess[PROC_WEIGHTED_POS] = oProcess; 00699 } 00700 00701 if(nMode & PROC_AV_MIN_DIST) 00702 { 00703 Process oProcess; 00704 oProcess.pResult = (*_pData)[OUTDATA_AV_MIN_DIST]; 00705 oProcess.oProcess = &measureSkeletonAgent::ProcessD1; 00706 _MProcess[PROC_AV_MIN_DIST] = oProcess; 00707 } 00708 } 00709 } 00711 00712 00713 //-------------------------------------------------------- 00715 00716 //-------------------------------------------------------- 00718 inline void operator() (const Skeleton & oSkeleton) 00719 { 00720 for(IProcess iProcess = _MProcess.begin(); iProcess != _MProcess.end(); ++iProcess){ 00721 (this->*((iProcess->second).oProcess))(oSkeleton, &(iProcess->second)); 00722 } 00723 } 00724 inline void operator() (Skeleton* oSkeleton) 00725 { 00726 for(IProcess iProcess = _MProcess.begin(); iProcess != _MProcess.end(); ++iProcess){ 00727 (this->*((iProcess->second).oProcess))(*oSkeleton, &(iProcess->second)); 00728 } 00729 } 00731 00732 00733 00734 private: 00735 00736 //-------------------------------------------------------- 00738 00739 //-------------------------------------------------------- 00741 void doNothing (const Skeleton & /*oSkeleton*/, Process * /*pProcess*/) {} 00742 00745 void ProcessL1 (const Skeleton & oSkeleton, Process * pProcess); 00746 void ProcessL1Scale (const Skeleton & oSkeleton, Process * pProcess); 00748 void ProcessL2 (const Skeleton & oSkeleton, Process * pProcess); 00749 void ProcessL2Scale (const Skeleton & oSkeleton, Process * pProcess); 00751 void ProcessL3 (const Skeleton & oSkeleton, Process * pProcess); 00752 void ProcessL3Scale (const Skeleton & oSkeleton, Process * pProcess); 00753 00755 void ProcessV1 (const Skeleton & oSkeleton, Process * pProcess); 00756 00758 void ProcessP1 (const Skeleton & oSkeleton, Process * pProcess); 00759 00761 void ProcessD1 (const Skeleton & oSkeleton, Process * pProcess); 00762 00763 00765 00766 //---------------------------------------------------------- 00768 00769 //---------------------------------------------------------- 00771 std::map<NProcessMode, Process> _MProcess; 00772 00773 00775 float _fLastLength; 00776 00778 std::list<Vector3> _LPoints; 00780 std::list<Vector3>::iterator IBack; 00782 std::list<Vector3>::iterator IMiddle; 00784 std::list<Vector3>::iterator IFront; 00785 00786 // interpolated Skeleton position 00787 Vector3 _vMean; 00789 Vector3 * _pScale; 00790 00792 DataMap * _pData; 00794 }; 00795 00796 ML_END_NAMESPACE 00797 00798 #endif // __GRAPHANALYSER_H 00799 00800 00801 00802