From 7f7d75c113d45d07f078a8535cdbf7ec98c0f286 Mon Sep 17 00:00:00 2001 From: "andrea.villa" Date: Mon, 23 Feb 2026 16:24:43 +0100 Subject: [PATCH] =?UTF-8?q?-=20BatchProcess=20non=20calcola=20pi=C3=B9=20l?= =?UTF-8?q?e=20prerotazioni=20-=20Modifiche=20varie=20per=20nuova=20gestio?= =?UTF-8?q?ne=20pre-rotazioni=20-=20Nuovo=20script=20FlipRot=20(per=20ora?= =?UTF-8?q?=20copiata=20da=20BatchProcess,=20poi=20dovr=C3=A0=20ruotare=20?= =?UTF-8?q?i=20pezzi=20e=20posizionarli=20in=20base=20alla=20migliore=20po?= =?UTF-8?q?sizione=20di=20lavoro)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BatchProcessNew.lua | 11 +- FlipRot.lua | 940 ++++++++++++++++++++++++++++++ LuaLibs/BeamExec.lua | 47 +- Strategies/GeneralParameters.json | 25 +- 4 files changed, 988 insertions(+), 35 deletions(-) create mode 100644 FlipRot.lua diff --git a/BatchProcessNew.lua b/BatchProcessNew.lua index 312d3d8..5a0947c 100644 --- a/BatchProcessNew.lua +++ b/BatchProcessNew.lua @@ -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 diff --git a/FlipRot.lua b/FlipRot.lua new file mode 100644 index 0000000..312d3d8 --- /dev/null +++ b/FlipRot.lua @@ -0,0 +1,940 @@ +-- BatchProcessNew.lua by Egalware s.r.l. 2025/04/24 + +-- 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 e carico log txt +local sMachine = BEAM.MACHINE +local sTxtLogFile +if ( BEAM.FLAG ~= 6) and ( BEAM.FLAG ~= 9) then + EgtResetCurrMachGroup() + if not EgtSetCurrMachine( sMachine) then + BEAM.ERR = 11 + BEAM.MSG = 'Error selecting machine : ' .. sMachine + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + return + end +end +if BEAM.FLAG ~= 9 then + sTxtLogFile = EgtChangePathExtension( BEAM.FILE, '.txt') +end +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') + BEAM.ERR = 12 + BEAM.MSG = 'Error not configured for beams machine : ' .. sMachine + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + 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') +local FeatureLib = require( 'FeatureLib') +local JSON = require( 'JSON') + +-- Variabili di modulo +local dRawW +local dRawH + +------------------------------------------------------------------------------------------------------------- +-- Funzioni di supporto + +local function GetDataConfig() + -- recupero utensili dal magazzino + BeamExec.GetToolsFromDB() + -- TODO da gestire eventuali errori bloccanti + return true +end + +local function WriteErrToLogFile( nErr, sMsg, nRot, idCut, idTask) + local hFile = io.open( sTxtLogFile, 'a') + hFile:write( 'ERR=' .. tostring( nErr) .. '\n') + hFile:write( sMsg .. '\n') + hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n') + hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n') + hFile:write( 'TASKID=' .. tostring( idTask or 0) .. '\n') + hFile:close() +end + +local function WriteFallToLogFile( nErr, sMsg, idCut, nFall) + local hFile = io.open( sTxtLogFile, 'a') + hFile:write( 'ERR=' .. tostring( nErr) .. '\n') + hFile:write( sMsg .. '\n') + hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n') + hFile:write( 'FALL=' .. tostring( nFall or 0) .. '\n') + hFile:close() +end + +local function WriteTimeToLogFile( dTime) + local hFile = io.open( sTxtLogFile, 'a') + hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n') + hFile:close() +end + +-- Funzioni per gestire visualizzazione dopo errore e dopo warning +local function PostErrView( nErr, sMsg) + if nErr ~= 0 and ( BEAM.FLAG == 1 or BEAM.FLAG == 2) then + EgtSetView( SCE_VD.ISO_SW, false) + EgtZoom( SCE_ZM.ALL) + EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS') + end +end + +local function PostWarnView( nWarn, sMsg) + if nWarn ~= 0 and ( BEAM.FLAG == 1 or BEAM.FLAG == 2) then + EgtSetView( SCE_VD.ISO_SW, false) + EgtZoom( SCE_ZM.ALL) + EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS') + end +end + +-- Funzione di reset gruppo di lavoro in caso di impossibilità di inserire i pezzi +local function ResetMachGroup( PARTS) + for i = 1, #PARTS do + EgtErase( PARTS[i].id) + end + EgtRemoveMachGroup( EgtGetCurrMachGroup() or GDB_ID.NULL) +end + +-- scrittura JSON risultati +-- TODO da migliorare/completare +local function WriteResultToJson( RESULT) + local sData = JSON:encode_pretty( RESULT) + + -- Salvataggio e visualizzazione tabella + local sOutFile = EgtChangePathExtension( BEAM.FILE, '.json') + local DestFh = io.open( sOutFile, 'w+') + if not DestFh then + EgtOutBox( 'Error opening ' .. sOutFile, 'TestJson', 'ERROR') + return false + end + DestFh:write( sData) + DestFh:close() + + return true +end + +------------------------------------------------------------------------------------------------------------- + +-- calcolo tempo esecuzione +TIMER:start() +EgtOutLog( ' Execution timer started') + +-- script principale + +local sFlag = '' +if BEAM.FLAG == 0 then + sFlag = 'GENERATE' +elseif BEAM.FLAG == 1 then + sFlag = 'MODIFY' +elseif BEAM.FLAG == 2 then + sFlag = 'SIMULATE' +elseif BEAM.FLAG == 3 then + sFlag = 'CHECK' +elseif BEAM.FLAG == 4 then + sFlag = 'CHECK+GENERATE' +elseif BEAM.FLAG == 6 then + sFlag = 'CREATE_BAR' +elseif BEAM.FLAG == 8 then + sFlag = 'CHECK_NOSIM' +elseif BEAM.FLAG == 9 then + sFlag = 'GET_TOPOLOGY' +elseif BEAM.FLAG == 10 then + sFlag = 'FLIP_ROT' +else + sFlag = 'FLAG='..tostring( BEAM.FLAG) +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) +local sOriFile = sDir..sTitle..'.ori.bwe' +local sNgeFile = sDir..sTitle..'.bwe' + +-- cancellazione file log txt precedente +-- in caso sia richiesta generazione senza check, verifico prima che il file log specifico non contenga errori: se sì, forzo il check +-- TODO serve ancora?? forzare sempre il check e simulazione? +if BEAM.FLAG == 0 then + local hLogFile = io.open( sTxtLogFile, 'r') + if hLogFile then + for line in hLogFile:lines() do + if EgtStartsWith( line, 'ERR') and tonumber( EgtSplitString( line, '=')[2] or 0) > 0 then + BEAM.FLAG = 4 + break + end + end + hLogFile:close() + end +-- restituisce all'interfaccia il nome della topologia della feature di id passato +-- TODO valutare se fare script separato +elseif BEAM.FLAG == 9 then + if type( BEAM.FEATUREID) == 'number' then + -- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella + local idTempGroup = BeamLib.CreateTempGroup() + + local Part = {} + Part.id = EgtGetParent( EgtGetParent( BEAM.FEATUREID)) + Part.idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( Part.id, 'Box') or GDB_ID.NULL) + Part.b3Part = EgtGetBBoxGlob( Part.idBoxTm, GDB_BB.STANDARD) + Part.idTempGroup = idTempGroup + + local Proc = FeatureLib.GetProcFromTrimesh( BEAM.FEATUREID, Part) + Proc.nGrp = EgtGetInfo( Proc.id, 'GRP', 'i') + Proc.nPrc = EgtGetInfo( Proc.id, 'PRC', 'i') + + Proc.Topology = {} + if FeatureLib.NeedTopologyFeature( Proc, Part) then + Proc.Topology = FeatureLib.ClassifyTopology( Proc, Part) + else + Proc = FeatureLib.GetAdditionalInfo( Proc, Part) + Proc.Topology = FeatureLib.GetTopologyFromFeature( Proc, Part) + end + + if Proc.Topology and Proc.Topology.sName then + BEAM.TOPOLOGY = Proc.Topology.sName + else + BEAM.TOPOLOGY = 'NOT_IMPLEMENTED' + end + + -- si cancella gruppo temporaneo contenente entità da cancellare + EgtErase( idTempGroup) + end + return +end + +-- Cancello file di log specifico +EgtEraseFile( sTxtLogFile) + +-- In generale va completamente riprocessato +local bToProcess = true +local bToRecalc = false +-- se BTL, barra ed esiste già il corrispondente progetto Nge +if EgtExistsFile( sOriFile) then + bToProcess = false + EgtCopyFile( sOriFile, sNgeFile) + -- se cambiata configurazione macchina da ultima elaborazione, devo aggiornare + if EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Beam\\TS3Data.lua') == -1 or + EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Tools\\Tools.data') == -1 or + EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\' .. sMachine ..'.mlde') == -1 then + bToRecalc = true + end +end + +-- Inizializzo contatori errori e avvisi +local nErrCnt = 0 +local nWarnCnt = 0 + +-- Se da elaborare +if bToProcess then + EgtOutLog( ' +++ Processing Parts >>>') + + -- Flag di barra da creare + local bCreateBar + -- Lunghezza della barra ed elenco travi + local dBarLen + + -- Se necessario, apro il file Bwe + if BEAM.FLAG ~= 6 then + if not EgtOpenFile( BEAM.FILE) then + BEAM.ERR = 13 + BEAM.MSG = 'Error opening BWE file : ' .. BEAM.FILE + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end + -- Faccio copia del file originale + EgtCopyFile( BEAM.FILE, sOriFile) + + -- Se già presente un gruppo di lavoro + if EgtGetFirstMachGroup() then + -- Barra già presente + bCreateBar = false + -- Rendo corrente il gruppo di lavoro + EgtSetCurrMachGroup() + -- Area tavola + local b3Tab = EgtGetTableArea() + -- Sezione del grezzo + local nRawId = EgtGetFirstRawPart() + if not nRawId then + BEAM.ERR = 14 + BEAM.MSG = 'Error no Raw Parts in the file : ' .. BEAM.FILE + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end + local b3Raw = EgtGetRawPartBBox( nRawId) + -- Calcolo posizione estremo TR o BR della tavola rispetto a sua origine in BL + local dPosY = EgtIf( BeamData.CENTER_BEAM, ( b3Tab:getDimY() + b3Raw:getDimY() * EgtIf( BeamData.RIGHT_LOAD, -1, 1)) / 2, EgtIf( BeamData.RIGHT_LOAD, 0, b3Tab:getDimY())) + BeamData.ptOriXR = Point3d( b3Tab:getDimX(), dPosY, 0) + BeamData.dPosXR = EgtIf( BeamData.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR) + -- Calcolo minimo grezzo scaricabile + BeamExec.CalcMinUnloadableRaw( b3Raw:getDimY(), b3Raw:getDimZ()) + -- altrimenti devo recuperare i pezzi per creare la barra + else + -- Barra da creare + bCreateBar = true + -- Recupero l'elenco ordinato delle travi + local nPartId = EgtGetFirstPart() + while nPartId do + table.insert( PARTS, { id = nPartId, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) + nPartId = EgtGetNextPart( nPartId) + end + if #PARTS == 0 then + BEAM.ERR = 14 + BEAM.MSG = 'Error no beams in the file : ' .. BEAM.FILE + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + else + local sOut = '' + for i = 1, #PARTS do + sOut = sOut .. PARTS[i].sName .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Travi trovate : ' .. sOut, 1) + end + -- Ne recupero le dimensioni + for i = 1, #PARTS do + local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box') + local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) + if not b3Solid then + BEAM.ERR = 15 + BEAM.MSG = 'Box undefined for beam ' .. PARTS[i].sName + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + else + PARTS[i].b3PartOriginal = b3Solid + end + end + -- Assegno lunghezza della barra + dBarLen = PARTS[1].b3PartOriginal:getDimX() + 10 + if dBarLen < 2200 then + dBarLen = dBarLen + 1800 + end + -- Assegno posizione prima ed unica trave + PARTS[1].dPosX = 10 + end + + -- Altrimenti, opero sul progetto corrente + else + -- Recupero l'identificativo del gruppo di lavoro corrente + local nMGrpId = EgtGetCurrMachGroup() + -- Barra da creare + bCreateBar = true + -- Lunghezza della barra + dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd') + -- Recupero l'elenco ordinato delle travi da inserire nella barra + for i = 1, 100 do + local sKey = 'PART'..tostring( i) + local sVal = EgtGetInfo( nMGrpId, sKey) + local vVal = EgtSplitString( sVal or '') + if not vVal or #vVal < 2 then break end + local nPartId = tonumber( vVal[1]) + local dPosX = tonumber( vVal[2]) + table.insert( PARTS, { id = nPartId, dPosX = dPosX, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) + end + if #PARTS == 0 then + BEAM.ERR = 14 + BEAM.MSG = 'Error : no beams in the project' + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + else + local sOut = '' + for i = 1, #PARTS do + sOut = sOut .. PARTS[i].sName .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Travi trovate : ' .. sOut, 1) + end + -- Ne recupero le dimensioni + for i = 1, #PARTS do + local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box') + local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) + if not b3Solid then + BEAM.ERR = 15 + BEAM.MSG = 'Box undefined for beam ' .. PARTS[i].sName + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + else + PARTS[i].b3PartOriginal = b3Solid + end + end + 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 + local idTempGroup = BeamLib.CreateTempGroup() + + -- Se devo creare la barra + if bCreateBar then + if #PARTS == 0 then + -- Recupero l'identificativo del gruppo di lavoro corrente + local nMGrpId = EgtGetCurrMachGroup() + -- Recupero le dimensioni della barra + dRawW = EgtGetInfo(nMGrpId, 'BARWIDTH', 'd') + dRawH = EgtGetInfo(nMGrpId, 'BARHEIGHT', 'd') + else + -- Ne verifico le dimensioni + dRawW = PARTS[1].b3PartOriginal:getDimY() + dRawH = PARTS[1].b3PartOriginal:getDimZ() + end + local vBeamErr = {} + for i = 2, #PARTS do + local dDimW = PARTS[i].b3PartOriginal:getDimY() + local dDimH = PARTS[i].b3PartOriginal:getDimZ() + if ( abs( dDimW - dRawW) > 100 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 100 * GEO.EPS_SMALL) and + ( abs( dDimH - dRawW) > 100 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 100 * GEO.EPS_SMALL) then + table.insert( vBeamErr, i) + end + end + if #vBeamErr > 0 then + local sOut = 'Rimosse travi con sezioni diverse dalla prima :\n' + for i = #vBeamErr, 1, -1 do + sOut = sOut .. PARTS[vBeamErr[i]].sName .. '\n' + table.remove( PARTS, vBeamErr[i]) + end + ResetMachGroup( PARTS) + BEAM.ERR = 16 + BEAM.MSG = sOut + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + return + end + + -- Verifico sezione barra non troppo grande + if not BeamData.MAX_WIDTH2 or not BeamData.MAX_HEIGHT2 then + if ( dRawW > BeamData.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT + 10 * GEO.EPS_SMALL) then + ResetMachGroup( PARTS) + local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. + 'oltre i limiti della macchina (' .. EgtNumToString( BeamData.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT, 2) .. ') ' + BEAM.ERR = 17 + BEAM.MSG = sOut + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end + else + if ( dRawW > BeamData.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT + 10 * GEO.EPS_SMALL) and + ( dRawW > BeamData.MAX_WIDTH2 + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT2 + 10 * GEO.EPS_SMALL) then + ResetMachGroup( PARTS) + local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. + 'oltre i limiti della macchina (' .. EgtNumToString( BeamData.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT, 2) .. ') ' .. + 'e (' .. EgtNumToString( BeamData.MAX_WIDTH2, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT2, 2) .. ')' + BEAM.ERR = 17 + BEAM.MSG = sOut + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end + end + + -- Verifico sezione barra non troppo piccola + if dRawW < BeamData.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < BeamData.MIN_HEIGHT - 10 * GEO.EPS_SMALL then + ResetMachGroup( PARTS) + local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. + 'sotto i limiti della macchina (' .. EgtNumToString( BeamData.MIN_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MIN_HEIGHT, 2) .. ')' + BEAM.ERR = 17 + BEAM.MSG = sOut + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end + + -- Lunghezza della barra + local dRawL = dBarLen + 0.1 + -- Sovramateriale di testa + local dOvmHead = 0 + if #PARTS > 0 then + dOvmHead = PARTS[1].dPosX or 0 + end + + -- Sistemo le travi nel grezzo + local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, bCalcBestPieceUnloadPosition) + if not bPbOk then + BEAM.ERR = 18 + BEAM.MSG = sPbErr + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + else + -- Scrivo altezza e larghezza barra nel gruppo di lavoro corrente + local nMGrpId = EgtGetCurrMachGroup() + EgtSetInfo(nMGrpId, 'BARHEIGHT', dRawH) + EgtSetInfo(nMGrpId, 'BARWIDTH', dRawW) + end + -- sistemazioni per pezzi nella barra + else + -- ciclo sui grezzi + local nRawId = EgtGetFirstRawPart() + while nRawId do + -- massimo un pezzo per grezzo + local nPartId = EgtGetFirstPartInRawPart( nRawId) + -- box del pezzo + local Ls = EgtGetFirstNameInGroup( nPartId, 'Box') + local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) + -- se nel grezzo c'è un pezzo + if nPartId then + -- creo o pulisco gruppo geometrie aggiuntive + BeamLib.CreateOrEmptyAddGroup( nPartId) + -- aggiungo faccia per taglio iniziale al pezzo + BeamLib.AddPartStartFace( nPartId, b3Solid) + -- aggiungo faccia per taglio finale al pezzo + BeamLib.AddPartEndFace( nPartId, b3Solid) + end + -- passo al successivo grezzo + nRawId = EgtGetNextRawPart( nRawId) + end + -- elimino le lavorazioni + EgtRemoveAllOperations() + -- Recupero l'identificativo del gruppo di lavoro corrente + local nMGrpId = EgtGetCurrMachGroup() + -- Recupero l'elenco ordinato delle travi da inserire nella barra + for i = 1, 100 do + local sKey = 'PART'..tostring( i) + local sVal = EgtGetInfo( nMGrpId, sKey) + local vVal = EgtSplitString( sVal or '') + if not vVal or #vVal < 2 then break end + local nPartId = tonumber( vVal[1]) + local dPosX = tonumber( vVal[2]) + table.insert( PARTS, { nInd = #PARTS + 1, id = nPartId, dPosX = dPosX, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) + end + -- se lunghezza barra non settata, la leggo ora + if not dBarLen then + dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd') + end + -- Recupero tutte le informazioni dei pezzi + local dLen = dBarLen + for i = 1, #PARTS do + -- aggiorno grezzo precedente + PARTS[i].idRaw = EgtGetRawPartFromPart( PARTS[i].id) + PARTS[i].bIsLastPart = ( i == #PARTS) + -- dimensioni del grezzo ( comprende sovramateriale di testa e lavorazione di coda per separazione) + PARTS[i].b3Raw = EgtGetRawPartBBox( PARTS[i].idRaw) + PARTS[i].dRawLength = PARTS[i].b3Raw:getDimX() + PARTS[i].dRawWidth = PARTS[i].b3Raw:getDimY() + PARTS[i].dRawHeight = PARTS[i].b3Raw:getDimZ() + -- dimensione pezzo finito + PARTS[i].idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL) + PARTS[i].b3Part = EgtGetBBoxGlob( PARTS[i].idBoxTm, GDB_BB.STANDARD) + PARTS[i].dLength = PARTS[i].b3Part:getDimX() + PARTS[i].dWidth = PARTS[i].b3Part:getDimY() + PARTS[i].dHeight = PARTS[i].b3Part:getDimZ() + PARTS[i].bSquareSection = abs( PARTS[i].dWidth - PARTS[i].dHeight) < 100 * GEO.EPS_SMALL + PARTS[i].nIndexInParts = i + 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}} + PARTS[i].sBTLInfo = EgtGetInfo( PARTS[i].id, 'PROJ', 's') or nil + PARTS[i].idTempGroup = idTempGroup + + PARTS[i].sAISetupConfig = EgtGetInfo( PARTS[i].id, 'AISETUP', 's') or + ( GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo] and GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo].sAISetupConfig) or -- i parametri BTL potrebbero non esistere + GENERAL_PARAMETERS.PROJECT.sAISetupConfig or nil + + -- si carica configurazione lavorazioni + TIMER:startElapsed('Json') + 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) + + -- sovramateriale in testa al pezzo + local dDeltaS = max( PARTS[i].dPosX - ( dBarLen - dLen), 0) + PARTS[i].dHeadOverMaterial = dDeltaS + + -- lunghezza grezzo (comprende sovramateriale di testa e mm tagliati in coda dalla lavorazione, tipicamente 5.4mm dello spessore lama) + local dCrawLen = PARTS[i].dRawLength + -- materiale tolto in coda dalla lavorazione di separazione + local dDeltaE = dCrawLen - PARTS[i].dLength - dDeltaS + local dDeltaNextPiece + if PARTS[i+1] then + dDeltaNextPiece = PARTS[i+1].dPosX - ( dBarLen - dLen) - dCrawLen + dDeltaE + else + dDeltaNextPiece = 10000 + end + PARTS[i].dDistanceToNextPiece = dDeltaNextPiece + + -- aggiorno la lunghezza residua della barra + dLen = dLen - dCrawLen + PARTS[i].dRestLength = dLen + end + end + + -- Se richiesta solo barra, esco + if BEAM.FLAG == 6 then + -- Completamento senza errori e avvisi + if nWarnCnt == 0 then + BEAM.ERR = 0 + BEAM.MSG = '---' + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + end + EgtOutLog( ' +++ BatchProcess completed') + return + end + + -- Imposto Nome file CN + local _, sName, _ = EgtSplitPath( BEAM.FILE) + EgtSetInfo( EgtGetCurrMachGroup(), 'NcName', sName .. '.cnc') + + -- Abilito Vmill + EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1') + + -- Aggiorno Setup utensili + EgtImportSetup() + + -- Lavoro le features + -- 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.ProcessMachinings( PARTS) + + -- si cancella gruppo temporaneo contenente entità da cancellare + EgtErase( idTempGroup) + + local sOutput = '' + + -- scrittura txt risultati + for i = 1, #RESULT do + local sMsg = '' + if RESULT[i].sType == 'Feature' then + if RESULT[i].ChosenStrategy.bIsApplyOk then + sMsg = RESULT[i].ChosenStrategy.sInfo + else + sMsg = RESULT[i].ChosenStrategy.sApplyInfo + end + 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 + if #EgtTrim( sMsg) > 0 then + BEAM.ERR = -19 + BEAM.MSG = sMsg + else + BEAM.ERR = 0 + BEAM.MSG = '---' + end + BEAM.ROT = -( RESULT[i].nRotation or 1) + 1 + BEAM.CUTID = RESULT[i].idCut + BEAM.TASKID = RESULT[i].idTask + WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) + -- 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) + BEAM.ERR = 19 + BEAM.MSG = sMsg + BEAM.ROT = -( RESULT[i].nRotation or 1) + 1 + BEAM.CUTID = RESULT[i].idCut + BEAM.TASKID = RESULT[i].idTask + WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) + 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 + BEAM.ERR = 0 + BEAM.MSG = sMsg + BEAM.CUTID = RESULT[i].idCut + BEAM.FALL = abs( RESULT[i].nErr + 100) + WriteFallToLogFile( BEAM.ERR, BEAM.MSG, BEAM.CUTID, BEAM.FALL) + -- errore da post apply, al momento non specifico + elseif RESULT[i].sType == 'Part' and RESULT[i].nErr > 0 then + nErrCnt = nErrCnt + 1 + sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg) + BEAM.ERR = 19 + BEAM.MSG = 'Clamp impossible' + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + return + -- feature incompleta e altro + elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then + nWarnCnt = nWarnCnt + 1 + sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg) + BEAM.ERR = -19 + BEAM.MSG = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg + BEAM.ROT = -( RESULT[i].nRotation or 1) + 1 + BEAM.CUTID = RESULT[i].idCut + BEAM.TASKID = RESULT[i].idTask + WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) + end + end + end + + -- TODO: se scarico a caduta (-101, -102) le lavorazioni dopo separazione vanno disattivate. Scrivere info feature incompleta su quelle feature + + -- Salvo il progetto + EgtSaveFile( sNgeFile) + -- copio come originale (per dichiarare progetto ricalcolato) + EgtCopyFile( sNgeFile, sOriFile) + + -- Visualizzazione avvisi o errori + if #sOutput > 0 then EgtOutLog( sOutput) end + if nErrCnt > 0 then + PostErrView( 19, sOutput) + elseif nWarnCnt > 0 then + PostWarnView( 19, sOutput) + end + +-- Altrimenti carico il progetto salvato e dichiaro nessun errore +else + EgtOutLog( ' +++ Loading Project already processed >>>') + -- Carico il progetto già fatto + EgtOpenFile( sNgeFile) + -- Passo in modalità lavora + EgtSetCurrMachGroup( EgtGetLastMachGroup()) + -- Se necessario eseguo aggiornamento con setup corrente e ricalcolo delle lavorazioni + if bToRecalc or BEAM.FLAG == 3 or BEAM.FLAG == 4 or BEAM.FLAG == 8 then + EgtOutLog( ' +++ Recalculating all dispositions and machinings >>>') + EgtImportSetup() + EgtApplyAllMachinings() + -- Salvo il progetto + EgtSaveFile( sNgeFile) + -- copio come originale (per dichiarare progetto ricalcolato) + EgtCopyFile( sNgeFile, sOriFile) + end +end + +-- log tempi di esecuzione +if EgtGetDebugLevel() >= 3 then + TIMER:logAllElapsed() +end + +-- *** Eseguo simulazione con verifica collisione in cieco *** +if ( BEAM.FLAG == 0 and ( bToProcess or bToRecalc)) or BEAM.FLAG == 3 or BEAM.FLAG == 4 then + EgtOutLog( ' +++ Simulating with collision check >>>') + -- verifico setup + local bSetUpOk, SetUpErrors = EgtVerifyCurrSetup() + if not bSetUpOk then + local sToolsList = "" + for ToolIndex = 1, #SetUpErrors do + sToolsList = sToolsList .. SetUpErrors[ToolIndex] + if ToolIndex ~= #SetUpErrors then + sToolsList = sToolsList .. ", " + end + end + BEAM.ERR = 19 + BEAM.MSG = 'Error in setup: tool/s ' .. sToolsList .. ' not found' + WriteErrToLogFile( BEAM.ERR, BEAM.MSG, 0, 0, 0) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end + -- lancio simulazione + local bSimOk, nErr, sErr = EgtSimulate() + if not bSimOk then + if nErr == MCH_SHE.INIT then + BEAM.ERR = 19 + BEAM.MSG = 'Error starting simulation' + elseif nErr == MCH_SHE.COLLISION then + BEAM.ERR = 22 + BEAM.MSG = 'Head-part collision' + elseif nErr == MCH_SHE.OUTSTROKE then + BEAM.ERR = 23 + BEAM.MSG = 'Axis outstroke ' .. sErr + elseif nErr == MCH_SHE.SPECIAL then + BEAM.ERR = 24 + BEAM.MSG = 'Special error ' .. sErr + else + BEAM.ERR = 25 + BEAM.MSG = 'General failure (contact supplier)' + end + BEAM.ROT = 0 + BEAM.CUTID = 0 + BEAM.TASKID = 0 + local vItem = EgtSplitString( sErr, ';') or {} + for i = 1, #vItem do + vItem[i] = EgtTrim( vItem[i] or '') + if string.find( vItem[i], 'CUTID', 1, true) then + BEAM.CUTID = EgtGetVal( vItem[i], 'CUTID', 'i') or 0 + elseif string.find( vItem[i], 'TASKID', 1, true) then + BEAM.TASKID = EgtGetVal( vItem[i], 'TASKID', 'i') or 0 + end + end + WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID) + -- TODO gestire collisione su feature specifica!!!!!!!!!!!!!!!!!!!!!!!!!!!! + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, BEAM.CUTID, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end +end + +-- *** Genero programma CN *** ( se richiesto) +local bIsGenerationEnabled = ( EgtVerifyKeyOption( 110) == false) +if bIsGenerationEnabled and ( BEAM.FLAG == 0 or BEAM.FLAG == 4) then + EgtOutLog( ' +++ Generating NC part program >>>') + local sInfo = 'EgtCAM5' .. EgtIf( EgtIs64bit(), ' 64bit', '') + if EgtGetExeVersion then + sInfo = sInfo .. ' ver.' .. EgtGetExeVersion() + end + sInfo = sInfo .. ' - ' + if not EgtGenerate( '', sInfo .. sNgeFile) then + BEAM.ERR = 20 + local _, sName, _ = EgtSplitPath( BEAM.FILE) + BEAM.MSG = 'Error generating NC part program : ' .. sName + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return + end +end + +-- *** Eseguo stima tempi *** +EgtOutLog( ' +++ Estimating T&L >>>') +if not EgtEstimate( '', 'EgtCAM5 - ' .. sNgeFile) then + BEAM.ERR = 21 + local _, sName, _ = EgtSplitPath( BEAM.FILE) + BEAM.MSG = 'Error estimating production time : ' .. sName + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) + PostErrView( BEAM.ERR, BEAM.MSG) + BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG) + BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) + WriteResultToJson( RESULT) + return +end +local Ttot = EgtGetInfo( EgtGetCurrMachGroup(), 'Ttot', 'd') +local sTime = 'Total Time = ' .. EgtNumToString( Ttot, 1) +EgtOutLog( sTime) + +-- Se modifica o simula, imposto la vista ISO 3d opportuna +if BEAM.FLAG == 1 or BEAM.FLAG == 2 then + local vView = { SCE_VD.ISO_NW, SCE_VD.ISO_SW, SCE_VD.ISO_NE, SCE_VD.ISO_SE} + local nV = min( max( BeamData.SIMUL_VIEW_DIR or 2, 1), 4) + EgtSetView( vView[nV], false) +end + +-- Completamento senza errori e avvisi +if nWarnCnt == 0 then + BEAM.ERR = 0 + BEAM.MSG = '---' + WriteErrToLogFile( BEAM.ERR, BEAM.MSG) +end + +-- Scrittura tempo totale stimato di lavorazione +WriteTimeToLogFile( Ttot) +RESULT[#RESULT+1] = { dTime = Ttot, sType = 'Time'} + +-- Riporto risultati in tabella globale BEAM +BEAM.RESULT = BeamLib.TableCopyDeep( RESULT) +-- Scrittura json risultati +WriteResultToJson( RESULT) + +EgtOutLog( ' +++ BatchProcess completed') diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index 870d833..6b7d246 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -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 @@ -1554,10 +1558,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 +1578,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 diff --git a/Strategies/GeneralParameters.json b/Strategies/GeneralParameters.json index 077696b..d727430 100644 --- a/Strategies/GeneralParameters.json +++ b/Strategies/GeneralParameters.json @@ -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,35 @@ "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": "true", + "sDescriptionShort": "Allow piece inversion", + "sDescriptionLong": "", + "sType": "b", + "sMessageId": " ", + "sMinUserLevel": "1" + }, { "nGroup": "MACHINE", "sName": "GEN_sPieceRotation",