- Calcolo strategie spostato in funzione dedicata

- Migliorato ciclo di calcolo in GetBestResultFromCombinationsMatrix
- Rimossi cicli per ricominciare il calcolo in caso di errore (non erano funzionanti e non compatibili con prossime modifiche rifacimento core)
This commit is contained in:
andrea.villa
2025-07-07 18:37:36 +02:00
parent e155fee802
commit 702d4617a0
3 changed files with 319 additions and 325 deletions
+317 -325
View File
@@ -1339,98 +1339,93 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
Logs.WriteMatrixLog( ProcessingsOnPart, PartInfo)
end
-- per ogni posizione di scarico
for nUnloadPos = 1, 4 do
-- calcolo per tutte le combinazioni disponibili precedentemente verificate
for i = 1, #PartInfo.CombinationList do
-- controllo che la combinazione abbia ultima fase come quella calcolata in fase di definizione combinazioni
if PartInfo.CombinationList[i].nUnloadPos == nUnloadPos then
local bRot90, bRot180
local SingleCombination = {}
SingleCombination.nRotations = 0
SingleCombination.dTotalRating = 0
SingleCombination.nComplete = 0
SingleCombination.nNotComplete = 0
SingleCombination.nNotExecute = 0
SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination
SingleCombination.nUnloadPos = nUnloadPos
-- creo liste dei proc suddivisi per rotazione
SingleCombination.Rot0 = {}
SingleCombination.Rot90 = {}
SingleCombination.Rot180 = {}
-- 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.dTotalRating = 0
SingleCombination.nComplete = 0
SingleCombination.nNotComplete = 0
SingleCombination.nNotExecute = 0
SingleCombination.sBitIndexCombination = PartInfo.CombinationList[i].sBitIndexCombination
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
if ProcessingsOnPart.Rotation[1][nProc].nPrc ~= 340 and ProcessingsOnPart.Rotation[1][nProc].nPrc ~= 350 then
-- 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
-- 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
if ProcessingsOnPart.Rotation[1][nProc].nPrc ~= 340 and ProcessingsOnPart.Rotation[1][nProc].nPrc ~= 350 then
-- 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
-- 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
-- se è ultima rotazione oppure se feature non impatta su misura laser, allora è valida e può essere effettivamente considerata
if nNextRot == nUnloadPos or not( ProcessingsOnPart.Rotation[nNextRot][nProc].bHindersLaserMeasure) then
-- controllo se è stata scelta una strategia
if ProcessingsOnPart.Rotation[nNextRot][nProc].ChosenStrategy then
local Proc = {}
Proc.nRotation = nNextRot
table.insert( Proc, ProcessingsOnPart.Rotation[nNextRot][nProc])
table.insert( ResultsList, Proc)
end
end
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)
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
-- 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
-- se è ultima rotazione oppure se feature non impatta su misura laser, allora è valida e può essere effettivamente considerata
if nNextRot == nUnloadPos or not( ProcessingsOnPart.Rotation[nNextRot][nProc].bHindersLaserMeasure) then
-- controllo se è stata scelta una strategia
if ProcessingsOnPart.Rotation[nNextRot][nProc].ChosenStrategy then
local Proc = {}
Proc.nRotation = nNextRot
table.insert( Proc, ProcessingsOnPart.Rotation[nNextRot][nProc])
table.insert( ResultsList, Proc)
end
end
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)
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.dTotalRating = SingleCombination.dTotalRating + Data.dCompositeRating
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][nProc].nIndexRotation = nUnloadPos
ProcessingsOnPart.Rotation[nUnloadPos][nProc].nFlg = 0
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos][nProc])
SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1
end
table.insert( SingleCombination.Rot180, Proc)
bRot180 = true
end
SingleCombination.dTotalRating = SingleCombination.dTotalRating + Data.dCompositeRating
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
if ProcessingsOnPart.Rotation[1][nProc].nPrc == 340 then
SingleCombination.nIndexHeadCutInVProc = nProc
elseif ProcessingsOnPart.Rotation[1][nProc].nPrc == 350 then
SingleCombination.nIndexTailCutInVProc = nProc
end
ProcessingsOnPart.Rotation[nUnloadPos][nProc].nIndexRotation = nUnloadPos
ProcessingsOnPart.Rotation[nUnloadPos][nProc].nFlg = 0
table.insert( SingleCombination.Rot0, ProcessingsOnPart.Rotation[nUnloadPos][nProc])
SingleCombination.nNotExecute = SingleCombination.nNotExecute + 1
end
end
-- aggiungo rotazioni
SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0)
-- aggiungo la combinazione all'elenco delle combinazioni disponibili
table.insert( CombinationsList, SingleCombination)
else
if ProcessingsOnPart.Rotation[1][nProc].nPrc == 340 then
SingleCombination.nIndexHeadCutInVProc = nProc
elseif ProcessingsOnPart.Rotation[1][nProc].nPrc == 350 then
SingleCombination.nIndexTailCutInVProc = nProc
end
end
end
-- aggiungo rotazioni
SingleCombination.nRotations = EgtIf( bRot90, 1, 0) + EgtIf( bRot180, 1, 0)
-- aggiungo la combinazione all'elenco delle combinazioni disponibili
table.insert( CombinationsList, SingleCombination)
end
-- ci deve essere almeno una combinazione, altrimenti errore
@@ -1450,6 +1445,25 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
return vFinalProc, BestCombinationResult
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.GetCombinationMatrix( PARTS)
-- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni
for nPart = 1, #PARTS do
-- calcolo della migliore strategia per ogni rotazione del pezzo
for dRotIndex = 1, 4 do
-- calcola le strategie applicabili
PROCESSINGS[nPart].Rotation[dRotIndex] = CalculateStrategies( PROCESSINGS[nPart].Rotation[dRotIndex], PARTS[nPart])
-- tra le calcolate, sceglie la migliore
PROCESSINGS[nPart].Rotation[dRotIndex] = GetBestStrategy( PROCESSINGS[nPart].Rotation[dRotIndex])
-- rotazione pezzo di 90° per volta
BeamLib.RotateRawPart( PARTS[nPart], 1)
-- aggiorno info pezzo
PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw)
PARTS[nPart].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[nPart].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
end
end
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessMachinings( PARTS)
-- ciclo sui pezzi
@@ -1477,270 +1491,248 @@ function BeamExec.ProcessMachinings( PARTS)
-- EgtOutBox( timeMachining, 'Machining calculation time')
--end
local nCurrLoop = 0
-- ciclo fino a che tutte le applicazioni delle lavorazioni sono corrette
while not ProcessCompleted do
-- aumento numero loop nel quale siamo
nCurrLoop = nCurrLoop + 1
-- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni
for nPart = 1, #PARTS do
-- si mette subito il pezzo nella fase
if nOrd == 1 then
EgtSetCurrPhase( 1)
-- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni
for nPart = 1, #PARTS do
-- si mette subito il pezzo nella fase
if nOrd == 1 then
EgtSetCurrPhase( 1)
else
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, 0)
end
-- 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
-- scrittura nel log del risultato della scelta della strategia migliore tra quelle disponibili
if EgtGetDebugLevel() >= 3 then
Logs.WriteFeaturesLog( PROCESSINGS[nPart], PARTS[nPart])
end
local vProc, MatrixResult
local bAllStrategiesApplied = false
-- si calcola la combinazione di lavorazione migliore
vProc, MatrixResult = GetBestResultFromCombinationsMatrix( PROCESSINGS[nPart], PARTS[nPart])
-- TODO NEXT TO MODIFY
-- GetBestResultFromCombinationsMatrix ritorna lista combinazioni
-- funzione per ricavare combinazioni. Se Process la migliore, se BatchProcess una lista selezionata
-- funzione che prepara vproc e MatrixResult da migliore combinazione
-- Probabilmente la variabile "PartInfo.CombinationList" deve prevedere le pre-rotazioni e inversione in caso di QuickVerify.
-- In caso di process e calcolo dopo nesting, calcolare solo con metodo essetre, dove quella è la posizione finale.
-- debug
if EgtGetDebugLevel() >= 1 then
PrintFeatures( vProc, PARTS[nPart])
end
EgtOutLog( ' *** AddMachinings ***', 1)
-- 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
-- anche se non ci sono feature da eseguire, bisogna comunque scrivrere i risultati
for nProc = 1, #vProc do
AddFeatureResultToGlobalList( vProc[nProc])
end
-- altrimenti si fanno tutti i calcoli
else
-- ordinamento di base delle feature
vProc = OrderFeatures( vProc)
-- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale
bAllStrategiesApplied = false
MACHININGS, bAllStrategiesApplied = CalculateMachinings( vProc, PARTS[nPart], MatrixResult.nInitialPosition)
end
-- salvo sul PART la posizione di partenza che è stata scelta
PARTS[nPart].nInitialPosition = MatrixResult.nInitialPosition
-- aggiunge tagli testa e coda in fasi opportune
local nRotHeadCut = MatrixResult.nInitialPosition + MACHININGS.Info.nHeadCutRotation - 1
if nRotHeadCut > 4 then
nRotHeadCut = nRotHeadCut - 4
end
local nRotSplitCut = MatrixResult.nInitialPosition + MACHININGS.Info.nSplitCutRotation - 1
if nRotSplitCut > 4 then
nRotSplitCut = nRotSplitCut - 4
end
-- 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].bSide = true
elseif MACHININGS.Info.nHeadCutRotation == 3 then
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = true
end
-- si imposta flag rotazione per taglio di coda
if MACHININGS.Info.nSplitCutRotation == 2 then
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = true
elseif MACHININGS.Info.nSplitCutRotation == 3 then
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = true
end
local vProcHeadTail = {}
table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc])
table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc])
bAllStrategiesApplied = false
MACHININGS, bAllStrategiesApplied = CalculateMachinings( vProcHeadTail, PARTS[nPart], MatrixResult.nInitialPosition)
-- cancellazione entità create ma non usate
-- TODO funzione?
local idAddGroup = BeamLib.GetAddGroup( PARTS[nPart].id)
local idCurrentEntity = EgtGetFirstInGroup( idAddGroup or GDB_ID.NULL)
while idCurrentEntity do
if EgtGetLevel( idCurrentEntity) == GDB_LV.TEMP then
local idEntityToDelete = idCurrentEntity
idCurrentEntity = EgtGetNext( idCurrentEntity)
EgtErase( idEntityToDelete)
else
BeamLib.AddPhaseWithRawParts( PARTS[nPart].idRaw, BeamData.ptOriXR, BeamData.dPosXR, 0)
end
-- 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)
idCurrentEntity = EgtGetNext( idCurrentEntity)
end
end
-- calcolo della migliore strategia per ogni rotazione del pezzo
for dRotIndex = 1, 4 do
-- calcola le strategie applicabili
PROCESSINGS[nPart].Rotation[dRotIndex] = CalculateStrategies( PROCESSINGS[nPart].Rotation[dRotIndex], PARTS[nPart])
-- tra le calcolate, sceglie la migliore
PROCESSINGS[nPart].Rotation[dRotIndex] = GetBestStrategy( PROCESSINGS[nPart].Rotation[dRotIndex])
-- rotazione pezzo di 90° per volta
BeamLib.RotateRawPart( PARTS[nPart], 1)
-- aggiorno info pezzo
PARTS[nPart].b3Raw = EgtGetRawPartBBox( PARTS[nPart].idRaw)
PARTS[nPart].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[nPart].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
end
-- ordinamento lavorazioni
-- TODO completare ordinamento. Mancano le dipendenze.
-- TODO la FinalizeSorting andrebbe rimossa e usato un sorting che non viola le dipendenze
MACHININGS = MachiningLib.PrepareMachiningsForSorting( PARTS[nPart])
MACHININGS = BeamLib.StableSort( MACHININGS, MachiningLib.CompareMachinings)
MACHININGS = MachiningLib.FinalizeSorting()
-- scrittura nel log del risultato della scelta della strategia migliore tra quelle disponibili
if EgtGetDebugLevel() >= 3 then
Logs.WriteFeaturesLog( PROCESSINGS[nPart], PARTS[nPart])
end
-- 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 bIsCombinationMachinable = false
local vProc, MatrixResult
while not bIsCombinationMachinable do
bIsCombinationMachinable = true
local bAllStrategiesApplied = false
-- si calcola la combinazione di lavorazione migliore
vProc, MatrixResult = GetBestResultFromCombinationsMatrix( PROCESSINGS[nPart], PARTS[nPart])
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)
EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( PARTS[nPart].idRaw) .. ' Part=' .. tostring( PARTS[nPart].id) .. ' ***', 1)
-- debug
if EgtGetDebugLevel() >= 1 then
PrintFeatures( vProc, PARTS[nPart])
end
EgtOutLog( ' *** AddMachinings ***', 1)
-- 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
-- anche se non ci sono feature da eseguire, bisogna comunque scrivrere i risultati
for nProc = 1, #vProc do
AddFeatureResultToGlobalList( vProc[nProc])
end
-- altrimenti si fanno tutti i calcoli
else
-- ordinamento di base delle feature
vProc = OrderFeatures( vProc)
-- esegue le strategie migliori che ha precedentemente scelto e salva le lavorazioni nella lista globale
bAllStrategiesApplied = false
MACHININGS, bAllStrategiesApplied = CalculateMachinings( vProc, PARTS[nPart], MatrixResult.nInitialPosition)
bIsCombinationMachinable = bAllStrategiesApplied
end
-- salvo sul PART la posizione di partenza che è stata scelta
PARTS[nPart].nInitialPosition = MatrixResult.nInitialPosition
-- aggiunge tagli testa e coda in fasi opportune
local nRotHeadCut = MatrixResult.nInitialPosition + MACHININGS.Info.nHeadCutRotation - 1
if nRotHeadCut > 4 then
nRotHeadCut = nRotHeadCut - 4
end
local nRotSplitCut = MatrixResult.nInitialPosition + MACHININGS.Info.nSplitCutRotation - 1
if nRotSplitCut > 4 then
nRotSplitCut = nRotSplitCut - 4
end
-- 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].bSide = true
elseif MACHININGS.Info.nHeadCutRotation == 3 then
PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc].bDown = true
end
-- si imposta flag rotazione per taglio di coda
if MACHININGS.Info.nSplitCutRotation == 2 then
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bSide = true
elseif MACHININGS.Info.nSplitCutRotation == 3 then
PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc].bDown = true
end
local vProcHeadTail = {}
table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotHeadCut][MatrixResult.nIndexHeadCutInVProc])
table.insert( vProcHeadTail, PROCESSINGS[nPart].Rotation[nRotSplitCut][MatrixResult.nIndexTailCutInVProc])
bAllStrategiesApplied = false
MACHININGS, bAllStrategiesApplied = CalculateMachinings( vProcHeadTail, PARTS[nPart], MatrixResult.nInitialPosition)
bIsCombinationMachinable = bIsCombinationMachinable and bAllStrategiesApplied
end
-- cancellazione entità create ma non usate
-- TODO funzione?
local idAddGroup = BeamLib.GetAddGroup( PARTS[nPart].id)
local idCurrentEntity = EgtGetFirstInGroup( idAddGroup or GDB_ID.NULL)
while idCurrentEntity do
if EgtGetLevel( idCurrentEntity) == GDB_LV.TEMP then
local idEntityToDelete = idCurrentEntity
idCurrentEntity = EgtGetNext( idCurrentEntity)
EgtErase( idEntityToDelete)
else
idCurrentEntity = EgtGetNext( idCurrentEntity)
end
end
-- ordinamento lavorazioni
-- TODO completare ordinamento. Mancano le dipendenze.
-- TODO la FinalizeSorting andrebbe rimossa e usato un sorting che non viola le dipendenze
MACHININGS = MachiningLib.PrepareMachiningsForSorting( PARTS[nPart])
MACHININGS = BeamLib.StableSort( MACHININGS, MachiningLib.CompareMachinings)
MACHININGS = MachiningLib.FinalizeSorting()
-- 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)
EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( PARTS[nPart].idRaw) .. ' Part=' .. tostring( PARTS[nPart].id) .. ' ***', 1)
-- creazione effettiva delle lavorazioni
MACHININGS.Info = {}
local nCurrPosition = 1
local 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 = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'DOWN')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
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
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 = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'SIDE')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
end
-- creazione effettiva delle lavorazioni
MACHININGS.Info = {}
local nCurrPosition = 1
local 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 = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'DOWN')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
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 or MatrixResult.bSomeFeatureSide then
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', 'END2')
EgtSetInfo( idDisp, 'TYPE', 'MID2')
else
EgtSetInfo( idDisp, 'TYPE', 'MID')
end
end
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
-- aggiunta lavorazioni in ultima fase
MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD')
EgtOutLog( ' *** End AddMachinings ***', 1)
-- azzero lavorazioni per pezzo successivo
MACHININGS = {}
MACHININGS.Info = {}
-- indice pezzo successivo
nOrd = nOrd + 1
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 = MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'SIDE')
bSplitAlreadyExecuted = bSplitAlreadyExecuted or bSplitExecutedOnRot
end
-- ===== 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')
-- 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)
end
-- Aggiornamento finale di tutto
EgtSetCurrPhase( 1)
local bApplOk, sApplErrors, sApplWarns = EgtApplyAllMachinings()
-- TODO a cosa serve questo ricalcolo? Con nuovo sistema si può eliminare?
-- eventuale ricalcolo per macchine tipo PF (ma tengo warning del primo calcolo)
if EgtExistsInfo( EgtGetCurrMachGroup(), 'RECALC') then
EgtOutLog( ' **** RECALC ****')
bApplOk, sApplErrors, _ = EgtApplyAllMachinings()
EgtRemoveInfo( EgtGetCurrMachGroup(), 'RECALC')
end
-- TODO qui restituire errori in modo migliore, come per feature
-- TODO in caso di lavorazioni di coda saltate, l'informazione va restituita anche sulle singole feature
if not bApplOk then
nTotErr = nTotErr + 1
AddApplyResultToGlobalList( 1, 0, sApplErrors)
elseif sApplWarns and #sApplWarns > 0 then
local vLine = EgtSplitString( sApplWarns, '\r\n')
for i = 1, #vLine do
local nPos = vLine[i]:find( '(WRN', 1, true)
if nPos then
local sData = vLine[i]:sub( nPos + 1, -2)
local vVal = EgtSplitString( sData, ',')
local nWarn = EgtGetVal( vVal[1] or '', 'WRN', 'i')
local nCutId = EgtGetVal( vVal[2] or '', 'CUTID', 'i')
if nWarn and nCutId then
AddApplyResultToGlobalList( -nWarn, nCutId, vLine[i])
end
end
-- se c'è già stata separazione
if bSplitAlreadyExecuted then
EgtSetInfo( idDisp, 'TYPE', 'END2')
else
EgtSetInfo( idDisp, 'TYPE', 'MID')
end
end
-- TODO per il momento non si cicla mai una seconda volta. Controllare anche parametro modalità scelta strategia
-- Gestione da fare completamente. La strategia che ha generato una lavorazione con errore deve essere annullata
-- si può salvare una lista delle strategie da non utilizzare e, nella CalculateStrategy, settare quella specifica strategia come non valida
-- si fa un reset del MACH e poi si ritorna a inizio ciclo e si rifà tutto
-- se i cicli superano il massimo si esce (nell'ultimo ciclo possibile si potrebbe escludere la feature e basta, anche se avesse altre strategie da provare)
if true or nCurrLoop > nMaxLoops then
ProcessCompleted = true
BeamLib.RotateRawPart( PARTS[nPart], nInitialPosition - 1)
-- aggiunta lavorazioni in ultima fase
MachiningLib.AddOperations( MACHININGS, PARTS[nPart], 'STD')
EgtOutLog( ' *** End AddMachinings ***', 1)
-- azzero lavorazioni per pezzo successivo
MACHININGS = {}
MACHININGS.Info = {}
-- indice pezzo successivo
nOrd = nOrd + 1
end
-- ===== 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, sApplErrors, sApplWarns = EgtApplyAllMachinings()
-- TODO a cosa serve questo ricalcolo? Con nuovo sistema si può eliminare?
-- eventuale ricalcolo per macchine tipo PF (ma tengo warning del primo calcolo)
if EgtExistsInfo( EgtGetCurrMachGroup(), 'RECALC') then
EgtOutLog( ' **** RECALC ****')
bApplOk, sApplErrors, _ = EgtApplyAllMachinings()
EgtRemoveInfo( EgtGetCurrMachGroup(), 'RECALC')
end
-- TODO qui restituire errori in modo migliore, come per feature
-- TODO in caso di lavorazioni di coda saltate, l'informazione va restituita anche sulle singole feature
if not bApplOk then
nTotErr = nTotErr + 1
AddApplyResultToGlobalList( 1, 0, sApplErrors)
elseif sApplWarns and #sApplWarns > 0 then
local vLine = EgtSplitString( sApplWarns, '\r\n')
for i = 1, #vLine do
local nPos = vLine[i]:find( '(WRN', 1, true)
if nPos then
local sData = vLine[i]:sub( nPos + 1, -2)
local vVal = EgtSplitString( sData, ',')
local nWarn = EgtGetVal( vVal[1] or '', 'WRN', 'i')
local nCutId = EgtGetVal( vVal[2] or '', 'CUTID', 'i')
if nWarn and nCutId then
AddApplyResultToGlobalList( -nWarn, nCutId, vLine[i])
end
end
end
end