Merge branch 'NewRotationMng' into develop

This commit is contained in:
andrea.villa
2026-03-02 13:26:56 +01:00
7 changed files with 802 additions and 149 deletions
+4 -7
View File
@@ -214,9 +214,6 @@ end
local sLog = 'BatchProcess : ' .. BEAM.FILE .. ', ' .. ( BEAM.MACHINE or EgtGetCurrMachineName()) .. ', ' .. sFlag
EgtOutLog( sLog)
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
local bCalcBestPieceUnloadPosition = true or BEAM.FLAG == 10
-- Dati dei file
-- TODO spostare a quando flag ~= 6 e 9
local sDir, sTitle = EgtSplitPath( BEAM.FILE)
@@ -551,7 +548,7 @@ if bToProcess then
end
-- Sistemo le travi nel grezzo
local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, bCalcBestPieceUnloadPosition)
local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, false)
if not bPbOk then
BEAM.ERR = 18
BEAM.MSG = sPbErr
@@ -640,7 +637,7 @@ if bToProcess then
BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig)
PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON)
TIMER:stopElapsed('Json')
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition)
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], false)
-- sovramateriale in testa al pezzo
local dDeltaS = max( PARTS[i].dPosX - ( dBarLen - dLen), 0)
@@ -693,8 +690,8 @@ if bToProcess then
-- TODO gestire errori e messaggi di ritorno in questo caso
if not GetDataConfig() then return end
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.GetProcessings( PARTS, false)
BeamExec.GetCombinationMatrix( PARTS, false)
BeamExec.ProcessMachinings( PARTS)
-- si cancella gruppo temporaneo contenente entità da cancellare
+242
View File
@@ -0,0 +1,242 @@
-- Process.lua by Egalware s.r.l. 2024/04/02
-- Gestione calcolo disposizione e lavorazioni per Travi
-- Si opera sulla macchina corrente
-- 2024/04/02 PRIMA VERSIONE
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua')
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
if not sMachDir then
EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR')
return
end
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamDataNew.lua') then
EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR')
return
end
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Segnalazione avvio
EgtOutLog( '*** Beam Process Start ***', 1)
-- Carico le librerie
_G.package.loaded.BasicCustomerStrategies = nil
_G.package.loaded.BeamExec = nil
_G.package.loaded.BeamLib = nil
_G.package.loaded.DiceCut = nil
_G.package.loaded.FaceData = nil
_G.package.loaded.FeatureLib = nil
_G.package.loaded.Identity = nil
_G.package.loaded.Logs = nil
_G.package.loaded.MachiningLib = nil
_G.package.loaded.PreSimulationLib = nil
_G.package.loaded.LeadInOutLib = nil
-- strategie di base sempre presenti
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
-- libreria macchina
_G.package.loaded.BeamDataNew = nil
-- libreria calcolo tempo esecuzione
_G.package.loaded.TimeLib = nil
-- TODO controllare se c'è un modo migliore per resettare librerie delle strategie caricate precedentemente
-- Per ottimizzare potremmo anche ciclare solo fino al numero di strategie raggiunto per il momento.
-- Infatti difficile ci siano 9999 strategie.
-- reset strategie caricate come librerie
for i = 1, 9999 do
local idSTRTemp = EgtReplaceString( EgtNumToString( i/10000, -4), '0.', '')
local sLibraryToReload = "STR" .. idSTRTemp .. "\\STR" .. idSTRTemp
if _G.package.loaded[sLibraryToReload] then
_G.package.loaded[sLibraryToReload] = nil
end
end
local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\StrategyLibs\\*.lua')
for i = 1, #vtCoreStrategiesNames do
local sCurrentName = EgtSplitString( vtCoreStrategiesNames[i], '.')[1]
if _G.package.loaded[sCurrentName] then
_G.package.loaded[sCurrentName] = nil
end
end
-- Variabili globali
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-- Carico i dati globali
local BeamData = require( 'BeamDataNew')
-- carico librerie
local BeamExec = require( 'BeamExec')
local BeamLib = require( 'BeamLib')
-------------------------------------------------------------------------------------------------------------
-- *** Recupero trave (E' SEMPRE E SOLO UNA) ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessInputData()
-- Recupero il pezzo e i suoi dati
local nId = EgtGetFirstPart()
if nId then
table.insert( PARTS, { nInd = #PARTS + 1, id = nId, sName = ( EgtGetName( nId) or ( 'Id=' .. tonumber( nId)))})
local Ls = EgtGetFirstNameInGroup( PARTS[1].id, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
return false
end
PARTS[1].b3PartOriginal = b3Solid
else
return false
end
return true
end
-------------------------------------------------------------------------------------------------------------
local function GetDataConfig()
-- recupero utensili dal magazzino
BeamExec.GetToolsFromDB()
-- TODO da gestire eventuali errori bloccanti
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Inserimento delle travi nel grezzo ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessBeams()
-- Lunghezza totale delle travi
local dLen = PARTS[1].b3PartOriginal:getDimX()
local dRawW = PARTS[1].b3PartOriginal:getDimY()
local dRawH = PARTS[1].b3PartOriginal:getDimZ()
-- Determinazione minimo grezzo scaricabile
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH)
local dOvmHead = BeamData.OVM_HEAD or 10
local dOvmMid = BeamData.OVM_MID or 10
local dRawL = max( dLen + dOvmHead + dOvmMid, BeamData.dMinRaw)
-- Recupero info pezzi
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, true)
if not bOk then
EgtOutLog( sErr)
return false
end
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Inserimento delle lavorazioni nelle travi ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessFeatures()
BeamExec.GetProcessings( PARTS, true)
BeamExec.GetCombinationMatrix( PARTS, true)
BeamExec.ProcessMachinings( PARTS)
local nErrCnt = 0
local nWarnCnt = 0
local sOutput = ''
for i = 1, #RESULT do
local sMsg = ''
if RESULT[i].sType == 'Feature' then
sMsg = RESULT[i].ChosenStrategy.sInfo
elseif RESULT[i].sType == 'Part' then
sMsg = RESULT[i].sMsg
end
sMsg = string.gsub( sMsg or '', '\n', ' ', 10)
sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
-- trovata almeno una strategia e feature lavorata completamente
if RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Completed' then
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg or '')
-- trovata almeno una strategia ma nessuna applicabile oppure non trovata alcuna strategia
elseif RESULT[i].sType == 'Feature'
and ( ( RESULT[i].ChosenStrategy.sStatus == 'Not-Applicable')
or ( not RESULT[i].ChosenStrategy.sStrategyName)) then
nErrCnt = nErrCnt + 1
if #sMsg == 0 then
sMsg = 'No applicable strategy found'
end
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
else
-- segnalazione scarico pezzo standard, incompleto o a caduta
if RESULT[i].sType == 'Part' and ( RESULT[i].nErr == -100 or RESULT[i].nErr == -101 or RESULT[i].nErr == -102) then
-- nulla da segnalare
-- feature incompleta e altro
elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then
nWarnCnt = nWarnCnt + 1
sMsg = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
end
end
end
-- si calcolano alternative
TIMER:startElapsed('Alternatives')
BeamExec.ProcessAlternatives( PARTS)
TIMER:stopElapsed('Alternatives')
-- cancello gruppo temporaneo
local idTempGroup = BeamLib.GetTempGroup()
EgtErase( idTempGroup)
if #sOutput > 0 then EgtOutLog( sOutput) end
if nErrCnt > 0 then
EgtOutBox( sOutput, 'Lavora Travi', 'ERRORS')
return false
elseif nWarnCnt > 0 then
EgtOutBox( sOutput, 'Lavora Travi', 'WARNINGS')
return true
end
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Esecuzione ***
-------------------------------------------------------------------------------------------------------------
-- calcolo tempo esecuzione
TIMER:start()
EgtOutLog( ' Execution timer started')
-- script principale
if not MyProcessInputData() then return end
-- recupero parametri generali da progetto
BeamExec.GetGeneralParameters()
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
BeamLib.CreateTempGroup()
if not MyProcessBeams() then return end
if not GetDataConfig() then return end
-- Abilito Vmill
EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
MyProcessFeatures()
-- log tempi di esecuzione
if EgtGetDebugLevel() >= 3 then
TIMER:logAllElapsed()
end
+492 -119
View File
@@ -251,28 +251,28 @@ function BeamExec.GetStrategiesFromJSONinBD( sAISetupConfigName)
end
end
-- TODO prevedere parametri per preferire carico del pezzo verticale oppure orizzontale?
-------------------------------------------------------------------------------------------------------------
-- funzione che controlla validità delle combinazioni proposte
local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection, GeneralParameters, bCalcBestPieceUnloadPosition)
local function IsCombinationAvailable( sCombination, nUnloadPos, GeneralParameters, bIsFlipRot)
-- PREROTATION : flip-rot, si considerano tutte le posizioni possibili, a meno che non si voglia come da BTL
if bCalcBestPieceUnloadPosition and GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' then
if bIsFlipRot and GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION' 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)
if not bSquareSection and ( nUnloadPos == 2 or nUnloadPos == 4) then
-- se fase di unload disabilitata e soluzioni con terza rotazione sempre disabilitate
if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, nExtraRotation, nExtraRotation) == '1' then
return false
elseif GeneralParameters.GEN_sPiecesLoadingPosition == 'STD_PRE_ROTATION' and ( nUnloadPos == 2 or nUnloadPos == 4) then
return false
else
if string.sub( sCombination, nUnloadPos, nUnloadPos) ~= '1' or string.sub( sCombination, nExtraRotation, nExtraRotation) == '1' then
if ( not BeamData.ROT90 or GeneralParameters.GEN_sPiecesLoadingPosition == 'STD_PRE_ROTATION') and string.sub( sCombination, nRotation90, nRotation90) == '1' then
return false
elseif not BeamData.ROT180 and string.sub( sCombination, nRotation180, nRotation180) == '1' then
return false
else
if not BeamData.ROT90 and string.sub( sCombination, nRotation90, nRotation90) == '1' then
return false
elseif not BeamData.ROT180 and string.sub( sCombination, nRotation180, nRotation180) == '1' then
return false
else
return true
end
return true
end
end
-- se invece si è nel caso standard di calcolo
@@ -286,7 +286,7 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection,
end
-- STANDARD : posizione di scarico come posizionamento iniziale
else
local ExtraRotation = nUnloadPos + 3
local ExtraRotation = EgtIf( nUnloadPos + 3 > 4, nUnloadPos + 3 - 4, nUnloadPos + 3)
if nUnloadPos ~= 1 then
return false
elseif string.sub( sCombination, nUnloadPos, nUnloadPos) == '1' and string.sub( sCombination, ExtraRotation, ExtraRotation) == '0' then
@@ -305,12 +305,16 @@ local function IsCombinationAvailable( sCombination, nUnloadPos, bSquareSection,
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.GetAvailableCombinations( PartInfo, bCalcBestPieceUnloadPosition)
function BeamExec.GetAvailableCombinations( PartInfo, bIsFlipRot)
local CombinationList = {}
CombinationList.Rotations = {0, 0, 0, 0} -- indice rotazione attiva, per calcolo collect feature
local nCycles = 1
-- se si sta calcolando il migliore posizionamento del pezzo, verifico se sono ammesse le combinazioni con pezzo invertito
if bIsFlipRot and PartInfo.GeneralParameters.GEN_bAllowPieceInversion then
nCycles = 2
end
-- se sto effettivamente calcolando, il pezzo è già in posizione e non può essere invertito. Se sono in preverifica, allora devo considerare anche eventuali inversioni del pezzo
local nCycles = EgtIf( bCalcBestPieceUnloadPosition and PartInfo.GeneralParameters.GEN_sPiecesLoadingPosition == 'BEST_POSITION', 2, 1)
-- verifico tutte le combinazioni che possono essere considerate
for nInvertIndex = 1, nCycles do
for nUnloadPos = 1, 4 do
@@ -318,7 +322,7 @@ function BeamExec.GetAvailableCombinations( PartInfo, bCalcBestPieceUnloadPositi
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, PartInfo.GeneralParameters, bCalcBestPieceUnloadPosition) then
if IsCombinationAvailable( sBitIndexCombination, nUnloadPos, PartInfo.GeneralParameters, bIsFlipRot) then
local Combination = {}
Combination.sBitIndexCombination = sBitIndexCombination
Combination.nUnloadPos = nUnloadPos
@@ -354,7 +358,7 @@ end
-------------------------------------------------------------------------------------------------------------
-- *** funzioni posizionamento pezzi all'interno della barra ***
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bCalcBestPieceUnloadPosition)
function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, bCreateMachGroup, bIsFlipRot)
-- gruppo per geometrie temporanee
local idTempGroup = BeamLib.GetTempGroup()
@@ -504,7 +508,7 @@ function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, b
BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig)
PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON)
TIMER:stopElapsed('Json')
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition)
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bIsFlipRot)
PARTS[i].idTempGroup = idTempGroup
else
@@ -966,7 +970,6 @@ local function CalculateStrategies( vProcSingleRot, Part)
-- eseguo file config con i parametri di default
local CurrentStrategy = {}
CurrentStrategy = RunStrategyLibraries( Proc.AvailableStrategies[nIndexCurrentStrategy].sStrategyId)
-- TODO in caso di ulteriore ciclo dovuto a errori imprevisti, controllare se questa strategia è quella che ha dato errore e disabilitarla senza calcolare nulla
-- controllo che le librerie siano state effettivamente caricate
if CurrentStrategy.Config and CurrentStrategy.Script then
-- eseguo la strategia solo come calcolo fattibilità e voto. Non si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati
@@ -1224,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)
@@ -1235,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
@@ -1246,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])
@@ -1260,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
@@ -1436,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
@@ -1554,10 +1574,10 @@ local function GetCombinationListFromMatrix( ProcessingsOnPart, PartInfo, bRePro
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
function BeamExec.GetCombinationMatrix( PARTS, bIsFlipRot)
-- ricerca strategia di lavorazione per ogni pezzo e applicazione lavorazioni
for nPart = 1, #PARTS do
local nCycles = EgtIf( bCalcBestPieceUnloadPosition and PARTS[nPart].GeneralParameters.GEN_sPiecesLoadingPosition ~= 'BTL_POSITION', 2, 1)
local nCycles = EgtIf( bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion, 2, 1)
-- per ogni inversione
for nInvertIndex = 1, nCycles do
-- calcolo della migliore strategia per ogni rotazione del pezzo
@@ -1574,7 +1594,8 @@ function BeamExec.GetCombinationMatrix( 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 bisogna invertire
if bIsFlipRot and PARTS[nPart].GeneralParameters.GEN_bAllowPieceInversion then
-- inversione del pezzo testa-coda
BeamLib.InvertRawPart( PARTS[nPart], 2)
-- aggiorno info pezzo
@@ -1899,5 +1920,357 @@ function BeamExec.ProcessMachinings( PARTS)
return ( nTotErr == 0), RESULT
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessAlternatives( PARTS)
-- ciclo sui pezzi
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 and not PARTS[nPart].bSquareSection) or not PARTS[nPart].GeneralParameters.GEN_bGetAlternativesNesting2D then
return
end
-- 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 nCycles = 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
+19 -8
View File
@@ -328,6 +328,18 @@ function BeamLib.RotateRawPart( Part, nNumberOfRotations)
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateAddGroup( PartId, sGroupName)
AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
if not AddGrpId then
return false
end
-- assegno nome, flag di layer per gruppo di lavoro e colore
EgtSetName( AddGrpId, sGroupName)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateOrEmptyAddGroup( PartId)
-- recupero i dati del gruppo aggiuntivo
@@ -341,15 +353,9 @@ function BeamLib.CreateOrEmptyAddGroup( PartId)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
return EgtEmptyGroup( AddGrpId)
end
-- altrimenti lo creo
AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
if not AddGrpId then
return false
end
-- assegno nome, flag di layer per gruppo di lavoro e colore
EgtSetName( AddGrpId, sMchGrp)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
BeamLib.CreateAddGroup( PartId, sMchGrp)
return true
end
@@ -769,6 +775,11 @@ function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut)
return ''
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.StringReplaceChar( sOriginal, nPosition, sChar)
return sOriginal:sub( 1, nPosition-1) .. sChar .. sOriginal:sub( nPosition+1)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.BinaryToDecimal( dNumber)
local sNumberToConvert = tostring( dNumber)
+2 -2
View File
@@ -1420,9 +1420,9 @@ function MachiningLib.AddOperations( MACHININGS, Part, sRotation)
bSplitExecuted = true
MACHININGS.Info.bSplitExecuted = true
BeamLib.AddPhaseWithRawParts( MACHININGS[i].Proc.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
BeamLib.AddPhaseWithRawParts( Part.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
-- se grezzo successivo senza pezzi e finale, va tolto
local nNextRawId = EgtGetNextRawPart( MACHININGS[i].Proc.idRaw)
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then
EgtRemoveRawPartFromCurrPhase( nNextRawId)
end
+3 -6
View File
@@ -15,9 +15,6 @@ EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua')
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
local bCalcBestPieceUnloadPosition = true
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
if not sMachDir then
@@ -290,7 +287,7 @@ local function MyProcessBeams()
end
-- Sistemo le travi nel grezzo
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, bCalcBestPieceUnloadPosition)
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, false)
if not bOk then
EgtOutLog( sErr)
EgtOutBox( sErr, 'Lavora Travi', 'ERROR')
@@ -305,8 +302,8 @@ end
-------------------------------------------------------------------------------------------------------------
local function MyProcessFeatures()
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.GetProcessings( PARTS, false)
BeamExec.GetCombinationMatrix( PARTS, false)
BeamExec.ProcessMachinings( PARTS)
local nErrCnt = 0
local nWarnCnt = 0
+40 -7
View File
@@ -1,10 +1,10 @@
[
{
"nGroup": "MACHINE",
"nGroup": "PIECE LOADING",
"sName": "GEN_sPiecesLoadingPosition",
"sNameNge": "GEN_PIECES_LOADING",
"sValue": "BEST_POSITION",
"sValue": "BTL_POSITION",
"sDescriptionShort": "Part loading position",
"sDescriptionLong": "",
"sType": "combo",
@@ -12,24 +12,57 @@
"Choices": [
{
"sValue": "BTL_POSITION",
"sDescriptionShort": "Last piece position as BTL",
"sDescriptionShort": "Loading position from BTL, no pre-rotation",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BEST_ROTATION",
"sDescriptionShort": "Allow piece rotations",
"sValue": "STD_PRE_ROTATION",
"sDescriptionShort": "Get Best loading position from 0° and 180°",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BEST_POSITION",
"sDescriptionShort": "Allow piece rotation and inversion",
"sValue": "FULL_PRE_ROTATION",
"sDescriptionShort": "Get Best loading position in each piece rotation",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"nGroup": "PIECE LOADING",
"sName": "GEN_bAllowPieceInversion",
"sNameNge": "ADMIT_INVERSION",
"sValue": "false",
"sDescriptionShort": "Allow piece inversion",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"nGroup": "PIECE LOADING",
"sName": "GEN_bTestAlternative",
"sNameNge": "TEST_ALTERNATIVE",
"sValue": "false",
"sDescriptionShort": "Enable the possibility to load the piece 90° turned",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"nGroup": "PIECE LOADING",
"sName": "GEN_bGetAlternativesNesting2D",
"sNameNge": "GET_ALTERNATIVES_NEST2D",
"sValue": "false",
"sDescriptionShort": "Enable material optimization function in nesting",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"nGroup": "MACHINE",
"sName": "GEN_sPieceRotation",