BOOL CPFAOptimize::FindBaseCircle( ComponentManager& ComManager, Pipe& BasePipe, BaseCircleDirection Direction, ComMap& JunKeyMap, ComMap& PipeKeyMap, int iMostCircle[] ) { //参数有效性判断 ASSERT( NULL != &ComManager ); ASSERT( NULL != &BasePipe ); ComAndCloseComs JunAndCloseJuns; JunAndCenter CloseJuns; // 记录节点和节点位置的Vector,形式如(节点编号,节点位置) Jun* pJun = NULL; Component* pJunComponent = NULL; Pipe* pPipe = NULL; Component* pPipeComponent = NULL; Jun* pPreJun = NULL; Jun* pNextJun = NULL; Jun* pStartJun = NULL; Jun* pStartNextJun = NULL; // 图形的上、左、右、下四个顶点的位置,为确定最大环做准备 int iTop = 2147483647; // 2的32次方减一 int iLeft = 2147483647; int iRight = 0; int iBotton = 0; IteratorPtr<Component> JunItPtr( ComManager.CreatJunIterator() ); // 把节点和与节点相连的节点信息都放入JunAndCloseJuns // 如节点1和节点3,4,5相连,则( 1, ( (3,节点3位置), (4,节点4位置), (5,节点5位置) ) ) // 然后把管道和与管道相连的管道编号放入PipeAndClosePipes // 如管道1和管道3,4,5相连,则(1,(3,4,5)) for( JunItPtr->Fist(); !JunItPtr->IsDone(); JunItPtr->Next() ) { CloseJuns.clear(); pJunComponent = &JunItPtr->CurrentItem(); pJun = dynamic_cast<Jun*>( pJunComponent ); IteratorPtr<Component> PipeItPtr( ComManager.CreatPipeIterator() ); for( PipeItPtr->Fist(); !PipeItPtr->IsDone(); PipeItPtr->Next() ) { pPipeComponent = &PipeItPtr->CurrentItem(); pPipe = dynamic_cast<Pipe*>( pPipeComponent ); if( pPipe->StartJun() == pJun->GetKey() ) { pair< int , CPoint > Temp( pPipe->EndJun(), pPipe->EndPt() ); CloseJuns.push_back( Temp ); } if( pPipe->EndJun() == pJun->GetKey() ) { pair< int , CPoint > Temp( pPipe->StartJun(), pPipe->StartPt() ); CloseJuns.push_back( Temp ); } if( pPipe->GetKey() == BasePipe.GetKey() ) { if ( DEASIL_DIRECTION == Direction ) { pPreJun = ComManager.LookUpJun( pPipe->StartJun() ); pNextJun = ComManager.LookUpJun( pPipe->EndJun() ); } else { pPreJun = ComManager.LookUpJun( pPipe->EndJun() ); pNextJun = ComManager.LookUpJun( pPipe->StartJun() ); } } } JunAndCloseJuns.insert( ComAndCloseComs::value_type( pJun->GetKey(), CloseJuns ) ); // 确定四个顶点 if( iTop > pJun->CenterPt().y ) { iTop = pJun->CenterPt().y; iMostCircle[0] = pJun->GetKey(); } if( iBotton < pJun->CenterPt().y ) { iBotton = pJun->CenterPt().y; iMostCircle[1] = pJun->GetKey(); } if( iLeft > pJun->CenterPt().x ) { iLeft = pJun->CenterPt().x; iMostCircle[2] = pJun->GetKey(); } if( iRight < pJun->CenterPt().x ) { iRight = pJun->CenterPt().x; iMostCircle[3] = pJun->GetKey(); } } JunItPtr->Fist(); pJunComponent = &JunItPtr->CurrentItem(); pJun = dynamic_cast<Jun*>( pJunComponent ); CloseJuns.clear(); ComAndCloseComs::iterator JunIt = JunAndCloseJuns.find( pJun->GetKey() ); CopyVector( CloseJuns, JunIt->second ); // 寻找环—节点矩阵 pStartJun = pPreJun; pStartNextJun = pNextJun; int iKeyOfChoiceJun = 0; // 用来标记哪个节点编号作为基环的下一节点编号 JunKeyMap.push_back( pNextJun->GetKey() ); BOOL bFirst = TRUE; while( ( pNextJun != pStartNextJun ) || ( pPreJun != pStartJun ) || bFirst ) { bFirst = FALSE; FindJunOfCircle( *pPreJun, *pNextJun, JunAndCloseJuns, iKeyOfChoiceJun ); pPreJun = pNextJun; pNextJun = ComManager.LookUpJun( iKeyOfChoiceJun ); JunKeyMap.push_back( pNextJun->GetKey() ); } // 寻找环—管道矩阵 ComMap::const_iterator JunKeyNextIterator = NULL; int iJunNextkey = 0; // 上面的环-节点矩阵中节点的编号, 下面的也一样 int iJunPreKey = 0; map< int, int > PipeOrder; // (管道在环中的位置,管道编号) int iPipePosition = 0; // 管道在环中的位置 IteratorPtr<Component> PipeItPtr( ComManager.CreatPipeIterator() ); for( PipeItPtr->Fist(); !PipeItPtr->IsDone(); PipeItPtr->Next() ) { pPipeComponent = &PipeItPtr->CurrentItem(); pPipe = dynamic_cast<Pipe*>( pPipeComponent ); JunKeyNextIterator = JunKeyMap.begin(); iPipePosition = 0; iJunPreKey = *JunKeyNextIterator; JunKeyNextIterator++; for ( ; JunKeyNextIterator != JunKeyMap.end(); JunKeyNextIterator++ ) { iJunNextkey = *JunKeyNextIterator; // 如果管道和环里的相邻节点相连,那么这根管道肯定是环里的管道 if( ( ( pPipe->StartJun() == iJunPreKey ) && ( pPipe->EndJun() == iJunNextkey ) )) { PipeOrder.insert( map<int,int>::value_type( iPipePosition, pPipe->GetKey() ) ); } if( ( ( pPipe->EndJun() == iJunPreKey ) && ( pPipe->StartJun() == iJunNextkey ) ) ) { int i = -1 * pPipe->GetKey(); PipeOrder.insert( map<int,int>::value_type( iPipePosition, i ) ); } iJunPreKey = iJunNextkey; iPipePosition++; } } // 把PipeOrder里的信息放入PipeKeyMap中 // PipeOrder信息(管道在环中的位置,管道的编号) int iCountCircleJun = PipeOrder.size(); int iPipeKey = 0; map< int, int >::iterator PipeIterator = NULL; for ( iPipePosition = 0, iPipeKey = 0; iPipePosition < iCountCircleJun; iPipePosition++ ) { PipeIterator = PipeOrder.find( iPipePosition ); if( PipeIterator == PipeOrder.end() ) { break; } iPipeKey = PipeIterator->second; PipeKeyMap.push_back( iPipeKey ); } return TRUE; }
// 最短路径,Dijkstra算法,网上抄的, 可能有点乱 bool CPFAOptimize::FindShortCut( ComponentManager& ComManager, const int& iKeyOfStartJun, const int& iKeyOfEndJun, vector< int >& JunToJunPipePath ) { map< int, vector< int > > AbutMatrix; //图的邻接矩 vector< int > MarkVector; //标记数组 vector< int > DistanceVector; //距离数组 vector< int > TempVector; //前缀节点 vector< int > PipePathVector; //临时路径存放数组 int iCountOfJun = ComManager.GetJunNum(); int iCountOfPipe = ComManager.GetPipeNum(); int iTemp = 0; int i = 0; int j = 0; int k = 0; int iMinDistance = 0; //读入数据 Component *pComponent = NULL; Pipe *pPipe = NULL; int iStartJun = 0; int iEndJun = 0; IteratorPtr<Component> PipeItPtr( ComManager.CreatPipeIterator() ); for( PipeItPtr->Fist(); !PipeItPtr->IsDone(); PipeItPtr->Next() ) { pComponent = &PipeItPtr->CurrentItem(); pPipe = dynamic_cast<Pipe*>(pComponent); iStartJun = pPipe->StartJun(); iEndJun = pPipe->EndJun(); SetProperties( AbutMatrix, iStartJun, iEndJun, 1 ); SetProperties( AbutMatrix, iEndJun, iStartJun, 1); } //赋初值 SetProperties( MarkVector, iKeyOfStartJun, 1 ); SetProperties( TempVector, iKeyOfStartJun, 0 ); for( i = 1; i <= iCountOfJun; i++ ) { iTemp = GetProperties( AbutMatrix, 1, i ); SetProperties( DistanceVector, i, iTemp ); if( 0 < iTemp ) { SetProperties( TempVector, i, 1 ); } } //Dijkstra for( i = 0; i <= iCountOfJun; i++ ) { //找到没有标号的最小dist下标 iMinDistance = 32000; k = 0; for( j = 1; j <= iCountOfJun; j++ ) { if( ( 0 == GetProperties( MarkVector, j ) ) && ( 0 < GetProperties( DistanceVector, j ) ) && ( iMinDistance > GetProperties( DistanceVector, j ) ) ) { k = j; iMinDistance = GetProperties( DistanceVector, j ); } } if( 0 == k ) //如果找不到就直接退出 { break; } SetProperties( MarkVector, k, 1 ); //标记 //修改最短值和路径 for( j = 1; j <= iCountOfJun; j++ ) { if( ( 0 == GetProperties( MarkVector, j ) ) && ( 0 < GetProperties( AbutMatrix, k, j ) ) && ( ( 0 == GetProperties( DistanceVector, j ) ) || ( GetProperties( DistanceVector, k ) + GetProperties( AbutMatrix, k, j ) < GetProperties( DistanceVector, j ) ) ) ) { iTemp = GetProperties( DistanceVector, k ) + GetProperties( AbutMatrix, k, j ); SetProperties( DistanceVector, j, iTemp ); SetProperties( TempVector, j, k ); } } } //输出值和路径 k = iKeyOfEndJun; i = 0; while( 0 < GetProperties( TempVector, k ) ) { SetProperties( PipePathVector, i++, k ); k = GetProperties( PipePathVector, k ); } SetProperties( PipePathVector, i, 1 ); // 根据节点把管道编号写进里,负号表示管道方向与前进方向相反 JunToJunPipePath.clear(); vector< int >::iterator IntVecIt = PipePathVector.begin(); iStartJun = *IntVecIt; IntVecIt++; for( ; PipePathVector.end() != IntVecIt; IntVecIt++ ) { iEndJun = *IntVecIt; for( PipeItPtr->Fist(); !PipeItPtr->IsDone(); PipeItPtr->Next() ) { pComponent = &PipeItPtr->CurrentItem(); pPipe = dynamic_cast<Pipe*>(pComponent); if( ( pPipe->StartJun() == iStartJun ) && ( pPipe->EndJun() == iEndJun ) ) { JunToJunPipePath.push_back( pPipe->GetKey() ); break; } if( ( pPipe->StartJun() == iEndJun ) && ( pPipe->EndJun() == iStartJun ) ) { JunToJunPipePath.push_back( -1 * pPipe->GetKey() ); break; } } iStartJun = iEndJun; } return true; }