diff --git a/BatchProcessNew.lua b/BatchProcessNew.lua index 78bfc19..ec9fc28 100644 --- a/BatchProcessNew.lua +++ b/BatchProcessNew.lua @@ -620,6 +620,7 @@ if bToProcess then -- Lavoro le features if not GetDataConfig() then return end BeamExec.GetProcessings( PARTS) + BeamExec.GetCombinationMatrix( PARTS) BeamExec.ProcessMachinings( PARTS) local sOutput = '' diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 425bcd5..af5e25d 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -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 diff --git a/Process.lua b/Process.lua index 58fc3ac..8e5ef5c 100644 --- a/Process.lua +++ b/Process.lua @@ -302,6 +302,7 @@ end ------------------------------------------------------------------------------------------------------------- local function MyProcessFeatures() BeamExec.GetProcessings( PARTS) + BeamExec.GetCombinationMatrix( PARTS) BeamExec.ProcessMachinings( PARTS) local nErrCnt = 0 local nWarnCnt = 0