Files
EgtNumKernel/MaximumFiller.cpp
DarioS 6cc9302660 EgtNumKernel 2.4g1 :
- miglioria a nesting dei lineari (MaximumFiller).
2022-08-01 19:49:26 +02:00

189 lines
5.6 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>
#include <algorithm>
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)
{
// sort dei pezzi sorgenti in ordine decrescente di lunghezza
sort( m_vpSou.begin(), m_vpSou.end(),
[]( const Part& a, const Part& b) { return ( max( a.dLen, a.dDispLen) > max( b.dLen, b.dDispLen)) ; }) ;
// inizializazioni
m_dLenToFill = max( dLenToFill, 0.) ;
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 = ( m_dLenToFill > EPSILON ? dFilledLen / m_dLenToFill : 0) ;
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 ;
}