- Aggiunto FLAG = 10 per QUICK_VERIFY (ancora da fare)

- Gestione inversione pezzo solo se durante la fase di QUICK_VERIFY
- Gestione rotazioni ADVANCED, verrà utilizzata solo durante QUICK_VERIFY. In tutti gli altri casi è standard (come ha sempre funzionato) senza calcolo prerotazioni.
This commit is contained in:
andrea.villa
2025-07-08 18:03:04 +02:00
parent 702d4617a0
commit 8211fbc4b0
4 changed files with 157 additions and 127 deletions
+133 -120
View File
@@ -233,24 +233,9 @@ end
-------------------------------------------------------------------------------------------------------------
-- funzione che controlla validità delle combinazioni proposte
local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection)
-- se non utilizzo BEAMWALL, forzo comportamento BASIC
if not BEAM.BW or not BEAM.Rotation then
BEAM.Rotation = {}
BEAM.Rotation.Basic = true
end
--------------------------------------------------------------------------
-- TODO scelta combinazione forzato DA RIMUOVERE!! Serve modifica al BEAM.
BEAM.BeamWall = true
BEAM.Rotation = {}
BEAM.Rotation.bBasic = false
BEAM.Rotation.bNoRotation = false
BEAM.Rotation.bAdvanced = true
--------------------------------------------------------------------------
-- BASIC : posizione di scarico come posizionamento iniziale
if not BEAM.BeamWall or BEAM.Rotation.bBasic then
local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection, bCalcBestPieceUnloadPosition)
-- STANDARD : posizione di scarico come posizionamento iniziale
if not bCalcBestPieceUnloadPosition then
local ExtraRotation = nUnloadPos + 3
if nUnloadPos ~= 1 then
return false
@@ -265,6 +250,7 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection)
else
return false
end
-- TODO capire come passare info che il pezzo non ha bisogno di rotazioni per velocizzare il caclolo. Magari non serve neanche entrare in questa funzione
-- NO ROTATION : solo posizione di partenza
elseif BEAM.Rotation.bNoRotation then
if sCombination == '1000' and nUnloadPos == 1 then
@@ -272,8 +258,8 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection)
else
return false
end
-- ADVANCED : come BASIC ma ammesse anche le prerotazioni (posizione di scarico può essere diversa da posizione iniziale)
elseif BEAM.Rotation.bAdvanced then
-- PREROTATION : ammesse anche le prerotazioni e le inversioni (serve per preparare il pezzo nella posizione migliore prima di metterlo nella barra)
elseif bCalcBestPieceUnloadPosition then
local nRotation90 = EgtIf( nUnloadPos + 1 > 4, nUnloadPos + 1 - 4, nUnloadPos + 1)
local nRotation180 = EgtIf( nUnloadPos + 2 > 4, nUnloadPos + 2 - 4, nUnloadPos + 2)
local nExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3)
@@ -297,37 +283,45 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection)
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.GetAvailableCombinations( PartInfo)
function BeamExec.GetAvailableCombinations( PartInfo, bCalcBestPieceUnloadPosition)
local CombinationList = {}
CombinationList.Rotations = {0, 0, 0, 0} -- indice rotazione attiva, per calcolo collect feature
-- se sto effettivamente calcolando, il pezzo è già in posizione e non può essere invertito. Se sono in preverifica, allora devo consoderare anche eventuali inversioni del pezzo
local nCycles = EgtIf( bCalcBestPieceUnloadPosition, 2, 1)
-- verifico tutte le combinazioni che possono essere considerate
for nUnloadPos = 1, 4 do
for i = 1, BeamLib.BinaryToDecimal( 1111) do
local nBitIndexCombination = BeamLib.DecimalToBinary( i)
local sBitIndexCombination = BeamLib.CalculateStringBinaryFormat( nBitIndexCombination, 4)
-- si calcolano le combinazioni all'inizio, ottimizzando calcolo della collect solo nelle rotazioni che possono essere considerate
if IsCombinationAvailable( sBitIndexCombination, nUnloadPos, PartInfo.bSquareSection) then
local Combination = {}
Combination.sBitIndexCombination = sBitIndexCombination
Combination.nUnloadPos = nUnloadPos
table.insert( CombinationList, Combination)
for nInvertIndex = 1, nCycles do
for nUnloadPos = 1, 4 do
for i = 1, BeamLib.BinaryToDecimal( 1111) do
local nBitIndexCombination = BeamLib.DecimalToBinary( i)
local sBitIndexCombination = BeamLib.CalculateStringBinaryFormat( nBitIndexCombination, 4)
-- si calcolano le combinazioni all'inizio, ottimizzando calcolo della collect solo nelle rotazioni che possono essere considerate
if IsCombinationAvailable( sBitIndexCombination, nUnloadPos, PartInfo.bSquareSection, bCalcBestPieceUnloadPosition) then
local Combination = {}
Combination.sBitIndexCombination = sBitIndexCombination
Combination.nUnloadPos = nUnloadPos
table.insert( CombinationList, Combination)
-- se posizionamento iniziale attivo
if string.sub( sBitIndexCombination, 1, 1) == '1' then
CombinationList.Rotations[1] = 1
end
-- se attiva rotazione 90
if string.sub( sBitIndexCombination, 2, 2) == '1' then
CombinationList.Rotations[2] = 1
end
-- se attiva rotazione 180
if string.sub( sBitIndexCombination, 3, 3) == '1' then
CombinationList.Rotations[3] = 1
end
-- se attiva rotazione 270
if string.sub( sBitIndexCombination, 4, 4) == '1' then
CombinationList.Rotations[4] = 1
if nInvertIndex == 2 then
Combination.bPartIsInverted = true
end
-- se posizionamento iniziale attivo
if string.sub( sBitIndexCombination, 1, 1) == '1' then
CombinationList.Rotations[1] = 1
end
-- se attiva rotazione 90
if string.sub( sBitIndexCombination, 2, 2) == '1' then
CombinationList.Rotations[2] = 1
end
-- se attiva rotazione 180
if string.sub( sBitIndexCombination, 3, 3) == '1' then
CombinationList.Rotations[3] = 1
end
-- se attiva rotazione 270
if string.sub( sBitIndexCombination, 4, 4) == '1' then
CombinationList.Rotations[4] = 1
end
end
end
end
@@ -338,7 +332,7 @@ end
-------------------------------------------------------------------------------------------------------------
-- *** funzioni posizionamento pezzi all'interno della barra ***
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup)
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bCalcBestPieceUnloadPosition)
-- default per nuove costanti qualora non definite
BeamData.OVM_BLADE_HBEAM = ( BeamData.OVM_BLADE_HBEAM or 11)
BeamData.OVM_CHAIN_HBEAM = ( BeamData.OVM_CHAIN_HBEAM or 8)
@@ -470,7 +464,7 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, b
PARTS[i].bSquareSection = abs( PARTS[i].dWidth - PARTS[i].dHeight) < 100 * GEO.EPS_SMALL
PARTS[i].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
PARTS[i].nIndexInParts = i
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i])
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition)
PARTS[i].SplittingPoints = BeamLib.GetPartSplittingPoints( PARTS[i])
PARTS[i].NotClampableLength = { STD = { dHead = 0, dTail = 0}, SIDE = { dHead = 0, dTail = 0}, DOWN = { dHead = 0, dTail = 0}}
else
@@ -1160,7 +1154,7 @@ local function PrintFeatures( vProc, Part)
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.GetProcessings( PARTS)
function BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
-- recupero tutti i processing di tutti i pezzi in tutte le rotazioni
-- TODO calcolo tempi da rimuovere o lasciare solo per debug
-- if EgtGetDebugLevel() >= 3 then
@@ -1174,24 +1168,36 @@ function BeamExec.GetProcessings( PARTS)
if not PARTS[nPart].id and PARTS[nPart].b3Raw:getDimX() < BeamData.dMinRaw then break end
local vProcRot = {}
for dRotIndex = 1, 4 do
-- si calcolano le feature solo se la rotazione può essere presa in considerazione
if PARTS[nPart].CombinationList.Rotations[dRotIndex] == 1 then
-- recupero le feature di lavorazione della trave
table.insert( vProcRot, CollectFeatures( PARTS[nPart], dRotIndex))
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
-- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no
vProcRot[dRotIndex] = GetFeatureInfoAndDependency( vProcRot[dRotIndex], PARTS[nPart])
else
-- inserisco una tabella vuota
table.insert( vProcRot, {})
local nCycles = EgtIf( bCalcBestPieceUnloadPosition, 2, 1) -- se è prerotazione, oltre al ciclo normale, si devono verificare anche invertiti
-- per ogni inversione
for nInvertIndex = 1, nCycles do
-- per ogni rotazione
for nRotIndex = 1, 4 do
local nOffsetIndex = EgtIf( nInvertIndex == 2, 4, 0)
local nIndex = nRotIndex + nOffsetIndex
-- si calcolano le feature solo se la rotazione può essere presa in considerazione
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])
else
-- inserisco una tabella vuota
table.insert( vProcRot, {})
end
-- 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
if bCalcBestPieceUnloadPosition then
-- inversione pezzo testa-coda
BeamLib.InvertRawPart( PARTS[nPart], 2)
-- TODO in caso di parallelepipedo rettangolare, non serve ricalcolare il box. Se grezzo sagomato potrebbe essere necessario. Da verificare.
end
-- 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
local Part = {}
Part.Rotation = vProcRot
@@ -1330,7 +1336,7 @@ end
-------------------------------------------------------------------------------------------------------------
-- funzione che calcola le combinazioni di rotazione per lavorare la trave e sceglie la migliore
local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo)
local BestCombination = {}
local CombinationsList = {}
@@ -1350,6 +1356,8 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
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.bPartIsInverted = PartInfo.CombinationList[i].bPartIsInverted
SingleCombination.nUnloadPos = nUnloadPos
-- creo liste dei proc suddivisi per rotazione
SingleCombination.Rot0 = {}
@@ -1360,6 +1368,7 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
-- 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
-- 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
@@ -1368,17 +1377,18 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
else
-- ciclo sulle rotazioni
local nNextRot = nUnloadPos
local nOffsetIndex = EgtIf( SingleCombination.bPartIsInverted, 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
-- 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
if nNextRot == nUnloadPos or not( ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc].bHindersLaserMeasure) then
-- controllo se è stata scelta una strategia
if ProcessingsOnPart.Rotation[nNextRot][nProc].ChosenStrategy then
if ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc].ChosenStrategy then
local Proc = {}
Proc.nRotation = nNextRot
table.insert( Proc, ProcessingsOnPart.Rotation[nNextRot][nProc])
table.insert( Proc, ProcessingsOnPart.Rotation[nNextRot+nOffsetIndex][nProc])
table.insert( ResultsList, Proc)
end
end
@@ -1408,9 +1418,9 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
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])
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
end
@@ -1428,38 +1438,34 @@ local function GetBestResultFromCombinationsMatrix( ProcessingsOnPart, PartInfo)
table.insert( CombinationsList, SingleCombination)
end
-- ci deve essere almeno una combinazione, altrimenti errore
if #CombinationsList < 1 then
error( 'UNEXPECTED ERROR: NO combinations available')
end
BestCombination = GetBestCombination( CombinationsList)
PartInfo.ChosenCombination = BestCombination.sBitIndexCombination
-- scrittura nel log delle combinazioni possibili
if EgtGetDebugLevel() >= 3 then
Logs.WriteCombinationLog( CombinationsList, BestCombination)
end
local vFinalProc, BestCombinationResult = GetProcessingListFromCombination( BestCombination)
return vFinalProc, BestCombinationResult
return CombinationsList
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.GetCombinationMatrix( PARTS)
function BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
-- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni
for nPart = 1, #PARTS do
local nCycles = EgtIf( bCalcBestPieceUnloadPosition, 2, 1)
-- per ogni inversione
for nInvertIndex = 1, nCycles 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)
for nRotIndex = 1, 4 do
local nOffsetIndex = EgtIf( nInvertIndex == 2, 4, 0)
local nIndex = nRotIndex + nOffsetIndex
-- calcola le strategie applicabili
PROCESSINGS[nPart].Rotation[nIndex] = CalculateStrategies( PROCESSINGS[nPart].Rotation[nIndex], PARTS[nPart])
-- tra le calcolate, sceglie la migliore
PROCESSINGS[nPart].Rotation[nIndex] = GetBestStrategy( PROCESSINGS[nPart].Rotation[nIndex])
-- 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
if bCalcBestPieceUnloadPosition then
-- inversione del pezzo testa-coda
BeamLib.InvertRawPart( PARTS[nPart], 2)
end
end
end
end
@@ -1494,6 +1500,34 @@ function BeamExec.ProcessMachinings( PARTS)
-- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni
for nPart = 1, #PARTS do
-- 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 bAllStrategiesApplied = false
-- si ricavano tutte le combinazioni possibili
local CombinationListFromMatrix = GetCombinationListFromMatrix( PROCESSINGS[nPart], PARTS[nPart])
-- ci deve essere almeno una combinazione, altrimenti errore
if #CombinationListFromMatrix < 1 then
error( 'UNEXPECTED ERROR: NO combinations available')
end
-- scelta delal migliore combinazione
local BestCombination = GetBestCombination( CombinationListFromMatrix)
PARTS[nPart].ChosenCombination = BestCombination.sBitIndexCombination
-- scrittura nel log delle combinazioni possibili
if EgtGetDebugLevel() >= 3 then
Logs.WriteCombinationLog( CombinationListFromMatrix, BestCombination)
end
-- compilazione della vProc finale contenente le feature da lavorare nella giusta rotazione
local vProc, MatrixResult = GetProcessingListFromCombination( BestCombination)
-- si mette subito il pezzo nella fase
if nOrd == 1 then
EgtSetCurrPhase( 1)
@@ -1510,27 +1544,6 @@ function BeamExec.ProcessMachinings( PARTS)
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])