EgtNumKernel :

- in Machining Optimization aggiunta gestione OpenBounds.
This commit is contained in:
Riccardo Elitropi
2025-12-17 15:03:14 +01:00
parent f258acefd0
commit 0efb3082d0
2 changed files with 239 additions and 154 deletions
+217 -139
View File
@@ -60,6 +60,7 @@ MachOptimization::MachOptimization( void)
m_dFeedA = 1. ;
m_bAllMandatory = false ;
m_bOptInGroup = false ;
m_vOpenBounds.clear() ;
}
//----------------------------------------------------------------------------
@@ -242,6 +243,44 @@ MachOptimization::SetOptimizationForGroups( bool bOptForGroups)
return true ;
}
//-----------------------------------------------------------------------------
bool
MachOptimization::SetOpenBound( bool bStartVsEnd, int nFlag, double dX, double dY, double dZ)
{
// Se parametro Start o End già impostato, lo sovrascrivo
for ( int i = 0 ; i < int( m_vOpenBounds.size()) ; ++ i) {
if ( m_vOpenBounds[i].bStartVsEnd == bStartVsEnd) {
m_vOpenBounds[i].nFlag = nFlag ;
m_vOpenBounds[i].dX = dX ;
m_vOpenBounds[i].dY = dY ;
m_vOpenBounds[i].dZ = dZ ;
return true ;
}
}
// altrimenti lo inserisco
m_vOpenBounds.emplace_back( -1, bStartVsEnd, nFlag, dX, dY, dZ) ;
return true ;
}
//----------------------------------------------------------------------------
bool
MachOptimization::SetOpenBoundForGroups( int nGroup, bool bStartVsEnd, int nFlag, double dX, double dY, double dZ)
{
// Se parametro Start o End del Gruppo scelto già impostato, lo sovrascrivo
for ( int i = 0 ; i < int( m_vOpenBounds.size()) ; ++ i) {
if ( m_vOpenBounds[i].nGroup == nGroup && m_vOpenBounds[i].bStartVsEnd == bStartVsEnd) {
m_vOpenBounds[i].nFlag = nFlag ;
m_vOpenBounds[i].dX = dX ;
m_vOpenBounds[i].dY = dY ;
m_vOpenBounds[i].dZ = dZ ;
return true ;
}
}
// altrimenti lo inserisco
m_vOpenBounds.emplace_back( nGroup, bStartVsEnd, nFlag, dX, dY, dZ) ;
return true ;
}
//----------------------------------------------------------------------------
/* Funzione che assegna le dipendenze suggerite in base ai Gruppi */
bool
@@ -290,7 +329,8 @@ MachOptimization::SetGroupDependences( void)
//----------------------------------------------------------------------------
/* Funzione per il controllo delle dipendenze inserite : se già presenti o se in conflitto */
bool
MachOptimization::CheckDependences( int nIdPrev, int nIdNext, const INTINTVECTOR& vDep, bool bBlockMessages, bool& bExist, bool& bConflict)
MachOptimization::CheckDependences( int nIdPrev, int nIdNext, const INTINTVECTOR& vDep,
bool bBlockMessages, bool& bExist, bool& bConflict) const
{
bExist = false ;
bConflict = false ;
@@ -334,7 +374,7 @@ MachOptimization::CheckDependences( int nIdPrev, int nIdNext, const INTINTVECTOR
/* Funzione per il calcolo della distanza euclidea tra assi Lineari o Angolari di due lavorazioni
Considerando lo stesso utensile */
double
MachOptimization::CalcTimeLavLav( const MachOptm& Lav1, const MachOptm& Lav2, bool bLin)
MachOptimization::CalcTimeLavLav( const MachOptm& Lav1, const MachOptm& Lav2, bool bLin) const
{
double dDist = 0. ;
double dFeed = EPS_SMALL ;
@@ -361,7 +401,7 @@ MachOptimization::CalcTimeLavLav( const MachOptm& Lav1, const MachOptm& Lav2, bo
bool
MachOptimization::CalcTimeLavLavTC( const MachOptm& Lav1, const MachOptm& Lav2, bool bLin,
double& dTimeLav1TC1, double& dTimeTC1TC2, double& dTimeTC2Lav2,
double& dTUnload1, double& dTLoad2)
double& dTUnload1, double& dTLoad2) const
{
/*
dTimeLav1TC1 : Tempo tra EndPoint di Lav1 e Posizione di TC per Utensile di Lav1
@@ -466,7 +506,7 @@ MachOptimization::CalcTimeLavLavTC( const MachOptm& Lav1, const MachOptm& Lav2,
/* Funzione per calcolare il tempo nel passare dalla lavorazione nInd1-esima alla lavorazione
nInd2-esima */
bool
MachOptimization::CalcMachTime( int nInd1, int nInd2, int& nTime)
MachOptimization::CalcMachTime( int nInd1, int nInd2, int& nTime) const
{
// Se Indice fuori dal range, errore
nTime = 0 ;
@@ -475,8 +515,8 @@ MachOptimization::CalcMachTime( int nInd1, int nInd2, int& nTime)
return false ;
// Recupero riferimento delle due lavorazioni
MachOptm& Lav1 = m_vMachOptm[nInd1] ;
MachOptm& Lav2 = m_vMachOptm[nInd2] ;
const MachOptm& Lav1 = m_vMachOptm[nInd1] ;
const MachOptm& Lav2 = m_vMachOptm[nInd2] ;
return ( CalcMachTime( Lav1, Lav2, nTime)) ;
}
@@ -484,7 +524,7 @@ MachOptimization::CalcMachTime( int nInd1, int nInd2, int& nTime)
//----------------------------------------------------------------------------
/* Funzione per calcolare il tempo nel passare da una lavorazione all'altra */
bool
MachOptimization::CalcMachTime( const MachOptm& Lav1, const MachOptm& Lav2, int& nTime)
MachOptimization::CalcMachTime( const MachOptm& Lav1, const MachOptm& Lav2, int& nTime) const
{
// Se l'utensile è lo stesso
if ( Lav1.nIdTool == Lav2.nIdTool)
@@ -508,7 +548,7 @@ MachOptimization::CalcMachTime( const MachOptm& Lav1, const MachOptm& Lav2, int&
//----------------------------------------------------------------------------
/* Funzione per il calcolo della Matrice dei tempi (NxN), dove N = #Lavorazioni */
bool
MachOptimization::ComputeTimeMatrix( INTMATRIX& mTimes)
MachOptimization::ComputeTimeMatrix( INTMATRIX& mTimes) const
{
// Creo una copia dei vettori delle dipendenze ( le cancello di volta in volta che le assegno)
const int N = int( m_vMachOptm.size()) ;
@@ -578,7 +618,7 @@ MachOptimization::ComputeTimeMatrix( INTMATRIX& mTimes)
//----------------------------------------------------------------------------
/* Funzione che restituisce la posizione della lavorazione di Id pari a nId nel vettore delle lavorazioni */
int
MachOptimization::GetIndById( int nId)
MachOptimization::GetIndById( int nId) const
{
// Scorro le lavorazioni
for ( int i = 0 ; i < int( m_vMachOptm.size()) ; ++ i) {
@@ -654,135 +694,114 @@ MachOptimization::SplitMachOptsInGroups( MACHOPTMMATRIX& matMachOpt, vector<INTI
//----------------------------------------------------------------------------
bool
MachOptimization::GetResult( INTVECTOR& vIds)
MachOptimization::GetGlobalResult( INTVECTOR& vIds)
{
// Se non ho lavorazioni, allora non faccio nulla
vIds.clear() ;
if ( m_vMachOptm.empty())
return true ;
// Se ho una sola lavorazione allora ritorno se stessa
if ( int( m_vMachOptm.size()) == 1) {
vIds.push_back( m_vMachOptm[0].nId) ;
return true ;
// Inserisco le lavorazioni per ordine di inserimento
for ( const MachOptm& myLav : m_vMachOptm)
vIds.push_back( myLav.nId) ;
// Inizializzo le dipendenze suggerite dai gruppi di lavorazione
if ( ! SetGroupDependences()) {
LOG_ERROR( GetENkLogger(), "Error in defining Group depedences") ;
return false ;
}
// --- Se richiesta ottimizzazione solo interna per i gruppi
if ( m_bOptInGroup) {
// Recupero tutti i gruppi e le dipendenze separatamente ed ordinate per priorità di gruppo
MACHOPTMMATRIX matMachOpt ;
vector<INTINTVECTOR> matDep, matSuggDep ;
if ( ! SplitMachOptsInGroups( matMachOpt, matDep, matSuggDep))
return false ;
// Per ognuna di esse eseguo l'algoritmo di ShortestPath
MachOptm LastMach ;
for ( int i = 0 ; i < int( matMachOpt.size()) ; ++ i) {
m_vMachOptm.clear() ;
m_vDependences.clear() ;
m_vSuggDependences.clear() ;
if ( matMachOpt.empty())
continue ;
m_vMachOptm = matMachOpt[i] ;
m_vDependences = matDep[i] ;
m_vSuggDependences = matSuggDep[i] ;
// Calcolo la matrice dei tempi
INTMATRIX mTimes ;
if ( ! ComputeTimeMatrix( mTimes)) {
LOG_ERROR( GetENkLogger(), "Error in Computing Time Matrix") ;
return false ;
}
// Istanzio il Problema ShortesPath con vincoli
PtrOwner<IShortestPath> mySP( CreateShortestPath()) ;
if ( IsNull( mySP))
return false ;
// Per ogni lavorazione inserisco gli estremi
for ( const MachOptm& Lav : m_vMachOptm) {
if ( ! mySP->AddPoint( Lav.dX_Start, Lav.dY_Start, Lav.dZ_End, 0., 0.,
Lav.dX_End, Lav.dY_End, Lav.dZ_End, 0., 0.)) {
LOG_ERROR( GetENkLogger(), "Error adding Machining Bounds") ;
return false ;
}
}
// Assegno la matrice delle distanze calcolata in precedenza
if ( ! mySP->SetDistMatrix( mTimes)) {
LOG_ERROR( GetENkLogger(), "Error setting distances matrix") ;
return false ;
}
// Se ho una lavorazione impostata in precedenza
if ( LastMach.nId != -1) {
// Cerco le lavorazioni che non presentano precedenze
MACHOPTMVECTOR vLav ; vLav.reserve( m_vMachOptm.size()) ;
if ( m_vDependences.empty())
vLav = m_vMachOptm ;
else {
INTSET setSecondDep ;
for ( const INTINT& Dep : m_vDependences)
setSecondDep.insert( Dep.second) ;
for ( int i = 0 ; i < int( m_vMachOptm.size()) ; ++ i) {
if ( setSecondDep.find( m_vMachOptm[i].nId) == setSecondDep.end())
vLav.emplace_back( m_vMachOptm[i]) ;
}
}
// Tra quelle valide cerco la migliore da cui partire
int nBestLavId = 0 ;
int nBestTime = MAXTIME ;
for ( int i = 0 ; i < int( vLav.size()) ; ++ i) {
int nCurrTime = MAXTIME ;
CalcMachTime( LastMach, vLav[i], nCurrTime) ;
if ( nCurrTime < nBestTime) {
nBestTime = nCurrTime ;
nBestLavId = vLav[i].nId ;
}
}
// Imposto la prima lavorazione
if ( ! SetFirstMachining( nBestLavId))
return false ;
}
// Per ogni dipendeza obbligatoria assegno un vincolo
for ( const INTINT& nnDep : m_vDependences) {
if ( ! mySP->SetConstraintOrder( GetIndById( nnDep.first), GetIndById( nnDep.second))) {
LOG_ERROR( GetENkLogger(), "Error in adding Constraints") ;
return false ;
}
}
// Aggiungo le dipendenza suggerite
for ( const INTINT& nnSuggDep : m_vSuggDependences) {
if ( ! mySP->SetSuggestedOrder( GetIndById( nnSuggDep.first), GetIndById( nnSuggDep.second))) {
LOG_ERROR( GetENkLogger(), "Error in adding Suggested Dependence") ;
return false ;
}
}
// Calcolo la soluzione
#if _TIME_DEBUG
PerformanceCounter PC ; PC.Start() ;
#endif
if ( ! mySP->Calculate( IShortestPath::SP_OPEN)) {
LOG_ERROR( GetENkLogger(), "Error in computing solution") ;
return false ;
}
// Recupero l'ordine
INTVECTOR U ;
if ( ! mySP->GetOrder( U)) {
LOG_ERROR( GetENkLogger(), "Error in ordering") ;
return false ;
}
// Restituisco gli Id ordinati
for ( int nInd = 0 ; nInd < int( U.size()) ; ++ nInd)
vIds.emplace_back( m_vMachOptm[U[nInd]].nId) ;
// Memorizzo l'ultima lavorazione per il gruppo successivo
LastMach = ( U.empty() ? MachOptm() : m_vMachOptm[U.back()]) ;
}
// Calcolo la matrice dei tempi
INTMATRIX mTimes ;
if ( ! ComputeTimeMatrix( mTimes)) {
LOG_ERROR( GetENkLogger(), "Error in Computing Time Matrix") ;
return false ;
}
//--- Se invece ottimizzazione globale
else {
// Inserisco le lavorazioni per ordine di inserimento
for ( const MachOptm& myLav : m_vMachOptm)
vIds.push_back( myLav.nId) ;
// Inizializzo le dipendenze suggerite dai gruppi di lavorazione
if ( ! SetGroupDependences()) {
LOG_ERROR( GetENkLogger(), "Error in defining Group depedences") ;
// Istanzio il Problema ShortesPath con vincoli
PtrOwner<IShortestPath> mySP( CreateShortestPath()) ;
if ( IsNull( mySP))
return false ;
// Per ogni lavorazione inserisco gli estremi
for ( const MachOptm& Lav : m_vMachOptm) {
if ( ! mySP->AddPoint( Lav.dX_Start, Lav.dY_Start, Lav.dZ_End, 0., 0.,
Lav.dX_End, Lav.dY_End, Lav.dZ_End, 0., 0.)) {
LOG_ERROR( GetENkLogger(), "Error adding Machining Bounds") ;
return false ;
}
}
// Assegno la matrice delle distanze calcolata in precedenza
if ( ! mySP->SetDistMatrix( mTimes)) {
LOG_ERROR( GetENkLogger(), "Error setting distances matrix") ;
return false ;
}
// Per ogni dipendeza obbligatoria assegno un vincolo
for ( const INTINT& nnDep : m_vDependences) {
if ( ! mySP->SetConstraintOrder( GetIndById( nnDep.first), GetIndById( nnDep.second))) {
LOG_ERROR( GetENkLogger(), "Error in adding Constraints") ;
return false ;
}
}
// Aggiungo le dipendenza suggerite
for ( const INTINT& nnSuggDep : m_vSuggDependences) {
if ( ! mySP->SetSuggestedOrder( GetIndById( nnSuggDep.first), GetIndById( nnSuggDep.second))) {
LOG_ERROR( GetENkLogger(), "Error in adding Suggested Dependence") ;
return false ;
}
}
// Se presenti dei incoli di OpenBound, li assegno
if ( ! m_vOpenBounds.empty()) {
for ( const OpenBoundOptm& OB : m_vOpenBounds) {
if ( OB.nGroup == -1) {
if ( ! mySP->SetOpenBound( OB.bStartVsEnd, OB.nFlag, OB.dX, OB.dY, OB.dZ, 0., 0.)) {
LOG_ERROR( GetENkLogger(), "Error in adding OpenBound") ;
return false ;
}
}
}
}
// Calcolo la soluzione
#if _TIME_DEBUG
PerformanceCounter PC ; PC.Start() ;
#endif
if ( ! mySP->Calculate( IShortestPath::SP_OPEN)) {
LOG_ERROR( GetENkLogger(), "Error in computing solution") ;
return false ;
}
#if _TIME_DEBUG
string sTime = string( to_string( m_vDependences.size()) + string( "Time : ") + ToString( PC.Stop())) ;
LOG_INFO( GetENkLogger(), sTime.c_str()) ;
#endif
// Recupero l'ordine
INTVECTOR U ;
if ( ! mySP->GetOrder( U)) {
LOG_ERROR( GetENkLogger(), "Error in ordering") ;
return false ;
}
// Restituisco gli Id ordinati
vIds.resize( m_vMachOptm.size()) ;
for ( int nInd = 0 ; nInd < int( U.size()) ; ++ nInd)
vIds[nInd] = m_vMachOptm[U[nInd]].nId ;
return true ;
}
//----------------------------------------------------------------------------
bool
MachOptimization::GetGroupResult( INTVECTOR& vIds)
{
// Se Flag ottimizzazione di gruppo non attivo, errore
if ( ! m_bOptInGroup)
return false ;
// Recupero tutti i gruppi e le dipendenze separatamente ed ordinate per priorità di gruppo
MACHOPTMMATRIX matMachOpt ;
vector<INTINTVECTOR> matDep, matSuggDep ;
if ( ! SplitMachOptsInGroups( matMachOpt, matDep, matSuggDep))
return false ;
// Per ognuna di esse eseguo l'algoritmo di ShortestPath
MachOptm LastMach ;
for ( int i = 0 ; i < int( matMachOpt.size()) ; ++ i) {
m_vMachOptm.clear() ;
m_vDependences.clear() ;
m_vSuggDependences.clear() ;
if ( matMachOpt.empty())
continue ;
m_vMachOptm = matMachOpt[i] ;
m_vDependences = matDep[i] ;
m_vSuggDependences = matSuggDep[i] ;
// Calcolo la matrice dei tempi
INTMATRIX mTimes ;
if ( ! ComputeTimeMatrix( mTimes)) {
@@ -806,6 +825,47 @@ MachOptimization::GetResult( INTVECTOR& vIds)
LOG_ERROR( GetENkLogger(), "Error setting distances matrix") ;
return false ;
}
// Se presente un vincolo OpenBound lo assegno
bool bForStart = false ;
for ( const OpenBoundOptm& OB : m_vOpenBounds) {
if ( OB.nGroup == m_vMachOptm[0].nGroup) {
bForStart = ( bForStart || OB.bStartVsEnd) ;
if ( ! mySP->SetOpenBound( OB.bStartVsEnd, OB.nFlag, OB.dX, OB.dY, OB.dZ, 0., 0.)) {
LOG_ERROR( GetENkLogger(), "Error in adding OpenBound") ;
return false ;
}
}
}
// Se ho una lavorazione impostata in precedenza e nessun vincolo OpenBound
if ( ! bForStart && LastMach.nId != -1) {
// Cerco le lavorazioni che non presentano precedenze
MACHOPTMVECTOR vLav ; vLav.reserve( m_vMachOptm.size()) ;
if ( m_vDependences.empty())
vLav = m_vMachOptm ;
else {
INTSET setSecondDep ;
for ( const INTINT& Dep : m_vDependences)
setSecondDep.insert( Dep.second) ;
for ( int i = 0 ; i < int( m_vMachOptm.size()) ; ++ i) {
if ( setSecondDep.find( m_vMachOptm[i].nId) == setSecondDep.end())
vLav.emplace_back( m_vMachOptm[i]) ;
}
}
// Tra quelle valide cerco la migliore da cui partire
int nBestLavId = 0 ;
int nBestTime = MAXTIME ;
for ( int i = 0 ; i < int( vLav.size()) ; ++ i) {
int nCurrTime = MAXTIME ;
CalcMachTime( LastMach, vLav[i], nCurrTime) ;
if ( nCurrTime < nBestTime) {
nBestTime = nCurrTime ;
nBestLavId = vLav[i].nId ;
}
}
// Imposto la prima lavorazione
if ( ! SetFirstMachining( nBestLavId))
return false ;
}
// Per ogni dipendeza obbligatoria assegno un vincolo
for ( const INTINT& nnDep : m_vDependences) {
if ( ! mySP->SetConstraintOrder( GetIndById( nnDep.first), GetIndById( nnDep.second))) {
@@ -828,10 +888,6 @@ MachOptimization::GetResult( INTVECTOR& vIds)
LOG_ERROR( GetENkLogger(), "Error in computing solution") ;
return false ;
}
#if _TIME_DEBUG
string sTime = string( to_string( m_vDependences.size()) + string( "Time : ") + ToString( PC.Stop())) ;
LOG_INFO( GetENkLogger(), sTime.c_str()) ;
#endif
// Recupero l'ordine
INTVECTOR U ;
if ( ! mySP->GetOrder( U)) {
@@ -839,10 +895,32 @@ MachOptimization::GetResult( INTVECTOR& vIds)
return false ;
}
// Restituisco gli Id ordinati
vIds.resize( m_vMachOptm.size()) ;
for ( int nInd = 0 ; nInd < int( U.size()) ; ++ nInd)
vIds[nInd] = m_vMachOptm[U[nInd]].nId ;
vIds.emplace_back( m_vMachOptm[U[nInd]].nId) ;
// Memorizzo l'ultima lavorazione per il gruppo successivo
LastMach = ( U.empty() ? MachOptm() : m_vMachOptm[U.back()]) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachOptimization::GetResult( INTVECTOR& vIds)
{
// Se non ho lavorazioni, allora non faccio nulla
vIds.clear() ;
if ( m_vMachOptm.empty())
return true ;
// Se ho una sola lavorazione allora ritorno se stessa
if ( int( m_vMachOptm.size()) == 1) {
vIds.push_back( m_vMachOptm[0].nId) ;
return true ;
}
// --- Se richiesta ottimizzazione solo interna per i gruppi
if ( m_bOptInGroup)
return ( GetGroupResult( vIds)) ;
// --- Se invece ottimizzazione globale
return ( GetGlobalResult( vIds)) ;
}
+22 -15
View File
@@ -39,6 +39,8 @@ class MachOptimization : public IMachOptimization
bool SetFeeds( double dFeedL, double dFeedA) override ;
bool SetAllGroupsAsMandatory( bool bAllMandatory) override ;
bool SetOptimizationForGroups( bool bOptForGroups) override ;
bool SetOpenBound( bool bStartVsEnd, int nFlag, double dX, double dY, double dZ) override ;
bool SetOpenBoundForGroups( int nGroup, bool bStartVsEnd, int nFlag, double dX, double dY, double dZ) override ;
// Risultati
bool GetResult( INTVECTOR& vIds) override ;
@@ -48,33 +50,38 @@ class MachOptimization : public IMachOptimization
private :
// Calcolo dei tempi tra le lavorazioni
double CalcTimeLavLav( const MachOptm& Lav1, const MachOptm& Lav2, bool bLin) ;
double CalcTimeLavLav( const MachOptm& Lav1, const MachOptm& Lav2, bool bLin) const ;
bool CalcTimeLavLavTC( const MachOptm& Lav1, const MachOptm& Lav2, bool bLin,
double& dTimeLav1TC1, double& dTimeTC1TC2, double& dTimeTC2Lav2,
double& dTUnload1, double& dTLoad2) ;
bool CalcMachTime( int nInd1, int nInd2, int& nTime) ;
bool CalcMachTime( const MachOptm& Lav1, const MachOptm& Lav2, int& nTime) ;
double& dTUnload1, double& dTLoad2) const ;
bool CalcMachTime( int nInd1, int nInd2, int& nTime) const ;
bool CalcMachTime( const MachOptm& Lav1, const MachOptm& Lav2, int& nTime) const ;
// Controllo Conflitti tra dipendenze e Gestione Dipendenze
bool CheckDependences( int nIdPrev, int nIdNext, const INTINTVECTOR& vDep,
bool bBlockMessages, bool& bExist, bool& bConflict) ;
bool bBlockMessages, bool& bExist, bool& bConflict) const ;
bool SetGroupDependences( void) ;
// Calcolo della Matrice dei tempi, Del fattore perso dipendenze suggerite e della soluzione ottimale
bool ComputeTimeMatrix( INTMATRIX& mTimes) ;
bool ComputeTimeMatrix( INTMATRIX& mTimes) const ;
// Calcolo dei risultati a seconda della modalità
bool GetGlobalResult( INTVECTOR& vIds) ;
bool GetGroupResult( INTVECTOR& vIds) ;
// Utility
int GetIndById( int nId) ;
int GetIndById( int nId) const ;
bool SplitMachOptsInGroups( MACHOPTMMATRIX& matMachOpt, vector<INTINTVECTOR>& matDep,
vector<INTINTVECTOR>& matSuggDep) ;
private :
MACHOPTMVECTOR m_vMachOptm ; // Vettore delle lavorazioni
TOOLOPTMVECTOR m_vToolOptm ; // Vettore degli utensili
INTINTVECTOR m_vDependences ; // Vettore di dipendenze ( IdPrev, IdSucc) -> deve essere rispettato
INTINTVECTOR m_vSuggDependences ; // Vettore delle dipendenze suggerite ( IdPrev, IdSucc) -> si cerca di rispettarle
double m_dFeedL ; // Feed Lineare
double m_dFeedA ; // Feed Angolare
bool m_bAllMandatory ; // Flag per impostare ogni dipendenza da Gruppo come vincolo
bool m_bOptInGroup ; // Flag per ottimizzazione solo interna ai gruppi
MACHOPTMVECTOR m_vMachOptm ; // Vettore delle lavorazioni
TOOLOPTMVECTOR m_vToolOptm ; // Vettore degli utensili
INTINTVECTOR m_vDependences ; // Vettore di dipendenze ( IdPrev, IdSucc) -> deve essere rispettato
INTINTVECTOR m_vSuggDependences ; // Vettore delle dipendenze suggerite ( IdPrev, IdSucc) -> si cerca di rispettarle
double m_dFeedL ; // Feed Lineare
double m_dFeedA ; // Feed Angolare
bool m_bAllMandatory ; // Flag per impostare ogni dipendenza da Gruppo come vincolo
bool m_bOptInGroup ; // Flag per ottimizzazione solo interna ai gruppi
MACHOPTOPENBOUNDVECTOR m_vOpenBounds ; // Vettore dei punti OpenBound
} ;