//---------------------------------------------------------------------------- // EgalTech 2020-2020 //---------------------------------------------------------------------------- // File : MaximumFiller.cpp Data : 05.11.20 Versione : 2.2k1 // Contenuto : Classe per il calcolo del massimo riempimento (nesting 1D). // // // // Modifiche : 05.11.20 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "MaximumFiller.h" #include using namespace std ; // --------------------------------------------------------------------------- const double BIG_LEN = 10e6 ; const double EPSILON = 1e-3 ; const int MAX_COMB = 10000 ; //---------------------------------------------------------------------------- IMaximumFiller* CreateMaximumFiller( void) { return static_cast ( new(nothrow) MaximumFiller) ; } // --------------------------------------------------------------------------- bool MaximumFiller::Clear() { m_vpSou.clear() ; m_vpCurr.clear() ; m_vpBest.clear() ; return true ; } // --------------------------------------------------------------------------- bool MaximumFiller::AddPart( int nPartId, double dLen) { m_vpSou.emplace_back( nPartId, dLen, dLen, 1) ; return true ; } // --------------------------------------------------------------------------- bool MaximumFiller::AddPart( int nPartId, double dLen, double dDispLen, int nCount) { if ( nPartId <= 0 || dLen <= 0 || nCount <= 0) return false ; m_vpSou.emplace_back( nPartId, dLen, dDispLen, nCount) ; return true ; } // --------------------------------------------------------------------------- bool MaximumFiller::Compute( double dLenToFill, double dStartGap, double dMidGap, double dEndGap, int nSortType) { // inizializazioni m_dLenToFill = dLenToFill ; m_dStartGap = dStartGap ; m_dMidGap = dMidGap ; m_dEndGap = dEndGap ; m_dBestDim = BIG_LEN ; // riempimento del grezzo dLenToFill -= m_dStartGap + m_dEndGap ; m_nComb = 0 ; Fill( dLenToFill, 0) ; // se riempimento non riuscito if ( m_dBestDim > BIG_LEN - 1) return false ; // sistemo la soluzione ottimale for ( int i = 0 ; i < int( m_vpBest.size()) ; ++ i) { if ( m_vpBest[i].nId < 0 || m_vpBest[i].nId >= int( m_vpSou.size())) m_vpBest.resize( i) ; else { m_vpBest[i] = m_vpSou[ m_vpBest[i].nId] ; m_vpBest[i].nCount = 1 ; } } // se richiesto sort, lo eseguo if ( nSortType != 0) { for ( int i = 0 ; i < int( m_vpBest.size()) ; ++ i) { for ( int j = i + 1 ; j < int( m_vpBest.size()) ; ++ j) { bool bSwap ; // prima gli oggetti grandi (type 1) if ( nSortType == 1) bSwap = m_vpBest[i].dLen < m_vpBest[j].dLen ; // prima gli oggetti piccoli (type -1) else bSwap = m_vpBest[i].dLen > m_vpBest[j].dLen ; if ( bSwap) swap( m_vpBest[i], m_vpBest[j]) ; } } } // unisco pezzi consecutivi identici for ( int i = 0 ; i < int( m_vpBest.size()) - 1 ; ++ i) { if ( m_vpBest[i].nId == m_vpBest[i+1].nId) { m_vpBest[i].nCount += m_vpBest[i+1].nCount ; m_vpBest.erase( m_vpBest.begin() + i + 1) ; -- i ; } } return true ; } // --------------------------------------------------------------------------- void MaximumFiller::Fill( double dLen, int nPos) { ++ m_nComb ; if ( m_nComb > MAX_COMB) return ; if ( dLen < m_dBestDim - EPSILON) { m_dBestDim = dLen ; m_vpBest = m_vpCurr ; } // se necessario, aggiungo un pezzo if ( int( m_vpCurr.size()) <= nPos) m_vpCurr.emplace_back( -1, 0., 0., 1) ; // tolgo distanza tra pezzi if ( nPos > 0) dLen -= m_dMidGap ; for ( int i = 0 ; i < int( m_vpSou.size()) ; ++ i) { // se ci stà lo aggiungo if ( dLen > m_vpSou[i].dDispLen && dLen > m_vpSou[i].dLen && m_vpSou[i].nCount > 0) { -- m_vpSou[i].nCount ; m_vpCurr[nPos].nId = i ; // per ora scrivo la posizione poi scriverò il valore corretto Fill( dLen - m_vpSou[i].dLen, nPos + 1) ; ++ m_vpSou[i].nCount ; } } m_vpCurr[nPos].nId = -1 ; } // --------------------------------------------------------------------------- bool MaximumFiller::GetResults( int& nFilledParts, int& nDiffParts, double& dTotFillRatio) const { nFilledParts = 0 ; nDiffParts = 0 ; double dFilledLen = 0 ; for ( int i = 0 ; i < int( m_vpBest.size()) ; ++ i) { nFilledParts += m_vpBest[i].nCount ; nDiffParts += 1 ; dFilledLen += m_vpBest[i].nCount * m_vpBest[i].dLen ; } dTotFillRatio = dFilledLen / m_dLenToFill ; return true ; } // --------------------------------------------------------------------------- bool MaximumFiller::GetOneResult( int nInd, int& nPartId, int& nCount) const { if ( nInd < 0 || nInd >= int( m_vpBest.size())) return false ; nPartId = m_vpBest[nInd].nId ; nCount = m_vpBest[nInd].nCount ; return true ; }