74d34fcd1e
- aggiunta classe MaximumFiller che risolve il problema del Nesting 1D.
184 lines
5.3 KiB
C++
184 lines
5.3 KiB
C++
//----------------------------------------------------------------------------
|
|
// 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 <new>
|
|
|
|
using namespace std ;
|
|
|
|
// ---------------------------------------------------------------------------
|
|
const double BIG_LEN = 10e6 ;
|
|
const double EPSILON = 1e-3 ;
|
|
const int MAX_COMB = 10000 ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
IMaximumFiller*
|
|
CreateMaximumFiller( void)
|
|
{
|
|
return static_cast<IMaximumFiller*> ( 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 ;
|
|
}
|