- Aggiunti parametri configurabili GEN_bTestAlternative e GEN_bGetAlternativesNesting2D per testare altre alternative valide
- Aggiunta funzione dedicata alla creazione del gruppo ausiliario al MachGroup - Alla funzione BeamExec.GetCombinationListFromMatrix si può passare una lista con le sole combinazioni da provare - Nella BeamExec aggiunta funzione ProcessAlternatives solo per provare le alternative (simile alla ProcessFeatures, ma completamente slegata). La ProcessFeature decide il posizionamento iniziale, la ProcessAlternatives verifica solamente le alternative. - FlipRot adeguata a nuovo funzionamento - Altre piccole migliorie varie - TODO : 1) manca la parte per settare nelle info pezzo la rotazione iniziale (per vista in Aedifica) e le altre alternative (per ottimizzazione in nesting) 2) In FlipRot gestire interazione con Aedifica, dato che verrà lanciato direttamente dal programma (per ora funziona lanciato come la Process)
This commit is contained in:
+471
-97
@@ -1227,8 +1227,8 @@ local function PrintFeatures( vProc, Part)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
-- recupero tutti i processing di tutti i pezzi in tutte le rotazioni
|
||||
-- funzione che recupera tutti i processing di tutti i pezzi in tutte le rotazioni
|
||||
function BeamExec.GetProcessings( PARTS, bIsFlipRot)
|
||||
|
||||
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
|
||||
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
|
||||
@@ -1238,7 +1238,8 @@ function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
local vProcRot = {}
|
||||
|
||||
-- se è prerotazione, oltre al ciclo normale, si devono verificare anche invertiti
|
||||
local nCycles = EgtIf( bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION', 2, 1)
|
||||
local bCalcInverted = bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion
|
||||
local nCycles = EgtIf( bCalcInverted, 2, 1)
|
||||
-- per ogni inversione
|
||||
for nInvertIndex = 1, nCycles do
|
||||
-- per ogni rotazione
|
||||
@@ -1249,7 +1250,7 @@ function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
if PARTS[nPart].CombinationList.Rotations[nRotIndex] == 1 then
|
||||
-- recupero le feature di lavorazione della trave
|
||||
table.insert( vProcRot, CollectFeatures( PARTS[nPart], nIndex))
|
||||
|
||||
|
||||
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
|
||||
-- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no
|
||||
vProcRot[nIndex] = GetFeatureInfoAndDependency( vProcRot[nIndex], PARTS[nPart])
|
||||
@@ -1263,7 +1264,8 @@ function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw)
|
||||
PARTS[nPart].b3Part = EgtGetBBoxGlob( PARTS[nPart].idBoxTm, GDB_BB.STANDARD)
|
||||
end
|
||||
if bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' then
|
||||
-- se si devono calcolare anche gli invertiti
|
||||
if bCalcInverted then
|
||||
-- inversione pezzo testa-coda
|
||||
BeamLib.InvertRawPart( PARTS[nPart], 2)
|
||||
-- aggiorno info pezzo
|
||||
@@ -1439,115 +1441,130 @@ end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- funzione che calcola le combinazioni di rotazione per lavorare la trave e sceglie la migliore
|
||||
local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bReProcessEmptyChosenStrategy)
|
||||
local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bReProcessEmptyChosenStrategy, BitCombinationListToReprocess)
|
||||
local CombinationsList = { dAllCombinationsTotalTime = 0}
|
||||
|
||||
-- calcolo per tutte le combinazioni disponibili precedentemente verificate
|
||||
for i = 1, #PartInfo.CombinationList do
|
||||
local bRot90, bRot180
|
||||
local SingleCombination = {}
|
||||
local nUnloadPos = PartInfo.CombinationList[i].nUnloadPos
|
||||
SingleCombination.nRotations = 0
|
||||
SingleCombination.dTotalTimeToMachine = 0
|
||||
SingleCombination.dTotalQuality = 0
|
||||
SingleCombination.dTotalCompletionIndex = 0
|
||||
SingleCombination.nComplete = 0
|
||||
SingleCombination.nNotComplete = 0
|
||||
SingleCombination.nNotExecute = 0
|
||||
SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination
|
||||
-- TODO se pezzo invertito bisogna considerare le rotazioni nell'array dalla 5 alla 8
|
||||
SingleCombination.bPartInCombiIsInverted = PartInfo.CombinationList[i].bPartInCombiIsInverted
|
||||
SingleCombination.nUnloadPos = nUnloadPos
|
||||
-- creo liste dei proc suddivisi per rotazione
|
||||
SingleCombination.Rot0 = {}
|
||||
SingleCombination.Rot90 = {}
|
||||
SingleCombination.Rot180 = {}
|
||||
local bToProcess = false
|
||||
-- controllo se debbano essere ricalcolate solo alcune soluzioni
|
||||
if BitCombinationListToReprocess and #BitCombinationListToReprocess > 0 then
|
||||
for c = 1, #BitCombinationListToReprocess do
|
||||
if PartInfo.CombinationList[i].sBitIndexCombination == BitCombinationListToReprocess[c].sBitIndexCombination and
|
||||
PartInfo.CombinationList[i].bPartInCombiIsInverted == BitCombinationListToReprocess[c].bPartInCombiIsInverted then
|
||||
bToProcess = true
|
||||
end
|
||||
end
|
||||
else
|
||||
bToProcess = true
|
||||
end
|
||||
-- si riprocessano tutte a meno che non sia indicata una specifica da riprovare
|
||||
if bToProcess then
|
||||
local bRot90, bRot180
|
||||
local SingleCombination = {}
|
||||
local nUnloadPos = PartInfo.CombinationList[i].nUnloadPos
|
||||
SingleCombination.nRotations = 0
|
||||
SingleCombination.dTotalTimeToMachine = 0
|
||||
SingleCombination.dTotalQuality = 0
|
||||
SingleCombination.dTotalCompletionIndex = 0
|
||||
SingleCombination.nComplete = 0
|
||||
SingleCombination.nNotComplete = 0
|
||||
SingleCombination.nNotExecute = 0
|
||||
SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination
|
||||
-- TODO se pezzo invertito bisogna considerare le rotazioni nell'array dalla 5 alla 8
|
||||
SingleCombination.bPartInCombiIsInverted = PartInfo.CombinationList[i].bPartInCombiIsInverted
|
||||
SingleCombination.nUnloadPos = nUnloadPos
|
||||
-- creo liste dei proc suddivisi per rotazione
|
||||
SingleCombination.Rot0 = {}
|
||||
SingleCombination.Rot90 = {}
|
||||
SingleCombination.Rot180 = {}
|
||||
|
||||
-- ciclo su tutte le feature, ad eccezione dei tagli testa/coda che dipendono dal risultato delle altre
|
||||
-- tagli testa e coda vengono aggiunti sempre alla fine
|
||||
for nProc = 1, #ProcessingsOnPart.Rotation[1] do
|
||||
-- Si controlla sempre la rotazione 1 perchè la dipendenza di una feature da un'altra non dipende dalla rotazione
|
||||
-- se feature disattivata perchè eseguita da master a lei associata dichiaro comunque eseguita
|
||||
if ProcessingsOnPart.Rotation[1][nProc].nFlg == 0 and ProcessingsOnPart.Rotation[1][nProc].nIndexMasterProc then
|
||||
ProcessingsOnPart.Rotation[1][nProc].nIndexRotation = nUnloadPos
|
||||
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[1][nProc])
|
||||
SingleCombination.nComplete = SingleCombination.nComplete + 1
|
||||
else
|
||||
if not ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) and not ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then
|
||||
-- ciclo sulle rotazioni
|
||||
local nNextRot = nUnloadPos
|
||||
-- ciclo su tutte le feature, ad eccezione dei tagli testa/coda che dipendono dal risultato delle altre
|
||||
-- tagli testa e coda vengono aggiunti sempre alla fine
|
||||
for nProc = 1, #ProcessingsOnPart.Rotation[1] do
|
||||
-- Si controlla sempre la rotazione 1 perchè la dipendenza di una feature da un'altra non dipende dalla rotazione
|
||||
-- se feature disattivata perchè eseguita da master a lei associata dichiaro comunque eseguita
|
||||
if ProcessingsOnPart.Rotation[1][nProc].nFlg == 0 and ProcessingsOnPart.Rotation[1][nProc].nIndexMasterProc then
|
||||
ProcessingsOnPart.Rotation[1][nProc].nIndexRotation = nUnloadPos
|
||||
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[1][nProc])
|
||||
SingleCombination.nComplete = SingleCombination.nComplete + 1
|
||||
else
|
||||
local nOffsetIndex = EgtIf( SingleCombination.bPartInCombiIsInverted, 4, 0)
|
||||
local ResultsList = {}
|
||||
for nRotation = 1, 3 do
|
||||
-- se rotazione abilitata da combinazione
|
||||
if string.sub( PartInfo.CombinationList[i].sBitIndexCombination, nNextRot, nNextRot) == '1' then
|
||||
local CurrProc = ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc]
|
||||
-- se è ultima rotazione oppure se feature non impatta su misura laser, allora è valida e può essere effettivamente considerata
|
||||
if nNextRot == nUnloadPos or not( CurrProc.bHindersLaserMeasure) then
|
||||
-- se non è settata la ChosenStrtegy, provo a cercare comunque tra quelle disponibili
|
||||
if not CurrProc.ChosenStrategy and bReProcessEmptyChosenStrategy then
|
||||
CurrProc = GetFeatureBestStrategy( CurrProc, PartInfo)
|
||||
end
|
||||
-- controllo se è stata scelta una strategia
|
||||
if CurrProc.ChosenStrategy then
|
||||
local Proc = {}
|
||||
Proc.nRotation = nNextRot
|
||||
table.insert( Proc, CurrProc)
|
||||
table.insert( ResultsList, Proc)
|
||||
if not ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) and not ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then
|
||||
-- ciclo sulle rotazioni
|
||||
local nNextRot = nUnloadPos
|
||||
local ResultsList = {}
|
||||
for nRotation = 1, 3 do
|
||||
-- se rotazione abilitata da combinazione
|
||||
if string.sub( PartInfo.CombinationList[i].sBitIndexCombination, nNextRot, nNextRot) == '1' then
|
||||
local CurrProc = ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc]
|
||||
-- se è ultima rotazione oppure se feature non impatta su misura laser, allora è valida e può essere effettivamente considerata
|
||||
if nNextRot == nUnloadPos or not( CurrProc.bHindersLaserMeasure) then
|
||||
-- se non è settata la ChosenStrtegy, provo a cercare comunque tra quelle disponibili
|
||||
if not CurrProc.ChosenStrategy and bReProcessEmptyChosenStrategy then
|
||||
CurrProc = GetFeatureBestStrategy( CurrProc, PartInfo)
|
||||
end
|
||||
-- controllo se è stata scelta una strategia
|
||||
if CurrProc.ChosenStrategy then
|
||||
local Proc = {}
|
||||
Proc.nRotation = nNextRot
|
||||
table.insert( Proc, CurrProc)
|
||||
table.insert( ResultsList, Proc)
|
||||
end
|
||||
end
|
||||
end
|
||||
nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1)
|
||||
end
|
||||
nNextRot = EgtIf( nNextRot + 1 > 4, nNextRot + 1 - 4, nNextRot + 1)
|
||||
end
|
||||
|
||||
-- se la feature può essere lavorata in almeno una rotazione
|
||||
if #ResultsList > 0 then
|
||||
local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo)
|
||||
Proc.nIndexRotation = Data.nIndexRotation
|
||||
-- inserisco la Proc nell'apposita lista
|
||||
if Data.nIndexRotation == nUnloadPos then
|
||||
table.insert( SingleCombination.Rot0, Proc)
|
||||
elseif Data.nIndexRotation == nUnloadPos + 1 then
|
||||
table.insert( SingleCombination.Rot90, Proc)
|
||||
bRot90 = true
|
||||
-- se la feature può essere lavorata in almeno una rotazione
|
||||
if #ResultsList > 0 then
|
||||
local Proc, Data = GetProcBestMachRotationFromList( ResultsList, PartInfo)
|
||||
Proc.nIndexRotation = Data.nIndexRotation
|
||||
-- inserisco la Proc nell'apposita lista
|
||||
if Data.nIndexRotation == nUnloadPos then
|
||||
table.insert( SingleCombination.Rot0, Proc)
|
||||
elseif Data.nIndexRotation == nUnloadPos + 1 then
|
||||
table.insert( SingleCombination.Rot90, Proc)
|
||||
bRot90 = true
|
||||
else
|
||||
table.insert( SingleCombination.Rot180, Proc)
|
||||
bRot180 = true
|
||||
end
|
||||
|
||||
SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + Data.dTimeToMachine
|
||||
SingleCombination.dTotalQuality = SingleCombination.dTotalQuality + Data.dQuality
|
||||
SingleCombination.dTotalCompletionIndex = SingleCombination.dTotalCompletionIndex + Data.dCompletionIndex
|
||||
SingleCombination.nComplete = SingleCombination.nComplete + EgtIf( Data.bComplete, 1, 0)
|
||||
SingleCombination.nNotComplete = SingleCombination.nNotComplete + EgtIf( Data.bNotComplete, 1, 0)
|
||||
SingleCombination.nNotExecute = SingleCombination.nNotExecute + EgtIf( Data.bNotApplicable, 1, 0)
|
||||
SingleCombination.nIndexInCombinationList = i
|
||||
SingleCombination.nIndexRotation = nUnloadPos
|
||||
else
|
||||
table.insert( SingleCombination.Rot180, Proc)
|
||||
bRot180 = true
|
||||
ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nIndexRotation = nUnloadPos
|
||||
ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nFlg = 0
|
||||
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc])
|
||||
SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1
|
||||
end
|
||||
|
||||
SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + Data.dTimeToMachine
|
||||
SingleCombination.dTotalQuality = SingleCombination.dTotalQuality + Data.dQuality
|
||||
SingleCombination.dTotalCompletionIndex = SingleCombination.dTotalCompletionIndex + Data.dCompletionIndex
|
||||
SingleCombination.nComplete = SingleCombination.nComplete + EgtIf( Data.bComplete, 1, 0)
|
||||
SingleCombination.nNotComplete = SingleCombination.nNotComplete + EgtIf( Data.bNotComplete, 1, 0)
|
||||
SingleCombination.nNotExecute = SingleCombination.nNotExecute + EgtIf( Data.bNotApplicable, 1, 0)
|
||||
SingleCombination.nIndexInCombinationList = i
|
||||
SingleCombination.nIndexRotation = nUnloadPos
|
||||
else
|
||||
ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nIndexRotation = nUnloadPos
|
||||
ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc].nFlg = 0
|
||||
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos+nOffsetIndex][nProc])
|
||||
SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1
|
||||
end
|
||||
else
|
||||
if ID.IsHeadCut( ProcessingsOnPart.Rotation[1][nProc]) then
|
||||
SingleCombination.nIndexHeadCutInVProc = nProc
|
||||
elseif ID.IsTailCut( ProcessingsOnPart.Rotation[1][nProc]) then
|
||||
SingleCombination.nIndexTailCutInVProc = nProc
|
||||
if ID.IsHeadCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
|
||||
SingleCombination.nIndexHeadCutInVProc = nProc
|
||||
elseif ID.IsTailCut( ProcessingsOnPart.Rotation[1+nOffsetIndex][nProc]) then
|
||||
SingleCombination.nIndexTailCutInVProc = nProc
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- aggiungo rotazioni
|
||||
SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0)
|
||||
|
||||
-- aggiungo tempo totale considerando le rotazioni -- TODO per il momento la rotazione impiega 1 minuto. Serve configurare?
|
||||
SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + ( SingleCombination.nRotations * 1)
|
||||
|
||||
-- aggiungo la combinazione all'elenco delle combinazioni disponibili
|
||||
table.insert( CombinationsList, SingleCombination)
|
||||
-- aggiorno tempo totale di tutte le combinazioni
|
||||
CombinationsList.dAllCombinationsTotalTime = CombinationsList.dAllCombinationsTotalTime + SingleCombination.dTotalTimeToMachine
|
||||
end
|
||||
-- aggiungo rotazioni
|
||||
SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0)
|
||||
|
||||
-- aggiungo tempo totale considerando le rotazioni -- TODO per il momento la rotazione impiega 1 minuto. Serve configurare?
|
||||
SingleCombination.dTotalTimeToMachine = SingleCombination.dTotalTimeToMachine + ( SingleCombination.nRotations * 1)
|
||||
|
||||
-- aggiungo la combinazione all'elenco delle combinazioni disponibili
|
||||
table.insert( CombinationsList, SingleCombination)
|
||||
-- aggiorno tempo totale di tutte le combinazioni
|
||||
CombinationsList.dAllCombinationsTotalTime = CombinationsList.dAllCombinationsTotalTime + SingleCombination.dTotalTimeToMachine
|
||||
end
|
||||
|
||||
-- si calsola il total rating
|
||||
@@ -1903,5 +1920,362 @@ function BeamExec.ProcessMachinings( PARTS)
|
||||
return ( nTotErr == 0), RESULT
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamExec.ProcessAlternatives( PARTS)
|
||||
-- ciclo sui pezzi
|
||||
local nTotErr = 0
|
||||
local Stats = {}
|
||||
local BestCombination = {}
|
||||
local nPart = 1
|
||||
local nOrd = 1
|
||||
local nMaxReProcessCycles = EgtClamp( PARTS[nPart].GeneralParameters.GEN_nMaxReProcessCycles, 1, 3)
|
||||
local bTryToReProcess = false
|
||||
|
||||
-- se non serve trovare altre soluzioni, si esce subito
|
||||
if not PARTS[nPart].GeneralParameters.GEN_bTestAlternative or not PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then
|
||||
return
|
||||
end
|
||||
|
||||
-- si analizzano le alternative solo del primo pezzo (la FlipRot viene chiamata sempre con un solo pezzo)
|
||||
local nCycles = 1
|
||||
|
||||
-- si copia il MachGroup originale
|
||||
local nOriginalMachGroup = EgtGetCurrMachGroup()
|
||||
local sMachGroupName = EgtGetMachGroupName( nOriginalMachGroup)
|
||||
local sTempMachGroupName = sMachGroupName .. '_A'
|
||||
|
||||
local nTempMachGroupName = EgtCopyMachGroup( sMachGroupName, sTempMachGroupName)
|
||||
EgtSetCurrMachGroup( nTempMachGroupName)
|
||||
EgtRemoveAllOperations()
|
||||
BeamLib.CreateAddGroup( PARTS[nPart].id, sTempMachGroupName)
|
||||
-- si aggiorna il raw dopo averlo copiato
|
||||
PARTS[nPart].idRaw = EgtGetFirstRawPart()
|
||||
|
||||
-- si riporta pezzo in posizione iniziale
|
||||
-- se combinazione prevedeva inversione, si rigira il pezzo
|
||||
if PARTS[nPart].bPartInCombiIsInverted then
|
||||
BeamLib.InvertRawPart( PARTS[nPart], -2)
|
||||
end
|
||||
-- si ribalta il pezzo in posizione iniziale
|
||||
BeamLib.RotateRawPart( PARTS[nPart], 1 - PARTS[nPart].nInitialPosition)
|
||||
|
||||
local TotalCombiToTest = {}
|
||||
-- se serve calcolare soluzione alternativa ruotata di 90°
|
||||
if PARTS[nPart].GeneralParameters.GEN_bTestAlternative and not PARTS[nPart].bSquareSection then
|
||||
local CombinationListToCheck = {}
|
||||
for i = 1, #PARTS[nPart].CombinationList do
|
||||
local nUnloadPos = PARTS[nPart].nInitialPosition
|
||||
local nOtherSimilarUnloadPos = EgtIf( nUnloadPos + 2 > 4, nUnloadPos + 2 - 4, nUnloadPos + 2)
|
||||
-- restano abilitate soluzioni ruotate di 90° o 270° rispetto alla migliore soluzione trovata nella prima analisi
|
||||
if PARTS[nPart].CombinationList[i].nUnloadPos ~= nUnloadPos and PARTS[nPart].CombinationList[i].nUnloadPos ~= nOtherSimilarUnloadPos then
|
||||
table.insert( CombinationListToCheck, { sBitIndexCombination = PARTS[nPart].CombinationList[i].sBitIndexCombination,
|
||||
bPartInCombiIsInverted = PARTS[nPart].CombinationList[i].bPartInCombiIsInverted})
|
||||
end
|
||||
end
|
||||
-- se c'è almeno una combinazione da testare
|
||||
if #CombinationListToCheck > 0 then
|
||||
table.insert( TotalCombiToTest, CombinationListToCheck)
|
||||
end
|
||||
end
|
||||
|
||||
-- se serve calcolare posizione per ottimizzazione tagli in nesting (le soluzioni non possono avere ribaltamenti)
|
||||
if PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then
|
||||
-- POSIZIONE 0 (e invertito)
|
||||
local sCombinationToCheck = BeamLib.StringReplaceChar( '0000', PARTS[nPart].nInitialPosition, "1")
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}})
|
||||
if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}})
|
||||
end
|
||||
|
||||
-- POSIZIONE 180 (e invertito)
|
||||
if PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition == 'STD_PRE_ROTATION' then
|
||||
local nOtherPosition = EgtIf( PARTS[nPart].nInitialPosition + 2 > 4, PARTS[nPart].nInitialPosition + 2 - 4, PARTS[nPart].nInitialPosition + 2)
|
||||
sCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1")
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}})
|
||||
if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}})
|
||||
end
|
||||
end
|
||||
-- POSIZIONE 90/270 (e invertito)
|
||||
if PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition == 'FULL_PRE_ROTATION' then
|
||||
local nOtherPosition = EgtIf( PARTS[nPart].nInitialPosition + 1 > 4, PARTS[nPart].nInitialPosition + 1 - 4, PARTS[nPart].nInitialPosition + 1)
|
||||
sCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1")
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}})
|
||||
if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}})
|
||||
end
|
||||
nOtherPosition = EgtIf( PARTS[nPart].nInitialPosition + 3 > 4, PARTS[nPart].nInitialPosition + 3 - 4, PARTS[nPart].nInitialPosition + 3)
|
||||
sCombinationToCheck = BeamLib.StringReplaceChar( '0000', nOtherPosition, "1")
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck}})
|
||||
if PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then
|
||||
table.insert( TotalCombiToTest, {{ sBitIndexCombination = sCombinationToCheck, bPartInCombiIsInverted = true}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- fino a che ci sono soluzioni da testare
|
||||
for z = 1, #TotalCombiToTest do
|
||||
|
||||
-- si svuota il machgroup e si resettano le variabili
|
||||
EgtRemoveAllOperations()
|
||||
MACHININGS = {}
|
||||
MACHININGS.Info = {}
|
||||
nOrd = 1
|
||||
|
||||
local bCombinationFound = true
|
||||
-- la parte di applicazione lavorazioni può essere lanciata più volte in caso della presenza di errori
|
||||
local bProcess = true
|
||||
while bProcess do
|
||||
bProcess = false
|
||||
|
||||
-- si ricavano tutte le combinazioni possibili
|
||||
local CombinationListFromMatrix = GetCombinationListFromMatrix( PROCESSINGS[nPart], PARTS[nPart], nCycles > 1, TotalCombiToTest[z])
|
||||
-- se ci sono soluzioni possibili
|
||||
if #CombinationListFromMatrix > 0 then
|
||||
BestCombination = GetBestCombination( CombinationListFromMatrix, PARTS[nPart])
|
||||
-- se la soluzione alternativa migliore è completa, allora la verifico, altrimenti si tiene la migliore in assoluto
|
||||
if BestCombination.nNotComplete == 0 and BestCombination.nNotExecute == 0 then
|
||||
|
||||
-- compilazione della vProc finale contenente le feature da lavorare nella giusta rotazione
|
||||
local vProc, MatrixResult = GetProcessingListFromCombination( BestCombination)
|
||||
|
||||
-- si mette subito il pezzo nella fase
|
||||
EgtSetCurrPhase( 1)
|
||||
|
||||
-- si sposta il pezzo nella posizione originale, di quando è stata fatta la collect. In questo modo tutti i dati calcolati nella collect restano validi.
|
||||
-- Altrimenti bisognava ricalcolare tutto, aumentando tempo di calcolo.
|
||||
local vtRawOffsetPos = PARTS[nPart].b3Raw:getMin() - EgtGetRawPartBBox( PARTS[nPart].idRaw):getMin()
|
||||
local nRawId = PARTS[nPart].idRaw
|
||||
while nRawId and abs( vtRawOffsetPos:len()) > 0 do
|
||||
EgtKeepRawPart( nRawId)
|
||||
EgtMoveRawPart( nRawId, vtRawOffsetPos)
|
||||
nRawId = EgtGetNextRawPart( nRawId)
|
||||
end
|
||||
|
||||
if BestCombination.bPartInCombiIsInverted then
|
||||
BeamLib.InvertRawPart( PARTS[nPart], 2)
|
||||
end
|
||||
|
||||
-- se la posizione iniziale non è calcolata, significa che non ci sono feature da eseguire. Solo taglio testa/coda
|
||||
if not MatrixResult.nInitialPosition then
|
||||
MatrixResult.nInitialPosition = 1
|
||||
MACHININGS.Info.nHeadCutRotation = 1
|
||||
MACHININGS.Info.nSplitCutRotation = 1
|
||||
-- altrimenti si fanno tutti i calcoli
|
||||
else
|
||||
-- TODO serve ancora ordinare le feature con nuovo metodo di calcolo ottimizzazione lavorazioni?
|
||||
-- ordinamento di base delle feature
|
||||
vProc = OrderFeatures( vProc)
|
||||
|
||||
-- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale
|
||||
MACHININGS = CalculateMachinings( vProc, PARTS[nPart], MatrixResult.nInitialPosition)
|
||||
-- se non sono sono settate le rotazioni di lavorazione di testa e coda, significa che le feature da eseguire non sono state eseguite per qualche problema. Si forza rotazione 1
|
||||
if not MACHININGS.Info.nHeadCutRotation or not MACHININGS.Info.nSplitCutRotation then
|
||||
MACHININGS.Info.nHeadCutRotation = 1
|
||||
MACHININGS.Info.nSplitCutRotation = 1
|
||||
end
|
||||
end
|
||||
|
||||
local nOffsetIndex = EgtIf( BestCombination.bPartInCombiIsInverted, 4, 0)
|
||||
-- aggiunge tagli testa e coda in fasi opportune
|
||||
local nRotHeadCut = MatrixResult.nInitialPosition + MACHININGS.Info.nHeadCutRotation - 1
|
||||
if nRotHeadCut > 4 then
|
||||
nRotHeadCut = nRotHeadCut - 4
|
||||
end
|
||||
nRotHeadCut = nRotHeadCut + nOffsetIndex
|
||||
local nRotSplitCut = MatrixResult.nInitialPosition + MACHININGS.Info.nSplitCutRotation - 1
|
||||
if nRotSplitCut > 4 then
|
||||
nRotSplitCut = nRotSplitCut - 4
|
||||
end
|
||||
nRotSplitCut = nRotSplitCut + nOffsetIndex
|
||||
-- setto nella Proc l'indice rotazione nella quale deve essere lavorata
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].nIndexRotation = nRotHeadCut
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].nIndexRotation = nRotSplitCut
|
||||
|
||||
-- si imposta flag rotazione per taglio di testa
|
||||
if MACHININGS.Info.nHeadCutRotation == 2 then
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bSide = true
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bStd = nil
|
||||
elseif MACHININGS.Info.nHeadCutRotation == 3 then
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = true
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bSide = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bStd = nil
|
||||
else
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bSide = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bStd = true
|
||||
end
|
||||
-- si imposta flag rotazione per taglio di coda
|
||||
if MACHININGS.Info.nSplitCutRotation == 2 then
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = true
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bStd = nil
|
||||
elseif MACHININGS.Info.nSplitCutRotation == 3 then
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = true
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bStd = nil
|
||||
else
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = nil
|
||||
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bStd = true
|
||||
end
|
||||
|
||||
local vProcHeadTail = {}
|
||||
table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc])
|
||||
table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc])
|
||||
|
||||
MACHININGS = CalculateMachinings( vProcHeadTail, PARTS[nPart], MatrixResult.nInitialPosition)
|
||||
|
||||
-- finiti i calcoli di applicazione delle lavorazioni, si riporta il pezzo nello zero della fase
|
||||
nRawId = PARTS[nPart].idRaw
|
||||
while nRawId and abs( vtRawOffsetPos:len()) > 0 do
|
||||
EgtKeepRawPart( nRawId)
|
||||
EgtMoveRawPart( nRawId, -vtRawOffsetPos)
|
||||
nRawId = EgtGetNextRawPart( nRawId)
|
||||
end
|
||||
|
||||
local bAreAllMachiningApplyOk
|
||||
local sErr
|
||||
local bSplitAlreadyExecuted = false
|
||||
local bSplitExecutedOnRot = false
|
||||
local nPhase = EgtGetCurrPhase()
|
||||
local idDisp = EgtGetPhaseDisposition( nPhase)
|
||||
EgtSetInfo( idDisp, 'TYPE', 'START')
|
||||
EgtSetInfo( idDisp, 'ORD', nOrd)
|
||||
|
||||
-- creazione effettiva delle lavorazioni
|
||||
MACHININGS.Info = {}
|
||||
local nCurrPosition = 1
|
||||
local nInitialPosition = MatrixResult.nInitialPosition
|
||||
BestCombination.nInitialPosition = MatrixResult.nInitialPosition
|
||||
|
||||
-- se c'è almeno una lavorazione in posizionamento con trave ribaltata
|
||||
if MatrixResult.bSomeFeatureDown then
|
||||
local nRotation = EgtIf( nInitialPosition + 2 > 4, nInitialPosition + 2 - 4, nInitialPosition + 2)
|
||||
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
|
||||
nCurrPosition = nRotation
|
||||
EgtSetInfo( idDisp, 'ROT', -2)
|
||||
bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'DOWN')
|
||||
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
|
||||
bProcess = bProcess or bTryToReProcess
|
||||
end
|
||||
|
||||
-- se c'è almeno una lavorazione in posizionamento con trave ruotata
|
||||
if MatrixResult.bSomeFeatureSide then
|
||||
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
|
||||
if MatrixResult.bSomeFeatureDown then
|
||||
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
|
||||
nPhase = EgtGetCurrPhase()
|
||||
idDisp = EgtGetPhaseDisposition( nPhase)
|
||||
EgtSetInfo( idDisp, 'ORD', nOrd)
|
||||
-- se c'è già stata separazione
|
||||
if bSplitAlreadyExecuted then
|
||||
EgtSetInfo( idDisp, 'TYPE', 'MID2')
|
||||
else
|
||||
EgtSetInfo( idDisp, 'TYPE', 'MID')
|
||||
end
|
||||
-- se combinazione prevede inversione, si gira il pezzo
|
||||
if BestCombination.bPartInCombiIsInverted and not PARTS[nPart].bIsInverted then
|
||||
BeamLib.InvertRawPart( PARTS[nPart], 2)
|
||||
end
|
||||
end
|
||||
local nRotation = EgtIf( nInitialPosition + 1 > 4, nInitialPosition + 1 - 4, nInitialPosition + 1)
|
||||
BeamLib.RotateRawPart( PARTS[nPart], nRotation - nCurrPosition)
|
||||
nCurrPosition = nRotation
|
||||
EgtSetInfo( idDisp, 'ROT', -1)
|
||||
bAreAllMachiningApplyOk, sErr, bSplitExecutedOnRot, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'SIDE')
|
||||
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
|
||||
bProcess = bProcess or bTryToReProcess
|
||||
end
|
||||
|
||||
-- se ci sono state lavorazioni in rotazione precedente devo creare altra fase. Altrimenti già creata da prima
|
||||
if MatrixResult.bSomeFeatureDown or MatrixResult.bSomeFeatureSide then
|
||||
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, EgtIf( bSplitAlreadyExecuted, BeamData.RAW_OFFSET, 0))
|
||||
nPhase = EgtGetCurrPhase()
|
||||
idDisp = EgtGetPhaseDisposition( nPhase)
|
||||
EgtSetInfo( idDisp, 'ORD', nOrd)
|
||||
-- se c'è già stata separazione
|
||||
if bSplitAlreadyExecuted then
|
||||
EgtSetInfo( idDisp, 'TYPE', 'END2')
|
||||
else
|
||||
EgtSetInfo( idDisp, 'TYPE', 'MID')
|
||||
end
|
||||
-- se combinazione prevede inversione, si gira il pezzo
|
||||
if BestCombination.bPartInCombiIsInverted and not PARTS[nPart].bIsInverted then
|
||||
BeamLib.InvertRawPart( PARTS[nPart], 2)
|
||||
end
|
||||
end
|
||||
|
||||
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
|
||||
|
||||
-- aggiunta lavorazioni in ultima fase
|
||||
_, _, _, bTryToReProcess = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD')
|
||||
bProcess = bProcess or bTryToReProcess
|
||||
|
||||
-- se bisogna riprocessare, si annulla tutto
|
||||
nCycles = nCycles + 1
|
||||
if bProcess and nCycles <= nMaxReProcessCycles then
|
||||
-- azzero liste
|
||||
MACHININGS = {}
|
||||
MACHININGS.Info = {}
|
||||
RESULT = {}
|
||||
EgtRemoveAllOperations()
|
||||
-- si riporta pezzo in posizione iniziale
|
||||
-- se combinazione prevedeva inversione, si rigira il pezzo
|
||||
if BestCombination.bPartInCombiIsInverted then
|
||||
BeamLib.InvertRawPart( PARTS[nPart], -2)
|
||||
end
|
||||
-- si ribalta il pezzo in posizione iniziale
|
||||
BeamLib.RotateRawPart( PARTS[nPart], 1 - nInitialPosition)
|
||||
else
|
||||
bProcess = false
|
||||
end
|
||||
else
|
||||
bCombinationFound = false
|
||||
end
|
||||
else
|
||||
bCombinationFound = false
|
||||
end
|
||||
end
|
||||
nOrd = nOrd + 1
|
||||
-- se ho trovato almeno una combinazione possibile
|
||||
if bCombinationFound then
|
||||
-- ===== finiti i pezzi, si scarica il restante =====
|
||||
local idRestPart = EgtGetNextRawPart( PARTS[#PARTS].idRaw)
|
||||
if idRestPart and EgtGetRawPartBBox( idRestPart):getDimX() >= BeamData.dMinRaw then
|
||||
BeamLib.AddPhaseWithRawParts( idRestPart, BeamData.ptOriXR, BeamData.dPosXR, 0)
|
||||
local nPhase = EgtGetCurrPhase()
|
||||
local idDisp = EgtGetPhaseDisposition( nPhase)
|
||||
EgtSetInfo( idDisp, 'TYPE', 'REST')
|
||||
EgtSetInfo( idDisp, 'ORD', nOrd)
|
||||
end
|
||||
-- Aggiornamento finale di tutto
|
||||
EgtSetCurrPhase( 1)
|
||||
local bApplOk, _, _ = EgtApplyAllMachinings()
|
||||
-- se non ci sono errori, soluzione alternativa valida
|
||||
if bApplOk then
|
||||
-- TODO scrivere info su pezzo!
|
||||
end
|
||||
|
||||
-- se ultima combinazione, si esce e non si riporta in posizione inizale. Verrà infatti cancellata
|
||||
if z == #TotalCombiToTest then break end
|
||||
|
||||
-- si riporta pezzo in posizione iniziale
|
||||
-- se combinazione prevedeva inversione, si rigira il pezzo
|
||||
if BestCombination.bPartInCombiIsInverted then
|
||||
BeamLib.InvertRawPart( PARTS[nPart], -2)
|
||||
end
|
||||
-- si ribalta il pezzo in posizione iniziale
|
||||
BeamLib.RotateRawPart( PARTS[nPart], 1 - BestCombination.nInitialPosition)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- si cancella eventuale mach group creato per le alternative
|
||||
EgtRemoveMachGroup( nTempMachGroupName)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return BeamExec
|
||||
|
||||
Reference in New Issue
Block a user